Code review annotations for codediff.nvim, optimized for AI feedback loops.
This is a hard fork of georgeguimaraes/review.nvim, diverged as of
v2.0.0. The storage layer was rewritten from a flat per-branch JSON file to a DuckDB-backed, multi-writer-safe design, and the project's direction has shifted toward being a more general-purpose multi-author commenting tool rather than a single-reviewer annotation layer.
review.nvim reviews local diffs (working tree, commits, revision ranges) — it does not integrate with GitHub/GitLab pull or merge requests. For reviewing and commenting on PRs/MRs from within Neovim, see octo.nvim.
- Add comments to specific lines in diff view (Note, Suggestion, Issue, Praise)
- Multi-line comment support with box-style virtual text display
- Comments displayed as signs, line highlights, and virtual text
- Comment box borders are colored deterministically per author (derived from a hash of the author string), so you can tell at a glance whose comment is whose — always on, and adapts automatically to
:set background - Comments persist per branch in a local DuckDB file (Neovim's XDG data directory:
~/.local/share/nvim/review/), safe for multiple writers (e.g. you and an AI agent) commenting concurrently - An AI agent can read and add comments in that same file directly via a bundled skill — no need to open Neovim to join the review
- Auto-export comments to clipboard when closing
- Export format optimized for AI conversations
- Send comments directly to sidekick.nvim for AI chat
- Commit picker modal to select specific commits to review
- Built on top of codediff.nvim
- Neovim >= 0.11
- codediff.nvim
- nui.nvim
duckdbCLI on your$PATH(used for comment storage)
This plugin uses semantic versioning. Pin to a tag to avoid breaking changes.
Using lazy.nvim:
{
"tkolleh/review.nvim",
version = "v*",
dependencies = {
"esmuellert/codediff.nvim",
"MunifTanjim/nui.nvim",
},
cmd = { "Review" },
keys = {
{ "<leader>r", "<cmd>Review<cr>", desc = "Review" },
{ "<leader>R", "<cmd>Review commits<cr>", desc = "Review commits" },
},
opts = {},
}:Review " Open codediff with comment keymaps (default)
:Review open " Same as above
:Review commits " Select commits to review (picker modal)
:Review commits SHA " Review a single commit (diffs SHA^ against SHA)
:Review commits REV1 REV2 " Review specific revision range (skips picker)
:Review close " Close and export comments to clipboard
:Review export " Export comments to clipboard
:Review preview " Preview exported markdown in split
:Review sidekick " Send comments to sidekick.nvim
:Review list " List all comments
:Review clear " Clear all comments
:Review toggle " Toggle readonly/edit modeOpen a review with :Review (staged/unstaged changes) or :Review commits (pick specific commits). The diff opens in a new tab with a file panel on the left.
Navigate with <Tab>/<S-Tab> (files), f (toggle file panel), t (side-by-side/inline), <C-w>h/<C-w>l (old/new pane). Press i on a line to comment; pick a type (note, suggestion, issue, praise) from the menu. The comment renders as a box below the line with a sign in the gutter.
Visually select a range before i for a multi-line comment, or press F for a file-level comment. Left-side (old) and right-side (new) comments only show on their own side.
Use ]n/[n to jump between comments, e to edit, d to delete, c to list and jump to any comment.
Press q to close the review — this copies all comments to the clipboard as structured markdown and shows a preview, ready to paste into Claude Code, sidekick.nvim (S), or any AI chat:
1. **[ISSUE]** `src/api.ts:23` - This endpoint doesn't handle errors
2. **[SUGGESTION]** `src/utils.ts:~10` - The old implementation was cleaner
A ~ prefix means the old (left) side of the diff. Comments persist per branch and survive closing Neovim, expiring after 7 days. Storage is DuckDB, not a flat file, so another writer — a teammate on the same branch, or an AI agent — can comment on the same session concurrently without clobbering yours.
Each comment's author border color is computed by DuckDB itself at insert time (a GENERATED ALWAYS AS column hashing the author string into a fixed, WCAG-validated palette) — not by Neovim — so it's consistent for any reader of the storage file. Because DuckDB can't add a generated column to an existing table, this only applies to sessions created after upgrading; run :Review clear to reset an older session's storage file if its comments don't show author colors.
An AI agent can join the review directly from the CLI, reading and adding comments in the same
DuckDB file this plugin uses — no need to open Neovim. Comments an agent adds show up in your
next :Review session, and comments you leave are visible to the agent's next read, so a human
and an agent can converse in the same review thread.
This is bundled as an Agent Skill at skills/review-nvim; see its
SKILL.md for usage. Install it with npx skills:
npx skills@latest add https://github.com/tkolleh/review.nvim/tree/main/skills/review-nvimReadonly mode (default):
| Key | Action |
|---|---|
i |
Add comment (pick type from menu) |
F |
Add file-level comment |
d |
Delete comment at cursor |
e |
Edit comment at cursor |
c |
List all comments |
f |
Toggle file panel visibility |
R |
Toggle readonly/edit mode |
<Tab> |
Next file |
<S-Tab> |
Previous file |
]n |
Jump to next comment |
[n |
Jump to previous comment |
C |
Export to clipboard and show preview |
S |
Send comments to sidekick.nvim |
<C-r> |
Clear all comments |
q |
Close and export comments to clipboard |
? |
Show review.nvim keymap help |
t |
Toggle side-by-side/inline layout |
g? |
Show codediff help |
Edit mode (when readonly = false):
| Key | Action |
|---|---|
<localleader>cc |
Add comment (pick type from menu) |
<localleader>cn/cs/ci/cp |
Add Note/Suggestion/Issue/Praise |
<localleader>cf |
Add file-level comment |
<localleader>cd |
Delete comment |
<localleader>ce |
Edit comment |
Comment popup (when adding/editing):
| Key | Action |
|---|---|
Enter |
Insert newline (multi-line comments supported) |
Ctrl+s |
Submit comment |
Tab |
Cycle comment type |
Esc / q |
Cancel (normal mode) |
All keymaps can be set to false to disable them.
Keymap options
| Option | Default | Action |
|---|---|---|
add_comment |
<localleader>cc |
Add comment, pick type (edit mode) |
add_note |
<localleader>cn |
Add note (edit mode) |
add_suggestion |
<localleader>cs |
Add suggestion (edit mode) |
add_issue |
<localleader>ci |
Add issue (edit mode) |
add_praise |
<localleader>cp |
Add praise (edit mode) |
add_file_comment |
<localleader>cf |
Add file-level comment (edit mode) |
delete_comment |
<localleader>cd |
Delete comment (edit mode) |
edit_comment |
<localleader>ce |
Edit comment (edit mode) |
next_comment |
]n |
Next comment |
prev_comment |
[n |
Previous comment |
next_file |
<Tab> |
Next file |
prev_file |
<S-Tab> |
Previous file |
toggle_file_panel |
f |
Toggle file panel |
list_comments |
c |
List all comments |
export_clipboard |
C |
Export to clipboard |
send_sidekick |
S |
Send comments to sidekick |
clear_comments |
<C-r> |
Clear all comments |
close |
q |
Close and export |
toggle_readonly |
R |
Toggle readonly/edit mode |
readonly_add |
i |
Add comment (readonly mode) |
readonly_delete |
d |
Delete comment (readonly mode) |
readonly_edit |
e |
Edit comment (readonly mode) |
readonly_add_file |
F |
Add file-level comment (readonly mode) |
show_help |
? |
Show review.nvim keymap help |
popup_submit |
<C-s> |
Submit comment (popup, insert & normal) |
popup_cancel |
q |
Cancel comment (popup, normal mode) |
popup_cycle_type |
<Tab> |
Cycle comment type (popup) |
require("review").setup({
comment_types = {
note = { key = "n", name = "Note", icon = "📝", hl = "ReviewNote" },
suggestion = { key = "s", name = "Suggestion", icon = "💡", hl = "ReviewSuggestion" },
issue = { key = "i", name = "Issue", icon = "⚠️", hl = "ReviewIssue" },
praise = { key = "p", name = "Praise", icon = "✨", hl = "ReviewPraise" },
},
keymaps = {
add_note = "<localleader>cn",
add_suggestion = "<localleader>cs",
add_issue = "<localleader>ci",
add_praise = "<localleader>cp",
delete_comment = "<localleader>cd",
edit_comment = "<localleader>ce",
next_comment = "]n",
prev_comment = "[n",
toggle_file_panel = "f",
},
codediff = {
readonly = true,
},
})Comments are exported as Markdown optimized for AI consumption:
I reviewed your code and have the following comments. Please address them.
Comment types: ISSUE (problems to fix), SUGGESTION (improvements), NOTE (observations), PRAISE (positive feedback)
1. **[ISSUE]** `src/components/Button.tsx:23` - Wrapping onClick creates a new function every render
2. **[SUGGESTION]** `src/utils/api.ts:~45` - The old implementation was cleaner
3. **[PRAISE]** `src/hooks/useAuth.ts:12-18` - Clean implementation of the auth flowLines prefixed with ~ (e.g. :~45) refer to the old (left) side of the diff. Range comments use start-end notation.
just testLicensed under the Apache License, Version 2.0. See LICENSE for details.
The PR review panel is heavily inspired by tuicr.