CLAUDE.md 不是 README:给 Claude Code 写规则的 5 条硬规矩
Claude Code 启动时会读项目根目录的 CLAUDE.md,把内容塞进每一轮对话的上下文。很多人第一反应是:那我把 README 贴进去,再把架构文档贴进去,越全越好。
然后发现它该守的规矩不守,不该动的文件照动,跑测试时总用错命令。
问题不在 Claude Code,在于 CLAUDE.md 不是给人看的文档,是给模型的常驻指令。文档追求完整,指令追求命中。按写文档的思路写它,字越多命中率越低。下面五条规矩,是我在自己的项目里改了几十版之后留下来的。
规矩一:只写代码里推不出来的东西
模型能读代码。目录结构、函数签名、依赖列表,它自己 ls 和 grep 一下就知道,你写进 CLAUDE.md 只是浪费上下文,还会在代码变化后变成过期信息误导它。
该写的是从代码里推不出来的事实:
- 构建、测试、类型检查用什么命令。
npm test还是npm run test:unit,跑全量还是只跑单个文件,模型猜不到。 - 环境的怪癖。比如「访问 GitHub 必须走本机代理 127.0.0.1:7897」「数据库迁移只能在容器里跑」。
- 团队约定。ES 模块不用 CommonJS、接口统一返回
{ code, msg, data }、分页排序由后端负责前端不翻转。 - 红线。不动
.env、不git push、不删文件。
一个判断方法:这句话删掉之后,模型靠读代码能不能得出同样的结论?能,就删。
规矩二:越短越管用
CLAUDE.md 的每一个字都在每一轮对话里重复出现。它不只是花钱,更重要的是稀释注意力。三百行的 CLAUDE.md 里藏一条「禁止修改 schema」,和三十行里放同一条,模型的遵守率差得很远。
Anthropic 自己的建议是:保持简洁、人类可读、像调提示词一样反复迭代。他们还提了一个实用技巧,对真正重要的规则加 IMPORTANT 或 YOU MUST 这类强调,能明显提高遵守率。反过来说,如果你每条都加强调,等于没加。
我的做法是给 CLAUDE.md 设一个预算:常驻部分不超过一屏。超出的内容要么删,要么用下一条规矩分出去。
规矩三:硬规则交给 hooks,不靠文字
「每次改完 TypeScript 文件自动跑类型检查」「提交前必须跑 lint」「禁止执行 rm -rf」,这类要求写在 CLAUDE.md 里是请求,模型大概率照做,但不保证。
Claude Code 有 hooks 机制,配置在 .claude/settings.json 里,在工具调用前后执行你指定的 shell 命令。写在这里的是规则,由运行环境执行,模型绕不过去。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "npm run typecheck" }
]
}
]
}
}
区分标准:违反了会造成损失的,用 hooks;违反了只是不好看的,用文字。 我的项目里 CLAUDE.md 只剩风格约定,安全类的全在 hooks 里。
规矩四:按层级拆,别堆在一个文件里
Claude Code 会按层级读多个 CLAUDE.md,从外到内依次是:
| 位置 | 作用范围 | 适合放什么 |
|---|---|---|
~/.claude/CLAUDE.md |
你所有项目 | 个人偏好:回复语言、回答长度、验证习惯 |
./CLAUDE.md |
当前项目,提交到仓库 | 团队共享的命令、约定、红线 |
./子目录/CLAUDE.md |
只在读取该目录文件时加载 | 某个模块的特殊规则 |
子目录那一层是按需加载的:模型读到 src/payments/ 下的文件时,才会把 src/payments/CLAUDE.md 拉进上下文。这意味着你可以把支付模块的二十条注意事项放进去,而不影响其他任务的上下文预算。
另外它支持 @路径 引用其他文件:
详细的 API 约定见 @docs/api-conventions.md
引用的文件在需要时才被读取,正文里只留一行指针。用这个代替整段复制粘贴。
规矩五:被纠正后当场回写
这是五条里最重要的一条,也是最少人做的。
你纠正了 Claude Code 一次,「不要用 CommonJS」,这次它改了。下次开新会话,它又用了。因为上下文没了,纠正也没了。
每一次纠正,都应该变成 CLAUDE.md 或旁边一个 lessons 文件里的一行。 我的项目里有个 tasks/lessons.md,格式固定为「现象、根因、解法」,CLAUDE.md 里写一句「会话开始时先读它」。三个月下来,同一个错误几乎不会犯第二次。
这一条的本质是:CLAUDE.md 不是写完就放着的配置,是一个随着你纠正次数增长的记忆。写它的最好时机不是项目开始,是每次你想说「我不是说过了吗」的时候。
一份可以直接抄的骨架
# 项目名
## 命令
- 构建:npm run build
- 类型检查:npm run typecheck(改完 TS 必跑)
- 测试:npm run test -- <文件>(只跑相关的,不跑全量)
## 约定
- ES 模块,不用 require
- 接口统一返回 { code, msg, data }
- 分页排序由后端负责,前端不做 reverse
## 环境
- 访问 GitHub / npm 官方源需要代理:HTTPS_PROXY=http://127.0.0.1:7897
- 数据库迁移只在容器内执行
## 红线
- 不改 .env,不 git push,不删文件
- 找根因,不打临时补丁
## 记忆
- 会话开始先读 tasks/lessons.md;被纠正后把模式写进去
三十行不到。剩下的内容,要么模型能从代码里读到,要么放到子目录和 @ 引用里,要么变成 hooks。
最后
写 CLAUDE.md 和写提示词是同一件事:你不是在描述项目,你是在纠正模型的默认行为。 它默认会做的事不用写,它默认做错的事才值得写。从这个角度看,一份好的 CLAUDE.md 应该越用越长,但每一行都对应一次你真实踩过的坑。
问一句:你的 CLAUDE.md 现在多少行?超过一百行的,评论区说一下里面最长的是哪一段,我猜是目录结构。