Skip to content

Repository files navigation

commentry.nvim

Neovim plugin for local diff review workflows, draft persistence, and optional agent handoff from inside Neovim.

Preview

Commentry inside Diffview with draft comments, type labels, and review context visible in-place:

Commentry diff review workflow

Install

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.nvim or sindrets/diffview.nvim for the diff UI

Optional integrations:

  • folke/snacks.nvim for :Commentry list-comments
  • a Sidekick runtime for :Commentry send-to-agent

Setup

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,
    },
  },
})

Commands

commentry.nvim provides a :Commentry command with subcommands.

  • :Commentry open opens a diffview for local changes (shortcut).
  • :Commentry add-range-comment creates a range comment from the current visual selection.
  • :Commentry list-comments opens a Snacks picker for active draft comments across the current review, with source preview and in-picker delete (<C-d> current, <M-d> selected). Requires snacks.nvim.
  • :Commentry set-comment-type sets default or per-comment type (note, suggestion, issue, praise).
  • :Commentry toggle-file-reviewed toggles reviewed status for the current file's exact displayed change.
  • :Commentry next-unreviewed jumps to the next unreviewed diff entry in panel order.
  • :Commentry export prints deterministic markdown for active draft comments.
  • :Commentry export register writes markdown to the unnamed register.
  • :Commentry export register:<name> writes markdown to a specific register (for example register:a).
  • :Commentry debug-store prints the active review context and the exact on-disk store path.
  • :Commentry diagnostics opens a scratch buffer with runtime diagnostics (config/log/store/diffview state).
  • :Commentry send-to-agent delegates the current review payload to Sidekick. Requires agent.enabled = true.

Agent Harness Handoff

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,
  },
})

Keymap Configuration

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_reviewed and next_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_comment mapping normally uses its configured/default value from setup normalization. The fallback chain to resolved add_comment (then mc) is a defensive runtime path when Config.keymaps is 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",
  },
})

Development

  • 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/

Behavior Notes

  • 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 :DiffviewOpen range lenses on the same branch until anchors become outdated by code changes.
  • Add/edit/range comment actions open a floating multiline editor (Enter for newline, Ctrl-s to save, q/Esc in normal mode to cancel, Tab to 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 open or 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.

Bug Reports

Use the minimal repro config to isolate issues:

nvim --clean -u repro.lua

This bootstraps a clean Neovim with only commentry + diffview loaded.

Troubleshooting

  • Draft store file does not exist yet: Commentry creates ~/.commentry/repos/<repo>/contexts/<context-id>/commentry.json lazily 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-comments is unavailable: install snacks.nvim, then rerun :checkhealth commentry to confirm picker.select support.
  • Incompatible pre-snapshot store: reviewed-file persistence now uses reviewed_changes snapshots rather than the former file_reviews boolean map. Remove the context's commentry.json if 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-store to confirm the active context id/path.
  • Agent handoff is unavailable: confirm Sidekick is installed, run :Commentry send-to-agent from an active review context, and use Sidekick's selector to attach to or start an agent.

About

Send PR style reviews to coding agents

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages