Claude Code 团队如何开展代码审查
文章介绍 Claude Code 团队的代码审查实践。所给素材仅包含文章链接和社区讨论热度,未提供具体流程或效果数据。
文章介绍 Claude Code 团队的代码审查实践。所给素材仅包含文章链接和社区讨论热度,未提供具体流程或效果数据。
面对智能体产出的海量代码,该如何进行审查?在 Claude Code 团队实现了高覆盖率和深入审查之后,我们开始优化另一个目标:在不增加回滚或事故的前提下,尽量减少人工审查所需的时间。
我们之前说过,Claude Code 自身大约 90% 的代码由 Claude 编写。那么,面对这样的代码产出量,我们如何审查?还有人读代码吗?如果出了问题,又由谁来发现?
本文介绍 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 会话发起,会经过多层代码审查。
一次变更的生命周期png一次典型的 Claude Code 变更,从作者的电脑到用户图 A大部分流程都已自动化;人的注意力集中在有风险的地方
多层检查,而非一道关卡png六层检查,下方还有回滚兜底图 B每一层都能发现一些问题,也会漏掉另一些问题。很少有问题能穿过所有检查层,剩下的则由回滚处理。
现在,大部分审查都发生在 PR 创建之前。我们会给 Claude 提供它能运行的验证手段,例如测试、构建,或用于与设计稿对比的截图,并要求它展示输出结果,而不是只说自己已经完成。然后,再让一个子智能体在全新的上下文中审查差异。这两个习惯都来自我们的最佳实践指南。
在创建 PR 之前,我们中的许多人还会运行几个内部技能:一个负责找 bug,一个负责简化差异,另一个负责端到端检查行为。UI 变更还会对照我们的设计规范进行检查。
Claude Code 的创建者 Boris Cherny 曾说,给 Claude 提供验证自身工作的方法,可能是获得良好结果最重要的一件事。他估计,这能让最终结果提升到原来的两到三倍。他写道:“不同领域的验证方式各不相同。它可能只是运行一条 bash 命令,也可能是运行一套测试,或在浏览器、手机模拟器中测试应用。”
当自动审查工具反复指出同一类问题时,我们会从源头解决:修改技能、添加 lint 规则,或更新以下指令文件:
CLAUDE.md 告诉 Claude 这个项目是什么:技术栈、约定、目标,以及明确不做的事。每次审查都会加载它,因此在大型代码库中,我们会保持它的简短,并在其中指向其他文档。审查工具也会标记违反其中约定的代码,以及导致其中某一行内容过时的变更。REVIEW.md 由代码负责人编写,告诉审查工具在他们负责的代码范围内,哪些事情最重要。我们还会单独检查审查工具是否真的遵守了它。写得好的文件都很简短。它们会说明该仓库中什么情况算失败(对文档来说是“内容不实”,对配置来说是“路由错误”),限制细枝末节意见的数量,列出应跳过的路径,并要求用文件和行号提供证据,而不是仅凭名称猜测。它们还要求摘要以问题数量开头,并在没有需要修复的内容时明确说明。每个拉取请求在交给人查看之前,都会先接受 Claude 审查。它会结合整个仓库和 PR 声明的意图阅读差异,并提出问题:这次变更是否解决了目标问题,是否符合系统的整体设计,会不会破坏其他功能?
对于 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 已经又经过了一轮处理。
安全也有单独的自动审查。只要 bug 审查或安全审查发现的任何问题仍未解决,PR 就不能合并。你要么修复问题,要么附上简短理由并关闭讨论;误报也是这样清除的。
如果后续提交修复了问题,对应的问题项会自动清除。你可以使用开源的安全审查 GitHub Action 或 /security-review 命令,搭建同样的流程。配置方法见 Claude Code 自动安全审查的相关说明。
常规项目一样不少:lint、类型检查、所有平台上的测试,以及构建。(我们曾在另一篇文章中介绍如何扩展 CI,以应对这样的规模。)一个典型的 CLI 拉取请求,在任何人查看之前,可能已经运行了几十项检查。PR 模板会询问这次变更是如何测试的,以及如何撤销。Claude 可以填写这些内容,但需要由提出变更要求的人确认。
修正文档和修改自动更新程序的风险不同,因此需要不同的审查方式。
分级由变更本身决定,而不是由作者决定。一个分类器读取变更,确定其风险等级。第二个分类器则会进一步判断:即使该风险等级不要求额外人员参与,这次具体变更是否仍然需要另一个人审查。有些路径始终需要人工审查,包括负责人列为敏感的所有路径,以及任何 CI 工作流文件。
只有受信任的作者才能走简化流程。只有仓库信任名单上的作者才能走这些流程,主要是负责该仓库的团队成员。其他人都需要第二个人批准。智能体的批准也绝不能算作人的批准。自动审查可以放行低风险变更,但不能替代明确要求由人承担的审批名额。
谁发出提示、要求进行这次变更,谁就要为它负责。对于智能体编写的 PR,指挥智能体的人算作所需审查者之一,就像代码是他们亲手写的一样。
一次批准只对某个特定提交有效。如果之后加入了系统无法担保的新提交,例如智能体推送的提交,或有人手动解决冲突后的合并提交,就必须重新批准。
合并队列会在 main 上应用变更后重新运行所有检查,避免两个各自通过检查的 PR 合在一起后破坏 main。新功能通常先通过功能开关向 Anthropic 员工开放,我们内部的高强度使用往往能在用户之前发现回归问题。公开发布会先进入 latest 通道,stable 通道则稍晚跟进。
有些错误仍然会漏过检查,所以最后一层防线就是尽快发现它们。功能开关无需部署就能关闭。Claude Code 采用每周轮换的值班制度,事故复盘时会追问:哪一层本该发现这个问题?
发现有问题的合并,仍然依赖作者、值班工程师,以及回滚和事故仪表盘。我们还没有在这些指标发生变化时自动收紧审批要求的熔断机制;团队里的工程师希望,先建立这样的机制,再让更多代码进入无需人工介入的合并流程。
一位同事说,放慢速度确实能降低错误率,但主要是因为你做的所有事情都变少了。我们更希望加快发现和修复问题的速度。
我们的代码审查流程在持续的反馈循环中不断改进。
现在,每次事故都会成为一个评测用例。团队收集了过去引发事故的 PR,以及后续的修复提交和回滚提交,再由熟悉相关代码的工程师确认每个 bug 及其所在位置。审查者每天都会在这套用例集上运行。
我们的事故就是评测集
png
基于过去的事故和回滚构建,每天运行
图 C
每发生一次事故,评测集就会扩充;对审查者的每次改动,都会在完整评测集上评分。
我们通过观察大家如何处理评论来衡量噪声。如果不介意把大量并非 bug 的问题也标出来,那么发现更多 bug 很容易,因此我们需要对此加以约束。我们根据 PR 参与者的回应,对审查者留下的每条评论分类:修复了问题、指出评论有误、说明该行为是有意为之,或认定问题无关紧要。我们还会让审查者检查已知没有问题的 PR,统计它报告的问题中,有多少会引导人做出有害的修改。我们明确写下的优先级是:首先发现真正的 bug,其次减少审查轮次。
当作者是智能体时,噪声的代价更高。人可以在几秒钟内忽略一条吹毛求疵的意见。智能体却会去修复它,这意味着又多一次提交、又多一轮审查。
审查必须能够收敛。智能体作者和智能体审查者可能让彼此无休止地忙下去。有一个 CLI PR 在一夜之间经历了五十多轮审查和修复,直到作者叫停。
我们对审查者反复标记的代码运行 git blame 后发现,其中约 59% 从第一轮审查时就已经存在。审查者很少发现新引入的 bug,而是在每一轮中又找出几个原有的 bug。
我们自己也让情况变得更糟。因为每轮都能发现新问题,我们逐渐习惯了默认运行多轮审查。对于高风险变更,这可能值得,但不适用于每个 PR。现在,团队除了跟踪召回率,也会跟踪通过审查所需的轮次,并调整了复审方式:
审查智能体还会每晚检查现有代码,帮助我们在旧 bug 影响其他地方之前发现它们。
能够收敛的审查
png
改进收敛机制前后的内部拉取请求
图 D
改进收敛机制后,每个内部拉取请求的审查轮次减少了
把资深工程师从专注工作中拉出来,去发现一个常规错误,成本远高于自动化审查。在 Anthropic,我们的工作已经从阅读每一份 diff,转向处理机器不擅长的决策:
由人做决定的地方
png
五类决策仍由人负责,其余环节运行检查
图 E
人的工作从阅读每一份 diff,转向处理机器不擅长的决策
代码审查的第二项职责,一直是传播对代码库的理解。阅读队友的 diff,能让你了解发生了哪些变化,以及各个部分如何配合。如果大部分阅读工作都由机器完成,大家又该如何了解代码?
我们没有为此制定正式流程。团队里没有人在脑中保有 Claude Code 的完整心智模型,我们也不认为谁有必要做到这一点。当有人想了解代码库中的某个部分时,就会请 Claude 专门针对那一部分写一份说明。只需几分钟,而且反映的是代码当前的实际状态。

