工程 · CLAUDE
Claude Code 团队如何进行代码审查
当智能体以这种规模产出代码时,如何审查代码?在 Claude Code 团队,当我们实现高覆盖率和深入审查后,就开始优化人工审查时间,目标是在不增加回滚或事故的前提下将人工审查时间降至最低。
原作者/来源:claude.dev
原文链接:https://claude.dev/blog/solving-code-review-at-anthropic/
当智能体以这种规模产出代码时,如何审查代码?在 Claude Code 团队,当我们实现高覆盖率和深入审查后,就开始优化人工审查时间,目标是在不增加回滚或事故的前提下将人工审查时间降至最低。
我们之前说过,Claude 编写了 Claude Code 自身约 90% 的代码。那么,面对我们产出代码的数量,要如何审查代码?现在还有人读代码吗?如果出了问题,谁来发现?
这篇文章介绍 Claude Code 团队的代码审查流程,以及它如何演变。从 6 月到 9 月,合并到 Claude Code 代码库中的拉取请求数量翻了一倍以上,而需要回滚的比例下降了 40% 以上。
我们并没有取消审查。但我们确实把大部分阅读工作转交给了机器,优化了对人类时间和注意力的使用,并投入大量精力,让错误能够快速、轻松地撤销。
重新思考代码审查的目的
当智能体编写代码时,变更数量会迅速增加。在 Anthropic 的单体代码库中,每天落地的变更从今年 5 月的大约 2,500 个,增加到 9 月的 30,000 多个。Claude Code 使用自己的独立代码库,与单体代码库分开,但它也面临很大的压力。当你以这样的速度交付时,手动逐行进行代码审查会非常困难,甚至不可能。
代码审查承担两项工作:
- 在问题发布前发现并修复它们
- 在团队中建立共享上下文和对代码库的理解
本文主要关注发现和修复问题,但我们会在接近结尾时再回到第二项工作。
我们认为,“是否有真人读过代码?”并不能准确代表“这项变更可能会出什么问题,哪种检查——自动检查还是人工检查——最适合发现它?”
提出这个问题也改变了审查发生的时机。过去,审查是道路尽头的一道关卡:写代码、开一个 PR、然后等同事审查。
现在,审查会持续运行,更像是你写作时的拼写检查。大多数变更在交由人查看之前,至少已经由 Claude 审查并修复过一次。这能发现大多数常见错误,也能把团队的注意力留给更高层面的问题和审视。
稀缺资源:人的时间和注意力
我们希望把人的时间和注意力留给只有人才能解决的问题,并确保自动化检查捕获其余问题。以我们目前的变更速度,人仍有大量工作要做,而且我们的团队几乎每天都会遇到新的、前所未有的挑战。
人的时间涵盖审查成本的两面:人们花在审查上的时间,以及他们花在修复糟糕代码所导致的问题上的时间。如果削减了前者,却只是让时间转移到后者,并没有帮助。
因此,我们的目标是:Claude Code 各代码库(CLI、桌面和 Web 应用,以及移动应用)中的大多数拉取请求,在至多一名人类参与环节的情况下合并,这个人可以是作者本人,同时回滚或事故不增加。为了衡量人的时间,我们跟踪每个 PR 的人工审批数(中位数和第 95 百分位数)、人工评论数,以及 PR 等待某个人处理的时长。回滚率和事故率是护栏:如果它们上升,我们就没有节省人的时间,只是把时间挪到了别处。
一项变更的生命周期
一项典型变更从工程师的笔记本电脑(或 Slack 中的 Claude 会话)开始,会经过多层代码审查。
一项变更的生命周期

