Claude Code 团队如何做代码审查
How the Claude Code team does code review
Anthropic 的 Claude Code 团队公开了其代码审查流程:从 6 月到 9 月,合并的 PR 数量翻倍以上,而需要回滚的比例下降超过 40%。流程分六层,包括提交前让 Claude 自验证、每个 PR 由 Claude 先审、可阻断的安全审查、自动化检查、按风险分级的人工批准和合并队列,多数 PR 最多只需一名人工参与。
Anthropic 团队公开了六层自动化代码审查流程与风险分级规则,可迁移到自建 Agent 工作流。
我们之前说过,Claude 编写了 Claude Code 自身约 90% 的代码。那么,在如此庞大的产出量下,我们如何审查代码?现在还有人读代码吗?如果出了问题,谁来发现?
这篇文章介绍了 Claude Code 团队的代码审查流程及其演变过程。从六月到九月,合并到 Claude Code 代码库的拉取请求数量翻了一倍多,而需要回滚的比例下降了 40% 以上。
我们并没有取消审查。但我们把大部分阅读工作交给了机器,以优化人类的时间和注意力,并大力投入让撤销错误变得快速而简单。
重新思考代码审查的目的
当智能体编写代码时,变更数量会迅速增长。在 Anthropic 的 monorepo 中,每天落地的变更从今年五月的约 2,500 个增加到九月的 30,000 多个。
Claude Code 位于独立的代码库中,与 monorepo 分开,但它也面临着巨大的压力。当你以如此快的速度交付时,手动逐行审查代码即使并非不可能,也是极其困难的。
代码审查有两个作用:
- 在发布前发现并修复问题
- 在团队中建立共享背景和代码库理解
本文主要关注发现和修复问题,但我们会在结尾回到第二个作用。
我们认为,“是否有人读过代码?”并不能精确地代表“这个变更可能出什么问题,哪种检查——自动的还是人工的——才是发现它的正确方式?”
提出这个问题也改变了审查发生的时机。以前,审查是道路尽头的关卡:写代码、开 PR、等同事。
现在,审查持续进行,更像是写作时的拼写检查。大多数变更在请求人工查看之前,已经由 Claude 至少审查和修复过一次。这能捕获大多数常规错误,并将团队注意力留给更高层次的问题和审查。
稀缺资源:人类的时间和注意力
我们希望将人类的时间和注意力保留给只有人类才能解决的问题,并确保自动化检查能捕获其余问题。以我们目前的变更速度,人类仍有大量工作要做,我们的团队几乎每天都会遇到新的、前所未有的挑战。
人类时间涵盖审查成本的两个方面:人们花在审查上的时间,以及他们花在修复劣质代码所造成问题上的时间。如果削减前者只是把时间转移到后者,那就没有帮助。
因此,目标是 Claude Code 代码库(CLI、桌面和 Web 应用以及移动应用)中的大多数拉取请求在合并时,最多只需一个人参与,这个人可以是作者,且回滚或事故不增加。为了衡量人类时间,我们追踪每个 PR 的人工批准数(中位数和第 95 百分位数)、人工评论数,以及 PR 等待某人的时长。回滚率和事故率是护栏:如果它们上升,我们就没有节省人类时间,只是转移了它。
一次变更的生命周期
一次典型的变更,从工程师的笔记本电脑(或 Slack 中的 Claude 会话)出发,经过多层代码审查。
一次变更的生命周期
一次典型的 Claude Code 变更,从作者的机器到用户
逐层解析
层层把关,而非单一关卡
六层检查,其下还有回滚机制
1. 工作成果在任何人查看之前就已得到验证
如今大多数审查都发生在 PR 存在之前。我们给 Claude 一些它可以运行的东西——比如测试、构建,或一张用来与设计稿对比的截图——并要求它展示输出结果,而不是只说完成了。然后一个子代理会用全新的上下文审查 diff。这两个习惯都来自我们的最佳实践指南。
在打开 PR 之前,我们中的许多人还会运行一些内部技能:一个查找 bug,一个简化 diff,还有一个做端到端的行为检查。UI 改动也会对照我们的设计准则进行检查。
创建 Claude Code 的 Boris Cherny 曾说,给 Claude 一种验证其工作成果的方式,是获得好结果的最重要的事情。他估计这能让最终结果好上两到三倍,并写道:“验证在每个领域看起来都不一样。它可能简单到运行一条 bash 命令,或运行一套测试,或在浏览器或手机模拟器中测试应用。”
当自动审查器反复标记同一个问题时,我们从源头修复它:在技能中、用 lint 规则,或更新诸如以下的指导文件:
CLAUDE.md告诉 Claude 这个项目是什么:技术栈、约定、目标和非目标。每次审查都会加载它,所以在大型代码库中我们保持它简短,并从那里指向其他文档。审查器还会标记违反其中约定的代码,以及让其中某一行过时的改动。REVIEW.md由代码所有者编写,告诉审查器在他们那部分代码中什么才是重要的。我们会单独检查审查器是否真的遵循它。好的那些都很简短。它们说明在那个仓库中失败是什么样子(对文档来说是“它在撒谎”,对配置来说是“它路由错了”),限制琐碎意见的数量,列出要跳过的路径,并要求以文件和行号作为证据,而不是凭名字猜测。它们还要求一份以计数开头的摘要,并在没有需要修复的内容时明确说明。
2. 每个拉取请求都进行 AI 审查
每个拉取请求在有人查看之前都会先得到一次 Claude 审查。它会对照整个仓库和 PR 声明的意图来阅读 diff,并追问:这个改动解决了它的问题吗,契合系统吗,还是破坏了别的东西?
对于 bug 修复,它会寻找根本原因。公开版本 Code Review for Claude Code 现已在 Team 和 Enterprise 计划上全面可用,而 /code-review 在本地运行一个更轻量的版本。
当我们推出研究预览版时,获得实质性审查评论的内部 PR 比例从 16% 上升到 54%。大多数超过 1,000 行的 PR 都能得到发现,而大多数小的 PR 则干净通过。管理员可以将每个仓库设置为 Quick、Standard 或 Deep。在漏掉一个 bug 的代价高于额外审查时间的地方,Deep 是值得的。
发现的问题在人类审查之前会由其他代理验证。多个代理同时查找 bug。然后一个单独的小组对每个发现进行投票,只有当足够多的代理同意它是真实的时,它才会被发布。仅涉及风格、诊断或清理的发现会被丢弃。我们在自己的 PR 上对这些过滤器做了 A/B 测试后才保留它们。剩下的会以按严重程度排序的行内评论形式出现。每条都被标记为 Important、Nit 或 Pre-existing,这样 PR 没有引入的 bug 就不会看起来像是作者的错。
每个发现都必须得到回应。你要么修复它,要么给出理由关闭该讨论串。通常智能体会在夜间接手修复,所以作者回来时会看到一个已经过另一轮处理的 PR。
3. 可阻止合并的安全审查
安全也有自己的自动审查。只要 bug 审查或安全审查中还有任何未解决的发现,PR 就不能合并。你要么修复它,要么用简短的理由关闭讨论串,这就是清除误报的方式。
如果后续提交修复了该问题,该发现会自动清除。你可以用开源安全审查 GitHub Action 或 /security-review 命令设置同样的机制。设置方法见 Claude Code 中的自动安全审查。
4. 可阻止合并的自动化检查
常规的那些:lint、类型检查、各平台上的测试,以及构建。(我们写过如何为这种规模扩展 CI,见此处。)一个典型的 CLI pull request 在任何人查看之前可能会运行几十项检查。PR 模板会询问该变更如何测试以及如何撤销。Claude 可以填写这些内容,但提出该变更的人要签字确认。
5. 按风险分级的人工批准
文档修复和自动更新器变更的风险不同,因此审查方式也不同。
| 风险 | 示例 | 人工批准 |
|---|---|---|
| 低 | 文档、文案、仅内部功能、标志位后的增量变更 | 一旦自动审查和安全检查通过,无需批准 |
| 中 | 普通产品变更,以及对缓存、自动更新器或系统提示等敏感区域的变更 | 一人 |
| 高 | 最高风险的代码,以及一小部分始终需要两人的路径 | 两人 |
变更本身决定层级,而非作者。一个分类器读取变更并选择其风险层级。第二个分类器询问该特定变更是否需要另一个人,即使其层级表明不需要。某些路径始终需要一个人,包括所有者列为敏感的任何内容以及任何 CI 工作流文件。
只有受信任的作者才能走更轻的路径。只有仓库受信任列表上的作者才能走更轻的路径,主要是拥有该仓库的团队。其他所有人都需要第二个人批准。智能体的批准也永远不算作人的批准。自动审查可以清除低风险变更,但无法填补需要人工的位置。
谁提示了该变更,谁就要对它负责。在智能体编写的 PR 上,指导智能体的人算作所需审查者之一,就像他们自己输入了代码一样。
一次批准只覆盖一个特定提交。如果新提交落地且系统无法为其担保,例如智能体的推送或有人手动解决的合并,则必须重新批准。
6. 合并队列、标志位和渐进式发布
合并队列会在应用变更的情况下针对 main 重新运行所有检查,因此两个单独通过的 PR 不会合并成一个损坏的 main。新行为通常先通过标志位发布给 Anthropic 员工,我们的重度使用往往会在用户之前发现回归。公开发布先进入 latest 渠道。stable 渠道随后跟进。
7. 快速检测,快速回滚
有些错误仍会漏过,所以最后一层是关于快速捕获它们。标志位无需部署即可关闭。Claude Code 有每周轮值的 on-call,事故复盘会询问哪一层本应捕获该问题。
发现糟糕的合并仍然依赖于作者和值班人员,以及回滚和事故仪表盘。我们还没有在那些数字变动时收紧审批的熔断机制;这里的工程师希望在更多代码转向零人工合并之前拥有它们。
一位同事说,放慢速度确实会降低错误率,但主要是因为你在所有事情上做得更少了。我们更愿意在发现和解决问题上变得更快。
我们如何让审查者变得更好
我们的代码审查流程在一个循环中不断改进。
任何事故现在都成为一项评估。团队收集了过去导致事故的 PR,连同它们的修复推进和回滚,并让了解那段代码的工程师确认每个 bug 及其所在位置。审查者每天针对该集合运行。
我们的事故就是评估集
由过去的事故和回滚构建,每天运行
我们通过观察人们如何处理评论来衡量噪音。如果你不介意标记大量非 bug,就很容易捕获更多 bug,所以我们需要对此进行检查。我们根据 PR 上的人如何回应来对审查者留下的每条评论进行分类:他们修复了它、说它是错的、说该行为是有意为之,或决定它无关紧要。我们还在已知干净的 PR 上运行审查者,并统计它报告会导致某人做出有害更改的情况的频率。我们写下来的优先事项是:首先捕获真正的 bug,其次减少审查轮次。
当作者是智能体时,噪音的代价更高。人可以几秒钟内挥开一个吹毛求疵的意见。智能体会修复它,这意味着又一次提交和又一轮审查。
审查必须收敛。智能体作者和智能体审查者可以让彼此无限忙碌。一个 CLI PR 在一夜之间经历了五十多轮审查和修复,直到其作者叫停。
当我们对审查者不断标记的内容运行 git blame 时,大约 59% 是自审查者第一遍以来就存在的代码。审查者很少发现新 bug,它每轮都在发现一些更旧的 bug。
我们自己让它变得更糟。我们已经习惯于默认运行几轮,因为每一遍都会捕获一些新东西。这在有风险的更改上可能值得,但不是每个 PR 都值得。团队现在将通过轮次与召回率一起跟踪,并改变了重新审查:
- 轮次上限。三轮之后,审查者要求作者退后一步,重新考虑方法。
- 仅差异重新审查,在前几遍之后。
- 标记 bug 类别,以便作者修复每个实例,而不是一行。
- 不重复已发布的发现。
审查智能体还会每晚对现有代码运行,帮助我们在旧 bug 出现在其他地方之前捕获它们。
收敛的审查
内部拉取请求,在收敛更改之前和之后
人类留在环中的地方
把一位资深工程师从深度工作中拉出来去捕获一个常规错误,代价远高于自动化审查。在 Anthropic,我们的工作已从阅读每个差异转变为机器不擅长的决策:
- 我们到底该不该做这件事?方向、品味和范围。一个宣称已解决审查瓶颈的团队,对于来自团队外部的变更仍然保留人工审查,所以有人会问“我们到底该不该做这件事?”
- 有风险的代码,例如计费、自动更新器和 CI 工作流。
- 架构,它会树立一个别人会效仿的模式。
- 阅读证据。测试输出、运行的命令及其返回结果、截图、审查者的发现。如果你说不出这些检查会漏掉什么,那就要求一次真正的审查,而不是快速批准。
- 对结果负责。每一个上线的变更都由某个人负责,无论代码是谁敲的。
由人做决定的地方
五项决定仍由人来做;其余所有地方都运行检查
在团队中共享上下文
代码审查的第二项职责一直是传播对代码库的理解。阅读队友的 diff 是你了解改了什么、各部分如何拼合的方式。如果大部分阅读都由机器完成,那大家还怎么学习代码?
我们没有为此设立正式流程。团队里没有人脑中保有 Claude Code 的完整心智模型,我们也认为没人需要这样。当有人想理解代码库的某一部分时,他们会请 Claude 专门为那一块写一份讲解。这只需几分钟,而且反映的是代码当下的样子。

