Brahim Bousnguar

Notes · Article

How the Claude Code team reviews code that Claude writes

By · · 12 min read

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

  1. PersonWrites the code
  2. PersonOpens a pull request
  3. PersonWaits for a colleague
  4. PersonReads every line

The questionDid a human read the code?

vs

Now

Spellcheck while you write

  1. ClaudeChecks and fixes it, at least once
  2. AgentsReview the pull request
  3. 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.

The same change, reviewed at the end or all the way through. The marker rows are where a person reviews. The goal and the numbers that track it are the team's own.

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.

  • automated
  • a person, scaled by risk
  • recovery
  • a problem stopped
The post's own picture is layers, not one gate. Which layer stops which problem is a schematic: it gives no counts per layer.

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.

  1. 1Run it

    Tests, a build, or a screenshot against the design

  2. 2Show it

    The output, not "done"

  3. 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?

Proof before review, then the two files a repeated finding goes into. The REVIEW.md lines are the post's description of a good one.

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.

  1. 1Hunt

    Several agents look for bugs at once

  2. 2Vote

    Posted only if enough voters agree it's real

  3. 3Filter

    Style, diagnostics and cleanup dropped

  4. 4Post

    ImportantNitPre-existing

    Inline, sorted by severity

Internal PRs with substantive review comments

Before the research preview16%

With Code Review54%

Every findingFixed, or resolved with a reason. An open one from this review or the security review blocks the merge.

The squares are a schematic: the post gives no counts per step. The two bars are to scale on a 0 to 100% axis.

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.

The tier table from the post, then the rules around it. Only authors on a repo's trusted list get the lighter paths.

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

  1. Incident or revertA change that broke something
  2. Expert-checkedEngineers who know the code confirm the bug and where it lived
  3. Added to the setOne case per incident

Every case, every day

The reviewer changes

  1. Change the reviewerIts prompts, tools or model
  2. Daily eval runScored against every case
  3. 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.

Incidents feed the set, the set scores every change to the reviewer, and what people do with the comments keeps the noise in check.

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:

  1. A round cap. After three rounds, the reviewer asks the author to step back and reconsider the approach.
  2. Diff-only re-review after the first few passes.
  3. Flag the class of bug, so the author fixes every instance, not one line.
  4. 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.

  1. 01A round cap

    After three rounds, step back and rethink the approach

  2. 02Diff only

    After the first few passes, review just the new diff

  3. 03The class of bug

    So the author fixes every instance, not one line

  4. 04No repeats

    A finding already posted isn't posted again

Pass after one review and fix round

Before65%

After78%

Need five or more rounds

Before8.9%

After1.5%

Mean reviews to pass

Before2.08

After1.32

OvernightOne CLI pull request went more than fifty rounds before its author stopped it.

The four changes, then the team's internal numbers before and after. Each pair of bars is to scale against its larger value.

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."

  1. Whether to build itDirection, taste and scope
  2. Risky codeBilling, the auto-updater, CI workflows
  3. ArchitectureChoices that set a pattern others copy
  4. The evidenceTest output, the command and what it returned, a screenshot, the findings
  5. 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.

What stays with people once the routine reading moved to machines, in the post's order.

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.

A diff where one line changed, next to an explainer of the part you're about to touch.

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.

Their layers next to my loop as it's written on /ai.html. The marker row is the one that differs.

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-review and /security-review locally, or a fresh-context subagent. Start a REVIEW.md and 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.md for 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.
  1. 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
  2. 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
  3. 3Approval

    • Tiers set by the change, strict first
    • CODEOWNERS for auth, billing, CI, release, installers
    • Bot approvals never count
    • Dismissed on new commits
  4. 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.

The checklist from the end of the post, shortened. The order is theirs.

If you want more:

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

Contact

Say hello.

b.bousnguar@gmail.com

SAP Commerce Cloud, MuleSoft and Salesforce integration · Nantes · EN / FR