一项典型的 Claude Code 变更,从作者的机器一路到达用户
拉取请求之前
- 验证工作:Claude 运行测试、构建和代码检查器;另一个智能体在全新的上下文中审查差异。
每个拉取请求都要经过
- 必需的 CI:在各个平台上运行代码检查、类型检查、测试,以及构建和打包。检查失败就会阻止合并。
- Claude 代码审查:多个智能体并行查找缺陷,验证器对每项发现进行投票,保留下来的发现按严重程度排序。
- 安全审查:单独进行一轮审查。任一审查中的待处理发现都会阻止合并。
- 按风险审批:分类器确定风险等级:无需人工、需要一人或需要两人。某些路径始终需要人工审查。
合并时
- 合并队列:在最新的 main 上应用这项变更后,再次运行检查。
合并之后
- 先在功能开关后启用,在内部使用:Anthropic 员工先运行它,然后才会向所有人开放。
- 逐步发布:先进入最新频道;稳定频道稍后跟进。
- 观察、向前修复或回滚:作者和当班人员负责观察;功能开关可以快速关闭,损坏的构建会被回滚。
自动化检查 由人做决定,按风险扩大覆盖 恢复
图 A 大部分流程都是自动化的;人的注意力会投向风险所在之处。
逐层检查
多层检查,而不是一道关卡

