by Cannon07
A Neovim plugin that shows a live diff preview of AI coding agent's file edits before you accept or reject them.
# Add to your Claude Code skills
git clone https://github.com/Cannon07/code-preview.nvimGuides for using ai agents skills like code-preview.nvim.
Last scanned: 5/30/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-05-30T15:58:12.069Z",
"npmAuditRan": true,
"pipAuditRan": true
}No comments yet. Be the first to share your thoughts!
30 days in the Featured rail
A Neovim plugin that shows a diff preview before your AI coding agent applies any file change — letting you review exactly what's changing before accepting.
Supports Claude Code, OpenCode, GitHub Copilot CLI, and OpenAI Codex CLI as backends.




nvim --headless -lFor Claude Code backend:
For OpenCode backend:
For GitHub Copilot CLI backend:
For OpenAI Codex CLI backend:
apply_patch PreToolUse hooks; older builds only fired hooks for Bash){
"Cannon07/code-preview.nvim",
config = function()
require("code-preview").setup()
end,
}
vim.opt.rtp:prepend("/path/to/code-preview.nvim")
require("code-preview").setup()
setup():CodePreviewInstallClaudeCodeHooks — writes hooks to .claude/settings.local.json<leader>dq to close the diff manuallysetup():CodePreviewInstallOpenCodeHooks — copies the plugin to .opencode/plugins/~/.config/opencode/opencode.json) has permission prompts enabled:
{
"permission": {
"edit": "ask",
"bash": "ask"
}
}
<leader>dq to close the diff manuallysetup():CodePreviewInstallCopilotCliHooks — writes .github/hooks/code-preview.json<leader>dq to close the diff manuallyNote: Copilot CLI does not fire post-tool hooks on rejection, so rejected diffs remain open until you dismiss them (same as Claude Code).
Install the plugin and call setup()
Open a project in Neovim
Run :CodePreviewInstallCodexCliHooks — writes .codex/hooks.json
The diff-preview workflow only makes sense when Codex asks before applying edits. Create or edit .codex/config.toml (project-local) or ~/.codex/config.toml (global) and add:
approval_policy = "on-request"
sandbox_mode = "read-only"
approval_policy = "on-request" and sandbox_mode = "read-only" ensure Codex prompts you before every edit, so the diff preview has time to open and you have time to review. Without them, Codex may apply changes without prompting and the preview window will never block on your decision.
Note on the hooks feature flag: Modern Codex enables hooks by default — no
[features]entry is required. If you previously disabled them with[features] hooks = false(or the legacycodex_hooks = false), remove that line.:CodePreviewStatusand:checkhealth code-previewwill warn if hooks are explicitly disabled.
Start Codex CLI in the project directory
Ask Codex to edit a file — a diff opens automatically in Neovim
Accept/reject in the CLI; the diff closes automatically on accept
If rejected, press <leader>dq to close the diff manually
Note: Today's Codex models route all file edits through the
apply_patchtool. New file creation that Codex performs via shell redirection (e.g.printf … > foo.txt) is not previewed — onlyapply_patchand edits via the dedicatedEdit/Writetools (when emitted) are.
AI Agent (terminal) Neovim
| |
Proposes an Edit |
| |
Hook/plugin fires ──→ compute diff ──→ RPC → show_diff()
| | (side-by-side or inline)
CLI: "Accept? (y/n)" |
| User reviews diff
User accepts/rejects |
| |
Post hook fires ────→ cleanup ─────→ RPC → close_diff()
Claude Code uses shell-based hooks (PreToolUse/PostToolUse) configured in .claude/settings.local.json.
OpenCode uses a TypeScript plugin (tool.execute.before/tool.execute.after) loaded from .opencode/plugins/.
GitHub Copilot CLI uses shell-based hooks (preToolUse/postToolUse) configured in .github/hooks/code-preview.json. The adapter translates Copilot's tool vocabulary (apply_patch, edit, create, bash) into the same normalized format used by the other backends.
OpenAI Codex CLI uses shell-based hooks (PreToolUse/PostToolUse) configured in .codex/hooks.json. Hooks are enabled by default in modern Codex; the only way to silence them is [features] hooks = false (or the legacy codex_hooks = false) in .codex/config.toml. The adapter passes Bash through and rewrites apply_patch (whose patch text lives in tool_input.command) into the canonical ApplyPatch shape with tool_input.patch_text.
All backends communicate with Neovim via RPC (nvim --server <socket> --remote-send).
All options with defaults:
require("code-preview").setup({
debug = false, -- enable debug logging to stdpath("log")/code-preview.log
diff = {
layout = "tab", -- "tab" (new tab) | "vsplit" (current tab) | "inline" (GitHub-style)
labels = { current = "CURRENT", proposed = "PROPOSED" },
equalize = true, -- 50/50 split widths (tab/vsplit only)
full_file = true, -- show full file, not just diff hunks (tab/vsplit only)
visible_only = false, -- skip diffs for files not open in any Neovim buffer
defer_claude_permissions = false, -- for Claude Code: let its own settings decide, don't prompt
},
highlights = {
current = { -- CURRENT (original) side — tab/vsplit layouts
DiffAdd = { bg = "#4c2e2e" },
DiffDelete = { bg = "#4c2e2e" },
DiffChange = { bg = "#4c3a2e" },
DiffText = { bg = "#5c3030" },
},
proposed = { -- PROPOSED side — tab/vsplit layouts
DiffAdd = { bg = "#2e4c2e" },
DiffDelete = { bg = "#4c2e2e" },
DiffChange = { bg = "#2e3c4c" },
DiffText = { bg = "#3e5c3e" },
},
inline = { -- inline layout
added = { bg = "#2e4c2e" }, -- added line background
removed = { bg = "#4c2e2e" }, -- removed line background
added_text = { bg = "#3a6e3a" }, -- changed characters (added)
removed_text = { bg = "#6e3a3a" }, -- changed characters (removed)
},
},
})
| Command | Description |
|---------|-------------|
| :CodePreviewInstallClaudeCodeHooks | Install Claude Code hooks to .claude/settings.local.json |
| :CodePreviewUninstallClaudeCodeHooks | Remove Claude Code hooks (leaves other hooks intact) |
| :CodePreviewInstallOpenCodeHooks | Install OpenCode plugin to .opencode/plugins/ |
| :CodePreviewUninstallOpenCodeHooks | Remove OpenCode plugin |
| :CodePreviewInstallCopilotCliHooks | Install Copilot CLI hooks to .github/hooks/code-preview.json |
| :CodePreviewUninstallCopilotCliHooks | Remove Copilot CLI hooks |
| :CodePreviewInstallCodexCliHooks | Install Codex CLI hooks to .codex/hooks.json |
| :CodePreviewUninstallCodexCliHooks | Remove Codex CLI hooks |
| :CodePreviewCloseDiff | Manually close the diff (use a