* feat: add ocr scan for full-file code review
Introduce a new top-level subcommand `ocr scan` (alias `s`) that reviews
whole files instead of git diffs. Use cases include reviewing unfamiliar
codebases, pre-migration audits, and ad-hoc per-directory reviews.
Architecture splits scan and diff review at the package level so the two
pipelines can evolve independently:
- internal/scan/ new package: file enumeration via `git ls-files`,
full-scan agent, FULL_SCAN_TASK rendering, preview
- internal/llmloop/ new package: shared LLM tool-use loop, three-zone
memory compression, CommentWorkerPool, AgentWarning.
Both internal/agent and internal/scan delegate to
llmloop.Runner; agent and scan never import each other
- internal/agent/ slimmed: LLM loop / compression / token aggregation
moved to llmloop; review-only orchestration remains
- internal/model/ new ScanItem (full-file payload) + Preview /
PreviewEntry / ExcludeReason shared by both modes
- internal/diff/ new gitignore.go exporting helpers reused by scan
- cmd/opencodereview/ new scan_cmd.go; shared.go consolidates startup
(loadCommonContext / loadLLMRuntime), output
(emitRunResult, ResultProvider) and stdout silencing
(quietHandle); review_cmd.go follows the same shape
Template additions:
- FULL_SCAN_TASK: dedicated prompt with Tool-call discipline guidance to
reduce gratuitous tool calls per file
- FULL_SCAN_MAX_TOOL_REQUEST_TIMES (default 60): scan-only per-file budget,
raised over diff's 30 to fit multi-finding files; --max-tools still
composes (only raise, never lower)
In scan mode, file_read_diff is filtered out of MainToolDefs since it has
no useful semantics without a diff.
Tests cover provider enumeration (with temp git repo), template rendering,
filter passes, dependency budget, flag validation, and excludeToolDef.
* feat(scan): v2 — exclude / non-git / split template / plan / batch / dedup / project-summary
Address design-review feedback by evolving `ocr scan` along seven axes
while keeping `ocr review` behavior unchanged:
1. File size cap is now configurable (ScanTemplate.MaxFileSizeBytes,
default 2 MiB; previously a hard-coded 5 MiB). The cap exists only to
bound memory reading; the real review-feasibility gate is the per-file
token budget downstream.
2. Drop the `--all` flag. Bare `ocr scan` now scans the whole repo;
`--path` narrows. Less ceremony, fewer redundant flags.
3. New `--exclude` flag on both review and scan. Comma-separated
gitignore-style patterns; merged with rule.json's exclude layer via
the new shared.applyCLIExcludes helper.
4. Scan supports non-git directories. internal/scan.Provider chooses
between `git ls-files` (full .gitignore semantics) and a
filepath.WalkDir fallback (root .gitignore + ExcludedDirs blocklist)
per isGitRepo probe. loadCommonContext takes a requireGit bool; review
keeps the hard requirement, scan relaxes it.
5. Scan configuration lives in its own file. internal/config/template:
- new ScanTemplate type with LoadScanDefault/ApplyLanguage/Validate
- new embedded scan_template.json
- Template loses the FULL_SCAN_* fields (review template unaffected)
scan.Agent.Args.Template now holds a ScanTemplate; toLoopTemplate
adapts it for llmloop.Runner.
6. New scan phases — each nil-able in the template and toggleable via a
CLI flag, so users can revert to v1 behavior trivially:
* PLAN_TASK (--no-plan): per-file pre-pass that outputs a JSON
summary + checkpoints, embedded into MAIN_TASK as {{plan_guidance}}.
formatPlanGuidance renders to markdown; malformed JSON falls back
to raw text. PLAN_TASK failure never blocks the main loop.
* BATCH_STRATEGY (--batch): files are grouped before dispatch.
"none" preserves v1, "by-language" (default) groups by extension,
"by-directory" groups by first-level subdir. BatchSize caps natural
groups so a single language with 500 files doesn't form one giant
batch. Batches are processed sequentially; files within a batch
remain concurrent up to MaxConcurrency.
* DEDUP_TASK (--no-dedup): per-batch postprocess that asks the LLM
to cluster near-duplicate comments. Output is a `groups` JSON;
every input id must appear exactly once or the result is rejected
and originals are kept (safety: never silently lose comments).
CommentCollector grows Snapshot/Since/ReplaceSince for this.
* PROJECT_SUMMARY_TASK (--no-summary): once-per-run cross-file
summary appended to text output and surfaced as `project_summary`
in JSON output. ResultProvider grows ProjectSummary(); agent.Agent
returns "" (review mode has no project summary).
All four new LLM steps record token usage via runner.RecordUsage so
aggregate counters stay accurate.
7. Tests cover the new pure code paths:
- batch_test.go: 3 strategies, BatchSize cap, language-key edge cases
- dedup_test.go: groups parser, malformed shapes, fence stripping,
payload field selection
- agent_test.go: formatPlanGuidance variants, buildSummaryCommentsList
truncation, maybeRunPlan skip paths
- provider_test.go: non-git directory walker fallback
- template_test.go: ScanTemplate loads / ApplyLanguage / review
template no longer contains scan fields
The seven phases can be reverted independently by toggling flags or
clearing the corresponding optional template fields; nothing forces the
new behavior on existing review users.
* fix(scan): three real bugs surfaced by SCAN_PLAN_TASK self-review
A v2 end-to-end test (ocr scan --path internal/scan/preview.go) had the
PLAN_TASK phase flag three concrete bugs in the scan package itself.
This commit fixes them and adds regression tests.
1. Preview() mutated a.items as a side-effect.
Both Preview and Run wrote to a.items. Calling Preview before Run
silently primed Run with the preview's enumeration instead of
triggering a fresh listFiles. Preview is documented as a read-only
dry-run; uphold that. Local variable now; a.items stays nil after
Preview returns.
2. Preview.result.Entries was nil when there were no items.
With no items at all the loop never ran, so Entries remained nil and
JSON marshalling produced "files":null. Pre-allocate to a non-nil
empty slice so the JSON contract stays "files":[] regardless.
3. Provider.Enumerate and listFilesViaWalk never checked ctx.Done().
On a large repo a cancelled context would still complete the full
walk before the caller saw an error (every iteration costs a stat or
ReadFile syscall). Add the check at the top of each iteration in
both the git-ls-files path and the walker fallback path; the walker
returns ctx.Err() so filepath.WalkDir propagates the cancellation.
Three new regression tests pin the contracts:
- TestPreview_DoesNotMutateAgentItems
- TestPreview_EmptyResultEntriesIsNonNilSlice
- TestProvider_Enumerate_RespectsContextCancellation
* feat(scan): cost estimate + token budget cap; fix file_find on non-git dirs
Two cost-control features and one robustness fix, all surfaced by running
the scanner against a real ~870K-token repository.
Cost estimate (internal/scan/estimate.go):
- Before dispatch, Run prints an order-of-magnitude projection of token
usage (input/output/total), derived from per-file content size × an
assumed round count, plus the optional plan/dedup/summary phases.
- Deliberately reports tokens only, not dollars — pricing varies per
provider/model and a precise figure would mislead. Actual usage is still
reported from the API after the run.
Token budget cap (--max-tokens-budget / ScanTemplate.MaxTokensBudget):
- Caps total token usage for one scan. The gate is checked per file inside
dispatchBatch, right before acquiring a concurrency slot: if tokens
already spent plus a look-ahead estimate of the next file would exceed
the budget, that file and all remaining files are skipped and a
token_budget_reached warning is recorded.
- An earlier batch-level gate was too coarse: with the default by-language
batching, a Go-heavy repo puts most files in one batch, so the gate only
fired between batches and overran the budget ~2.4×. The per-file gate
bounds overrun to roughly one in-flight file per worker (~1.3× at
concurrency=1 in testing).
- 0 = unlimited (unchanged default behavior).
Phase-gate helpers (planEnabled/dedupEnabled/summaryEnabled) consolidate
the "template defines it AND --no-* flag not set" checks so the cost
estimate and the dispatch path agree on which phases will actually run.
file_find non-git fallback (internal/tool/file_find.go):
- `git ls-files` exits 128 in a non-git directory, which spammed failures
when scanning plain directories (scan already supports non-git repos via
the provider's walker, but the file_find tool did not). Now falls back
to filepath.WalkDir honoring the root .gitignore and the default
excluded-dir blocklist when git fails and no specific ref is requested.
Tests:
- estimate_test.go: humanTokens formatting, per-file vs aggregate estimate
consistency, phase scaling, phase-gate tri-state.
- budget_test.go: fake LLM client drives the gate deterministically —
verifies dispatch stops before exceeding budget and that 0 = unlimited.
- file_find_test.go: non-git directory fallback finds files, honors
.gitignore / blocklist, and returns the not-found sentinel correctly.
* docs(readme): document ocr scan subcommand and flags
ocr scan existed but was undiscoverable from the README. Add it to the
intro blurb, Quick Start, the Commands table, Examples, and a dedicated
flags table (path / exclude / preview / max-tokens-budget / no-plan /
no-dedup / no-summary / batch / format / concurrency / rule / repo).
Note non-git support and the pre-run cost estimate. Also backfill the
--exclude flag in the ocr review flags table (added during the v1.3 merge
but never documented).
Flag names and defaults verified against `ocr scan -h`.
* fix(scan): code_search works in non-git directories via git grep --no-index
code_search relied on `git grep`, which exits 128 in a non-git directory —
so `ocr scan` on a plain directory (already supported by file enumeration and
file_find) silently returned errors instead of search results. Detect that
failure and retry with `git grep --no-index --exclude-standard`, which searches
the working tree directly while still honoring .gitignore. Reuses all existing
grep flag/parsing logic; ref-based search still requires a real repo.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(scan): preserve context on compression failure; fix NUL parsing in gitLs
Address three real bugs from the PR #93 automated review that regressed when
compression moved into internal/llmloop:
- Sync compression failure / empty summary now return the original messages
instead of truncating to the frozen zone, which discarded the whole
per-file conversation context.
- Async compression now abandons the job on error instead of applying a
truncated snapshot, and re-applies messages appended while it ran
(snapshotLen), so concurrent tool results are no longer lost.
- scan Provider.gitLs uses cmd.Output() instead of CombinedOutput() so
stderr can't corrupt the NUL-delimited (-z) filename parsing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|---|---|---|
| .claude/commands | ||
| .claude-plugin | ||
| .github | ||
| bin | ||
| cmd | ||
| examples | ||
| extensions/vscode | ||
| imgs | ||
| internal | ||
| npm | ||
| pages | ||
| plugins/open-code-review | ||
| scripts | ||
| skills/open-code-review | ||
| .gitignore | ||
| .npmignore | ||
| CONTRIBUTING.ja-JP.md | ||
| CONTRIBUTING.ko-KR.md | ||
| CONTRIBUTING.md | ||
| CONTRIBUTING.ru-RU.md | ||
| CONTRIBUTING.zh-CN.md | ||
| go.mod | ||
| go.sum | ||
| install.sh | ||
| LICENSE | ||
| Makefile | ||
| package.json | ||
| README.ja-JP.md | ||
| README.ko-KR.md | ||
| README.md | ||
| README.ru-RU.md | ||
| README.zh-CN.md | ||
| SECURITY.md | ||
English | 简体中文 | 日本語 | 한국어 | Русский
What is Open Code Review?
Open Code Review is an AI-powered code review CLI tool. It originated as Alibaba Group's internal official AI code review assistant — over the past two years, it has served tens of thousands of developers and identified millions of code defects. After thorough validation at massive scale, we incubated it into an open source project for the community. Simply configure a model endpoint to get started.
It reads Git diffs, sends changed files to a configurable LLM via an agent with tool-use capabilities, and generates structured review comments with line-level precision. The agent can read full file contents, search the codebase, inspect other changed files for context, and produce deep reviews — not just surface-level diff feedback. Beyond diff review, ocr scan reviews entire files for auditing unfamiliar codebases or directories that have no meaningful diff.
Benchmark
Compared to general-purpose agents (Claude Code), Open Code Review achieves significantly higher Precision and F1 with the same underlying model, while consuming only ~1/9 of the tokens and completing reviews faster. Note that its Recall is lower than general-purpose agents — a deliberate trade-off favoring precision over noise.
A real-world code review benchmark built from 50 popular open-source repositories, 200 real Pull Requests, and 10 programming languages — cross-validated by 80+ senior engineers (1,505 annotated ground-truth issues).
| Metric | What it measures | Why it matters |
|---|---|---|
| F1 | Harmonic mean of precision and recall | Best single number for overall review quality |
| Precision | Proportion of reported issues that are real defects | Higher = fewer false alarms to triage |
| Recall | Proportion of real defects that are found | Higher = fewer issues slip through review |
| Avg Time | Wall-clock time per review | Matters for CI pipeline latency |
| Avg Token | Total tokens consumed per review | Directly impacts API cost |
Why Open Code Review?
The Problem with General-Purpose Agents
If you've used general-purpose agents like Claude Code with Skills for code review, you've likely encountered these pain points:
- Incomplete coverage — On larger changesets, agents tend to "cut corners," selectively reviewing only some files and missing others.
- Position drift — Reported issues frequently don't match the actual code location, with line numbers or file references drifting off target.
- Unstable quality — Natural-language-driven Skills are hard to debug, and review quality fluctuates significantly with minor prompt variations.
The root cause: a purely language-driven architecture lacks hard constraints on the review process.
Core Design: Deterministic Engineering × Agent Hybrid
Open Code Review's core philosophy is to combine deterministic engineering with an agent, each handling what it does best.
Deterministic Engineering — Hard Constraints
For review steps that must not go wrong, engineering logic — not the language model — guarantees correctness:
- Precise file selection — Determines exactly which files need review and which should be filtered, ensuring no important change is missed.
- Smart file bundling — Groups related files into a single review unit (e.g.,
message_en.propertiesandmessage_zh.propertiesare bundled together). Each bundle runs as a sub-agent with isolated context — a divide-and-conquer strategy that stays stable on very large changesets and naturally supports concurrent review. - Fine-grained rule matching — Matches review rules to each file's characteristics, keeping the model's attention sharply focused and eliminating information noise at the source. Compared to purely language-driven rule guidance, template-engine-based rule matching is more stable and predictable.
- External positioning and reflection modules — Independent comment-positioning and comment-reflection modules systematically improve both the location accuracy and content accuracy of AI feedback.
Agent — Dynamic Decision-Making
The agent's strengths are concentrated where they matter most — dynamic decisions and dynamic context retrieval:
- Scenario-tuned prompts — Prompt templates deeply optimized for code review, improving effectiveness while reducing token consumption.
- Scenario-tuned toolset — Distilled from deep analysis of tool-call traces in large-scale production data — including call frequency distributions, per-tool repetition rates, and the impact of new tools on the overall call chain — resulting in a purpose-built toolset that is more stable and predictable for code review than a generic agent toolkit.
How to Use
CLI
Install
Via NPM (Recommended)
npm install -g @alibaba-group/open-code-review
After installation, the ocr command is available globally.
From GitHub Release
Install the latest binary for your OS/architecture with one command (macOS / Linux):
curl -fsSL https://raw.githubusercontent.com/alibaba/open-code-review/main/install.sh | sh
The script picks the right release binary, verifies its SHA-256 checksum, and installs it as ocr in /usr/local/bin. Override the target with OCR_INSTALL_DIR or pin a release with OCR_VERSION:
OCR_INSTALL_DIR="$HOME/.local/bin" OCR_VERSION=v1.3.13 \
sh -c "$(curl -fsSL https://raw.githubusercontent.com/alibaba/open-code-review/main/install.sh)"
Manual download (all platforms, including Windows)
Download the binary for your platform from GitHub Releases:
# macOS (Apple Silicon)
curl -Lo ocr https://github.com/alibaba/open-code-review/releases/latest/download/opencodereview-darwin-arm64
chmod +x ocr && sudo mv ocr /usr/local/bin/ocr
# macOS (Intel)
curl -Lo ocr https://github.com/alibaba/open-code-review/releases/latest/download/opencodereview-darwin-amd64
chmod +x ocr && sudo mv ocr /usr/local/bin/ocr
# Linux (x86_64)
curl -Lo ocr https://github.com/alibaba/open-code-review/releases/latest/download/opencodereview-linux-amd64
chmod +x ocr && sudo mv ocr /usr/local/bin/ocr
# Linux (ARM64)
curl -Lo ocr https://github.com/alibaba/open-code-review/releases/latest/download/opencodereview-linux-arm64
chmod +x ocr && sudo mv ocr /usr/local/bin/ocr
# Windows (x86_64) — move ocr.exe to a directory in your PATH
curl -Lo ocr.exe https://github.com/alibaba/open-code-review/releases/latest/download/opencodereview-windows-amd64.exe
# Windows (ARM64) — move ocr.exe to a directory in your PATH
curl -Lo ocr.exe https://github.com/alibaba/open-code-review/releases/latest/download/opencodereview-windows-arm64.exe
From Source
git clone https://github.com/alibaba/open-code-review.git
cd open-code-review
make build
sudo cp dist/opencodereview /usr/local/bin/ocr
Quick Start
1. Configure LLM
You must configure an LLM before reviewing code.
Option A: Interactive setup (Recommended)
ocr config provider # Select a built-in provider or add a custom one
ocr config model # Pick a model for the active provider
Option B: Manual config
ocr config set llm.url https://api.anthropic.com/v1/messages
ocr config set llm.auth_token your-api-key-here
ocr config set llm.model claude-opus-4-6
ocr config set llm.use_anthropic true
Config is stored in ~/.opencodereview/config.json.
auth_header (optional): Controls which HTTP header carries the API key when using Anthropic. Defaults to authorization (Bearer token) if omitted. If you use a standard sk-ant-* API key, you must set it to x-api-key:
ocr config set llm.auth_header x-api-key
Supported values: x-api-key, authorization (alias: bearer). Other values are rejected with an error.
Option C: Environment variables (highest priority)
export OCR_LLM_URL=https://api.anthropic.com/v1/messages
export OCR_LLM_TOKEN=your-api-key-here
export OCR_LLM_MODEL=claude-opus-4-6
export OCR_USE_ANTHROPIC=true
It is also compatible with Claude Code environment variables (ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_MODEL) and parses ~/.zshrc / ~/.bashrc for those exports.
Note for CC-Switch Users: If you are using CC-Switch with routing service enabled, you can point
llm.urlto the CC-Switch proxy address without additional configuration:
- For Claude provider: set
llm.urltohttp://127.0.0.1:15721- For Codex provider: set
llm.urltohttp://127.0.0.1:15721/v1- Set
llm.modelaccording to your provider settingsllm.auth_tokencan be any valueextra_bodysettings still apply
2. Test Connectivity
ocr llm test
3. Review
cd your-project
# Workspace mode — review all staged, unstaged, and untracked changes
ocr review
# Branch range — compare two refs
ocr review --from main --to feature-branch
# Single commit
ocr review --commit abc123
# Full-file scan — review whole files instead of a diff (no git history needed)
ocr scan # scan the entire repository
ocr scan --path internal/agent # scan a directory or specific files
Integrate with Coding Agents
OCR can be seamlessly integrated into AI coding agents as a slash command, enabling code review directly within your agent workflow.
Option 1: Install as a Skill
Use npx to install the OCR skill into your project:
npx skills add alibaba/open-code-review --skill open-code-review
This installs the open-code-review skill from the skills registry, which teaches your coding agent how to invoke ocr for code review, classify issues by priority, and optionally apply fixes.
Option 2: Install as a Claude Code Plugin
For Claude Code, install the command plugin through the following command in Claude Code:
/plugin marketplace add alibaba/open-code-review
/plugin install open-code-review@open-code-review
This registers the /open-code-review:review slash command, which runs OCR and automatically filters and fixes issues.
Option 3: Install as a Codex Plugin
For local Codex, install the Open Code Review plugin from this repository:
codex plugin marketplace add alibaba/open-code-review
codex
/plugins
For a local checkout or fork:
codex plugin marketplace add .
codex
/plugins
Install and enable Open Code Review, then start a new Codex thread and invoke it explicitly:
@Open Code Review review my current changes
@Open Code Review review this branch against main
@Open Code Review review and fix high-confidence issues
This registers a Codex skill that runs the local OCR CLI:
ocr review --audience agent
This integration does not change OCR's internal LLM backend and does not require configuring an OpenAI Responses API endpoint for Codex. OCR itself still requires the ocr CLI to be installed and configured as described in the CLI setup section.
Korean guide: plugins/open-code-review/CODEX.ko-KR.md
Option 4: Copy the Command File Directly
For a quick setup without any package manager, simply copy the command file to use the /open-code-review slash command in Claude Code.
Project-level (shared with team via git):
mkdir -p .claude/commands
curl -o .claude/commands/open-code-review.md \
https://raw.githubusercontent.com/alibaba/open-code-review/main/plugins/open-code-review/commands/review.md
User-level (personal global use across all projects):
mkdir -p ~/.claude/commands
curl -o ~/.claude/commands/open-code-review.md \
https://raw.githubusercontent.com/alibaba/open-code-review/main/plugins/open-code-review/commands/review.md
Prerequisite: All integration methods require the
ocrCLI to be installed and an LLM configured. See Install and Configure LLM above.
CI/CD Integration
OCR can be integrated into CI/CD pipelines to automate code review on Merge Requests / Pull Requests.
The core command for CI integration:
ocr review \
--from "origin/main" \
--to "<commit_sha>" \
--format json
The --from flag accepts a branch ref (e.g., origin/main) or commit SHA as the base, while --to accepts a commit SHA or branch ref as the head. In CI environments, using commit SHA for --to is recommended to correctly handle fork PRs/MRs where the source branch doesn't exist on the origin remote.
The --format json flag outputs machine-readable results suitable for parsing in CI scripts.
See the examples/ directory for integration examples:
github_actions/— GitHub Actions integration examplegitlab_ci/— GitLab CI integration example
Commands
| Command | Alias | Description |
|---|---|---|
ocr review |
ocr r |
Start a diff-based code review |
ocr scan |
ocr s |
Review whole files (no diff required) |
ocr rules check <file> |
— | Preview which review rule applies to a file path |
ocr config provider |
— | Interactive provider setup (built-in, custom, or manual) |
ocr config model |
— | Interactive model selection for the active provider |
ocr config set <key> <value> |
— | Set configuration values |
ocr config unset custom_providers.<name> |
— | Delete a custom provider |
ocr llm test |
— | Test LLM connectivity |
ocr llm providers |
— | List built-in LLM providers |
ocr viewer |
ocr v |
Launch WebUI session viewer on localhost:5483 |
ocr version |
— | Show version info |
ocr review Flags
| Flag | Shorthand | Default | Description |
|---|---|---|---|
--repo |
— | current dir | Git repository root |
--from |
— | — | Source ref (e.g., main) |
--to |
— | — | Target ref (e.g., feature-branch) |
--commit |
-c |
— | Single commit to review |
--exclude |
— | — | Comma-separated gitignore-style patterns to skip; merged with rule.json excludes |
--preview |
-p |
false |
Preview which files will be reviewed without running the LLM |
--format |
-f |
text |
Output format: text or json |
--concurrency |
— | 8 |
Max concurrent file reviews |
--timeout |
— | 10 |
Concurrent task timeout in minutes |
--audience |
— | human |
human (show progress) or agent (summary only) |
--background |
-b |
— | Optional requirement/business context for the review; auto-filled from commit message when using --commit |
--model |
— | — | Select or override the LLM model for this review |
--rule |
— | — | Path to custom JSON review rules |
--max-tools |
— | built-in | Max tool call rounds per file; only takes effect when greater than template default |
--max-git-procs |
— | built-in | Max concurrent git subprocesses |
--tools |
— | — | Path to custom JSON tools config |
ocr scan Flags
ocr scan reviews entire files rather than a diff — useful for auditing an unfamiliar
codebase, a pre-migration sweep, or any directory with no meaningful diff. It works in
non-git directories too (it falls back to a filesystem walk that honors .gitignore).
| Flag | Shorthand | Default | Description |
|---|---|---|---|
--path |
— | whole repo | Comma-separated dirs/files to scan |
--exclude |
— | — | Comma-separated gitignore-style patterns to skip; merged with rule.json excludes |
--preview |
-p |
false |
List which files would be scanned without running the LLM |
--max-tokens-budget |
— | 0 (unlimited) |
Cap total token usage; dispatch stops once exceeded |
--no-plan |
— | false |
Skip the per-file planning pre-pass |
--no-dedup |
— | false |
Skip per-batch de-duplication of similar comments |
--no-summary |
— | false |
Skip the project-level summary |
--batch |
— | by-language |
Batching strategy: none, by-language, or by-directory |
--format |
-f |
text |
Output format: text or json (JSON includes a project_summary field) |
--concurrency |
— | 8 |
Max concurrent file scans |
--rule |
— | — | Path to custom JSON review rules |
--repo |
— | current dir | Repository or directory root to scan |
Before each run, ocr scan prints a rough token-cost estimate. Use --preview to see the
file list first, and --max-tokens-budget to cap spend on large repositories.
Examples
# Interactive provider and model setup
ocr config provider
ocr config model
ocr llm providers
# Delete a custom provider
ocr config unset custom_providers.my-gateway
# Preview which files will be reviewed (no LLM calls)
ocr review --preview
ocr review -c abc123 -p
# Review workspace changes with default settings
ocr review
# Review branch diff with higher concurrency
ocr review --from main --to my-feature --concurrency 4
# Review a specific commit with verbose JSON output
ocr review --commit abc123 --format json --audience agent
# Select or override model for this review
ocr review --model claude-opus-4-6
ocr review --commit abc123 --model claude-sonnet-4-6
# Provide requirement context for more targeted review
ocr review --background "Adding rate limiting to the login API"
# Use custom review rules
ocr review --rule /path/to/my-rules.json
# Preview which rule applies to a file
ocr rules check src/main/java/com/example/Foo.java
ocr rules check --rule custom.json src/main/resources/mapper/UserMapper.xml
# Full-file scan: preview the file list first (no LLM calls)
ocr scan --preview
# Scan the whole repo, cap spend at ~500k tokens
ocr scan --max-tokens-budget 500000
# Scan a subdirectory, skipping generated/test files
ocr scan --path internal --exclude '**/*_test.go,**/generated/**'
# Scan a non-git directory with JSON output (includes project_summary)
ocr scan --repo /path/to/plain/dir --format json
# Fastest scan: skip planning, dedup, and the project summary
ocr scan --no-plan --no-dedup --no-summary
# View review session history in browser
ocr viewer
ocr viewer --addr :3000
Viewer security
The viewer serves session JSONL contents (LLM request messages and responses) over HTTP. It enforces a Host-header allowlist on every request: loopback names (localhost, 127.0.0.0/8, ::1) and the concrete bind host are always allowed. Wildcard binds (--addr :3000, --addr 0.0.0.0:3000) and other non-loopback Hostnames must be added via the OCR_VIEWER_ALLOWED_HOSTS environment variable (comma-separated):
OCR_VIEWER_ALLOWED_HOSTS=review.internal,ocr.lan ocr viewer --addr :3000
This blocks DNS-rebinding attacks against the local viewer.
Review Rules
OCR resolves review rules using a four-layer priority chain. Each layer uses first-match-wins: if a file path matches a pattern, that rule is used; otherwise it falls through to the next layer.
| Priority | Source | Path | Description |
|---|---|---|---|
| 1 (highest) | --rule flag |
User-specified path | CLI explicit override |
| 2 | Project config | <repoDir>/.opencodereview/rule.json |
Per-project rules, can be committed to git |
| 3 | Global config | ~/.opencodereview/rule.json |
User-wide personal preferences |
| 4 (lowest) | System default | Embedded system_rules.json |
Built-in rules covering common languages and file types |
Rule File Format
Layers 1–3 share the same JSON format:
{
"rules": [
{
"path": "force-api/**/*.java",
"rule": "All new methods must validate required parameters for null values",
"merge_system_rule": true
},
{
"path": "**/*mapper*.xml",
"rule": "Check SQL for injection risks, parameter errors, and missing closing tags"
}
]
}
pathsupports**recursive matching and{java,kt}brace expansion.merge_system_ruleis optional. Whentrue, the matched built-in system rule is merged with this user rule; otherwise the user rule replaces the system rule.- Within each layer, rules are evaluated in declaration order — the first match wins.
- If a rule file does not exist, it is silently skipped.
Path Filtering
Rule files also support include and exclude fields to control which files enter the review scope:
{
"rules": [
{"path": "**/*.java", "rule": "Check for null safety"}
],
"include": ["src/main/**/*.java", "lib/**/*.kt"],
"exclude": ["**/generated/**", "vendor/**"]
}
Filter decision priority (highest to lowest):
| Step | Condition | Result |
|---|---|---|
| 1 | File is binary | Excluded |
| 2 | Path matches user exclude pattern |
Excluded |
| 3 | File extension not in supported list | Excluded |
| 4 | include is configured and path matches |
Reviewed (skips step 5) |
| 5 | Path matches built-in default exclude pattern (test files, etc.) | Excluded |
| 6 | None of the above | Reviewed |
How it works:
includeandexcludefollow the same priority chain as review rules (--rule> project config > global config). The highest-priority layer that has include/exclude configured takes effect as a whole — patterns are not merged across layers.excludealways wins overinclude— a file matching both is excluded.includeacts as a bypass for built-in default exclude patterns (e.g., test files), not as an exclusive allowlist — files not matching anyincludepattern still proceed through the default filter checks normally.- Pattern syntax: supports
**recursive matching,*single-segment matching, and{a,b}brace expansion. Matching is case-insensitive.
Built-in default exclude patterns (filters test files, etc. — can be overridden with include):
**/*_test.go, **/*Test.java, **/*Tests.java, **/*_test.rs,
**/*.test.{js,jsx,ts,tsx}, **/*.spec.{js,jsx,ts,tsx}, **/__tests__/**,
**/src/test/java/**/*.java, **/src/test/**/*.kt,
**/test/**/*_test.py, **/tests/**/*_test.py, **/*_test.py,
**/*_spec.rb, **/spec/**/*_spec.rb, **/oh_modules/**
Configuration Reference
Config file: ~/.opencodereview/config.json
| Key | Type | Example |
|---|---|---|
provider |
string | anthropic | openai | dashscope | deepseek | z-ai |
providers.<name>.api_key |
string | Provider-specific API key |
providers.<name>.url |
string | Provider base URL override |
providers.<name>.protocol |
string | anthropic | openai |
providers.<name>.model |
string | Model name for the provider |
providers.<name>.models |
array | Optional provider model list for interactive selection |
providers.<name>.auth_header |
string | x-api-key | authorization |
custom_providers.<name>.* |
— | Same fields as providers.<name>.*, including optional models |
llm.url |
string | https://api.openai.com/v1/chat/completions |
llm.auth_token |
string | sk-xxxxxxx |
llm.auth_header |
string | Anthropic only: x-api-key | authorization |
llm.model |
string | claude-opus-4-6 |
llm.use_anthropic |
boolean | true | false |
language |
string | Any language name, e.g. English, Chinese (default: English) |
telemetry.enabled |
boolean | true | false |
telemetry.exporter |
string | console | otlp |
telemetry.otlp_endpoint |
string | OTLP collector address |
telemetry.content_logging |
boolean | Include prompts in telemetry |
Environment variables take precedence over the config file.
Environment Variables
| Variable | Purpose |
|---|---|
OCR_LLM_URL |
LLM API endpoint URL |
OCR_LLM_TOKEN |
API key / auth token |
OCR_LLM_AUTH_HEADER |
Anthropic auth header (x-api-key or authorization) |
OCR_LLM_MODEL |
Model name |
OCR_USE_ANTHROPIC |
true = Anthropic, false = OpenAI |
Telemetry
OpenTelemetry integration for observability (spans, metrics). Disabled by default.
ocr config set telemetry.enabled true
ocr config set telemetry.exporter otlp
ocr config set telemetry.otlp_endpoint localhost:4317
Set telemetry.content_logging to include LLM prompts and responses in exported data.
Contributing
See CONTRIBUTING.md for development setup, coding guidelines, and how to submit pull requests.
Star History
License
Apache-2.0 — Copyright 2026 Alibaba


