Skip to content

代码审查

用 Claude Code 做 diff review、发现真实 bug 的方法。

Claude Code 做代码审查有两个天然优势:读得快、不累。同一个 PR 你自己审 20 分钟走神,它审 20 秒还能盯细节。但它也有两个天然弱点:顺着自己写的代码找不到问题(confirmation bias)、倾向于说好话

这一节讲怎么用得对:让它按维度审、用独立 subagent 审、必要时二次复核。

/review 或直接 prompt

Claude Code 内置了 /review 命令,会自动读当前 diff(相对于默认分支)做一次通用审查。适合快速过一遍:

text
你: /review

Claude Code:
[git diff main...HEAD --stat]
[Read 变更文件]

发现 3 个问题:
1. src/auth/login.ts:88 — 密码比较用了 == 而不是 timing-safe 比较,
   有 timing attack 风险。
2. src/api/users.ts:142 — 新加的 /users/:id 端点没有权限校验。
3. src/services/mailer.ts:56 — 邮件模板里直接拼了 user.name,
   如果 name 含 HTML 会 XSS。

要我打印详细说明吗?

/review 好用,但通用视角有时候会漏掉你关心的重点。这种情况用具体 prompt 效果更好:

text
你: 审一下这个 PR 的 diff,我特别关心权限和 SQL 注入。
其他 style 类的先别提。

明确的关注点,Claude Code 的输出会精准很多。

按维度审:correctness / security / performance / test

好的代码审查覆盖多个维度。让 Claude Code 一次审所有维度容易散,逐维度过更稳。

四个维度的 prompt 模板

  • Correctness(正确性):这段改动有没有边界情况处理错?null、空数组、并发、错误路径?
  • Security(安全):注入、越权、XSS、CSRF、密钥泄露、日志泄露、依赖漏洞?
  • Performance(性能):N+1 查询、内存爆炸、无限循环、同步阻塞、无索引?
  • Test coverage(测试覆盖):新逻辑是否有测试?边界 case 有没有覆盖?测试是否真的能挂?

一次问一个维度,例:

text
你: 只看 correctness 维度审这个 diff。列所有可能的边界失效。
不要讨论安全、性能、测试,那些下一轮。

Claude Code:
correctness 维度 4 个发现:

1. src/order/refund.ts:34
   如果 order.items 是空数组,reduce 没有 initial value 会抛 TypeError。

2. src/order/refund.ts:52
   totalRefund 是 float 求和,累加多次会有浮点误差。金额建议
   用 integer cents 或 decimal 库。

3. src/api/refund.ts:19
   POST /refund 没做 idempotency key 校验,重试请求会重复退款。

4. src/order/refund.ts:68
   updateOrder 和 sendRefundEmail 之间没有事务保护,
   邮件发出后如果 updateOrder 失败,用户以为退款成功。

要继续下一维度吗?

四个维度依次过,最后你能得到一份分门别类的问题清单,比一大坨混着讲清楚得多。

用 subagent 做独立审查

如果这个 PR 是 Claude Code 自己写的,让它审自己容易翻车。它会顺着自己的思路走,找不到真正的问题(这是 confirmation bias,人也一样)。

解法是派独立的 subagent 来审。subagent 拿到的只有 diff 和你的 prompt,看不到主 loop 之前的会话,能给出更中立的视角。

text
你: 派一个 subagent 独立审这个 diff。它只能看当前 branch 相对 main
的改动,不许看我们之前对话里讨论过的实现细节。重点看 security。

Claude Code:
[派 subagent → 只给它 git diff main...HEAD 的输出和 prompt]

Subagent 报告回来:

安全维度 3 个发现:
1. src/auth/token.ts:22 — 新加的 refresh token 存在 localStorage,
   XSS 一发作直接被偷。应该走 httpOnly cookie。
2. src/api/users.ts:88 — GET /users?search= 参数直接拼进 SQL LIKE,
   SQL injection。
3. src/upload.ts:44 — MIME type 只校验 Content-Type 头,没查文件
   magic bytes,能通过改 Content-Type 上传 exe。

主 loop 之前不知道有这些问题(否则一开始就修了),subagent 从零看,反而能挑出来。

什么时候一定要用 subagent

  • PR 是 Claude Code 自己写的
  • 你已经和它讨论过实现方案,想验证是不是有盲区
  • 涉及安全、金融、医疗这类高风险场景,至少两个视角

Verify 环节:让第二个 subagent 复核

发现问题清单之后,还有一步:让第二个 subagent 复核第一个的发现是不是真的问题。

