██████╗ ██████╗ ██████╗ ███████╗
██╔════╝██╔═══██╗██╔══██╗██╔════╝
██║ ██║ ██║██║ ██║█████╗
██║ ██║ ██║██║ ██║██╔══╝
╚██████╗╚██████╔╝██████╔╝███████╗
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
██████╗ ███████╗██╗ ██╗██╗███████╗██╗ ██╗
██╔══██╗██╔════╝██║ ██║██║██╔════╝██║ ██║
██████╔╝█████╗ ██║ ██║██║█████╗ ██║ █╗ ██║
██╔══██╗██╔══╝ ╚██╗ ██╔╝██║██╔══╝ ██║███╗██║
██║ ██║███████╗ ╚████╔╝ ██║███████╗╚███╔███╔╝
╚═╝ ╚═╝╚══════╝ ╚═══╝ ╚═╝╚══════╝ ╚══╝╚══╝
Note: This project is in active development. Core features are operational, but some areas are still being refined. Please report issues or unexpected behavior via GitHub Issues.
- GitHub + GitLab — auto-detects provider from git remote
- Dual-pane diff viewer — sidebar file tree + unified diff with inline comments
- Threaded discussions — view, reply, edit, delete, and resolve/unresolve comment threads
- Note selection — cycle through notes in a thread with
<Tab>/<S-Tab>, then edit or delete inline - AI-powered review — multi-provider support (Claude CLI, Anthropic API, OpenAI, Ollama, custom) with accept/dismiss/edit suggestions
- Review sessions — accumulate draft comments, submit in batch
- MR actions — approve, merge, open in browser, create new MR/PR
- Pipeline view — monitor CI/CD status, view job logs, retry failed jobs
- Picker integration — Telescope, FZF, or Snacks
- Fully remappable keybindings — override or disable any binding
---@module "lazy"
---@type LazySpec
{
"afewyards/codereview.nvim",
dependencies = { "nvim-lua/plenary.nvim" },
cmd = {
"CodeReview",
"CodeReviewAI",
"CodeReviewAIFile",
"CodeReviewStart",
"CodeReviewSubmit",
"CodeReviewApprove",
"CodeReviewOpen",
"CodeReviewPipeline",
"CodeReviewComments",
"CodeReviewFiles",
"CodeReviewToggleScroll",
"CodeReviewCommits",
},
---@module "codereview"
---@type codereview.Config
opts = {},
}use {
"afewyards/codereview.nvim",
requires = { "nvim-lua/plenary.nvim" },
config = function()
require("codereview").setup()
end,
}:CodeReviewOpens a picker with open PRs/MRs. Select one to enter the review view with a file sidebar and diff viewer.
Create a .codereview.nvim file in your project root to set per-project defaults:
# codereview.nvim project config
platform = github
project = afewyards/codereview.nvim
base_url = https://api.github.com
token = ghp_xxxxxxxxxxxxLines starting with # are comments. Keys and values are trimmed of whitespace.
| Key | Description |
|---|---|
platform |
github or gitlab (auto-detected from git remote if omitted) |
project |
owner/repo (auto-detected from git remote if omitted) |
base_url |
API URL override (e.g., self-hosted GitLab instance) |
token |
Auth token for this project |
ai_skip_patterns |
Comma-separated glob patterns — files matching any pattern are excluded from AI review |
Security: Add
.codereview.nvimto your.gitignoreif it contains a token.
Token resolution order (first match wins):
- Environment variable —
GITHUB_TOKENorGITLAB_TOKEN - Project config —
tokenkey in.codereview.nvim - Plugin setup —
github_tokenorgitlab_tokeninsetup()
require("codereview").setup({
-- Provider settings (all auto-detected from git remote)
base_url = nil, -- API base URL override (e.g. "https://gitlab.example.com")
project = nil, -- "owner/repo" override
platform = nil, -- "github" | "gitlab" | nil (auto-detect)
github_token = nil, -- GitHub personal access token
gitlab_token = nil, -- GitLab personal access token
-- Picker: "telescope", "fzf", or "snacks" (auto-detected)
picker = nil,
-- Debug logging to .codereview.log
debug = false,
-- Open review in a new tab (set false to use current window)
open_in_tab = true,
-- Diff viewer
diff = {
context = 8, -- lines of context (0-20)
scroll_threshold = 50, -- use scroll mode when file count <= threshold
comment_width = 80, -- comment float width
separator_char = "╳", -- hunk separator character
separator_lines = 3, -- lines in hunk separator
},
-- Pipeline
pipeline = {
poll_interval = 10000, -- status poll interval (ms)
log_max_lines = 5000, -- max lines in job log viewer
},
-- AI review
ai = {
enabled = true,
provider = "claude_cli", -- "claude_cli" | "codex_cli" | "copilot_cli" | "gemini_cli" | "opencode_cli" | "qwen_cli" | "anthropic" | "openai" | "ollama" | "custom_cmd"
review_level = "info", -- "info" | "suggestion" | "warning" | "error"
max_file_size = 500, -- skip files larger than N lines (0 = unlimited)
claude_cli = { cmd = "claude", model = nil, agent = "code-review" },
codex_cli = { cmd = "codex", model = nil },
copilot_cli = { cmd = "copilot", model = nil, agent = nil },
gemini_cli = { cmd = "gemini", model = nil },
opencode_cli = { cmd = "opencode", model = nil, agent = "plan", variant = nil },
qwen_cli = { cmd = "qwen", model = nil },
anthropic = { api_key = nil, model = "claude-sonnet-4-20250514" },
openai = { api_key = nil, model = "gpt-4o", base_url = nil },
ollama = { model = "llama3", base_url = "http://localhost:11434" },
custom_cmd = { cmd = nil, args = {} },
},
-- Override or disable keybindings
keymaps = {
-- quit = "q", -- remap quit to q
-- toggle_resolve = false, -- disable toggle resolve
},
})Set ai.provider to choose a backend. Each provider has its own sub-table:
| Provider | Config key | Requirements |
|---|---|---|
| Claude CLI | claude_cli |
Claude CLI installed |
| Codex CLI | codex_cli |
Codex CLI installed and authenticated |
| Copilot CLI | copilot_cli |
Copilot CLI installed and authenticated |
| Gemini CLI | gemini_cli |
Gemini CLI installed and authenticated |
| OpenCode CLI | opencode_cli |
OpenCode CLI installed and authenticated |
| Qwen CLI | qwen_cli |
Qwen CLI installed and authenticated |
| Anthropic API | anthropic |
api_key set |
| OpenAI | openai |
api_key set |
| Ollama | ollama |
Ollama running locally |
| Custom command | custom_cmd |
cmd set |
Example — Anthropic API:
ai = {
provider = "anthropic",
anthropic = { api_key = vim.env.ANTHROPIC_API_KEY, model = "claude-sonnet-4-20250514" },
},Example — Ollama (local):
ai = {
provider = "ollama",
ollama = { model = "llama3", base_url = "http://localhost:11434" },
},The ai.review_level option controls the verbosity of AI code reviews. Higher levels filter out lower-severity comments:
| Level | Shows |
|---|---|
"info" |
Everything (default) |
"suggestion" |
Suggestions, warnings, and errors |
"warning" |
Warnings and errors only |
"error" |
Errors only |
The AI is instructed to skip items below the configured level, saving tokens and reducing noise. To see lower-severity items again, change the level and re-run the AI review.
Skip specific files from AI review by adding patterns to .codereview.nvim:
ai_skip_patterns=*.test.ts,docs/**,*.snap,fixtures/**
Patterns are comma-separated globs, merged with plugin config ai.skip_patterns and built-in defaults (lockfiles, minified files, generated code, vendor directories).
| Key | Action |
|---|---|
]f / [f |
Next / previous file |
]c / [c |
Next / previous commit |
j / k |
Move down / up (comment-aware) |
<Tab> / <S-Tab> |
Next / previous note in thread |
| Key | Action |
|---|---|
cc |
New comment (normal mode) |
cc |
Range comment (visual mode) |
r |
Reply to thread |
e |
Edit selected note |
x |
Delete selected note |
rr |
React to note |
R |
Toggle resolve / unresolve |
| Key | Action |
|---|---|
A |
Start / cancel AI review |
af |
AI review current file |
a |
Accept suggestion |
x |
Dismiss suggestion |
e |
Edit suggestion |
ds |
Dismiss all suggestions |
| Key | Action |
|---|---|
<C-f> |
Toggle full file view |
| Key | Action |
|---|---|
<C-s> |
Submit draft comments |
<C-a> |
Approve MR/PR |
<C-r> |
Refresh |
<C-q> |
Quit |
M |
Merge |
o |
Open in browser |
p |
Show pipeline status |
| Key | Action |
|---|---|
<leader>fc |
Browse comments / suggestions |
<leader>ff |
Browse changed files |
C |
Browse commits |
Every keybinding can be remapped to a different key or disabled entirely via the keymaps option:
keymaps = {
quit = "q", -- remap quit from <C-q> to q
toggle_resolve = false, -- disable toggle resolve
ai_review = "<leader>ar", -- remap AI review
},Available action names: next_file, prev_file, next_commit, prev_commit, move_down, move_up, select_next_note, select_prev_note, create_comment, create_range_comment, accept_suggestion, dismiss_suggestion, edit_suggestion, reply, edit_note, delete_note, react, toggle_resolve, toggle_full_file, dismiss_all_suggestions, submit, approve, refresh, quit, open_in_browser, merge, show_pipeline, ai_review, ai_review_file, pick_comments, pick_files, pick_commits.
| Command | Description |
|---|---|
:CodeReview |
Open review picker |
:CodeReviewAI |
Run AI review on entire diff |
:CodeReviewAIFile |
Run AI review on current file |
:CodeReviewStart |
Start manual review session (comments become drafts) |
:CodeReviewSubmit |
Submit draft comments |
:CodeReviewApprove |
Approve current MR/PR |
:CodeReviewOpen |
Create new MR/PR |
:CodeReviewPipeline |
Show pipeline status |
:CodeReviewComments |
Browse comments and suggestions |
:CodeReviewFiles |
Browse changed files |
:CodeReviewToggleScroll |
Toggle scroll / per-file mode |
:CodeReviewCommits |
Browse commits |
| Provider | Reviews | Comments | Resolve | AI Review | Create MR/PR |
|---|---|---|---|---|---|
| GitLab | Yes | Yes | Yes | Yes | Yes |
| GitHub | Yes | Yes | Yes | Yes | Yes |
Provider is auto-detected from the git remote URL. Use platform = "github" or platform = "gitlab" to override.
MIT


