实操一:仓库改造——CLAUDE.md、REVIEW.md、hooks 与本地验证环的四件套落地

71次阅读
实操一:仓库改造——CLAUDE.md、REVIEW.md、hooks 与本地验证环的四件套落地

循序渐进实操 · 2026-10-29 · 本篇为 ”AI 代码评审 ” 系列第 3 篇(实操一),第 1 篇解读 · 第 2 篇选型 · 对应 Anthropic 七层的 L1(PR 前验证) · 前置:任意 GitHub 仓库 + 已装 Claude Code 或兼容 agent


写在前面

选型篇给了三条路线($0 自托管 / $120 SaaS / Claude 全套),无论选哪条,第一层防御——PR 存在之前的验证——都是从同一个四件套开始的 :CLAUDE.md、REVIEW.md、hooks、本地验证环。这一层是第 1 篇里性价比最高的部分:Boris Cherny 说 ” 给 Claude 一个可运行的验证方式 ” 能让结果好两到三倍;而第 1 篇的排障数据(59% 的重复 finding 是旧代码)也从反面证明—— 没有这一层的 PR 评审,是在花钱让评审器发现旧账。本篇零成本(不订阅任何服务),产出是一套可以立刻提交到仓库的配置文件。全文以一个假想的 my-api 仓库为例,所有命令可直接替换仓库名套用。

一、四件套总览与放置位置

文件 作用 谁读它 何时读
CLAUDE.md 项目是什么:技术栈、约定、目标 / 非目标 agent(每次评审 / 编码都加载) 每次会话自动
.claude/settings.json hooks:工具调用的自动拦截器 Claude Code 运行时 每次工具调用
REVIEW.md 这部分代码里什么要紧(失败长什么样) 评审 agent 每次评审
PR_TEMPLATE.md 怎么测的、风险、怎么撤销 人 + agent 填写 每次开 PR

三份 Markdown 都是 ” 写给 agent 的人话 ”,唯一的要求是 短——第 1 篇原话:”The good ones are short.”。下面逐个落地。

二、CLAUDE.md:50 行以内的项目宪法

原则:只写 agent 无法从代码里自己推断的东西;其余指向专门文档(”in a large codebase we keep it short and point to other docs from there”)。

# CLAUDE.md — my-api

## Stack
Node 22 + TypeScript 5.x, Fastify, PostgreSQL 16 (pgx), Vitest.

## Commands
- Test all: `npm test`
- Test one file: `npm test -- path/to/file.test.ts`
- Lint + type: `npm run lint && npm run typecheck`
- Local run: `npm run dev` (port 3000; needs .env, see .env.example)

## Conventions
- Errors: throw `AppError` subclasses; never raw `Error` in routes
- DB access only in `src/db/`; routes stay thin
- Every route handler has a Vitest integration test (supertest)
- Commit style: conventional commits (feat/fix/chore/refactor)

## Non-goals
- No new frameworks; no ORM migration away from pgx
- Don't bump major deps without an ADR in docs/adr/

## Where things live
- Auth logic: src/auth/ (see docs/auth.md)
- Rate limiting: src/middleware/ratelimit.ts (redis-backed)

要点 :① Commands 区是给 agent 的 ” 可运行验证 ” 清单——第 1 篇说的 ”give it something it can run” 就落在这里,agent 做完改动会自己跑这些命令并展示输出;② Non-goals 与 Where-things-live 让 agent 少走弯路(少一半的无效探索);③ 每次评审器加载它,所以 它会过时也要保养——评审器会标记使它过时的变更(第 1 篇原话),别让它长过 50 行。

三、REVIEW.md:告诉评审器失败长什么样

这是第 1 篇里最容易被忽略、回报却最高的文件——它把 ” 团队里资深工程师脑子里的评审清单 ” 外化成了文本。放在仓库根目录(或 .claude/REVIEW.md):

# REVIEW.md — review guidance for my-api

## What failure looks like here
- Docs: it lies (endpoint docs drift from actual routes → blocking)
- Config: it misroutes (wrong queue/topic binding → blocking)
- Money paths: any change to billing/ or usage-metering needs
  explicit rounding tests (float vs Decimal)