我们中的一些人还会更进一步,让 Claude 制作一个小型交互作品,将那部分代码可视化,并按照自己喜欢的学习方式进行讲解。
如果目标是把人的注意力用在值得的地方,这比逐行阅读琐碎的 diff 更有效。改一行文案,几乎学不到什么;针对你即将修改的模块写一份说明,却能让你学到很多。我们默认在公开 Slack 频道中协作的文化也很有帮助,因为你能在其他人开发的过程中看到他们正在做什么。
如果你合入了一项中小规模的变更,之后仍然出了问题,团队的惯例通常是由你来修复。以下几点能确保这种做法顺利运转:
责任也由大家共同承担。团队中的许多人在公开频道中工作,任何人都能看到其他人正在开发什么、接着某个讨论继续推进,或让 Claude 去补上某个缺口;反馈也会来自不负责相关代码的人。这种开放性,是我们无需对每一行代码都设卡,仍能保持高质量的重要原因。
智能体让启动一项工作的成本变得很低,因此,有些工作最终就不该合入。通常,频道里会有人追问原因、指出之前的决定,或建议一条更简单的路径,作者随后就会关闭或调整 PR。
由于代码写得很快,关闭 PR 并不会让人觉得损失了什么。关键是在讨论中尽早提出不同方向,而不是等 PR 完成后,再用阻塞合并的评论提出。
如今,让你的团队采用这套流程所需的大部分组件都已具备。
限制审查轮数;前几轮之后,只重新审查新增的 diff。
明确记录风险等级,根据变更本身而非作者来划分;起初采用严格标准,再根据证据逐步放宽。
为你信任的作者保留更简化的审批流程。
使用 CODEOWNERS 和分支保护,确保身份验证、计费、CI 和发布工作流,以及安装程序的变更始终需要人工审批。
绝不允许用机器人的批准替代必需的人工批准;有新提交时,撤销已有批准。
使用合并队列、功能开关、内部先行试用、分阶段发布和一键回滚。
将事故和回退案例整理成评估集,并在审查工具的提示词、工具或模型发生变化时,重新对其评分。
衡量人工投入的时间,并以回退率和事故率作为护栏。
Code Review 的发布公告表示,是否批准拉取请求仍由人来决定;该产品只发布审查发现,不会给出批准。我们自己的仓库更进一步,允许负责人决定哪些低风险变更可以仅凭自动化检查通过就合并,而这条界线也在不断调整。
当审查漏掉问题时,我们会追问模型当时缺少哪些上下文,并将相应的改进写入 CLAUDE.md、技能或新增的检查中。目标始终没变:减少每次变更所需的人工时间,同时让回退次数不比以前更多。
如果你的团队允许智能体创建拉取请求,我们很想听听:你们已经将哪些检查自动化,哪些仍需要人工处理,以及你们认为我们有哪些地方做得不对。
感谢 Emma Webb、Michael Segner 和 Amie Rotherham 的审阅。