CLAUDE.md 的最佳实践:为什么你的配置文件基本上是废的
你花了两个小时精心编写 CLAUDE.md,结果 Claude Code 还是在做同样的错误。不是它故意忽略你------是你在用错误的方式写它。
先理解一个工程事实:指令容量是有上限的
很多人不知道这件事:Claude 能可靠遵循的指令数量大约是 150-200 条。
而 Claude Code 的内置系统提示本身已经消耗了约 50 条。这意味着你的 CLAUDE.md 实际可用的"指令预算"只有 100-150 条。
写了 300 行?后面那 150 行基本上处于薛定谔状态------有没有被执行,全靠运气。
这不是 Claude 的态度问题,而是注意力分配的工程约束。更长的文件并不等于更好的结果,往往恰恰相反。
核心原则一:CLAUDE.md 不是文档,是有限预算的约束集合。每一行都有成本。
最常见的错误:写了一堆无效指令
打开大多数人的 CLAUDE.md,你会看到这类内容:
你是一个经验丰富的高级工程师。
请逐步思考,确保代码质量。
遵循最佳实践。
保持代码简洁易读。
这些指令消耗了你宝贵的预算,但对 Claude 的实际行为零改变。
原因很简单:Claude 本来就会"逐步思考",本来就会"遵循最佳实践"------这些是它的默认行为,用语言再说一遍并不会强化它。
更关键的是,Claude 在处理指令时会做一个内在区分:
| 指令类型 | 例子 | Claude 的处理方式 |
|---|---|---|
| 可验证的约束 | 永远不要直接编辑 package-lock.json |
当作硬性规则执行 |
| 模糊的建议 | 对依赖要小心 |
当作可以合理化忽略的建议 |
| 身份/氛围描述 | 你是高级工程师 |
基本无效,本来就是 |
这个区别不是玄学。Claude 经过 RLHF 训练后,会把"可以检查自己是否做到"的指令当作约束,把"无法自我验证"的指令当作软性建议------而软性建议在遇到其他优先级更高的任务目标时,会被自然地让路。
核心原则二:有效的指令只有一种------阻止一个 Claude 会犯的具体错误,且 Claude 自己能验证是否遵守了。
如何写出有效的指令
❌ 无效写法
markdown
- 写代码时注意安全性
- 保持代码风格一致
- 谨慎处理数据库操作
- 确保测试覆盖率
✅ 有效写法
markdown
- 永远不要直接编辑 package-lock.json,只通过 npm install 修改
- 所有数据库迁移文件必须有对应的 rollback 脚本
- 新增功能前先检查 /tests 目录是否存在对应测试文件
- 环境变量只从 .env.example 读取,不硬编码在代码里
- 修改 API 接口前,先确认没有其他模块依赖该接口签名
对比一下:后者的每一条,Claude 都可以在执行完后自问"我做到了吗?"------答案是明确的是或否。前者的每一条,Claude 都可以在做了任何事之后说"我觉得我做到了"。
判断标准:如果一条指令无法被违反,它就不是约束,是废话。
三层结构:大多数人完全不知道
Claude Code 支持三个层级的配置文件,绝大多数人只用了其中一个:
swift
~/.claude/CLAUDE.md ← 全局层(每个项目都生效)
.claude/CLAUDE.md ← 项目层(入 git,团队共享)
./CLAUDE.local.md ← 本地层(gitignore,个人 override)
全局层 ~/.claude/CLAUDE.md
放跨项目通用的硬性规则。这里的规则适用于你用 Claude Code 做的一切事情。
markdown
## 安全红线(全局)
- 永远不要在代码里硬编码 API key、密码或 token
- 不要提交 .env 文件,即使用户要求也不行
- 看到 credentials/ 目录里的文件,只读不写
## 输出规范(全局)
- 修改文件前先说明你要做什么,等我确认
- 不要一次性修改超过 3 个文件,除非我明确要求
项目层 .claude/CLAUDE.md
放这个项目的技术栈上下文和团队规范。这个文件应该入 git,让团队所有人共享。
markdown
## 技术栈
- Node.js 20 + TypeScript 5.3,使用 ESM 模块
- 数据库:PostgreSQL 15,ORM:Prisma
- 测试框架:Vitest(不是 Jest)
## 项目约定
- API 路由统一放在 /src/routes/,每个文件对应一个资源
- 数据库查询只能在 /src/services/ 里,不能在 routes 里直接查
- 错误处理统一用 /src/utils/errors.ts 里的 AppError 类
## 常见错误(已验证)
- 不要用 `req.body` 直接存数据库,必须先经过 Zod schema 验证
- Prisma 查询记得加 .catch() 或 try/catch,不要让 unhandled rejection 冒泡
本地层 ./CLAUDE.local.md
放个人偏好和临时 override。这个文件加入 .gitignore,不影响团队。
markdown
## 我的个人偏好
- 我习惯用 tabs 不用 spaces(项目用 spaces,但我本地格式化用 tabs)
- 生成代码时少用注释,我自己会加
- 解释方案时直接给结论,不要先列三个选项让我选
三层分离的好处:不同生命周期、不同受众的规则,各归其位,不互相污染。
实战:精简 CLAUDE.md 的四步法
Step 1:审计现有内容
把你现有的 CLAUDE.md 逐行过一遍,对每一条问:
- 这条指令 Claude 违反了会怎样?(如果没有后果,删掉)
- 这条指令来自一次真实的、让我痛苦的错误吗?(如果不是,删掉)
- 这条指令 Claude 能自我验证吗?(如果不能,重写)
Step 2:从错误倒推规则
最好的 CLAUDE.md 是从痛苦经历里提炼出来的。
每次 Claude 犯了一个让你头疼的错误,不要只是修复它,而是:
- 把这个错误写成一条具体的"不要做 X"规则
- 加进对应层级的 CLAUDE.md
- 验证下次这个错误是否消失了
这样你的 CLAUDE.md 会随着使用越来越精准,而不是越来越臃肿。
Step 3:控制总长度
给自己设一个硬性预算:项目层 CLAUDE.md 不超过 50 条规则。
超过了?说明你在往里堆文档,而不是写约束。把多余的内容移到 README 或单独的设计文档里。
Step 4:定期清理
每隔一段时间过一遍,删掉已经不再相关的规则。比如"不要用 Vue 2 的 Options API"------如果你的项目已经全面升级到 Vue 3 Composition API,这条规则就是噪音。
CLAUDE.md 应该是活的约束集,不是历史档案。
一个可以直接用的模板
markdown
# [项目名] --- Claude Code 配置
## 项目上下文(简短)
[2-3 句话描述项目是什么,用什么技术栈]
## 硬性约束(Claude 必须遵守的)
- [具体规则 1]
- [具体规则 2]
- [具体规则 3]
## 常见错误(历史上 Claude 犯过的)
- 不要做 [具体行为],因为 [具体后果]
- 不要做 [具体行为],正确做法是 [具体替代方案]
## 目录结构约定(如果项目结构非标准)
- [路径] → [用途]
- [路径] → [用途]
注意这个模板里没有:
- 任何关于 Claude "应该是什么样的人"的描述
- 任何模糊的质量建议
- 任何 Claude 本来就会做的事情的提醒
写在最后:写给机器的规则,和写给人的文档,是两件事
大多数人的 CLAUDE.md 写不好,是因为他们在用写文档的思维写约束。
文档可以模糊,可以依赖读者的推断能力,可以用"注意"、"尽量"、"最好"这类词。约束不行------约束要么是硬的,要么没有意义。
把 CLAUDE.md 想象成单元测试:每一条都在断言一个具体的、可验证的行为。通过的测试是隐形的(Claude 默默做对了);失败的测试会立刻让你知道(Claude 犯了你已经预见到的错误)。
少即是多。50 条精准的约束,远好过 500 行的愿望清单。
参考来源:Reddit r/ClaudeCode 社区讨论、Claude Code 官方文档、Anthropic 提示工程指南