Notes · Article
How the Claude Code team reviews code that Claude writes
Claude writes about 90% of Claude Code, and the team still reviews every change. What changed is who does the reading. Claude checks its own work before a pull request exists, a panel of agents reviews every PR, and a person's approval is required only where the risk is. From June to September, merged pull requests more than doubled while the share that had to be reverted fell by more than 40%.
That's from How the Claude Code team does code review, posted on the claude.dev blog on October 15 by Addy Osmani, Morgan Westlee Lunt and Qing Wang. Addy republished it as an X article on October 26. Earlier this month I wrote up another answer to the same problem, Overmind's: review the plan, not the pull request. The Claude Code team kept review after the code. They just stopped treating it as one gate.
Reading every line stopped being the test
When agents write code, the number of changes explodes. In Anthropic's monorepo, changes landing per day went from about 2,500 in May to more than 30,000 in September. Claude Code lives in its own repository, but it's under the same pressure. Nobody reads that line by line.
So the team went back to what review is for. It does two jobs: find and fix problems before they ship, and spread an understanding of the codebase across the team. Most of the post is about the first one.
Their key line is that "did a human read the code?" is an imprecise proxy. The real question is what could go wrong with this change, and which check, automated or human, is the right one to catch it.
That moved review in time too. It used to be a gate at the end of the road: write the code, open a PR, wait for a colleague. Now it runs more like spellcheck while you write. Most changes have been reviewed and fixed by Claude at least once before a person is asked to look.
The goal is concrete. Most PRs in the Claude Code repos (the CLI, the desktop and web apps, the mobile apps) should merge with at most one person in the loop, and that person can be the author. They track human approvals per PR at the median and the 95th percentile, human comments, and how long a PR waits on a person. Reverts and incidents are the guardrail, because human time has two sides: the time spent reviewing, and the time spent fixing what bad code breaks. If reverts go up, they haven't saved time, only moved it.
Before
A gate at the end
- PersonWrites the code
- PersonOpens a pull request
- PersonWaits for a colleague
- PersonReads every line
The questionDid a human read the code?
vs
Now
Spellcheck while you write
- ClaudeChecks and fixes it, at least once
- AgentsReview the pull request
- PersonLooks where the risk is
The questionWhat could go wrong, and which check catches it?
Trackedapprovals per PR, median and p95human commentstime waiting on a person
Guardrailrevert rateincident rate
GoalMost pull requests merge with at most one person in the loop, who can be the author.
Six layers, then rollback
A typical change, from a laptop or a Claude session in Slack, crosses six layers of checks: verification before the PR, required CI, the AI review, a security review, a human approval scaled by risk, and a merge queue with feature flags. Under all of them sits fast rollback.
Each layer catches some problems and misses others. Few get through all six, and rollback handles the rest. Most of the path is automated, and a person's attention goes where the risk is.
Problems in
Verificationbefore the PR
Required CIlint, types, tests, build
AI reviewagents hunt and vote
Security reviewa separate pass
Human approvalnone, one or two people
Merge queue, flagschecks again on main
Fast rollbackflags off, revert
- automated
- a person, scaled by risk
- recovery
- a problem stopped
Before the PR, show the output
Most review now happens before a pull request exists. Claude gets something it can run, like tests, a build or a screenshot to compare against the design, and has to show the output instead of saying it's done. Then a subagent reviews the diff with fresh context. Many people on the team also run internal skills before opening a PR: one hunts for bugs, one simplifies the diff, one checks the behaviour end to end.
Boris Cherny, who created Claude Code, calls giving Claude a way to verify its work probably the most important thing for good results. He estimates it makes the final result two to three times better.
When the reviewer keeps flagging the same thing, the team fixes it at the source: in the skill, with a lint rule, or in two instruction files. CLAUDE.md says what the project is: the stack, the conventions, the goals and the non-goals. Every review loads it, so it stays short and points to other docs. The reviewer also flags code that breaks one of its conventions, and changes that make a line in it out of date.
REVIEW.md is written by code owners, to tell the reviewer what matters in their part of the code, and the team checks separately whether the reviewer follows it. The good ones are short. They say what failure looks like in that repo (for docs it's "it lies", for config it's "it misroutes"), cap the nits, list paths to skip, and ask for a file and line as evidence instead of a guess from a name. They also ask for a summary that starts with a count and says plainly when there's nothing to fix.
1Run it
Tests, a build, or a screenshot against the design
2Show it
The output, not "done"
3Fresh eyes
A subagent reviews the diff with a clean context
Boris ChernyHis estimate: a way to verify its work makes the result two to three times better.
Every review loads it
CLAUDE.md
- The stack and the conventions
- The goals and the non-goals
- Short, pointing to other docs
The reviewer flags code that breaks a convention, and a change that makes a line out of date
and
Code owners write it
REVIEW.md
- What failure looks like here: docs that lie, config that misroutes
- A cap on nits
- Paths to skip
- A file and line as evidence, not a guess from a name
- A summary that starts with a count, and says plainly when there's nothing to fix
Checked separately: does the reviewer follow it?
The reviewer votes before it comments
Every pull request gets a Claude review before a person looks. It reads the diff against the whole repo and the PR's stated intent, and asks whether the change solves its problem, fits the system, or breaks something else. On a bug fix, it looks for the root cause.
Findings get checked before anyone sees them. Several agents hunt for bugs at the same time. A separate group votes on each finding, and it's posted only if enough of them agree it's real. Findings that are only about style, diagnostics or cleanup are dropped; the team A/B tested those filters on its own PRs first. What's left lands as inline comments sorted by severity, each tagged Important, Nit or Pre-existing, so an old bug doesn't look like the author's fault.
When the research preview launched, the share of internal PRs getting substantive review comments went from 16% to 54%. Most PRs over 1,000 lines get findings, and most small ones come back clean. Admins set each repo to Quick, Standard or Deep.
Every finding has to be answered: fix it, or resolve the thread with a reason. A separate security review works the same way, and an open finding from either one blocks the merge. CI blocks too, with dozens of checks on a typical CLI pull request. The PR template asks how the change was tested and how to undo it. Claude can fill that in, but the person who asked for the change signs off on it.
1Hunt
Several agents look for bugs at once
2Vote
Posted only if enough voters agree it's real
3Filter
Style, diagnostics and cleanup dropped
4Post
Inline, sorted by severity
Every findingFixed, or resolved with a reason. An open one from this review or the security review blocks the merge.
The change sets the tier, not the author
A docs fix and an auto-updater change don't carry the same risk, so they don't get the same review. The post has three tiers:
- Low: docs, copy, internal-only features, additive changes behind a flag. No human approval once automated review and security checks are green.
- Medium: ordinary product changes, and sensitive areas like caching, the auto-updater or system prompts. One person.
- High: the highest-risk code, plus a small set of paths that always need two. Two people.
A classifier reads the change and picks the tier. A second classifier asks whether this particular change needs a person even when its tier says it doesn't. Paths that owners list as sensitive, and any CI workflow file, always need a person.
The rules around the table are what make it hold. Only authors on the repo's trusted list get the lighter paths; everyone else needs a second person. An agent's approval never counts as a person's. Whoever prompted an agent-written PR counts as one of its required reviewers, as if they'd typed the code. And an approval covers one commit: an agent's push, or a merge someone resolved by hand, needs a new one.
Low
No person
once automated review and security checks are green
Docs, copy, internal-only features, additive changes behind a flag
Medium
One person
Ordinary product changes, and sensitive areas: caching, the auto-updater, system prompts
High
Two people
The highest-risk code, and a small set of paths that always need two
Sets the tierThe change, read by a classifier. A second one asks if it needs a person anyway.
Always a personPaths that owners list as sensitive, and any CI workflow file
An agent's approvalNever fills a person's slot
One approval coversOne commit. An agent's push or a merge resolved by hand needs a new one.
On the hookOn an agent-written PR, the person who prompted it is one of the required reviewers.
Incidents are the test set
The team built the reviewer's test set from real failures. They collected past PRs that caused incidents, with their fix-forwards and reverts, and had engineers who know that code confirm each bug and where it lived. The reviewer runs against that set every day. Each new incident adds a case, and every change to the reviewer's prompts, tools or model is scored against all of them.
Catching more bugs is easy if you don't mind flagging non-bugs, so they measure noise too. Every comment is sorted by what the person on the PR did with it: fixed it, said it was wrong, said the behaviour was intentional, or decided it didn't matter. They also run the reviewer on PRs known to be clean, and count the reports that would have led someone to make a harmful change. The priority is written down: real bugs first, fewer review rounds second.
The set grows
- Incident or revertA change that broke something
- Expert-checkedEngineers who know the code confirm the bug and where it lived
- Added to the setOne case per incident
Every case, every day
The reviewer changes
- Change the reviewerIts prompts, tools or model
- Daily eval runScored against every case
- Score went up?Keep it. If not, drop it.
Noisefixed itsaid it was wrongintentionaldidn't matter
PriorityReal bugs first, fewer review rounds second. Written down.
Review has to converge
Noise costs more when the author is an agent. A person waves off a nit in seconds. An agent fixes it, which means another commit and another round of review. An agent author and an agent reviewer can keep each other busy forever: one CLI pull request went through more than fifty rounds overnight before its author stopped it.
When the team ran git blame on what the reviewer kept flagging, about 59% of it was code that had been there since the reviewer's first pass. It wasn't finding new bugs. It was finding a few more old ones each round. They'd made it worse themselves, by running several rounds by default because each pass catches something new.
So they changed re-review:
- A round cap. After three rounds, the reviewer asks the author to step back and reconsider the approach.
- Diff-only re-review after the first few passes.
- Flag the class of bug, so the author fixes every instance, not one line.
- No repeats of findings already posted.
Old bugs still get hunted, just not on your PR: review agents also run nightly over existing code. After the change, PRs passing after one review-and-fix round went from 65% to 78%, PRs needing five or more rounds fell from 8.9% to 1.5%, and the mean number of reviews to pass fell from 2.08 to 1.32.
01A round cap
After three rounds, step back and rethink the approach
02Diff only
After the first few passes, review just the new diff
03The class of bug
So the author fixes every instance, not one line
04No repeats
A finding already posted isn't posted again
OvernightOne CLI pull request went more than fifty rounds before its author stopped it.
People keep five jobs
Pulling a senior engineer out of deep work to catch a routine mistake costs far more than an automated review. So people keep the jobs only people can do:
- Deciding whether to build it at all: direction, taste and scope. One team that declared its review bottleneck solved still keeps human review for changes from outside the team, so someone asks whether the change should exist.
- Reviewing risky code like billing, the auto-updater and CI workflows.
- Reviewing architecture that sets a pattern others will copy.
- Reading the evidence: test output, the command that ran and what it returned, a screenshot, the reviewer's findings.
- Owning the outcome. A person is accountable for every change that ships, whoever typed it.
The evidence job comes with a rule worth stealing: "If you can't say what the checks would miss, ask for a real review rather than a quick approval."
- Whether to build itDirection, taste and scope
- Risky codeBilling, the auto-updater, CI workflows
- ArchitectureChoices that set a pattern others copy
- The evidenceTest output, the command and what it returned, a screenshot, the findings
- The outcomeA person answers for every change that ships, whoever typed it
The ruleIf you can't say what the checks would miss, ask for a real review rather than a quick approval.
You land it, you own it
Review's second job was spreading context. Reading a teammate's diff is how you learn the code. The team has no formal replacement, and says nobody keeps a complete model of Claude Code in their head, or needs to. When someone needs a part of the codebase, they ask Claude for an explainer of exactly that slice. It takes minutes and matches the code as it is today. A one-line copy change teaches you almost nothing. An explainer for the module you're about to change teaches you a lot.
Ownership works the same way. If you land a small or medium change and it breaks, you usually fix it. That doesn't go badly because changes are small, flags and reverts and staged releases undo most mistakes in minutes, the blast radius sets the bar, regressions show up fast in telemetry and internal use, and incident reviews look at the system, not the person.
Cheap code also makes it cheap to change course. When someone in the channel points at an earlier decision or a simpler route, the author closes or reshapes the PR, and it doesn't feel like a loss. The trick is to raise it early in the thread, not as a blocking comment on a finished PR.
Learning the code, before
Read the diffs
A one-line copy change teaches almost nothing
vs
Learning the code, now
Ask for an explainer
Exactly the slice you're about to change, in minutes, as the code is today
Owning it works becausesmall changeseverything reversibleblast radius sets the barregressions surface fastno blame
Changing courseRaise it early in the thread, not as a blocking comment on a finished PR.
Next to my own loop
My loop is on How I work with AI: an issue first, an agent builds on its own branch, it proves the change works, a model from another vendor gives a second opinion, and a pull request closes it. Two of my rules there say what this post says. "Check what the model produced, not what it says it did" is their "show the output instead of saying it's done". "An empty review is not a pass" is their REVIEW.md asking for a summary that says plainly when there's nothing to fix.
My Forge pipeline already caps rounds harder than they do. A blocking finding from its reviewer gets one more fix, then the pull request opens. That's in the OpenShell note.
The difference is the last step. On that page every change ends as a pull request I read and merge, and in my software factory note the slow part of my setup is my review queue. Their tier table is aimed right at that: a docs fix needs nobody once the checks are green, and a person's time goes to billing, CI and the auto-updater.
Proof first
The teamClaude shows the output: tests, a build, a screenshot
MeBuild and tests, screenshots in a real browser at 320 px and on desktop
AI review
The teamClaude agents hunt, vote, then post by severity
MeA model from another vendor reviews the change
Nothing found
The teamThe summary says so plainly, with a count
MeAn empty review is not a pass
Rounds
The teamThree, then rethink the approach
MeForge: one more fix after a blocking finding
Who approves
The teamThe change sets the tier: no one, one or two people
MeEvery pull request, me
My queueThe last row is where it builds up. The tier table is the piece aimed at it.
Try it
The post ends with a checklist, and most of it works with tools you already have:
- Before the PR: give your agent checks it can run, listed in a short
CLAUDE.md, plus hooks for formatters and linters. Run/code-reviewand/security-reviewlocally, or a fresh-context subagent. Start aREVIEW.mdand move repeated comments into it. - On every PR: require CI, add Testing, Risk and How to revert to the PR template, put an AI reviewer on one repo and tune
REVIEW.mdfor a few weeks before widening it, and require every review thread resolved. Cap the rounds, and re-review only the new diff after the first few. - Approval: write down risk tiers set by the change, start strict and loosen with evidence. Use CODEOWNERS and branch protection so auth, billing, CI, release workflows and installers always need a person. Never let a bot's approval fill a human slot, and dismiss approvals on new commits.
- After the merge: a merge queue, feature flags, internal use first, staged releases and a one-step rollback. Turn incidents and reverts into an eval set, and measure human time with reverts as the guardrail.
1Before the PR
- Runnable checks in a short CLAUDE.md
- Hooks for formatters and linters
- /code-review and /security-review locally
- A REVIEW.md for repeated comments
2On every PR
- Required CI
- Testing, Risk and How to revert in the template
- An AI reviewer on one repo first
- Every thread resolved, rounds capped
3Approval
- Tiers set by the change, strict first
- CODEOWNERS for auth, billing, CI, release, installers
- Bot approvals never count
- Dismissed on new commits
4After the merge
- Merge queue and feature flags
- Internal users first, then staged
- One-step rollback
- Incidents and reverts as the eval
MeasureHuman time per change, with reverts and incidents as the guardrail.
If you want more:
- How the Claude Code team does code review, the post, 14 minutes
- Addy Osmani's X article, the same post, rewritten
- Code Review for Claude Code, the docs
- Claude Code best practices, where the verify-your-work habit comes from
- Review the plan, not the pull request, Overmind's answer to the same problem
Pick one piece this week, a REVIEW.md or a round cap, and tell me what it does to your review queue.
Plain text: claude-code-team-code-review.md · Atom feed · All notes