大模型偶尔会“过度警觉”,把一些不是问题的东西报出来。第二个 subagent 拿到“第一个说 X 是问题,你去验证”的任务,会实际读代码、跑测试或者写 POC 来确认。

text
你: 派第二个 subagent,验证刚才那 3 条发现。每一条它要给出:
真问题 / 误报 / 不确定,以及理由。

Claude Code:
[派 subagent 2 → 给它第一个的清单 + 项目 read 权限]

复核结果:

1. localStorage 存 refresh token
   → 真问题。已确认 auth.ts:22 用的是 localStorage.setItem。
     不过项目 CLAUDE.md 里说了“暂时接受这个风险,等下一版切 cookie”,
     所以是已知遗留问题不是新增问题。

2. SQL LIKE 拼参数
   → 误报。src/api/users.ts:88 用的是 knex query builder 的 .where,
     底层是参数化查询,不存在注入。第一个 subagent 只看了这一行没看
     上下文。

3. MIME 校验只看 header
   → 真问题。已复核 upload.ts 完整代码,确实只信 req.headers。
     建议加 file-type 库做 magic bytes 校验。

一轮复核之后,你手上是一份可信度很高的问题清单。误报被剔除、误漏被兜底、遗留问题被明确标注。这是自动化 review 能达到的上限。

完整案例:审一个 Auth PR

假设同事发了一个 PR,标题“feat(auth): 支持 refresh token 和 rate limit”,涉及 8 个文件、300 行改动。你想让 Claude Code 帮你先过一遍。

第 1 步 — 拉分支:

text
你: 切到 PR #142 的分支。
Claude Code: [gh pr checkout 142] 已切到 feat/auth-refresh。

第 2 步 — 先看整体:

text
你: /review

Claude Code: [git diff main...HEAD --stat]
8 files changed, 312 insertions(+), 47 deletions(-)

高层判断:改动集中在 src/auth/ 和 src/middleware/rate-limit.ts。
新增 3 张表迁移。有 5 条新测试。

我准备按 correctness → security → performance → test coverage
逐维度过。可以吗?

第 3 步 — Correctness:

text
你: 走 correctness。

Claude Code: [详细审查]
2 个发现:
1. refresh 端点没处理并发刷新(同一个用户同时发两次 refresh 请求
   会产生两条互相失效的 token)。
2. rate limit 用了 in-memory Map,重启就丢,多实例部署时不共享。

第 4 步 — Security(用 subagent):

text
你: security 维度派一个 subagent 独立审。我不给它我们刚才的讨论。

Claude Code: [派 subagent A]
Subagent A 报告:
1. refresh token 明文存 DB。应该 hash 后存,泄露也无法复用。
2. rate limit 的 key 是 IP,proxy 后面所有用户共用一个 key,
   容易被单个恶意用户拖垮整站。应该 IP + user 组合。
3. login 失败的错误信息区分“用户不存在”和“密码错误”,
   会被拿去做用户名枚举。

第 5 步 — 复核 security 发现:

text
你: 派 subagent B 复核这 3 条。

Claude Code: [派 subagent B]
Subagent B 复核:
1. 真问题。schema 里 refresh_token 字段是明文 varchar,无 hash 迹象。
2. 真问题。middleware/rate-limit.ts:22 key 直接用 req.ip。
3. 部分真问题。errors.ts 里区分了 USER_NOT_FOUND 和 WRONG_PASSWORD,
   但对外返回都被 wrap 成同一条“登录失败”,前端看不到区别。
   实际不构成用户名枚举。建议:内部日志也别打这个区分,避免日志泄露。

第 6 步 — Performance / Test 略过或简做(视情况)。

第 7 步 — 汇总到 PR comment:

text
你: 汇总所有真问题成一份 PR review 评论,Markdown 格式,给我贴。

Claude Code: [产出格式化的 review 评论]

你复制粘贴到 PR 页面,这一次审查完成。前后大约 15 分钟,覆盖的维度和深度比自己肉眼审强得多。

什么时候不要走这一套

  • 一行改动的 typo 修正、纯格式化 PR,直接肉眼过。
  • 你自己就是这块代码的作者且非常熟悉,可能你比模型准。
  • 涉及大量业务判断的 PR(比如“这个价格策略是否符合运营意图”),Claude Code 帮不了,让业务对方审。

工具审能替你挡下一大部分低级问题,剩下的判断题永远归你。

本教程为社区中文学习整理,非官方发布。Claude Code 属于 Anthropic。