local-review
Local, BYOK code review for any language.
Runs against a git diff, hands it to whichever LLM you point it at, prints findings.
No SaaS, no telemetry, no signup.
Install •
Quick Start •
Multi-LLM •
Checklist •
Website
📋 Looking for the human-readable code review checklist this tool implements? See CHECKLIST.md — OWASP 2025-aligned, with severity tiers and concrete measurables. Use it for human reviews, or run local-review review to get an LLM pass against the same rules.
✨ New in v0.7 — Smarter, more visible reviews. Three changes you'll notice on your first run after upgrading:
- Diff-too-large preflight. Agents whose context window can't fit the prompt + diff are skipped before the run starts, with a one-line hint on how to scope smaller. No more 5-minute fan-outs that fail with N opaque errors.
- Per-LLM token visibility. Each completion line shows the prompt and response size for that agent (
· 12.3k in / 4.5k out); the closing line aggregates the run total. Same data persists in <commit>_metadata.json. (For Anthropic, "in" includes cache-read tokens — these numbers are prompt size, not billed amount; check your vendor dashboard for actual spend.)
- Live progress streaming. Per-agent lines print as each agent finishes — no more blank terminal while the slow one grinds. See CHANGELOG for the full notes.
What it is, what it isn't
| ✅ What it is |
❌ What it isn't |
Reads your auth state from local files only — env vars and parsed contents of ~/.claude/sessions/, ~/.gemini/google_accounts.json, ~/.codex/auth.json (to detect login state); never transmits credentials |
A keychain scraper or credential-exfil tool — auth files are read locally to determine readiness, never sent anywhere |
Each LLM call goes against the endpoint you configured — vendor CLI subprocess (multi-LLM mode) or HTTP to your provider.base_url (single-LLM fallback); your account, your key, your quota |
A proxy, mirror, or reseller running between you and the LLM — no local-review-operated relay, no shared capacity |
| A local CLI that reviews a git diff using LLMs you've already authenticated |
A replacement for Claude's /review or /simplify — those are single-prompt commands; this is multi-LLM diff orchestration |
| An orchestrator that runs Claude / Gemini / Codex CLIs in parallel and merges findings into one report |
"Code never leaves your machine" — the diff still goes to whichever LLM you authenticate (run Ollama for true offline) |
| BYOK — your API key, requests go direct to the vendor (no middleman server) |
A SaaS — no hosted dashboard, no account, no team collaboration features |
A pre-commit gate — exits non-zero on major / critical findings so hooks can block the commit |
A linter or static analyzer — it's LLM-based, with the heuristic tradeoffs that implies |
| A single Go binary — no Node, no Python, no Docker, no telemetry |
A chat interface — reads a diff, prints findings, exits |
Why
Reviewer tools today are mostly:
- SaaS — your code leaves the building. Hard sell for enterprise.
- CI-only — you find out about issues after pushing the branch.
- Tied to a vendor — single-provider lock-in (OpenAI-only or Anthropic-only).
- Runtime-heavy — Node/Python/Java install required just to run the reviewer.
local-review is the opposite: a single static binary that runs locally on a diff, sends that diff to whatever LLM(s) you've authenticated, and prints findings. Privacy posture depends on which LLM(s) you point it at — see the Privacy section for the matrix. Run with Ollama for fully-offline review.
Install
curl -fsSL https://raw.githubusercontent.com/mshykov/local-review/main/install.sh | sh
Or grab a binary from Releases.
Or build from source:
go install github.com/mshykov/local-review/cmd/local-review@latest
Quick start
# 1. Install one or more LLM CLIs (each one is a "team mate" reviewing your code)
npm install -g @anthropic-ai/claude-code # Claude — free tier via `claude login`
npm install -g @google/gemini-cli # Gemini — free key from Google AI Studio
npm install -g @openai/codex # Codex — ChatGPT Plus or OPENAI_API_KEY
# 2. Authenticate the ones you want
claude login
export GEMINI_API_KEY=...
export OPENAI_API_KEY=...
# 3. Check who's ready
local-review doctor
# 4. Review your branch — every authenticated CLI runs in parallel and findings get merged
local-review review
That's it. local-review review is the canonical command — it runs every LLM CLI that's installed AND authenticated, in parallel, and prints a merged report.
By default findings at warning+ are shown and major/critical exit non-zero (good for pre-commit hooks).
If you don't have any LLM CLI installed, run local-review init to set up a single-LLM review against any OpenAI-compatible API instead.
Multi-LLM is the default
Every authenticated LLM CLI runs by default. No opt-in, no enabling — if you claude login, claude runs. If you export OPENAI_API_KEY=..., codex runs. If you don't authenticate one, it's silently skipped.
# Default: all active LLMs
local-review review
# Restrict to a subset (overrides config)
local-review review --only claude,gemini
# Pick a specific model for one agent
local-review review --claude-model claude-opus-4-7
# Use a specific agent to do the merge
local-review review --merge-with claude
Supported LLMs
| LLM |
Free Option |
Installation |
| Claude |
✅ Free tier via claude login (claude.ai account) |
npm install -g @anthropic-ai/claude-code |
| Gemini |
✅ Free API key from Google AI Studio |
npm install -g @google/gemini-cli |
| Codex |
⚠️ ChatGPT Plus ($20/mo) or OpenAI API key (pay-per-token) |
npm install -g @openai/codex |
How it works:
- Detects installed LLM CLIs and which are authenticated (
local-review doctor)
- Runs every authenticated CLI in parallel
- Saves each review to
.local-review/reviews/<branch>/<commit>_<llm>_<version>.md
- Merges findings (dedup, consensus tagging) into one report
- Prints the merged report to stdout (also saved as
<commit>_merged.md)
Authentication — what each LLM needs:
| LLM |
Default (preferred) |
Alternative |
| Claude |
claude login — Anthropic OAuth, works with the free tier on a claude.ai account |
export ANTHROPIC_API_KEY=... (paid API access) |
| Gemini |
export GEMINI_API_KEY=... — free key from Google AI Studio |
gemini /auth for Google OAuth |
| Codex |
codex login — uses your ChatGPT Plus subscription ($20/mo) |
export OPENAI_API_KEY=... — pay-per-token; usually cheaper for occasional review use |
Run local-review doctor to see which CLIs you have installed and authenticated. Each row that isn't ✓ ready tells you exactly what to fix.
Configuration is optional. If ~/.local-review.yml or ./.local-review.yml exists it overrides defaults; CLI flags override config:
# .local-review.yml — example: pin specific models, disable codex
llms:
claude:
model: claude-opus-4-7
gemini:
model: gemini-2.0-flash
api_key_env: GEMINI_API_KEY
codex:
enabled: false # opt-out (still runs if --only codex is passed)
merge:
preferred_llm: auto # or: claude, gemini, codex
See examples/.local-review-multi.yml for full schema.
local-review loads YAML from a cascade — built-in defaults → ~/.local-review.yml → ./.local-review.yml → CLI flags.
A minimal ~/.local-review.yml:
provider:
base_url: https://api.openai.com/v1
model: gpt-4o-mini
api_key_env: LOCAL_REVIEW_API_KEY
review:
min_severity: warning
max_findings: 20
See examples/.local-review.yml for the full schema with comments.
Switching providers
local-review speaks the OpenAI chat-completions API — every major provider supports it:
| Provider |
base_url |
Notes |
| OpenAI |
https://api.openai.com/v1 |
Default. gpt-4o-mini is cheap; gpt-4o for harder reviews. |
| Anthropic |
https://api.anthropic.com/v1 |
Anthropic's OpenAI-compatible endpoint. Use exact model names (e.g. claude-sonnet-4-6, claude-opus-4-7). |
| Mistral |
https://api.mistral.ai/v1 |
EU-hosted; Codestral is code-tuned. See examples/.local-review.mistral.yml. |
| DeepSeek |
https://api.deepseek.com/v1 |
Cheapest cloud option. See examples/.local-review.deepseek.yml. |
| Groq |
https://api.groq.com/openai/v1 |
Fast inference; Llama, Qwen, etc. |
| Together |
https://api.together.xyz/v1 |
Llama, Mixtral, Qwen — many open-weights options. |
| OpenRouter |
https://openrouter.ai/api/v1 |
One key, all models. |
| Ollama |
http://localhost:11434/v1 |
Fully offline. No data leaves your machine. |
| vLLM |
http://your-host/v1 |
Self-hosted. |
The fastest way to set any of these up is local-review init, which writes a working .local-review.yml from a preset.
Pre-commit hook
cp examples/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Or with husky / lefthook: run local-review staged in the pre-commit step.
Bypass for emergencies: LOCAL_REVIEW_SKIP=1 git commit ....
CLI
# Review (multi-LLM by default; falls back to single-LLM via configured provider if no CLI is active)
local-review review [<base>] # canonical: current branch vs <base> (default: main)
local-review staged # review git diff --cached (pre-commit)
local-review commit [<rev>] # review one commit (default: HEAD)
local-review branch [<base>] # alias of `review` for muscle-memory
# Utilities
local-review init # interactive setup (writes .local-review.yml)
local-review doctor # check LLM installations + auth state
local-review config # print resolved config (API keys masked)
local-review version # print version
local-review bench # run the review-quality benchmark suite (see bench/README.md)
Common flags:
| Flag |
Purpose |
--only <list> |
Comma-separated agents to run (e.g. claude,gemini); overrides config |
--claude-model <id> |
Override claude's model (same for --gemini-model, --codex-model) |
--merge-with <agent> |
Pick which agent merges findings (default: auto) |
--model <id> |
Override provider.model (single-LLM fallback only) |
--base-url <url> |
Override provider.base_url (single-LLM fallback only) |
--min-severity <tier> |
nit / info / warning / major / critical (single-LLM fallback only) |
--max-findings <n> |
Cap output (single-LLM fallback only) |
--json |
Emit JSON (single-LLM fallback only — see below) |
In multi-LLM mode the merger returns markdown, not structured findings, so --json, --min-severity, and --max-findings are ignored: they only take effect in the single-LLM fallback path (when no LLM CLI is authenticated and we hit the configured provider: directly). Multi-LLM emits a stderr warning when those flags are passed so you know they had no effect. A structured-JSON multi-LLM output mode (where the merger emits both markdown and a JSON envelope) is on the post-v0.7 roadmap — no fixed date; we'll unpark it when the third user asks for it.
Config wins by default; flags override config at runtime (e.g., --only codex runs codex even if your config sets codex.enabled: false).
Exit codes:
0 — no blocking findings
2 — major or critical findings present (pre-commit gate)
- non-zero — local-review itself failed (the hook ignores this and lets the commit through)
Prompt packs
local-review ships with packs for default, typescript, go, python, rust, with more coming. The CLI auto-picks based on the dominant language in your diff. Force a specific pack with review.prompt_pack: <id> in your YAML config.
Each pack is a markdown file (in internal/prompts/packs/) that defines:
- What to look for (priority-ordered)
- Severity tiering rules
- Hard rules ("never invent code that isn't in the diff")
- Output JSON schema
See docs/prompt-packs.md for how to write or override one.
Customise the review prompt (v0.8+)
Different teams have different opinions about what's a "warning" vs a "nit." Forking the binary to change the bundled packs is a heavy hammer. Three lighter knobs in .local-review.yml:
prompts:
# 1. Per-language override directory. A `<language>.md` file here
# replaces the embedded pack of the same name. Missing files
# fall through to the embedded pack — partial overrides are
# fine.
pack_dir: .local-review/prompts
# 2. Inline rules spliced BEFORE every pack body. Use for house
# rules that should colour the entire review.
prepend: |
Additional house rules:
- Never approve commented-out code.
- Flag any new dependency in package.json or go.mod.
# 3. Inline rules spliced AFTER every pack body. Use for output-
# shape rules the LLM should see last.
append: |
Output language: English only.
All three apply to the multi-LLM path AND the single-LLM fallback, so a team's customizations reach every reviewer (claude, gemini, codex).
For one-off runs, --prompt-pack-dir <dir> overrides prompts.pack_dir for a single review without touching the YAML.
local-review config shows where each language's prompt actually came from:
# Resolved prompt sources:
# default embedded
# go /Users/me/repo/.local-review/prompts/go.md
# python embedded+prepend
# rust embedded
# typescript embedded
local-review doctor actively probes the prompt configuration and warns on every misconfiguration the resolver tolerates silently: missing pack_dir, pack_dir pointing at a file (not a directory), pack_dir with no <language>.md files matching a shipped pack, or known-language override files that exist but aren't readable. The resolver itself stays fall-through-on-error so a transient FS glitch can't kill every review; doctor surfaces the same conditions once at setup-check time.
What it does NOT do (yet)
- No multi-file refactor reasoning. local-review reviews diffs, not architectures.
- No auto-fix / auto-PR. Findings are advisory.
- No GitHub integration in the binary. The
--json output is structured for piping into your CI's PR-comment tool of choice. A native local-review github mode is parked — open an issue if you need it.
- No telemetry. None. Ever.
On the roadmap
These are queued and will land in priority order; ping the issue tracker if you want to influence the sequence.
- Org-config fetching (near-term) — an
org: block in your .local-review.yml (with a config_url: field) will fetch + cache an org-wide policy YAML, so a team can ship a single repo-local config that pulls org defaults from a central URL. Example shape:
org:
config_url: https://your-internal-host/local-review.yml
- Structured JSON multi-LLM output — the merger will emit markdown plus a JSON envelope so CI integrations don't have to text-scrape. Demand-pull: open an issue if you need it.
- Cosign release signing —
install.sh already verifies SHA-256 checksums (defense against accidental corruption + basic tampering). Cosign signatures will add stronger supply-chain provenance: every release tarball signed via keyless OIDC at build time, verified by the installer against the GitHub Actions identity. Useful for enterprise installs that need to prove an artifact came from this repo's release pipeline and wasn't swapped at the channel/CDN layer.
For organizations
Distributing to a few hundred engineers? Two patterns work:
- Org config repo. Drop a
.local-review.yml in each project that sets:
org:
config_url: https://your-internal-host/local-review.yml
(Org-config fetching is the next planned feature — see "On the roadmap" above; today, just commit the YAML to each repo.)
- One install command in onboarding.
curl -fsSL <install.sh> | sh plus an env var = done.
Privacy
local-review is telemetry-free: no analytics, no auto-update calls, no signup, no SaaS. The only network traffic is to the LLM endpoint(s) you configure — either an HTTP call from local-review's built-in client (single-LLM mode) or the authenticated CLI subprocesses (multi-LLM mode). What "private" means therefore depends on which LLM(s) you point it at:
| Mode |
Where your diff goes |
Single-LLM, provider.base_url: http://localhost:11434/v1 (Ollama) |
Stays on your machine. Fully offline. |
| Single-LLM, any cloud provider (OpenAI, Anthropic, Mistral, etc.) |
The provider you configured, over TLS. Their privacy policy applies. |
| Multi-LLM (default) — Claude / Gemini / Codex CLIs |
Each authenticated CLI calls its own backend (Anthropic, Google AI, OpenAI). One review fans out to multiple cloud vendors. Your provider.base_url is irrelevant in this mode. |
Multi-LLM with --only restricted to a fully-local agent |
Roadmap. Will be possible once a fully-local-agent preset lands; today every multi-LLM agent (claude / gemini / codex) calls its own cloud backend. |
If you need air-gapped review today, use single-LLM mode against a local Ollama and stay off local-review review (which fans out to authenticated cloud CLIs by default).
Develop
go test ./...
go build -o local-review ./cmd/local-review
./local-review staged
See CONTRIBUTING.md.
License
MIT. See LICENSE.