Leave short, project-local comments in Neovim and retrieve them as JSON from a coding agent or shell script.
Comments live in .nvim-agent-comments.json at the Git repository or worktree root. The plugin ignores this file by default and never writes comment text into source buffers.
Place the cursor on a line and run :NvimAgentCommentsAdd. To comment on several lines, select them and run :NvimAgentCommentsAddVisual. Type the instruction, then press <CR> to save it.
The saved comment appears below its line. It does not change the file contents.
The bundled SKILL.md tells coding agents how to find, resolve, and act on comments in .nvim-agent-comments.json.
After handling a comment, the coding agent records a reply beneath the original comment. Long replies wrap and updates appear without reloading the source file.
- Neovim 0.9 or newer. The floating comment editor uses window titles introduced in Neovim 0.9.
- Git repository or worktree
With lazy.nvim:
{
'WorldOccupier/nvim-agent-comments',
config = function()
require('nvim-agent-comments').setup()
end,
}With packer.nvim:
use {
'WorldOccupier/nvim-agent-comments',
config = function()
require('nvim-agent-comments').setup()
end,
}The plugin registers its commands automatically. Call setup() to change options or add mappings.
Copy this block into your Neovim config. It maps every plugin command:
require('nvim-agent-comments').setup({
signs = true,
navigation = true,
store_name = '.nvim-agent-comments.json',
context_lines = 2,
keymaps = {
n = {
['<leader>aca'] = '<cmd>NvimAgentCommentsAdd<cr>',
['<leader>ace'] = '<cmd>NvimAgentCommentsEdit<cr>',
['<leader>acd'] = '<cmd>NvimAgentCommentsDelete<cr>',
['<leader>acj'] = '<cmd>NvimAgentCommentsJump<cr>',
['<leader>acl'] = '<cmd>NvimAgentCommentsList<cr>',
['<leader>acr'] = '<cmd>NvimAgentCommentsReanchor<cr>',
['<leader>acs'] = '<cmd>NvimAgentCommentsSearch<cr>',
['<leader>act'] = '<cmd>NvimAgentCommentsRetrieve<cr>',
},
x = {
['<leader>aca'] = ':NvimAgentCommentsAddVisual<cr>',
['<leader>acr'] = ':NvimAgentCommentsReanchor<cr>',
},
},
})| Shortcut | Mode | Action |
|---|---|---|
<leader>aca |
Normal | Add a comment to the current line |
<leader>aca |
Visual | Add a comment to the selected lines |
<leader>ace |
Normal | Edit the comment at the current line |
<leader>acd |
Normal | Delete the comment at the current line |
<leader>acj |
Normal | Jump to the comment at the current line |
<leader>acl |
Normal | List all project comments and jump to one |
<leader>acr |
Normal | Re-anchor a stale comment to the current line |
<leader>acr |
Visual | Re-anchor a stale comment to the selected lines |
<leader>acs |
Normal | Search project comments by path or body |
<leader>act |
Normal | Retrieve all project comments as JSON |
]q |
Normal | Move to the next comment, wrapping at the end |
[q |
Normal | Move to the previous comment, wrapping at the start |
keymaps defaults to false. During setup, the plugin creates custom mappings only when keymaps is a table like the example above. Comment navigation uses [q and ]q by default; set navigation = false to leave those keys unchanged. context_lines defaults to 2, and signs defaults to true.
| Command | Action |
|---|---|
:NvimAgentCommentsAdd |
Add a comment to the current line |
:NvimAgentCommentsAddVisual |
Add a comment to the selected line range |
:NvimAgentCommentsEdit |
Edit a comment on the current line |
:NvimAgentCommentsDelete |
Delete a comment on the current line |
:NvimAgentCommentsJump |
Jump to a comment anchor |
:NvimAgentCommentsList |
List all project comments and jump to one |
:NvimAgentCommentsSearch |
Search project comments by path or body and jump to one |
:NvimAgentCommentsNext |
Move to the next comment, wrapping at the end |
:NvimAgentCommentsPrev |
Move to the previous comment, wrapping at the start |
:NvimAgentCommentsReanchor |
Attach a stale comment to the current line or range |
:NvimAgentCommentsRetrieve [path] |
Write project comments as JSON, optionally filtered by path |
Adding or editing opens a one-line floating editor. Press Enter (<CR>) to submit or Escape (<Esc>) to cancel. Neovim returns to normal mode when the editor closes. Saved comments render below their resolved ranges with virtual lines, so source text stays unchanged. Coding agents can append replies to a comment's replies array; replies render immediately below the original comment with green vertical-line styling.
Comment search filters as you type. It matches literal text in comment bodies and project-relative paths, without case sensitivity. Use <C-n> and <C-p> to move through matches, <CR> to jump, and <Esc> to close.
Range comments show ┌, │, and └ signs beside every line they cover, and their box title includes the resolved range. Edit, delete, and jump commands work from any line inside that range.
If stored context has no unique match, the plugin marks the comment stale instead of moving it to a guessed location.
The add commands also work in the working-tree pane opened by :DiffviewOpen, including setups that map it to <leader>dv. The plugin does not define or replace that mapping.
Comments created there use the real project-relative file path and render in the Diffview pane. Diffview uses the loaded working-tree buffer for that pane, so the same virtual comment remains visible when the file opens outside Diffview. Unsaved file-buffer content is the source of truth.
Commit, index, deleted-file, and synthetic Diffview panels reject add attempts. If changed buffer content prevents one exact range match, the plugin reports an error instead of attaching the comment to a guessed line.
Retrieve every comment in the current file's project:
:NvimAgentCommentsRetrieveFilter by a project-relative path:
:NvimAgentCommentsRetrieve lua/example.luaThe command writes one JSON object to stdout. Resolved records include resolved_start_line and resolved_end_line. Missing files and missing or ambiguous context produce a stale record.
For headless use, open any file in the project so the plugin can find its root:
nvim --headless -u NONE \
"+set rtp+=/path/to/nvim-comments" \
"+lua require('nvim-agent-comments').setup()" \
/work/project/README.md \
"+NvimAgentCommentsRetrieve" \
"+qa!"Invalid stores, roots, and path filters make Neovim exit with a nonzero status. Retrieval prints no progress messages.
The first saved comment creates .nvim-agent-comments.json in the nearest Git repository or worktree root. The bundled .gitignore rule keeps comments local.
To share comments, remove this line from your project's .gitignore and commit the store:
.nvim-agent-comments.jsonThe file uses a versioned JSON schema. Each comment may contain replies, an array of objects with a required body and an optional created_at field. The bundled agent skill appends a reply after successfully handling a comment without running a command just to obtain the time.
Run :help nvim-agent-comments inside Neovim for the command and configuration reference.
Run the headless test suite with:
make test


