rag_for_git
Health Pass
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 11 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
AI pull-request reviewer: hybrid RAG + a code graph + Claude Code. Whole-repo context, inline GitHub comments grounded on exact code. MCP server + Claude Code plugin.
rag_for_git
An AI pull-request reviewer that reads your whole repository — hybrid RAG + a code graph + Claude Code.
Plain linters check a diff in isolation; this agent gives the model the same context a human
reviewer has — semantic + lexical retrieval over the entire repo and a structural code graph —
then posts the result back to GitHub as inline comments on the exact diff lines, with applyable fixes.
🇷🇺 Русская версия — глубокий, сверенный с кодом разбор: README.ru.md
Table of contents
- Why it exists
- What a review looks like
- Highlights
- How a review runs
- How it works / Architecture
- One-click install prompt
- Installation
- Configuration reference
- CLI reference
- Skills reference
- MCP tools reference
- Plugin usage
- Per-repo policy & task board
- Observability web admin
- Known limitations & caveats
- Tests
- Project layout
- Contributing
- License
Why it exists
Plain linters catch syntax and style but miss meaning and relationships — the things a human
reviewer actually looks for:
- a changed function contract that silently breaks its callers,
- a guard clause removed three files away from where it mattered,
- a change that contradicts an existing test,
- an edge case that only shows up once you read the helper it calls.
Catching those needs context beyond the diff: who calls this, what it implements, which tests
pin its behaviour. rag_for_git gives the model that context — semantic + lexical retrieval over
the whole repository and a structural code graph — then runs an agentic tool loop per
changed file and posts the result back to GitHub as inline comments on the exact diff lines,
plus a summary and applyable fixes.
It is not a wrapper around "send the diff to an LLM." It is a retrieval + code-graph pipeline with
a deterministic, anti-hallucination publishing tail.
What a review looks like
An illustrative inline comment the agent posts on a changed line — it found the bug by following
the call graph from the edited function to its callers and a contract test:
🟠 correctness — an expired token is no longer rejected
verify_tokenused to raise on an expired signature; the new guard only checkspayload is None, so_decode()returning a payload with a pastexpnow passes as valid. Two call sites
depend on that raise —require_auth(auth/deps.py:48) and the contract testtest_expired_rejected(tests/test_auth.py:71), which this change would break.if payload is None or payload.get("exp", 0) < now: raise InvalidToken("expired or malformed token")
Every finding is grounded on an exact quote from the diff, carries a category / severity /
confidence, and — when it's safe — ships as a one-click GitHub suggestion. A hidden fingerprint
(<!-- ai-review:… -->) makes re-runs idempotent: the same issue is never posted twice.
Highlights
- Whole-repo context, not just the diff. Hybrid retrieval (pgvector ANN + BM25, fused with RRF,
reranked by Voyage) over the entire indexed codebase — for changed files the agent sees the new
version, for everything else a stable base index. - It sees impact. A Neo4j code graph (
CALLS/IMPLEMENTS) expands each changed symbol 1–2
hops to surface callers, callees, implementations, and the tests that pin them. - Anti-hallucination by construction. A finding must quote real code to be placed on a line; a
dedicated verify pass drops invented findings; line grounding is exact-match. - Real GitHub output. Inline comments on diff lines, applyable
suggestionblocks under safe
invariants, a summary for everything off-diff — idempotent across re-runs. - Lives in your editor, not a CI black box. Ships as a Claude Code plugin and as an MCP
server usable from 12+ AI clients (Cursor, VS Code, Gemini CLI, Codex, Windsurf, Claude
Desktop, …). Oneuvxcommand; published on PyPI. - Local-first. Your code stays on your machine — only embedding/query text goes to Voyage; the
stores (Postgres/ParadeDB + Neo4j) run in local Docker. - More than review. The same RAG + graph powers grounded codebase Q&A (
ask), disciplined
task-context gathering (solve-task), PR walkthroughs, and per-subsystem summaries.
How a review runs
A single PR review is three stages:
prepare_review (MCP) → analyze (Claude subagents) → publish_review (MCP)
- prepare —
GitHubProviderpulls the PR (base/head SHA) and changed files; changed.py
files are chunked (tree-sitter) and embedded (Voyage) into an ephemeral overlayref="pr:N";
policy and per-file review units are assembled. - analyze — the Claude Code skill fans out one subagent per file. Each reasons over the diff
in a tool loop, pulling in whatever code it needs:search_code,get_related_symbols,read_file,get_definition,find_callers,get_changed_file_diff. In parallel,
dimension subagents run a performance and maintainability pass, plus a requirements
pass when a task board is wired up, and a final verify pass strips hallucinations. - publish — a deterministic tail: policy gate (category/severity/confidence/paths) → line
grounding by exact code quote (anti-hallucination) → dedup → assemble (inline vs summary,
suggestion invariants, fingerprint idempotency, comment cap) → post to GitHub → history record
→ overlay/session cleanup.
Status: working v1. Target analysis language is Python; VCS is GitHub (behind a
VCSProviderinterface). Proven live: it catches real bugs and sees the impact on calling code
and existing tests.
How it works / Architecture
The core is the reviewer/ library, assembled in reviewer/app.py::build_components(settings)
from Settings (pydantic-settings, .env). Entry points are reviewer/entrypoints/cli.py (Click)
and reviewer/entrypoints/mcp_server.py (FastMCP). Three pieces work together:
- RAG (hybrid retrieval). Postgres/ParadeDB stores code chunks with
pgvector(HNSW ANN) andpg_search(BM25). A query embeds with Voyage, runs both ANN and BM25 search, and the result
lists are merged with Reciprocal Rank Fusion (RRF), then reranked with Voyagererank-2.5. - Code graph (SCIP or tree-sitter, Neo4j). Symbols and their relationships live in Neo4j.
The graph orchestrator (graph/backend.py) picks a backend viaGRAPH_BACKEND
(auto|scip|treesitter): SCIP (@sourcegraph/scip-python) gives a precise, type-aware graph
withCALLS+IMPLEMENTSedges; tree-sitter is a fast fallback withCALLS-by-name only.
Retrieval expands the changed symbols 1–2 hops to surface callers/callees/implementations/tests. - Claude Code plugin via MCP. The
reviewer-mcpserver exposesprepare_review,publish_review, and the agent tools. The Claude Code plugin (plugin/) drives the review: it
callsprepare_review, runs analysis subagents against those MCP tools, then callspublish_review.
The single key linking RAG and the graph is node_id = "path#fqn" (e.g.rag/embedder.py#VoyageEmbedder.embed_query). Both the chunk in Postgres and the node in Neo4j use
it, so graph expansion and chunk retrieval are stitched together without any mapping table.
Index freshness: a stable base + a PR overlay. A full reindex of a large repo is expensive, so
the index keeps a persistent base and layers PR changes on top:
ref="base:<branch>"— the persistent index of a tracked branch (e.g."base:main","base:master"). Each tracked branch inREVIEW_BRANCHEShas its own isolated index. Updated
incrementally byreviewer index --ref <branch>(only changed files are chunked; only chunks
with a newcontent_hashare re-embedded — embeddings are reused across branches by hash,
saving Voyage quota).ref="pr:N"— an ephemeral overlay of just the PR's changed files at its HEAD.- On a query:
retrieval = (base:<branch> where path ∉ changed) ∪ overlay. For changed files
the agent sees the new version; for everything else, the stable base. - Multi-branch. A PR is reviewed against the index of its target branch (
base_reffrom the
PR). A PR targeting an untracked branch is skipped (prepare_reviewreturns{"status":"skipped",...}). The code graph (Neo4j:Symbol) is also branch-scoped via abranchproperty, with unique constraint(repo, branch, id).
┌─────────────────────────── reviewer (core library) ───────────────────────────┐
│ │
GitHub PR ───▶│ VCSProvider (github.py) ──diff/files/patches──▶ MCPReviewService │
(owner/repo#N)│ ▲ publish inline + summary │ prepare_review │
│ │ ▼ │
│ │ ┌──────────── retrieval/Retriever ──────────┐ │
│ │ │ hybrid search graph expansion │ │
│ │ │ ┌──────────────┐ ┌───────────────────┐ │ │
│ │ │ │ Postgres │ │ Neo4j │ │ │
│ │ │ │ (ParadeDB) │ │ Symbol(path#fqn) │ │ │
│ │ │ │ pgvector(HNSW)│ │ -[:CALLS]-> │ │ │
│ │ │ │ + pg_search │ │ (IMPLEMENTS: SCIP) │ │ │
│ │ │ │ (BM25, RRF) │ │ expand 1–2 hops │ │ │
│ │ │ └──────┬───────┘ └─────────┬─────────┘ │ │
│ │ │ Voyage embed/rerank tree-sitter graph │ │
│ │ └─────────────────┬─────────────────────────┘ │
│ │ ▼ ContextPack │
│ │ Claude Code subagents (skill /rag-reviewer:reviewer_review-pr)
│ │ tools: search_code, get_related_symbols, │
│ │ read_file, get_definition, find_callers, … │
│ └─────────────────── publish_review (gate/grounding/dedup/assemble) ◀─────┘
└─────────────────────────────────────────────────────────────────────────────────┘
Stores (Docker): Postgres/ParadeDB (:5433) · Neo4j (:7687)
External API: Voyage (embeddings voyage-code-3 + reranker rerank-2.5)
For a deeper, code-verified walkthrough of every module and the data flow, see
README.ru.md (Russian).
One-click install prompt
Copy and paste into any AI coding assistant (Claude Code, Cursor, Gemini CLI, Mimo Code, OpenCode, Kimi Code, Codex, Copilot…):
Set up the rag-reviewer MCP server in this AI tool.
Rules:
- Use `uvx --from rag-reviewer@latest reviewer-mcp` to run the server — do NOT pip install, do NOT clone the repo.
- The `bash -lc` wrapper is required on macOS/Linux so uvx is found by GUI tools: command="/bin/bash", args=["-lc", "uvx --from rag-reviewer@latest reviewer-mcp"]. On Windows use command="uvx", args=["--from","rag-reviewer@latest","reviewer-mcp"].
- Detect which AI tool you are running in, then write the MCP entry to the correct config file:
- Claude Code / generic: .mcp.json in project root ({"mcpServers":{"reviewer":{"command":"/bin/bash","args":["-lc","uvx --from rag-reviewer@latest reviewer-mcp"]}}})
- Cursor: ~/.cursor/mcp.json (same format)
- Gemini CLI: ~/.gemini/settings.json ({"mcpServers":{"reviewer":{"command":"/bin/bash","args":["-lc","uvx --from rag-reviewer@latest reviewer-mcp"]}}})
- Antigravity: ~/.gemini/antigravity/mcp_config.json (same mcpServers format)
- Windsurf: ~/.codeium/windsurf/mcp_config.json (same mcpServers format)
- Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows (same mcpServers format)
- Mimo Code: ~/.config/mimocode/mimocode.json ({"mcp":{"reviewer":{"type":"local","command":["/bin/bash","-lc","uvx --from rag-reviewer@latest reviewer-mcp"],"enabled":true}}})
- OpenCode: ~/.config/opencode/opencode.json ({"mcp":{"reviewer":{"type":"local","command":["/bin/bash","-lc","uvx --from rag-reviewer@latest reviewer-mcp"]}}})
- Kimi Code: ~/.kimi-code/mcp.json ({"mcpServers":{"reviewer":{"command":"/bin/bash","args":["-lc","uvx --from rag-reviewer@latest reviewer-mcp"]}}})
- Codex CLI: ~/.codex/config.toml ([mcp_servers.reviewer] command="/bin/bash" args=["-lc","uvx --from rag-reviewer@latest reviewer-mcp"])
- VS Code: ~/Library/Application Support/Code/User/mcp.json (key is "servers" not "mcpServers": {"servers":{"reviewer":{"command":"/bin/bash","args":["-lc","uvx --from rag-reviewer@latest reviewer-mcp"]}}})
- After writing the config, run: uvx --from rag-reviewer reviewer check
- Report what config file was written and whether the check passed.
Installation
The MCP server is published on PyPI as rag-reviewer
and runs via uvx — no clone of this repo required.
Requirements: Docker, uv (includes uvx),
a Voyage API key, a GitHub token. Python 3.11–3.13 (only needed for a pip/editable install; uvx
manages its own).
Quick setup (recommended, all platforms)
# 0) Install the reviewer CLI — once, globally
uv tool install rag-reviewer
# uv and uvx are the same binary; installing uv gives you both.
# The MCP server launched by your editor uses uvx @latest and self-updates automatically.
# 1) Infrastructure
curl -O https://raw.githubusercontent.com/mimfort/rag_for_git/main/docker-compose.yml
docker compose up -d # Postgres/ParadeDB (:5433) + Neo4j (:7687)
# 2) Configure keys and settings interactively
reviewer init
# Interactive wizard: fills VOYAGE_API_KEY, GITHUB_TOKEN, and optional groups
# (stores, multi-repo, task board). Re-run any time to update settings.
# CI / non-interactive: reviewer init --yes (accepts all defaults silently)
# 3) Register the MCP server (and skills) in your editor/CLI
reviewer install --all # auto-detect installed clients + install skills
# or a specific one: reviewer install cursor|vscode|claude-code|claude-desktop|windsurf|gemini|antigravity|mimo|opencode|kimi|trae|codex
# skills go to clients that support them (Gemini/Mimo/Kimi); add --no-skills to skip
# 4) Verify
reviewer check
# Update CLI later:
uv tool upgrade rag-reviewer
reviewer installis cross-platform (Windows / macOS / Linux). It injects the
absolute path touvxautomatically — nobash -lcwrapper needed. The manual
JSON configs below usebash -lcfor macOS/Linux only; on Windows usereviewer installor set"command": "uvx"with"args": ["--from", "rag-reviewer@latest", "reviewer-mcp"]directly.
Claude Code: tools work out of the box.
reviewer install claude-codealso
writes an allowlist rulemcp__reviewer__*into your global~/.claude/settings.json(permissions.allow), so the reviewer MCP tools run in
every project without hitting theauto-mode safety classifier — no manual
settings edits. Being global, it also covers the plugin (marketplace) install,
where the server is available everywhere but ships no permission grants.
Where keys are read from. The reviewer resolves its
.envfrom a fixed
location, not the current working directory — MCP clients launch the server
with an arbitrary CWD, so a project-local.envis unreliable. Lookup order:$REVIEWER_ENV_FILE→$XDG_CONFIG_HOME/rag-reviewer/.env(default~/.config/rag-reviewer/.env) →./.env(handy when running from a repo clone).
Real environment variables always win over the file, so you can instead pass keys
via an"env": { "VOYAGE_API_KEY": "…", "GITHUB_TOKEN": "…" }block in your MCP
client config — works in every client.
- Voyage (
VOYAGE_API_KEY): https://dashboard.voyageai.com/ — free token pool; attach a card
to lift the 3 RPM / 10K TPM limit (charged only beyond the free pool). - GitHub (
GITHUB_TOKEN): a PAT with Pull requests: Read and write + Contents: Read
(fine-grained) or thereposcope (classic). Quick option:gh auth token.
All other settings have defaults (documented in .env.example and in
Configuration reference below).
Manual setup (alternative)
If you prefer to configure your client config by hand rather than using reviewer install:
Each AI coding tool has its own config file. Pick yours:
| Tool | Global config file | Project config | Install guide |
|---|---|---|---|
| Claude Code | /plugin marketplace add (see below) |
.claude-plugin/ ✓ |
— |
| Cursor | ~/.cursor/mcp.json |
.cursor/mcp.json ✓ |
— |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
— | — |
| Claude Desktop | macOS: ~/Library/Application Support/Claude/claude_desktop_config.json; Windows: %APPDATA%\Claude\claude_desktop_config.json |
— | — |
| Antigravity | ~/.gemini/antigravity/mcp_config.json |
— | — |
| Mimo Code | ~/.config/mimocode/mimocode.json |
.mimocode/mimocode.json ✓ |
INSTALL.md |
| OpenCode | ~/.config/opencode/opencode.json |
.opencode/opencode.json ✓ |
INSTALL.md |
| Kimi Code | ~/.kimi-code/mcp.json |
.kimi-code/mcp.json ✓ |
INSTALL.md |
| Gemini CLI | ~/.gemini/settings.json |
.gemini/settings.json ✓ |
GEMINI.md |
| Codex CLI | ~/.codex/config.toml |
.codex-plugin/plugin.json ✓ |
AGENTS.md |
| Copilot CLI | — | .github-copilot/plugin.json ✓ |
— |
| Trae IDE | ~/Library/Application Support/Trae/User/mcp.json |
— | — |
| VS Code | ~/Library/Application Support/Code/User/mcp.json (key: servers, not mcpServers) |
— | — |
Files marked ✓ are already present in this repo — if you open rag_for_git as a project in
that tool, the MCP server auto-connects. For a global install (works from any project),
add the entry to the corresponding global config file.
The MCP entry format by tool (macOS/Linux — use reviewer install on Windows):
Mimo Code (mimocode.json):
{
"$schema": "https://mimo.xiaomi.com//config.json",
"mcp": {
"reviewer": {
"type": "local",
"command": ["/bin/bash", "-lc", "uvx --from rag-reviewer@latest reviewer-mcp"],
"enabled": true
}
}
}
OpenCode (opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"reviewer": {
"type": "local",
"command": ["/bin/bash", "-lc", "uvx --from rag-reviewer@latest reviewer-mcp"]
}
}
}
Kimi Code / Cursor / Gemini CLI / Codex CLI / Trae / Claude Desktop / Windsurf / Antigravity (standard mcpServers JSON):
{
"mcpServers": {
"reviewer": {
"command": "/bin/bash",
"args": ["-lc", "uvx --from rag-reviewer@latest reviewer-mcp"]
}
}
}
VS Code (mcp.json — note: key is servers, not mcpServers):
{
"servers": {
"reviewer": {
"command": "/bin/bash",
"args": ["-lc", "uvx --from rag-reviewer@latest reviewer-mcp"]
}
}
}
Codex CLI (~/.codex/config.toml):
[mcp_servers.reviewer]
command = "/bin/bash"
args = ["-lc", "uvx --from rag-reviewer@latest reviewer-mcp"]
After adding, restart the tool — reviewer will appear alongside other MCP servers.
Claude Code (plugin marketplace)
Two commands, from any project:
/plugin marketplace add mimfort/rag_for_git
/plugin install rag-reviewer@rag-reviewer-marketplace
You get:
- Skills:
/rag-reviewer:reviewer_review-pr,/rag-reviewer:reviewer_solve-task,/rag-reviewer:reviewer_sync-codebase,/rag-reviewer:reviewer_sync-tasks,/rag-reviewer:reviewer_performance-review,/rag-reviewer:reviewer_maintainability-review,/rag-reviewer:reviewer_ask(see Skills reference). - MCP server
reviewerexposing the 20 tools in MCP tools reference.
Run
/pluginto confirmrag-revieweris installed and enabled.
Install skills globally (optional)
The 7 skills wrap the MCP tools into guided flows. Without them you can still call MCP tools
directly, but the skills are the intended entry point.
reviewer install already installs them for clients that support file-based skills (Gemini,
Mimo, Kimi). To (re)install just the skills — or pick a specific client — use:
uvx --from rag-reviewer reviewer install-skills --all # all detected skills-capable clients
uvx --from rag-reviewer reviewer install-skills gemini # a specific one
uvx --from rag-reviewer reviewer install-skills --list # show targets + directories
It downloads the skills from GitHub (no repo clone) and unpacks them into each client's global
skills directory, with a path-traversal guard. Manual fallback (equivalent):
curl -sL https://github.com/mimfort/rag_for_git/archive/refs/heads/main.tar.gz -o /tmp/rag-reviewer.tgz
mkdir -p ~/.gemini/skills
tar xz -C ~/.gemini/skills --strip-components=3 -f /tmp/rag-reviewer.tgz 'rag_for_git-main/plugin/skills'
rm /tmp/rag-reviewer.tgz
| Tool | Global skills directory |
|---|---|
| Gemini CLI | ~/.gemini/skills/ |
| Mimo Code | ~/.config/mimocode/skills/ |
| Kimi Code | ~/.kimi-code/skills/ + extra_skill_dirs in ~/.kimi-code/config.toml |
| OpenCode | ~/.config/opencode/skills/ |
| Claude Code | bundled in the plugin (step above) |
| Cursor | project-level via .cursor-plugin/plugin.json |
That's it. Build the base index (recommended — see CLI reference) and review a PR
(see Plugin usage).
Configuration reference
Everything is configured through environment variables (.env, see .env.example with comments).
The only required external key is VOYAGE_API_KEY; GITHUB_TOKEN is required for PR review.
All other settings have working defaults that match the bundled docker-compose.yml. The .env
is resolved from $REVIEWER_ENV_FILE → ~/.config/rag-reviewer/.env → ./.env (real env vars
always win).
Voyage — embeddings + reranker (required)
| Variable | Default | Purpose |
|---|---|---|
VOYAGE_API_KEY |
"" |
Required. Voyage key for embeddings + reranking. |
EMBEDDING_MODEL |
voyage-code-3 |
Embedding model. |
EMBEDDING_DIM |
1024 |
Embedding dimension; must match the vector(N) column in Postgres — changing it requires a reindex. |
EMBEDDING_BATCH_SIZE |
256 |
Texts per embedding request (≤1000 and ≤120K tokens). |
RERANK_MODEL |
rerank-2.5 |
Voyage reranker model. |
GitHub (required for PR review)
| Variable | Default | Purpose |
|---|---|---|
GITHUB_TOKEN |
"" |
PAT — Pull requests: Read and write + Contents: Read. |
GITHUB_RETRY_ATTEMPTS |
3 |
Retries on GitHub API network errors. |
GITHUB_RETRY_BACKOFF_BASE |
1.0 |
Exponential backoff base (seconds). |
Stores (Postgres/ParadeDB + Neo4j)
| Variable | Default | Purpose |
|---|---|---|
PG_DSN |
postgresql://reviewer:reviewer@localhost:5433/reviewer |
ParadeDB (pgvector + pg_search) on host port 5433. |
PG_POOL_MIN_SIZE |
1 |
Min Postgres pool connections. |
PG_POOL_MAX_SIZE |
4 |
Max Postgres pool connections. |
NEO4J_URI |
neo4j://localhost:7687 |
Neo4j bolt URI. |
NEO4J_USER |
neo4j |
Neo4j user. |
NEO4J_PASSWORD |
reviewerpass |
Neo4j password (one-off dev default). |
GRAPH_BACKEND |
auto |
Code-graph engine: auto (SCIP if scip-python in PATH, else tree-sitter), scip, treesitter. |
Multi-repo / multi-branch (optional)
| Variable | Default | Purpose |
|---|---|---|
DEFAULT_REPO |
"" |
Default owner/name for session-less tools and reviewer index without --repo; empty = multi-repo (repo must be passed explicitly). |
REVIEW_BRANCHES |
main |
CSV of tracked branches; the first is primary (default for reviewer index --ref and CLI search). PRs targeting a branch outside the list are skipped. |
Review policy (env defaults; per-repo .review.yml overrides)
| Variable | Default | Purpose |
|---|---|---|
REVIEW_SEVERITY_THRESHOLD |
medium |
Minimum severity to keep: low/medium/high/critical. |
REVIEW_MIN_CONFIDENCE |
0.5 |
Drop findings with confidence below this (0..1). |
REVIEW_MAX_COMMENTS |
25 |
Cap on inline comments per review. |
REVIEW_MAX_FILES |
50 |
Cap on .py files reviewed; the rest go to the summary as skipped. |
REVIEW_CATEGORIES |
"" |
CSV whitelist of categories (correctness, security, performance, style, requirements); empty = all. |
REVIEW_SUGGESTIONS |
apply |
apply = applyable GitHub suggestion blocks; text = text-only advice. |
REVIEW_OUTPUT_LANGUAGE |
ru |
Language of the published findings' text. |
REVIEW_SKIP_DRAFTS |
true |
Don't review draft PRs. |
MAX_TOOL_RESULT_CHARS |
8000 |
Max length of a tool result fed into the prompt. |
Observability & sessions (optional)
| Variable | Default | Purpose |
|---|---|---|
REVIEW_HISTORY |
true |
Record run history in Postgres (review_runs/review_findings), fail-soft. |
REVIEW_SESSION_PERSIST |
true |
Persist the PR session in Postgres for crash recovery. |
REVIEW_SESSION_TTL_HOURS |
24 |
TTL (hours) of a persisted session. |
WEB_ADMIN_USER |
"" |
Basic-auth user for reviewer serve; empty = no auth. |
WEB_ADMIN_PASSWORD |
"" |
Basic-auth password; empty = no auth. |
Task board (optional) — deploy-wide default
A board connection is the same for every repo of one team, so it is configured once in the
reviewer-mcp env rather than duplicated in each repo's .review.yml. See
Per-repo policy & task board.
| Variable | Default | Purpose |
|---|---|---|
TASK_BOARD_TYPE |
"" |
Board type: yougile, jira, … (selects the skill playbook). |
TASK_BOARD_MCP |
"" |
Name of the connected board MCP server (LLM-side tools mcp__<mcp>__*). |
TASK_BOARD_KEY_PATTERN |
"" |
Task-key regex, e.g. [A-Z]+-\d+. |
TASK_BOARD_URL_TEMPLATE |
"" |
Task-link template, e.g. https://ru.yougile.com/team/<id>/#{code}. |
TASK_BOARD_API_KEY |
"" |
REST API key for server-side bulk sync (sync_board). Server-internal — never returned to clients. |
TASK_BOARD_API_BASE |
"" |
REST API base URL; empty → default per type (yougile: https://yougile.com/api-v2). |
Getting
TASK_BOARD_API_KEY(Yougile). UI: pressCtrl + ~(or ⚙ next to the company name →
"Настроить") → API → create/copy the key. REST: getcompanyId(Ctrl + Alt + Q, orPOST /api-v2/auth/companies {login,password}), thenPOST /api-v2/auth/keys {login,password,companyId}.
The key belongs only in the reviewer-mcp env (~/.config/rag-reviewer/.env), not in a chat or a client config.
CLI reference
All commands run via uvx --from rag-reviewer <command>, or after uv tool install rag-reviewer /pip install -e ".[dev]" simply as reviewer. Two entry points are installed:reviewer (the CLI below) and reviewer-mcp (the MCP server, started by your editor/plugin).
| Command | Arguments | Options | What it does |
|---|---|---|---|
check |
— | — | Verify environment readiness (keys, Postgres, Neo4j, GitHub). Prints ✓/✗ per item; exits 1 on any problem. Spends no Voyage quota. |
init |
— | --path FILE (default ~/.config/rag-reviewer/.env), --yes (accept defaults, CI mode) |
Interactive wizard that writes the .env (Voyage/GitHub + optional groups). |
install |
[client] |
--all, --list, --path FILE, --pin VERSION, --no-latest, --no-skills, --dry-run |
Register the MCP server (and skills) in AI clients (cross-platform). |
install-skills |
[client] |
--all, --list, --path FILE |
Install only the skills into a client's global skills directory. |
update |
— | — | Check PyPI for a newer rag-reviewer and report how to upgrade. |
index |
<repo> (path to local clone) |
--ref BRANCH (git ref to read; default = primary branch), --branch NAME (storage key; default = --ref), --repo OWNER/NAME (default from git origin) |
Build/update the base index of a branch (vectors + graph). Done once, then incremental. |
search |
<query> |
--repo OWNER/NAME (default DEFAULT_REPO), --branch NAME (default primary) |
Diagnostic hybrid search over a branch's base index. |
status |
[path] (default .) |
--repo OWNER/NAME (default from git origin), --branch NAME (default: all REVIEW_BRANCHES) |
Index health / freshness vs the clone's HEAD. Spends no Voyage quota. |
migrate-branches |
— | — | One-time: rename legacy ref="base" → base:<primary> after upgrading to multi-branch. |
serve |
— | --host HOST (default 127.0.0.1), --port PORT (default 8000) |
Run the observability web admin on the host. |
reviewer-mcp |
— | — | MCP server (stdio transport). Started automatically by the plugin / editor. |
Examples:
# First-time setup
uvx --from rag-reviewer reviewer init
uvx --from rag-reviewer reviewer install --all
uvx --from rag-reviewer reviewer check
# Build the base index (whole-repo context for RAG + graph)
uvx --from rag-reviewer reviewer index /path/to/repo --ref main --repo owner/name
uvx --from rag-reviewer reviewer index /path/to/repo --ref master --repo owner/name # second tracked branch
# Diagnostics (no Voyage spend except `search`)
uvx --from rag-reviewer reviewer search "token verification" --branch master
uvx --from rag-reviewer reviewer status /path/to/repo --branch dev
# Web admin
uvx --from rag-reviewer reviewer serve --host 127.0.0.1 --port 8000
Reviewing works even without a prior index — context is then limited to the diff and the overlay
(RAG/graph are "thin"). For full whole-repo impact analysis, run index against the target branch.
Skills reference
Skills are the guided entry points for the workflow. With the plugin installed they are invoked as/rag-reviewer:<name> in Claude Code (the leading /rag-reviewer: is the plugin namespace; on
other clients the skill name is the same). Arguments are passed as free text after the skill name
($ARGUMENTS).
reviewer_review-pr — full PR review
Orchestrates the three-stage pipeline (prepare_review → subagents → publish_review).
- Arguments: the PR as
owner/repo#N,owner/repo N, or a GitHub PR URL. Add--dry-runto
assemble and return the full report without posting to GitHub. - MCP tools used:
prepare_review,search_code,get_related_symbols,read_file,get_definition,find_callers,get_changed_file_diff,publish_review; plusindex_task/get_task_context/search_taskswhen a task board is wired up. - Flow: prepare (PR + policy + units + board config) → fan out one analysis subagent per file →
parallel performance / maintainability dimensions (+ requirements if aTaskBrief
exists) → verify pass (dropsis_real=falsefindings) → publish (gate/grounding/dedup/assemble).
Ifprepare_reviewreturnsstatus:"skipped"(target branch not tracked) it stops; draft PRs are
skipped unlessREVIEW_SKIP_DRAFTS=false.
reviewer_solve-task — gather context for a task, then hand off to dev
Reads a task (if a key + board), pulls related/similar tasks and relevant code, distills a brief,
and enters brainstorming. It disciplines context-gathering — it does not write the code.
- Arguments: a task key (e.g.
PRI-4, must matchkey_pattern) or a free-text description
(e.g. "add a logout endpoint"). Board-less mode falls back to description + code search. - MCP tools used:
get_board_config,index_task,get_task_context,search_tasks,search_codebase,related_symbols,callers,definition,get_pr_diff; plus the connected
board MCP (mcp__<board>__*) to read the task. - Flow: resolve board config → identify task (key vs free text) → best-effort, fail-open context
gathering (task graph, similar tasks, relevant code, lazy PR diffs of similar tasks) → distill a
structured brief (Task / Related work / Relevant code / Constraints) → hand off tosuperpowers:brainstormingwith the brief as seed.
reviewer_sync-codebase — build/update the base index
Thin wrapper over reviewer index (vector store + code graph) from a local clone.
- Arguments (all optional):
--path <path>(default: CWD),--ref <branch>(default:main),--repo <owner/name>(default: derived fromgit remote get-url origin),--backend <auto|scip|treesitter>(default:auto, setsGRAPH_BACKEND). - MCP tools used: none directly — it shells out to
uvx --from rag-reviewer reviewer index. - Flow: resolve inputs → check prerequisites (
uvx, git repo,reviewer check, Docker up) →
run indexing → optionalreviewer searchto verify → report chunks/nodes/edges and which graph
backend was used.
reviewer_sync-tasks — warm the task graph & vector store
A thin trigger over the server-side ETL tool sync_board — the reviewer enumerates the board over
REST itself, so the LLM passes no task text (O(1) tokens regardless of board size).
- Arguments (all optional):
--board <name>(limit to one board/project),--limit <N>(smoke
run; disables purge and watermark advance),--purge-orphaned(remove tasks no longer on the
board; off by default),--no-keep-with-prs(with purge, also remove tasks that have PR history —
protected by default). - MCP tools used:
sync_board(single call). - Flow: map args → one
sync_board(...)call → print a counts summary (enumerated/changed/
embedded/unchanged/failed, purge, warnings). On{"status":"error",...}the board is not
configured server-side — setTASK_BOARD_*in~/.config/rag-reviewer/.envand reconnect.
reviewer_performance-review — performance-only review
Reviews a diff only for performance/efficiency risks (N+1 queries, repeated work, bad asymptotics,
missing batching/caching, blocking I/O, memory growth).
- Arguments (standalone): scope —
staged,unstaged, uncommitted, branch-vs-base, a commit,
a branch comparison, a file list, or a PR-like scope. If unclear, it asks. Insidereviewer_review-prit runs as a dimension over the provided unit diffs. - MCP tools used (when run in the PR pipeline):
search_code,read_file,find_callers,get_related_symbols,get_definition,get_changed_file_diff. - Output: JSON
{"findings":[{category:"performance", severity, file, line, side, code_quote, message, suggestion, fix, confidence}]}.
reviewer_maintainability-review — maintainability-only review
Reviews a diff only for maintainability risks (unnecessary complexity, poor readability,
duplication, weak separation of concerns, convention drift).
- Arguments (standalone): same scope options as the performance review. Inside
reviewer_review-prit runs as a dimension over the provided unit diffs. - MCP tools used (when run in the PR pipeline):
search_code,get_related_symbols,read_file,get_definition,find_callers,get_changed_file_diff. - Output: JSON
{"findings":[{category:"maintainability", severity, file, line, side, code_quote, message, suggestion, fix, confidence}]}.
reviewer_ask — grounded codebase Q&A
Answers a free-text question about the codebase with citations (path:line), using RAG + the code
graph. For onboarding / explaining a subsystem — not for reviewing PRs. Requires a built base
index.
- Arguments: a free-text question (e.g. "where is authentication", "how does index freshness
work", "explain the retrieval pipeline", "как устроено…"). - MCP tools used:
search_codebase,related_symbols,callers,definition; plus harnessRead/Grep/Glob. - Flow: resolve repo/branch →
search_codebase→ optionally expand via the graph → answer with
an Evidence list ofpath:linecitations.
MCP tools reference
The reviewer-mcp server exposes 20 tools. PR-session tools require an active prepare_review for
that (repo, pr) in the same running server; the rest are session-less.
Review lifecycle
| Tool | Signature | Returns / does |
|---|---|---|
prepare_review |
(repo: str, pr: int) |
Open a PR session: sync base index, build the PR overlay, load policy, assemble per-file units. Returns PR meta + policy + units (or {"status":"skipped"} for an untracked target branch). |
publish_review |
(repo, pr, summary, findings: list[dict], dry_run=False, task_key=None) |
Deterministic tail: gate → grounding → dedup → inline/summary split → post to GitHub → history → overlay cleanup. dry_run=true returns the report without posting; task_key links the PR to a task on real publish. |
Each finding: {category, severity(low|medium|high|critical), file, line, side(RIGHT|LEFT), code_quote, message, suggestion, fix:{start_line,end_line,replacement}|null, confidence:0..1}.
PR-session analysis tools (require prepare_review)
| Tool | Signature | Returns / does |
|---|---|---|
search_code |
(repo, pr, query: str) |
Hybrid semantic+lexical search over base ∪ overlay. |
get_related_symbols |
(repo, pr, node_id: str) |
Graph neighbors (calls/implementations) of node_id = path#fqn. |
read_file |
(repo, pr, path, start=1, end=400) |
Source of a file at the PR HEAD (1-based, inclusive). |
get_definition |
(repo, pr, symbol: str) |
Definition of a symbol (graph → index → semantic fallback). |
find_callers |
(repo, pr, node_id: str) |
Direct callers of node_id path#fqn (impact analysis). |
get_changed_file_diff |
(repo, pr, path: str) |
Unified diff of another changed file in the same PR. |
Session-less tools (Q&A, solve-task)
| Tool | Signature | Returns / does |
|---|---|---|
search_codebase |
(repo, query, top_k=10, branch=None, include_tests=False) |
Hybrid search over a repo's base index; line-numbered, deduped, tests excluded by default. |
related_symbols |
(repo, node_id, branch=None) |
Graph neighbors (calls/implements/tests) of a symbol. |
callers |
(repo, node_id, branch=None) |
Incoming CALLS of node_id path#fqn. |
definition |
(repo, symbol, branch=None) |
Symbol definition (graph → index → semantic fallback). |
get_pr_diff |
(repo, number: int) |
Unified diff of any (historical) PR; capped, fail-soft. |
Tasks / boards
| Tool | Signature | Returns / does |
|---|---|---|
sync_board |
(board=None, limit=None, purge_orphaned=False, keep_with_prs=True) |
Server-side ETL: enumerate the board over REST, normalize to TaskBrief, index. Incremental via a per-board watermark; O(1) tokens. |
index_task |
(task: dict) |
Index one normalized TaskBrief into the task graph + vector store (idempotent). |
index_tasks_batch |
(tasks: list[dict]) |
Same for a list, in one Voyage call. |
search_tasks |
(query, top_k=5) |
Semantically similar tasks from the indexed corpus. |
get_task_context |
(key: str) |
Graph context: the task, its PRs, linked tasks and their PRs, and the touched code. |
purge_orphaned_tasks |
(active_keys: list[str], keep_with_prs=True) |
Remove tasks no longer on the board (PR-linked tasks protected by default). |
get_board_config |
() |
Deploy-wide board config (TASK_BOARD_*); fallback for sync-tasks/solve-task. Credentials are not returned. |
Plugin usage
With the plugin installed and Claude Code open at the repo root, call a skill:
/rag-reviewer:reviewer_review-pr owner/repo#42 # review a PR (prepare → subagents → publish)
/rag-reviewer:reviewer_review-pr owner/repo#42 --dry-run # assemble the report without posting
/rag-reviewer:reviewer_sync-codebase --ref main # build/update vector store + code graph
/rag-reviewer:reviewer_sync-tasks # warm the task graph (server-side ETL)
/rag-reviewer:reviewer_solve-task PRI-4 # gather task context, then hand off to dev
/rag-reviewer:reviewer_ask how does index freshness work # grounded codebase Q&A
A typical end-to-end run:
git clone https://github.com/ORG/REPO /tmp/REPO
reviewer index /tmp/REPO --ref main # build base index + graph for main
reviewer index /tmp/REPO --ref master # optionally index a second branch (REVIEW_BRANCHES=main,master)
# in Claude Code (from the repo root): /rag-reviewer:reviewer_review-pr ORG/REPO#42
Per-repo policy & task board
A .review.yml file in the target (base) branch overrides the env defaults (a PR cannot weaken
its own review — see Caveats):
categories: { correctness: true, security: true, performance: true, style: false, requirements: true }
severity_threshold: medium
min_confidence: 0.5
paths: { ignore: ["**/migrations/**", "vendor/**"] }
max_comments: 25
# Optional task context: read the task from a board and check requirement compliance.
# The board (MCP) is connected by the user on the Claude Code side; the plugin does not bundle it.
task_board:
type: yougile # yougile | jira — selects the skill playbook
mcp: yougile # name of the connected board MCP server (tools are mcp__<mcp>__*)
key_pattern: "[A-Z]+-\\d+" # optional; matches Yougile PRI-34/ID-34 and Jira PROJ-123
The task_board block is a deploy-wide default, not a per-repo requirement. A board connection
is the same for every repo of one team, so configure it once in the reviewer .env
(TASK_BOARD_TYPE / TASK_BOARD_MCP / TASK_BOARD_KEY_PATTERN / TASK_BOARD_URL_TEMPLATE) and
every repo inherits it — no .review.yml needed just for the board. A task_board block in a repo's.review.yml overrides that default for that repo; an explicit empty task_board: disables
the board for it. review-pr reads this through the policy; solve-task reads it via theget_board_config MCP tool (and the board-MCP, LLM-side) as a fallback when the local .review.yml
has no block.
Bulk task sync is server-side, not LLM (sync_board). The sync-tasks skill is a thin trigger:
it calls one MCP tool, sync_board(board, limit, purge_orphaned, keep_with_prs), and the reviewer
server enumerates the board over REST itself (reviewer/tasks/boards/, behind aTaskBoardProvider interface — Yougile is the reference), normalizes each task into a TaskBrief
in Python, and indexes it via the existing batch indexer. The LLM passes no task text, so a sync
costs O(1) tokens regardless of board size. It is incremental via a per-board timestamp watermark inindex_meta (ref="tasks:<board>"): a repeat sync touches ~0 tasks; --limit disables purge and
the watermark advance. The board REST credentials live only in the reviewer-mcp environment
(TASK_BOARD_API_KEY / TASK_BOARD_API_BASE). This inverts the "reviewer Python never touches the
board" rule for bulk sync only — single-task reads in solve-task / review-pr still go through
the board-MCP on the LLM side. The task graph (:Task) is global, so one task can span PRs across
several microservice repos.
Observability web admin
Every publish_review records the run in Postgres (review_runs / review_findings): repo/PR,
model, timings, status, findings with verdicts and whether they were posted. The write is
fail-soft (a logging failure never breaks the review) and gated by REVIEW_HISTORY (defaulttrue). The web admin (FastAPI + React/Vite SPA) shows run history, aggregates (gate filter rate,
trends over time, findings by category/severity) and per-run details with finding drill-down.
# On the host — build the frontend, then serve the SPA + FastAPI:
pip install -e ".[web]"
(cd web/frontend && npm install && npm run build)
reviewer serve # http://127.0.0.1:8000 (options: --host / --port)
API: GET /api/runs (filterable list), GET /api/runs/{id} (run + findings),GET /api/runs/{id}/trace (step trace, forward-only — empty for pre-feature runs),GET /api/stats?days=N (aggregates).
Known limitations & caveats
A factual list of what this does and does not do today.
- No automatic trigger. A review is not started on PR open/update. It is a manual skill
invocation inside Claude Code — there is no GitHub App / webhook / CI integration out of the box. - Graph auto-reindex is incremental, not full-precision. On
prepare_review, when the base
branch SHA drifts, the code graph is patched for the changed files (tree-sitter, repo-scoped) in
the same step that self-heals vector chunks — incomingCALLSedges from unchanged callers are
preserved. Not refreshed until the next manualreviewer index:IMPLEMENTSedges, outgoingCALLSinto unchanged files, and new incomingCALLSfrom unchanged callers. Full SCIP precision
is restored byreviewer index. - Multi-repo via a
repodiscriminator. One deployment hosts N repositories isolated by arepo(owner/name) column/property across Postgres and Neo4j; each review is scoped to its PR's
repo (no cross-repo retrieval). Index a repo withreviewer index <path> --repo owner/name(or let
it deriveowner/namefrom the gitoriginremote, or setDEFAULT_REPO). The task graph
(:Task) is intentionally global, so one task can span PRs across several microservice repos.
Within a repo, each tracked branch has its own isolated index (ref="base:<branch>"in Postgres;branchproperty on Neo4j:Symbolnodes, unique constraint(repo, branch, id)). - Language scope: Python only. The chunker (tree-sitter) and the SCIP backend (
scip-python)
are Python-specific. Other languages would go behind the same chunker/GraphIndexerinterfaces. - VCS scope: GitHub only. Only GitHub implements
VCSProvider; GitLab/Bitbucket are not
implemented (the abstraction exists, the providers do not). - Graph backend trade-off. A precise, type-aware graph (
CALLS+IMPLEMENTSedges) requiresscip-pythoninPATH. Without it, the tree-sitter fallback givesCALLS-by-name only (noIMPLEMENTS). Mode is chosen viaGRAPH_BACKEND=auto|scip|treesitter; inauto, a SCIP failure
silently falls back to tree-sitter with a warning, whilescippropagates the error. - Review surface. Inline comments are only possible on diff lines (the changed/context lines of a
hunk); everything else goes into the summary. An applyablesuggestionblock is emitted only under
safe invariants (applymode, an exact replacement, the whole range inside the RIGHT side of the
diff, no overlap with other fixes); otherwise the advice is plain text. - MCP session is in-process. State between
prepare_reviewandpublish_reviewlives in the
runningreviewer-mcpprocess (_SessioninMCPReviewService). Both calls for one PR must hit
the same running server — a restart in between loses the session (mitigated byREVIEW_SESSION_PERSIST). - Voyage free tier = 3 RPM / 10K TPM; TPM is the main blocker — a full
reviewer indexof a
large repo throttles (there is retry/backoff with jitter). A single PR review (overlay + query
embeddings) fits within the limit. - LLM cost. A review fans out Claude subagents per file plus dimension passes — that is real
token cost, not free. - Observability web admin auth is optional. Basic auth is enabled only if
WEB_ADMIN_USER/WEB_ADMIN_PASSWORDare set; by default it is not hardened for public exposure (reviewer serve
binds to loopback by default). - GitHub API caps. The PR file list is paginated by 100; the compare API used to re-sync the base
index returns at most 300 files — very large diffs are truncated. .review.ymlcomes from the base branch (by design — a PR cannot weaken its own review), not
from the PR head.
Tests
.venv/bin/pytest -q # unit: fast, on fakes; never hit external APIs
.venv/bin/pytest -m integration # integration: needs running Postgres/Neo4j + a Voyage key
.venv/bin/ruff check . # lint (line-length 100, target py311)
pytest excludes integration tests by default (addopts = -m 'not integration'). External services
(GitHub, Voyage, Postgres, Neo4j) are isolated behind interfaces and mocked in unit tests; real calls
happen only in integration/E2E.
Project layout
reviewer/
config/ Settings (pydantic-settings): env → review thresholds, stores, branches, board
vcs/ VCSProvider + github.py (httpx) · diff.py (lines available for inline)
index/ chunker(tree-sitter) · embeddings(Voyage) · reranker · store(pgvector+pg_search/RRF) · freshness
graph/ builder(tree-sitter call-graph) · scip(SCIP parser) · backend(backend orchestrator) · store(Neo4j)
retrieval/ Retriever: hybrid + graph expansion + rerank → ContextPack
llm/ _retry.py (retry/backoff for Voyage)
tools/ agent tools (search_code, get_related_symbols, read_file, get_definition, …)
tasks/ TaskBrief normalization · boards/ (TaskBoardProvider REST: yougile) · TaskService.index_batch
agent/ state (ReviewUnit) · assemble · dedup
mcp/ MCPReviewService: prepare / tool calls / publish; session management
services/ ReviewService.prepare: ingest PR, overlay, units
policy/ ReviewPolicy: env defaults + .review.yml + gating
entrypoints/ cli.py (Click) · mcp_server.py (FastMCP, 20 tools)
install.py reviewer init / install / install-skills (cross-platform client wiring)
web/ FastAPI + React/Vite SPA — observability web admin
app.py dependency assembly from Settings
plugin/ Claude Code plugin (7 skills /rag-reviewer:reviewer_*)
docker-compose.yml ParadeDB (pgvector+pg_search) + Neo4j
Contributing
Issues and PRs are welcome. To work on the project locally:
git clone https://github.com/mimfort/rag_for_git
cd rag_for_git
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
docker compose up -d # Postgres/ParadeDB (:5433) + Neo4j (:7687)
.venv/bin/pytest -q # unit tests — fast, on fakes, no external APIs
.venv/bin/ruff check . # lint (line-length 100, target py311)
External services (GitHub, Voyage, Postgres, Neo4j) sit behind interfaces and are mocked in unit
tests; real calls happen only in integration/E2E. Commit messages follow Conventional Commits. The
architecture is documented in depth in README.ru.md (Russian) and CLAUDE.md.
License
MIT © rag_for_git contributors.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found