我们中有些人更进一步,让 Claude 构建一个小型产物,把那部分代码可视化,并按那个人喜欢的学习方式来讲解。
如果目标是把人的注意力花在刀刃上,这比逐行阅读琐碎的 diff 要好。改一行文案几乎学不到什么。为你即将修改的模块写一份讲解则能学到很多。我们默认在公开 Slack 频道里工作的文化也有帮助,因为你能在别人构建时看到他们在做什么。
“你合入,你负责”
如果你合入了一个小型或中型变更,而之后仍然出了问题,团队惯例通常是由你来修复。有几件事能防止这变得糟糕:
- 变更很小,所以容易审查、调试和回滚。
- 一切都是可逆的。功能开关、回滚和分阶段发布能在几分钟内撤销大多数错误。
- 影响范围决定门槛。代价高昂的代码需要更多人、更多检查。
- 回归问题会很快浮现,通过遥测和内部使用。
- 这不是追责。负责修复意味着你掌握最多上下文;事故复盘看的是系统。
责任也是共享的。团队中很多人都在公开频道里工作,任何人都能看到别人在构建什么、接上一个话题,或让 Claude 去填补某个缺口,反馈也来自并不拥有这段代码的人。这种开放性是质量得以保持高水平、而无需对每一行都设关卡的重要原因。
当我们改变方向时
智能体让启动事情变得很便宜,所以有些工作不该合入。通常频道里会有人问为什么、指出早先的决定,或建议一条更简单的路径,然后作者关闭或重塑这个 PR。
既然代码写得很快,关闭 PR 并不会让人觉得是损失。诀窍是在话题里尽早提出不同的方向,而不是在已完成的 PR 上作为阻塞性评论提出。
你如何采用这套流程
与你的团队一起做这件事所需的大部分组件如今都已具备。
在拉取请求之前
- 给你的 agent 提供它可以运行的检查项,列在一个简短的
CLAUDE.md中,再加上运行格式化和 linter 的 hooks。 - 在本地运行
/code-review和/security-review,或进行一次全新上下文的子 agent 审查。 - 添加一个
REVIEW.md,并把重复出现的审查意见移入其中。
在每个 pull request 上
- 要求 CI,并把 "Testing"、"Risk" 和 "How to revert" 加入你的 PR 模板。
- 在一个仓库上添加 AI 审查者(Code Review for Claude Code,或 Claude Code GitHub Action),用几周时间调优
REVIEW.md,然后再扩大范围。 - 添加自动化安全审查,并要求在合并前解决每个审查线程。
- 让审查力度与风险匹配:对常规变更快速过一遍,对漏掉 bug 代价高昂的地方深入审查(Code Review 中的 Quick、Standard 或 Deep)。
- 限制审查轮数;在最初几轮之后,只重新审查新的 diff。
批准
- 写下风险层级,根据变更而非作者来设定;从严开始,有证据后再放宽。
- 对你信任的作者保留更轻量的批准路径。
- 使用 CODEOWNERS 和分支保护,让 auth、billing、CI 和发布工作流以及安装程序始终需要人工介入。
- 绝不让 bot 的批准替代必需的人工批准;在新提交上撤销批准。
合并及之后
- 使用 merge queue、feature flags、先内部使用、分阶段发布和一步回滚。
- 把事故和回滚转化为 eval set,并在审查者的 prompts、工具或模型变化时重新评分。
- 衡量人工时间,以回滚率和事故率作为护栏。
未来走向
Code Review 的 announcement 表示,批准 pull request 仍是人工决定;该产品发布的是发现,而非批准。我们自己的仓库走得更远,让 owner 决定哪些低风险变更仅凭自动化检查即可合并,而这条界线还在不断移动。
当审查漏掉某些东西时,我们会问模型当时眼前没有什么,并把修复放入 CLAUDE.md、skill 或新的检查中。目标没有改变:每次变更花费更少的人工时间,且回滚不比以前更多。
如果你的团队让 agent 打开 pull request,我们想听听你自动化了哪些检查、哪些仍需要人工,以及你认为我们哪里做错了。
感谢 Emma Webb、Michael Segner 和 Amie Rotherham 的审阅。
来源:Claude.dev 开发者博客 · claude.dev