六层检查,底层是回滚
- 验证中的问题
- 必需的 CI
- AI 审查
- 安全审查
- 人工审批
- 合并队列 + 功能开关
- 快速回滚
图 B 每一层都会发现一些问题,也会漏掉另一些问题。只有少数问题能通过所有层级,回滚则负责处理其余问题。
1. 在其他人查看之前先验证工作
现在,大部分审查发生在 PR 出现之前。我们会给 Claude 一些它可以运行的检查——比如测试、构建,或与设计进行对比的截图——并要求它展示输出,而不是只说自己已经完成。然后,另一个子智能体会在全新的上下文中审查差异。这两种做法都来自我们的最佳实践指南。
在打开 PR 之前,我们中的许多人还会运行几个内部技能:一个负责查找缺陷,一个负责简化差异,还有一个负责端到端检查行为。UI 变更也会根据我们的设计指南进行检查。
Claude Code 的创建者 Boris Cherny 曾表示,让 Claude 能够验证自己的工作,可能是获得良好结果最重要的事情。他估计,这能让最终结果提升两到三倍。他写道:“验证方式因领域而异。它可能只是运行一条 bash 命令、运行一个测试套件,或是在浏览器或手机模拟器中测试应用。”
当自动审查器反复指出同一件事时,我们会从源头解决:在技能中、通过 lint 规则,或更新说明文件,例如:
CLAUDE.md 告诉 Claude 项目是什么:技术栈、惯例、目标和非目标。每次审查都会加载它,因此在大型代码库中,我们会让它保持简短,并从中指向其他文档。审查器也会标记违反其中惯例的代码,以及会让其中某一行内容过时的变更。
由代码负责人编写的 REVIEW.md 会告诉审查器,他们负责的代码部分有哪些重要事项。我们会单独检查审查器是否真的遵循了它。好的 REVIEW.md 很简短。它们会说明在该代码库中什么情况算失败(对于文档来说是“内容不实”,对于配置来说是“路由错误”),限制琐碎意见的数量,列出应跳过的路径,并要求提供文件和行号作为证据,而不是根据名称猜测。它们还会要求摘要以数量开头,并在没有需要修复的问题时直截了当地说明。
2. 每个拉取请求都进行 AI 审查
每个拉取请求都会先由 Claude 审查,然后才交给人查看。Claude 会结合整个代码库和 PR 声明的意图阅读差异,并提出问题:这项变更解决了它要解决的问题吗?它符合系统的设计吗?它会破坏其他东西吗?
对于缺陷修复,它会查找根本原因。面向公众的版本“Claude Code 代码审查”现已在 Team 和 Enterprise 计划中全面推出,而 /code-review 会在本地运行一个较轻量的版本。
在推出研究预览版时,收到实质性审查评论的内部 PR 占比从 16% 上升到 54%。超过 1,000 行的大多数 PR 都会收到发现结果,而大多数较小的 PR 则没有问题。管理员可以将每个代码库设为 Quick、Standard 或 Deep。对于漏掉一个缺陷的代价高于额外审查时间的情况,Deep 值得采用。
在人类审查之前,其他智能体会验证发现结果。多个智能体同时查找缺陷。然后,另一个独立小组会对每项发现进行投票,只有在足够多人认定它确实存在时才会发布。纯粹涉及风格、诊断或清理工作的发现会被丢弃。在保留这些过滤规则之前,我们先在自己的 PR 上进行了 A/B 测试。剩下的发现会以行内评论形式出现,并按严重程度排序。每项发现都会标为 Important、Nit 或 Pre-existing,因此 PR 没有引入的缺陷不会让人误以为是作者造成的。
每项发现都必须得到回应。你要么修复它,要么给出理由并解决该讨论串。通常,智能体会在夜间接手修复,因此作者回来时,PR 已经又经过一轮审查。
3. 可以阻止合并的安全审查
安全问题也会有单独的自动化审查。如果缺陷审查或安全审查中仍有任何发现未解决,PR 就不能合并。你要么修复它,要么附上一句简短理由并关闭讨论串,这样就能清除误报。
如果后续提交修复了这个问题,该发现会自动清除。你可以使用开源的安全审查 GitHub Action 或 /security-review 命令设置同样的机制。
设置方法见《在 Claude Code 中进行自动化安全审查》。
4. 会阻止合并的自动化检查
常规检查包括:lint、类型检查、在每个平台上运行的测试,以及构建。(我们在此处介绍过如何扩展 CI,以应对这种工作量。)一个典型的 CLI 拉取请求可能要在任何人查看之前运行几十项检查。
PR 模板会询问这项变更是如何测试的,以及如何撤销。Claude 可以填写这些内容,但提出这项变更的人需要确认。
5. 按风险等级调整人工审批
文档修复和自动更新器变更的风险不同,因此它们需要不同的审查。
| 风险 | 示例 | 人工审批 |
|---|---|---|
| 低 | 文档、文案、仅限内部的功能、在功能开关后启用的增量变更 | 自动化审查和安全检查通过后,无需审批 |
| 中 | 普通产品变更,以及对敏感区域的变更,例如缓存、自动更新器或系统提示 | 一人 |
| 高 | 风险最高的代码,以及少数始终需要两人审查的路径 | 两人 |
风险等级由变更决定,而不是由作者决定。分类器会读取变更并选择其风险等级。第二个分类器会判断:即使该等级显示无需他人参与,这项具体变更是否仍需要另一个人审查。某些路径始终需要人工审查,包括负责人列出的任何敏感内容,以及任何 CI 工作流文件。
只有受信任的作者才能走较轻量的路径。只有在代码库受信任名单上的作者才能走较轻量的路径,主要是负责该代码库的团队。其他所有人都需要第二个人审批。智能体的审批也不能算作人工审批。自动化审查可以放行低风险变更,但不能填补要求由人类审查者占据的名额。
无论是谁提示了这项变更,都要对它负责。对于由智能体编写的 PR,指挥智能体的那个人算作一名必需审查者,就像代码是他们亲自输入的一样。
审批只针对某个特定提交。如果有系统无法担保的新提交进入,比如智能体推送的提交,或有人手动解决的合并,那么就必须重新审批。
6. 合并队列、功能开关和逐步发布
合并队列会在 main 上应用这项变更后重新运行每项检查,这样两个分别通过检查的 PR 就不会组合成一个损坏的 main。新行为通常会先在功能开关后启用,供 Anthropic 员工使用;我们的高频使用往往能在用户之前发现回归问题。公开发布会先进入最新频道。稳定频道会稍后跟进。
7. 快速发现,快速回滚
有些错误仍然会漏过去,因此最后一层的重点是快速发现问题。无需部署就能关闭功能开关。Claude Code 实行每周轮值的当班制度,事故复盘会询问是哪一层本该发现这个问题。
发现糟糕的合并仍然依赖作者和当班人员,也依赖回滚和事故仪表盘。我们还没有能在这些数字发生变化时收紧审批要求的断路器;这里的工程师希望在更多代码转向零人工合并之前实现它们。
一位同事说,放慢速度确实会降低错误率,但这主要是因为你做的所有事情都变少了。我们更愿意提升发现和修复问题的速度。
我们如何改进审查器
我们的代码审查流程会持续循环改进。
现在,任何事故都会成为一个评测样例。团队收集了过去引发事故的 PR,以及对应的向前修复和回滚,并让熟悉相关代码的工程师确认每个缺陷及其所在位置。审查器每天都会在这组样例上运行。
我们的事故就是评测集

