A code reviewer that reads before it comments.
ocra splits a change into focused review tasks. Each agent can only read your repository, has to quote the code it means, and must say what it checked. Most runs end with a handful of findings. Some end with none, and that is fine.
Node 22+, any model OpenCode supports
$ ocra review --from main[ocra] 4 file(s) selected, 1 excluded · risk tier: full[ocra] 2 bundle(s) (grouped)[ocra] 4 review task(s), 2 reviewer/bundle pair(s) skipped by scope[ocra] security-1 completed in 9.2s · 2 finding(s)[ocra] correctness-1 completed in 7.4s · 2 finding(s)[ocra] Verified 3 finding(s), dropped 1 that the code disproves[ocra] Verdict: significant concernssrc/auth/session.tscritical L42 Every session is treated as expired [verified] #a41c9e03isExpired() compares expiresAt in seconds with Date.now() inmilliseconds, so users are logged out right after signing in.Suggestion: return session.expiresAt * 1000 < Date.now();1 finding(s) (1 critical, 0 warning, 0 suggestion) · tokens: 48912 in (31040 cached), 1106 out, 212 reasoning · $0.0412
What happens when you run ocra review
The steps that must not go wrong are plain, tested code. Models are only asked for judgment.
Example run · Changed files
Select
Five files changed. The lock file is set aside with its reason; four are worth reading.
- src/auth/session.ts
- src/auth/token.ts
- src/api/login.ts
- docs/auth.md
- package-lock.jsonlock file, set aside
Binaries, lock files, vendored and generated code, likely secrets and oversized diffs are set aside, each with a recorded reason. Migrations are always kept. A secret can never be opted back in.
Decisions we made on purpose
Each of these costs something. We think the trade is worth it.
- 01
The model never picks the line.
Models are bad at line numbers and good at quoting. So they quote, and ocra finds the lines.
- 02
Reviewers are told what to leave alone.
Style, speculation, missing tests and untouched code are out of scope in every prompt. You get fewer comments, not weaker ones.
- 03
Nothing runs with write access.
Agents can read files, read diffs and search. Editing, shell and network tools are switched off.
- 04
Your machine stays out of the prompt.
Local OpenCode config, installed skills and instruction files are disabled before the first request.
- 05
Every attempt shows its bill.
Input, output, reasoning and cached tokens, with cost, per model call and per run.
- 06
When a model falls over, the next one takes the task.
Give each tier a list of models. Overloads move on to the next model, a model that keeps failing is paused for a while, short rate limits are waited out, and a model out of quota is dropped for the rest of the run.
What a finding looks like
An inline comment on the pull request, with enough to decide in a few seconds whether to fix it or dismiss it. What happens next is up to the code and the reviewers.
github-actionsbot
Every session is treated as expiredcriticalverifiedcorrectness2
isExpired() compares expiresAt in seconds with Date.now() in milliseconds, so every session counts as expired and users are logged out right after signing in.3
Suggestion: return session.expiresAt * 1000 < Date.now();4
Example pull request
The finding stays open on the next push as long as its code is unchanged, even if no reviewer reports it again, so the same code keeps the same verdict.
- 1The line the agent quoted, found in the diff by ocra
- 2Severity, whether the verifier confirmed it, and which reviewer found it
- 3Why it is wrong, in plain words
- 4The smallest fix, when there is one
Your team's rules, as a plugin
The Git and GitHub adapters, the OpenCode runtime and the three reviewers that ship today are plugins too. Yours get the same small contract: register rules, reviewers, tools or listeners, and receive your own settings.
- Three lifecycle hooks, run in a fixed order
- Settings validated per plugin
- Clashing or late registrations fail with the plugin's name
export default { name: "team-rules", configure(ctx) { ctx.registerRules([{ path: "services/**", rule: `${ctx.settings.team}: require idempotency keys`, }]); }, };
Where it stands
M1Local reviewshipped
CLI, selection, bundling, anchoring, the correctness reviewer, OpenCode runtime, plugins, benchmark harness.
M2More reviewersshipped
Security and performance reviewers, a review matrix, verification, a judge and a fixed verdict rubric.
M3GitHubshipped
ocra review --pr and a GitHub Action: inline comments, one summary comment, and re-reviews of only what changed since the last push that resolve fixed threads and respect dismissals.
M4Hardeningshipped
Circuit breakers per model, shared configuration over https, a review memory, and --ultra for recall.
NextMeasured qualityplanned
A baseline of precision and recall on AACR-Bench with a stronger model, then tuning prompts and stages against it.
NextDeeper reviewsplanned
Reviewers for docs and AGENTS.md, a planning phase and caller impact analysis for --ultra, model re-location of hard-to-anchor findings, and the judge reassessing disagreements.
Nextnpm releaseplanned
Publishing the @open-cr-agent packages; today ocra installs from source.
Try it on a repository you know
It runs against any Git repository on your machine, or on pull requests through the GitHub Action. Your model provider sees the change under review and the files the agents open, nothing else.
git clone https://github.com/jma49/Open-CR-Agent.git cd Open-CR-Agent && npm install && npm run build npm link --workspace @open-cr-agent/cli export GEMINI_API_KEY=... cd your-repository && ocra review