## Cap the nits
- Style nits: only if they violate .editorconfig or lint config
- No "consider adding types" on files already fully typed

## Skip paths
- CHANGELOG.md, .github/workflows/* (owned by platform team)
- Generated: src/generated/, openapi.json

## Evidence rules
- Every finding must cite file:line
- Summary starts with a count; say "nothing to fix" plainly
  if that's the truth

## Sensitive areas (always human)
- src/auth/, src/billing/, .github/workflows/, migrations/

要点 :① “What failure looks like” 必须是 你仓库里真实发生过的失败模式——从最近三起事故或三次 hotfix 里各提炼一句,比任何通用清单都值钱;② “cap the nits” 直接对应第 1 篇的噪声治理——评审器把 nit 打上 Nit 标签不发评论;③ Sensitive areas 是给第 5 篇(风险分级)预留的锚点。

四、hooks:让验证自动发生

.claude/settings.json(Claude Code 的 hook 配置;其他 agent 用等价的 hook 机制):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "npx prettier --write $CLAUDE_FILE_PATHS 2>/dev/null || true"}
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [{ "type": "command", "command": "npm run lint && npm run typecheck"}
        ]
      }
    ]
  }
}

逻辑 :每次 Edit/Write 工具调用后自动 format(消灭风格类 nit 的来源);Claude 停止响应前自动跑 lint+typecheck——这就是第 1 篇 ”review runs continuously, like spellcheck” 的最小实现。注意 hooks 是 拦截器不是评审器:它保证代码卫生,发现问题靠后面两层。

五、本地验证环:跑通 ” 给 Claude 一个可运行的东西 ”

四件套配好后,做一次端到端验证(这一步同时是给团队的演示):

# 1. 给 Claude 一个典型任务(含验证指令)claude "Add a DELETE /users/:id endpoint. Follow CLAUDE.md conventions.
        Write the integration test first, see it fail, then implement.
        Show me the test output and lint result when done."

# 2. 期望行为链:#    agent 写测试 → 运行 → 看到失败 → 实现 → 再运行 → 通过
#    → 自动跑 lint/typecheck(Stop hook)→ 展示输出

# 3. 提交前再让它自查一轮(第 1 层的 " 子代理评审 " 简化版)claude "Review the diff vs HEAD~1 with fresh eyes. Check CLAUDE.md
        conventions and REVIEW.md failure modes. Cite file:line for
        each finding. Start your summary with a count."

验收标准:agent 的输出里出现了测试的真实输出(不是 ” 应该能通过 ”);lint/typecheck 零错误;评审请求返回了带 file:line 的发现列表且以计数开头。三样齐了,L1 就算落地。

六、常见坑

  1. CLAUDE.md 写成了百科全书——超过 50 行就该拆:主文件留指针,细节进 docs/。它每次评审都加载,长度直接乘以评审次数变成 token 账单
  2. REVIEW.md 抄模板不抄事故——最有价值的内容是你仓库自己的失败史;没有事故库就先写 ” 预期失败模式 ”,随事故补充
  3. hooks 全量拦截拖慢节奏——PostToolUse 里放秒级命令(format),把分钟级命令(全量测试)放 Stop 或 CI
  4. 四件套进了 .gitignore——它们的价值随团队成员数放大,必须入库;个人偏好放 ~/.claude/CLAUDE.md(用户级)
  5. 验证环只配了 happy path——” 看它失败 ” 是 TDD 的一半;REVIEW.md 里写清楚哪些场景必须有失败测试(如鉴权失败、余额不足)

七、小结与下一篇

本篇落地了七层的 L1:四件套 + 本地验证环,零订阅成本,当天可提交。验收三件套:agent 展示真实测试输出、hook 自动跑 lint/typecheck、评审请求返回带 file:line 的计数式发现。下一篇(实操二)在 PR 层接入双评审(AI 评审 + 安全门禁),落地 findings 必答制与轮次上限——那时第 2 篇选的型(PR-Agent 或 security-review Action)才真正进场。


参考与延伸

by 飞熊 · yunying(增长运营官)· 所有配置片段为可直接套用的模板;具体 hook 字段以所用 agent 版本文档为准

正文完