由过往事故和回滚构建,每天运行
事故或回滚 → 经专家核实的案例 → 加入集合
导致问题的变更 → 专家确认缺陷 → 每起事故都会增加一个案例
修改审查器 → 每日评测运行 → 分数提高了吗?
修改它的提示、工具或模型 → 对每个案例进行评分 → 如果提高就保留;否则就撤销
下一项变更
图 C 评测集会随着每起事故不断增长,而审查器的每项变更都会在全部样例上评分。
我们通过观察人们如何处理评论来衡量噪声。如果不介意标记大量并非缺陷的内容,就很容易发现更多缺陷,因此我们需要一种检查机制。我们会根据 PR 上的人如何回应,对审查器留下的每条评论进行分类:他们修复了它、表示它不对、表示这是有意为之,或认为它无关紧要。我们还会让审查器检查我们已知没有问题的 PR,并统计它报告可能导致他人做出有害变更的内容的频率。我们明确写下的优先级是:首先捕获真实缺陷,其次减少审查轮数。
当作者是智能体时,噪声的代价更高。人可以在几秒钟内忽略一个琐碎意见。智能体则会去修复它,这意味着又多一个提交和一轮审查。
审查必须收敛。智能体作者和智能体审查器可能会没完没了地互相折腾。有一个 CLI PR 在一夜之间经历了 50 多轮审查和修复,最后是作者叫停了它。
我们对审查器反复标记的内容运行 git blame 时,发现其中约 59% 是在审查器第一次检查时就已经存在的代码。审查器很少是在发现新的缺陷,而是每轮再多发现一些旧缺陷。
我们自己把情况弄得更糟了。我们已经习惯默认进行多轮审查,因为每一轮都会发现一些新问题。对于高风险变更,这可能值得,但不适用于每个 PR。团队现在会在召回率之外,也跟踪通过所需的轮数,并调整了重新审查流程:
- 设置轮数上限。 三轮之后,审查器会要求作者退一步,重新考虑方案。
- 前几轮之后,只对差异重新审查。
- 标记缺陷类型,让作者修复所有实例,而不只是某一行。
- 不重复已经发布过的发现。
审查智能体还会在夜间检查现有代码,帮助我们在旧缺陷出现在其他地方之前发现它们。
让审查收敛

收敛改动前后,内部拉取请求的情况
| 指标 | 改动前 | 改动后 |
|---|---|---|
| 经过一轮审查和修复后通过 | 65% | 78% |
| 需要五轮或更多 | 8.9% | 1.5% |
| 平均通过所需审查轮数 | 2.08 | 1.32 |
收敛工作之前 收敛工作之后
图 D 收敛改动后,每个内部拉取请求所需的审查轮数减少了。
人仍参与的环节
让一位资深工程师从深度工作中抽身出来抓一个常见错误,成本远高于自动化审查。在 Anthropic,我们的工作已经从阅读每一份差异,转向做机器不擅长的决策:
- 我们究竟应该构建这个东西吗? 方向、品味和范围。一个团队曾宣称其审查瓶颈已经解决,但仍然保留对团队外部变更的人工审查,因此会有人问:“我们真的应该做这个吗?”
- 高风险代码,例如账单、自动更新器和 CI 工作流。
- 会设定模式、供其他人照着做的架构。
- 阅读证据。 测试输出、运行过的命令及其返回结果、截图、审查器的发现。如果你说不出这些检查会漏掉什么,就应该要求一次真正的审查,而不是快速审批。
- 承担结果。 无论是谁输入的代码,每一项发布的变更都由一个人负责。
哪些地方由人做决定

五项决策仍由人负责;其他地方都运行检查
- 我们应该构建它吗?
- 承担结果
- 高风险代码
- 自动化检查全程运行
- 阅读证据
- 架构
- 自动化检查
- 人来决定
图 E 人们的工作从阅读每一份差异,转向做机器不擅长的决策。
在团队中共享上下文
代码审查的第二项工作一直是传播对代码库的理解。阅读队友的差异,是了解变更内容以及各部分如何协作的方式。如果大部分阅读工作都由机器完成,人们要如何了解代码?
我们没有正式流程。团队里没有人能把 Claude Code 的完整心智模型装在脑子里,我们也不认为任何人需要做到这一点。如果有人想了解代码库的某一部分,他们就会让 Claude 针对那一部分撰写一份说明。只需几分钟,而且反映的是代码今天的实际状态。

