A purr-fectly structured way to annotate and review code in Neovim.
meow.review.nvim annotates AI-generated code with structured, typed review comments directly in Neovim and exports them as Markdown so your AI agent knows exactly what to fix and where.
Part of the project meow plugin family.
- Typed annotations — ISSUE, SUGGESTION, NOTE with distinct icons and highlight groups (fully customizable)
- Contextual capture — Treesitter symbol name (function/class) attached to each annotation
- Hunk detection — automatically associates annotations with git hunks (gitsigns) or vimdiff hunks
- JSON persistence —
.meow-review.jsonat the project root; survives Neovim restarts - Pluggable export — register custom exporters; built-in
file,file_prompt, andclipboardtargets included - Navigation — jump forward/backward between annotations across files
- Sign column — per-type signs track position drift as buffers are edited (extmarks)
:checkhealth—meow.reviewhealth check reports dependency status, config, and exporters
| Requirement | Details |
|---|---|
| Neovim | ≥ 0.11.0 |
| Dependencies | nui.nvim |
| Dependency | Details |
|---|---|
| nvim-treesitter | Symbol context in annotations |
| gitsigns.nvim | Git hunk association |
| snacks.nvim | Enhanced picker UI (falls back to nui.menu) |
{
"retran/meow.review.nvim",
dependencies = { "MunifTanjim/nui.nvim" },
event = "VeryLazy",
config = function()
require("meow.review").setup({
context_lines = 3,
})
end,
keys = {
{ "<leader>ra", "<Plug>(MeowReviewAdd)", mode = { "n", "v" }, desc = "Add Review Comment" },
{ "<leader>rd", "<Plug>(MeowReviewDelete)", mode = { "n", "v" }, desc = "Delete Review Comment" },
{ "<leader>re", "<Plug>(MeowReviewEdit)", desc = "Edit Review Comment" },
{ "<leader>rv", "<Plug>(MeowReviewView)", desc = "View Review Comment" },
{ "<leader>rE", "<Plug>(MeowReviewExport)", desc = "Export Review" },
{ "<leader>rc", "<Plug>(MeowReviewClear)", desc = "Clear All Comments" },
{ "<leader>rg", "<Plug>(MeowReviewGoto)", desc = "Go to Review Comment" },
{ "<leader>rr", "<Plug>(MeowReviewReload)", desc = "Reload Review" },
{ "]r", "<Plug>(MeowReviewNext)", desc = "Next Review Comment" },
{ "[r", "<Plug>(MeowReviewPrev)", desc = "Previous Review Comment" },
},
}use {
"retran/meow.review.nvim",
requires = { "MunifTanjim/nui.nvim" },
config = function()
require("meow.review").setup({})
end,
}rocks.nvim (untested)
:Rocks install meow.review.nvimAdd to your Neovim configuration:
require("meow.review").setup({})- Open any file in a git repository.
- Position the cursor on a line to annotate.
- Run
:MeowReview addor press your mapped key. - In the modal, press
<Tab>to cycle the annotation type, type your comment, press<C-s>to save. - The annotation appears in the sign column.
- Run
:MeowReview exportto export all annotations to Markdown.
Pass a configuration table to setup(). All keys are optional.
require("meow.review").setup({
-- Lines of source context captured above and below the annotated range.
-- Set to 0 to disable snippet capture.
context_lines = 3,
-- Built-in exporters to disable. Available: "file", "file_prompt", "clipboard".
disabled_exporters = {},
-- Default exporter used by :MeowReview export (no name given).
default_exporter = "clipboard",
-- Filename written by the `file` and `file_prompt` exporters.
export_filename = ".meow-review.md",
-- Text inserted after the document heading in the exported Markdown.
-- Instructs the AI agent to apply each annotation as a targeted, minimal fix.
-- Set to "" to omit the preamble entirely.
prompt_preamble = "The following annotations were left during a code review. "
.. "For each annotation, read the code snippet and comment carefully, "
.. "then apply the requested fix directly to the file. "
.. "Prefer minimal, targeted edits. Do not refactor unrelated code.",
-- Custom annotation types. Replaces the built-in ISSUE / SUGGESTION / NOTE set.
-- To keep a built-in type, include it explicitly in this table.
-- Keys become the type names used in annotations and exported Markdown headings.
annotation_types = nil, -- default: { ISSUE = …, SUGGESTION = …, NOTE = … }
-- Tab-cycling order for the add-comment modal.
-- Defaults to sorted keys when annotation_types is set, or { "ISSUE", "SUGGESTION", "NOTE" }.
annotation_type_order = nil,
})Set configuration before the plugin loads:
vim.g.meow_review = {
context_lines = 5,
disabled_exporters = { "clipboard" },
default_exporter = "file",
export_filename = ".review.md",
prompt_preamble = "Fix the issues below. Keep changes minimal.",
}Three annotation types are built in. All are customizable via annotation_types and annotation_type_order. Providing annotation_types replaces the entire set — to keep a built-in type, include it explicitly.
require("meow.review").setup({})
-- ISSUE, SUGGESTION, NOTE — built-in icons and highlight groupsrequire("meow.review").setup({
annotation_types = {
ISSUE = { icon = "", hl = "DiagnosticError", label = "ISSUE" },
SUGGESTION = { icon = "", hl = "DiagnosticWarn", label = "SUGGESTION" },
NOTE = { icon = "", hl = "DiagnosticInfo", label = "NOTE" },
QUESTION = { icon = "?", hl = "DiagnosticHint", label = "QUESTION" },
},
annotation_type_order = { "ISSUE", "SUGGESTION", "NOTE", "QUESTION" },
})require("meow.review").setup({
annotation_types = {
BUG = { icon = "", hl = "DiagnosticError", label = "BUG" },
FEEDBACK = { icon = "", hl = "DiagnosticInfo", label = "FEEDBACK" },
},
annotation_type_order = { "BUG", "FEEDBACK" },
})Each annotation type entry accepts:
| Field | Type | Default | Description |
|---|---|---|---|
icon |
string |
built-in icon or "" |
Sign column character |
hl |
string |
built-in hl or "Normal" |
Highlight group for the sign |
label |
string |
key name | Label used in the exported Markdown heading |
sign_name |
string |
"MeowReview" .. key |
Reserved — unused since extmark rewrite (0.11+) |
The plugin ships with <Plug> mappings only — no default keymaps are set.
<Plug> Mapping |
Suggested Key | Mode | Description |
|---|---|---|---|
(MeowReviewAdd) |
<leader>ra |
n, v |
Add annotation at cursor / visual selection |
(MeowReviewDelete) |
<leader>rd |
n, v |
Delete annotation at cursor |
(MeowReviewEdit) |
<leader>re |
n |
Edit annotation at cursor |
(MeowReviewView) |
<leader>rv |
n |
View annotation popup at cursor |
(MeowReviewExport) |
<leader>rE |
n |
Export all annotations to Markdown |
(MeowReviewClear) |
<leader>rc |
n |
Clear all annotations (with confirmation) |
(MeowReviewGoto) |
<leader>rg |
n |
Open picker — jump to any annotation |
(MeowReviewReload) |
<leader>rr |
n |
Reload from .meow-review.json |
(MeowReviewNext) |
]r |
n |
Jump to next annotation |
(MeowReviewPrev) |
[r |
n |
Jump to previous annotation |
| Command | Description |
|---|---|
:MeowReview add |
Add annotation at cursor |
:MeowReview delete |
Delete annotation at cursor |
:MeowReview edit |
Edit annotation at cursor |
:MeowReview view |
View annotation popup |
:MeowReview export |
Run the default exporter (clipboard unless configured) |
:MeowReview export file |
Write to export_filename in the project root |
:MeowReview export file_prompt |
Prompt for filename, then write |
:MeowReview export clipboard |
Copy to system clipboard |
:MeowReview export <name> |
Run a custom exporter by name |
:MeowReview clear |
Clear all annotations |
:MeowReview goto |
Open picker — jump to any annotation |
:MeowReview reload |
Reload from JSON |
:MeowReview next |
Next annotation |
:MeowReview prev |
Previous annotation |
Exporter names are tab-completed.
Press your mapped key or run :MeowReview add. The current annotation type is shown in the bottom border.
| Key | Mode | Action |
|---|---|---|
<Tab> |
insert | Cycle annotation type |
<C-s> |
insert, normal | Confirm and save |
<CR> |
normal | Confirm and save |
<Esc> |
insert | Switch to normal mode |
<Esc> / q |
normal | Cancel |
<C-c> |
insert | Cancel |
Opens pre-filled with the existing comment. Same keys as the add modal.
The export system is pluggable. Three built-in exporters are registered by setup():
| Name | Behaviour |
|---|---|
clipboard |
Copies Markdown to the system clipboard (+ register) — default |
file |
Writes to the configured export_filename in the project root |
file_prompt |
Prompts for a filename (pre-filled with export_filename), then writes |
Run the configured default_exporter:
:MeowReview exportTarget a specific exporter by name:
:MeowReview export file
:MeowReview export file_prompt
:MeowReview export clipboardRegister any function as an exporter after setup():
---@type meow.review.ExporterFn
require("meow.review").register_exporter("my_exporter", function(markdown, root)
-- markdown: full Markdown string
-- root: absolute project root path
end)Trigger it:
:MeowReview export my_exporterUnregister at runtime:
require("meow.review").unregister_exporter("clipboard")require("meow.review").setup({
disabled_exporters = { "clipboard" },
})Sends the review to the active zellij pane so opencode can act on it immediately.
require("meow.review").register_exporter("zellij", function(markdown, _root)
local tmp = os.tmpname() .. ".md"
local f = io.open(tmp, "w")
if not f then
vim.notify("MeowReview: zellij: could not write temp file", vim.log.levels.ERROR)
return
end
f:write(markdown)
f:close()
vim.fn.system({
"zellij", "run", "--",
"sh", "-c",
"cat " .. vim.fn.shellescape(tmp) .. " | opencode --stdin && rm " .. vim.fn.shellescape(tmp),
})
end):MeowReview export zellijThe Markdown is structured for AI agent consumption — each file gets a ## @file section, and each annotation heading is machine-parseable:
# Code Review — 2026-04-12
The following annotations were left during a code review. For each annotation,
read the code snippet and comment carefully, then apply the requested fix
directly to the file. Prefer minimal, targeted edits.
## @path/to/file.lua
### [ISSUE] path/to/file.lua — line 42 — `M.setup`
```lua
39: -- context line
40: -- context line
41: -- context line
42: local broken = thing() -- annotated line
43: -- context line
```
Your comment text here.Open an issue or submit a pull request at github.com/retran/meow.review.nvim.
Code style:
.stylua.toml: 4-space indent, 120-column,AutoPreferDoublequotes- Full MIT license headers in all Lua files
- LuaLS annotations (
---@param,---@return,---@class) @file:and@brief:comment tags
Licensed under the MIT License. See LICENSE for details.
meow.review.nvim builds on:
- Neovim
- nui.nvim — UI components
- nvim-treesitter — symbol context
- gitsigns.nvim — hunk detection
Happy coding with project meow! 🐱
Made with ❤️ by Andrew Vasilyev with help from GitHub Copilot and OpenCode, and feline assistants Sonya Blade, Mila, and Marcus Fenix.