Neovim plugin for local diff review workflows, draft persistence, and optional agent handoff from inside Neovim.
Commentry inside Diffview with draft comments, type labels, and review context visible in-place:
Using lazy.nvim with Diffview+:
{
"commentry/commentry.nvim",
dependencies = {
"dlyongemallo/diffview-plus.nvim",
},
opts = {},
}The upstream sindrets/diffview.nvim package is also supported. Install only
one implementation; both expose the same diffview module and commands.
Required:
- Neovim
0.10+ dlyongemallo/diffview-plus.nvimorsindrets/diffview.nvimfor the diff UI
Optional integrations:
folke/snacks.nvimfor:Commentry list-comments- a Sidekick runtime for
:Commentry send-to-agent
require("commentry").setup({
log = {
level = "warn", -- error|warn|info|debug
sink = "notify", -- notify|echo|file
file = nil, -- path when sink == "file"
},
diagnostics = {
open_style = "split", -- split|vsplit|float
},
agent = {
enabled = false,
},
diffview = {
auto_attach = true,
comment_cards = {
max_width = 76,
max_body_lines = 6,
show_markers = true,
},
comment_ranges = {
enabled = true,
line_highlight = true,
},
},
})commentry.nvim provides a :Commentry command with subcommands.
:Commentry openopens a diffview for local changes (shortcut).:Commentry add-range-commentcreates a range comment from the current visual selection.:Commentry list-commentsopens a Snacks picker for active draft comments across the current review, with source preview and in-picker delete (<C-d>current,<M-d>selected). Requiressnacks.nvim.:Commentry set-comment-typesets default or per-comment type (note,suggestion,issue,praise).:Commentry toggle-file-reviewedtoggles reviewed status for the current file's exact displayed change.:Commentry next-unreviewedjumps to the next unreviewed diff entry in panel order.:Commentry exportprints deterministic markdown for active draft comments.:Commentry export registerwrites markdown to the unnamed register.:Commentry export register:<name>writes markdown to a specific register (for exampleregister:a).:Commentry debug-storeprints the active review context and the exact on-disk store path.:Commentry diagnosticsopens a scratch buffer with runtime diagnostics (config/log/store/diffview state).:Commentry send-to-agentdelegates the current review payload to Sidekick. Requiresagent.enabled = true.
Commentry delegates agent selection and lifecycle to require("sidekick.cli").send().
Sidekick reuses an attached agent when possible; otherwise it opens its CLI
selector and can attach to an existing session or start a new one. Commentry
does not maintain a separate session inventory or picker.
Sidekick owns the supported-agent list, so Commentry remains provider agnostic. Enable agent handoff with:
require("commentry").setup({
agent = {
enabled = true,
},
}):Commentry send-to-agent leaves the Sidekick tool filter unset, so Sidekick
chooses among any configured agent harnesses.
If you open diffview directly (for example :DiffviewOpen main), Commentry will
auto-attach to diff buffers by default.
You can disable auto-attach with:
require("commentry").setup({
diffview = {
auto_attach = false,
},
})Commentry supports nine configurable diffview-local keymap actions:
| Action | Default | Mode | Empty-string disable ("") |
Command fallback |
|---|---|---|---|---|
add_comment |
mc |
Normal | No | None |
add_range_comment |
mc |
Visual | No | :Commentry add-range-comment |
edit_comment |
me |
Normal | No | None |
delete_comment |
md |
Normal | No | None |
set_comment_type |
mt |
Normal | No | :Commentry set-comment-type |
toggle_file_reviewed |
mr |
Normal | Yes | :Commentry toggle-file-reviewed |
next_unreviewed_file |
]r |
Normal | Yes | :Commentry next-unreviewed |
send_to_agent |
ms |
Normal | No | :Commentry send-to-agent |
list_comments |
ml |
Normal | No | :Commentry list-comments |
Notes:
- Keymaps attach only in buffers marked as Commentry diffview buffers.
- Empty-string disable is intentionally scoped to
toggle_file_reviewedandnext_unreviewed_file. - For remap-only actions (
add_comment,add_range_comment,edit_comment,delete_comment,set_comment_type,send_to_agent,list_comments),""is invalid and setup warns, then default/effective mapping remains active. add_range_commentmapping normally uses its configured/default value from setup normalization. The fallback chain to resolvedadd_comment(thenmc) is a defensive runtime path whenConfig.keymapsis missing or bypasses normalization.
Example override (partial remap + selective disable):
require("commentry").setup({
keymaps = {
add_comment = "gc",
add_range_comment = "gc",
edit_comment = "ge",
delete_comment = "gd",
set_comment_type = "gt",
send_to_agent = "gs",
list_comments = "gl",
toggle_file_reviewed = "",
next_unreviewed_file = "]u",
},
})Example keep defaults except one mapping:
require("commentry").setup({
keymaps = {
next_unreviewed_file = "]n",
},
})- Run tests:
./scripts/test - Validate docs:
./scripts/docs - First release checklist:
docs/release-checklist.md - Canonical feature/design plans:
docs/plans/ - Legacy Speckit archive (read-only history):
docs/archive/speckit/
- Draft comments are persisted per review context under
~/.commentry/repos/<repo>/contexts/<context-id>/. - Review context identity is branch-scoped (
<root>::review::branch::<branch-name>), so comments remain stable across different:DiffviewOpenrange lenses on the same branch until anchors become outdated by code changes. - Add/edit/range comment actions open a floating multiline editor (
Enterfor newline,Ctrl-sto save,q/Escin normal mode to cancel,Tabto cycle type). - Draft comment bodies are rendered as persistent boxed cards on commented lines, even when the cursor moves away.
- Range comments render start/mid/end gutter signs (
╭,│,╰) with subtle line tinting to show covered lines. - Reviewed state is content-addressed from each file's base/head Git blob and mode identities. It survives unstaged -> staged -> committed -> pushed transitions when the displayed before/after content is unchanged, regardless of commit IDs or Diffview range syntax.
- A file is unreviewed when either displayed endpoint changes. Returning to an exact previously reviewed before/after snapshot restores its reviewed state.
- Commentry renders
[reviewed]marks in the Diffview file panel,[partial]on partially reviewed directories, and a lightweight[reviewed]/[unreviewed]indicator in active diff buffers. These marks are independent from Diffview+ batch selections. - Send flow is explicit: open/attach a review (
:Commentry openor auto-attach), enable the generic agent integration, then run:Commentry send-to-agent. - Sidekick owns agent selection, attachment, terminal creation, display/focus, and prompt submission. Commentry only builds the review payload and delegates it.
- Agent sends require an active Commentry review context. Running them outside an attached review buffer/context fails.
- Send is send-and-forget in v1: Commentry delegates a compact human-readable payload (
COMMENTRY_REVIEW_V1) once and reports whether delegation started. Sidekick owns subsequent selection or cancellation. - v1 does not persist send history, delivery receipts, retries, or any outbound queue state.
Use the minimal repro config to isolate issues:
nvim --clean -u repro.luaThis bootstraps a clean Neovim with only commentry + diffview loaded.
- Draft store file does not exist yet:
Commentry creates
~/.commentry/repos/<repo>/contexts/<context-id>/commentry.jsonlazily on first successful write (add/edit/delete comment, set type, toggle reviewed). If no writes happened in that context yet, the file is absent. :Commentry list-commentsis unavailable: installsnacks.nvim, then rerun:checkhealth commentryto confirmpicker.selectsupport.- Incompatible pre-snapshot store:
reviewed-file persistence now uses
reviewed_changessnapshots rather than the formerfile_reviewsboolean map. Remove the context'scommentry.jsonif it predates this format. - Wrong context:
review context is branch-scoped (
<root>::review::branch::<branch-name>) and shared across diff ranges on that branch. Comments become stale/outdated when anchor reconciliation detects code drift. Use:Commentry debug-storeto confirm the active context id/path. - Agent handoff is unavailable:
confirm Sidekick is installed, run
:Commentry send-to-agentfrom an active review context, and use Sidekick's selector to attach to or start an agent.