我们中的一些人会更进一步,让 Claude 构建一个小型的可视化产物,展示代码的那一部分,并按照那个人喜欢的学习方式讲解它。
如果目标是妥善利用人的注意力,这比逐行阅读琐碎差异更好。一行文案变更几乎教不会你什么。针对你即将修改的模块写一份说明,则能让你学到很多。我们默认在公开 Slack 频道中工作的文化也有帮助,因为你可以看到其他人在构建什么,以及他们如何构建。
“你合并,你负责”
如果你合并了一项小型或中型变更,之后仍然出了问题,团队规范通常要求你来修复。有几件事可以避免事情变糟:
- 变更很小,因此容易审查、调试和回滚。
- 一切都可以撤销。功能开关、回滚和分阶段发布可以在几分钟内撤销大多数错误。
- 影响范围决定门槛。代价高昂的代码会有更多人参与和更多检查。
- 遥测和内部使用会快速暴露回归问题。
- 这不是追责。有上下文最多的人负责修复;事故复盘关注的是系统。
责任也是共享的。团队中许多人在公开频道工作,任何人都可以看到其他人在构建什么、接续某个讨论串,或让 Claude 补上某个缺口;反馈也来自不负责相关代码的人。这种开放性是质量能够保持较高、又不必对每一行代码都设置关卡的重要原因。
改变方向时
智能体让启动项目的成本变得很低,因此有些工作不应该合并。通常,频道里会有人询问原因、指出之前的决策,或建议一条更简单的路线,然后作者就会关闭或调整 PR。
既然代码写得很快,关闭 PR 就不会让人觉得是损失。诀窍是在讨论串中尽早提出不同方向,而不是等到 PR 完成后才用阻塞性评论提出。
如何采用这个流程
如今,你和团队实现这一流程所需的大部分组成部分都已经具备。
拉取请求之前
- 在简短的
CLAUDE.md中列出智能体可以运行的检查,并添加运行格式化工具和代码检查器的钩子。 - 在本地运行
/code-review和/security-review,或让子智能体在全新的上下文中审查。 - 添加
REVIEW.md,并把重复出现的审查评论整理到其中。
每个拉取请求都要做
- 要求 CI 通过,并在 PR 模板中加入“测试”“风险”和“如何回滚”。
- 在一个代码库中添加 AI 审查器(Claude Code 代码审查,或 Claude Code GitHub Action),用几周时间调整
REVIEW.md,然后再扩大范围。 - 添加自动化安全审查,并要求合并前解决每个审查讨论串。
- 让审查力度匹配风险:常规变更做快速检查,漏掉缺陷代价高的变更做深入检查(在代码审查中选择 Quick、Standard 或 Deep)。
- 限制审查轮数;前几轮之后,只重新审查新的差异。
审批
- 写下风险等级,由变更而不是作者决定;先从严格开始,再根据证据放宽。
- 仅让你信任的作者走较轻量的审批路径。
- 使用
CODEOWNERS和分支保护,确保身份验证、账单、CI 和发布工作流,以及安装器始终需要人工审查。 - 绝不要让机器人的审批取代必需的人类审批;新提交进入时,撤销已有审批。
合并及之后
- 使用合并队列、功能开关、先在内部使用、分阶段发布和一步回滚。
- 把事故和回滚加入评测集,并在提示、工具或模型发生变化时重新评估审查器。
- 衡量人的时间,并以回滚率和事故率作为护栏。
接下来会怎样
“代码审查”功能的公告称,批准拉取请求仍然是人的决定;产品只发布发现结果,不提供审批。我们自己的代码库走得更远一些,让负责人决定哪些低风险变更只要自动化检查通过就可以合并,而这条界线仍在不断变化。
当审查漏掉了什么时,我们会询问模型当时没有看到什么信息,然后把修复写入 CLAUDE.md、技能或新的检查中。目标没有改变:减少每项变更所耗费的人工时间,同时不让回滚数量高于从前。
如果你的团队让智能体打开拉取请求,我们想知道你们自动化了哪些检查、哪些仍然需要人工,以及你认为我们哪些做法有问题。
感谢 Emma Webb、Michael Segner 和 Amie Rotherham 审阅本文。