CLAUDE.md 最佳实践:该写什么、不该写什么、项目变大后怎么拆
CLAUDE.md 是写给 AI 编码助手的持久工作指令,作用是在每次会话开始时告诉它:这个项目是什么、怎么构建、必须遵守哪些规矩。写好它的关键不是多,而是准——只保留 AI 看代码猜不出来、猜错了又会把活干偏的信息。
它解决什么问题
AI 助手每次开新会话都是”零记忆”状态:不知道项目用 Maven 还是 Gradle,不知道跑测试要加哪个参数,更不知道哪个目录是雷区。这些约束靠每次对话临时交代,既容易遗漏又不稳定。CLAUDE.md 把长期有效的事实固化在仓库里,会话启动时自动注入,相当于给 AI 发了一张入职须知。
要分清它和两类邻居的分工。README 面向人,讲项目背景、愿景和快速上手;CLAUDE.md 面向 AI,讲可执行的工作指令。单次任务的规格文件(Spec)管”这次做什么、怎么验收”,CLAUDE.md 管”在这个仓库里永远都该怎么干活”。把这三者混为一谈,是规则文件越写越乱的根源。
内容组织:该写什么
一份实用的 CLAUDE.md 通常围绕四块内容展开。
技术栈与版本
框架大版本直接影响生成结果:Spring Boot 2 和 3 的配置方式、javax 与 jakarta 的包名都不一样。不写清楚,AI 就可能按训练数据里的旧习惯输出。选型背后的理由也值得附一句——“用 MyBatis-Plus 而非 JPA,因为 SQL 审计依赖 Wrapper 解析”——AI 知道了为什么,才能在相邻场景做出一致的判断。
常用命令
构建、测试、启动、lint 命令用代码块原样给出,AI 不必把自然语言翻译成命令,拿到就能执行:
## Commands |
项目约定与禁区
分层职责、统一返回体、异常处理套路、提交信息格式,这些”新人入职要问一圈”的东西都适合写入。禁区清单同样重要:哪些目录不能动(如 migrations/)、哪些操作被禁止(如事务里调外部接口)。禁令最好搭配替代方案——“不要用字段注入”后面紧跟”统一用构造器注入并参考 UserController 的写法”,AI 才知道该往哪走,而不是绕到第三种错误写法上。
不该写什么
缩进几个空格、import 怎么排序,交给格式化工具;”JPA 实体对应数据库表”这类框架默认行为,写了纯属占地方;大段外部 API 文档不要整篇塞进来,放个路径让 AI 需要时自己读。检验标准是一行一行问:删掉这行,AI 会更容易犯错吗? 答案是不会,就删掉。
分层放置:根目录 vs 子目录
Claude Code 支持多个层级的 CLAUDE.md。用户级(~/.claude/CLAUDE.md)放个人偏好,对所有项目生效;项目根目录的文件放团队共享规范,提交进 Git;子目录里的文件则在 AI 访问该目录时才按需加载,不占每次会话的上下文。
小项目一份根目录文件就够。项目变大后,所有规则挤在一起会让每个会话都背着无关规则,可以分两层拆:根文件只留全局信息并负责”路由”,指向 docs/ 下的详细文档;只对部分代码生效的规则,下沉到子目录 CLAUDE.md,或者 .claude/rules/ 里带 paths 限域的规则文件——编辑 Controller 时才加载 Controller 规范,处理 Service 时它就不出现。拆完记得用 /context 确认规则真的被加载了:文件放对位置,不等于 AI 已经读到。
常见反模式
写太长。 CLAUDE.md 和对话记录、代码共享上下文窗口,文件越长,真正关键的规则越容易被淹没。经验值是控制在 200 行以内;几百行的参考文档不要用 @ 整篇导入,那会让会话还没开始就占掉一大块空间。
写太泛。 “写干净的代码””注意可读性”这类话,删掉之后 AI 的行为不会有任何变化,留在文件里只会稀释有效信息。AI 反复违反某条规则时,加粗、加感叹号通常没用,该检查的是文件是否过长、规则是否放错了作用域。
过期不维护。 项目换了构建工具、改了分层方式,旧规则还留在文件里,AI 拿到的就是错误指令。规则要跟着代码一起演进:同类错误重复出现时补一条,约束失效时删一条;能交给 Linter、Hook、CI 机械检查的,就不要靠自然语言提醒——CLAUDE.md 只能影响倾向,拦不住一次具体的工具调用。
小结
- CLAUDE.md 是给 AI 的持久工作指令,与 README、Spec 分工明确,只写”猜不到、猜错会走偏”的信息。
- 内容围绕技术栈、命令、约定、禁区组织,禁令要配替代方案。
- 分层放置:全局规则常驻根文件,局部规则按目录或路径按需加载。
- 警惕太长、太泛、过期三个反模式,定期用”删掉会怎样”检验每一条规则。

