CLAUDE.md:写给Claude Code的项目共识手册,让AI效率翻倍
1. 为什么说 CLAUDE.md 是 Claude Code 项目里的“隐藏功能”先说个我自己的经历。第一次拿到 Claude Code 的时候我完全是用聊天窗口的思路去用的在终端里写下需求等它逐行执行然后我发现效果远没有宣传里那么神奇。代码改到一半就忘了项目结构刚说完的技术方案换个会话就彻底失忆同一个报错被它解决过三次第四次于同一个坑里再次跌倒。后来我才意识到问题不在模型能力而在缺了一本“给 AI 看的项目手册”。Claude Code 启动时会把项目里的 CLAUDE.md 当成第一页上下文读进去但绝大多数人从来没写它或者只写了三五行“你是一个编程助手”之类的废话。于是这个文件成了整个工作流里最不起眼、却最值得投入的一环——Carather. 从效果来看写好 CLAUDE.md 前后的差距确实可以用“放大 100 倍”来形容。这个结论不是玄学背后有非常直接的机制原因。Claude Code 是一个长上下文 agent它的每一次工具调用、每一段代码生成都建立在“它对当前项目状态的理解”之上。你可以在对话里反复叮嘱它一百遍“记住用 pnpm”但只要会话一关全部清零而 CLAUDE.md 是每次启动都稳定存在的资产。它不是提示词模板而是你写给机器的“团队共识”是项目的运行时记忆。如果你正在用 Claude Code 做每周的代码任务、大型重构、脚手架搭建或者只是想在接手别人代码时少踩点坑那么我今天想聊的这份 CLAUDE.md应该能让你少走很多弯路。这篇文章不打算讲什么高深理论就是从一个实际项目配置者的角度拆一拆我踩过的坑、试出来的结构以及为什么这个东西比大多数人想象中重要得多。1.1 “又一个配置文件”的错觉为什么多数人根本不碰它CLAUDE.md 看起来实在太平凡了。一个 markdown 文件放在项目根目录没有任何高亮、没有任何代码高亮要求既不影响运行也不影响编译——很多人会觉得它跟“项目简介”差不多随便写两句就算完了。我刚接触时也是这样第一次打开它里面只有一行“你是一个帮助用户完成开发任务的 AI 助手”。然后我就把所有希望寄托在对话本身结果是一次又一次地重复解释先解释这是 monorepo再解释服务端代码在哪里再解释测试怎么跑。每开一个新会话就要重新武装一遍这只 AI而且要捡起的细节数量几乎不可控。实际用下来你会发现CLAUDE.md 能解决的问题恰恰是每次会话丢失的那部分——项目结构、命令习惯、技术边界、已知隐患。它等于给 Claude Code 装了一个“冷启动缓存”让 AI 一开始就跑在正确轨道上而不是靠你在聊天框里现场补课。1.2 和聊天窗口式的调教完全不同相当多人习惯用“在对话里多重复几次”来调教 AI。遇到问题就补充一句“记住以后都怎么做”在单次长会话里确实有点用但跨会话就全部归零。更关键的是聊天式调教的信息是隐性的模型只能从它回答过的几十轮中推断你的偏好很容易猜偏。CLAUDE.md 则是显性的它直接把约束写到上下文里不需要模型猜测。比如你写“本项目禁止使用any”它下一次生成代码时就会直接避开而不是等到你 review 时才发现然后打回重改。这种“把规则前置”的思路和写代码注释、做 Code Review 其实是完全同构的与其事后反复纠错不如事前定义边界。2. 一份真正能打的 CLAUDE.md 长什么样从“项目简介”改成“项目共识”我把我自己项目里的 CLAUDE.md 从第一版改到第七版之后总结出一个结论这个文件的正确名字不叫“项目说明”而应该叫“项目共识”。它需要回答的不是“这个项目是干什么的”而是“在这份代码里工作哪些事情永远是对的哪些事情永远不能做”。你完全可以把它想象成一位新同事入职第一天发到手里的手册。手册里不会写“我们的公司是卖软件的”而会写“代码提交前必须跑 lint”“数据库变更要走迁移脚本”“CI 上不要手动补环境变量”。Claude Code 就像一个能力很强但完全不了解本地规矩的新同事CLAUDE.md 就是让它快速入伙的那本手册。我尝试过的无效写法包括写大段空泛的原则“请写出高质量的代码”、写和 README 重复的项目介绍、写已经过时的目录树。它们不是没有用而是信息密度太低等于把宝贵的上下文窗口浪费在废话上。2.1 九类真正值得写进去的内容经过反复试错我把值得写进 CLAUDE.md 的内容收敛成了下面这九类。每一条都得有“可操作的动作”而不是一句抽象口号。第一类任务基线和命令规范。这里写清楚“运行测试、启动开发服务器、构建产物、代码格式化、类型检查”分别是什么命令。我见过太多 Claude Code 生成代码后不知道如何验证然后自作主张用node直接跑源码结果因为不支持 TS 语法而报错。你如果把pnpm dev、pnpm test、pnpm build:check写进 CLAUDE.md它就会老老实实按项目的方式验证修改。第二类目录地图。不需要复制整棵目录树只需要标注“哪个目录是入口”“哪个目录是纯组件”“哪个目录是共享工具”“哪个目录是服务端逻辑”。对 monorepo 来说尤其关键Claude Code 默认看到的是一堆同名文件夹如果没有目录说明它极可能改错包。第三类代码风格和禁区。这包括显式的偏好条款和红线。比如“组件命名必须用 PascalCase”“API 返回类型必须显式声明”“状态管理只允许使用现有库不允许新引依赖”“禁止把环境变量硬编码进源码”。这些条款越具体它生成的产物就越接近你本来就会 review 通过的样子。第四类技术栈锁定。写明这个项目用的是什么版本的运行时、框架、包管理器以及是否允许升级依赖。Claude Code 有时会“好心”给你引入一个你完全不认识的新依赖而写死技术栈能有效减少这种顺手牵羊。第五类已知陷阱和历史坑。比如“测试环境有时会出现缓存导致误报遇到 xxx 错误请先清缓存”“npm install不要直接跑请优先使用 pnpm install”。这类信息很难直接推导出来只有踩过坑的人才知道写上去能省下一轮很长的排查时间。第六类工作流顺序。比如“修改代码前先跑一次测试确认基线”“实现新功能前先给出技术方案让我确认再动手”“改接口必须先改类型定义再改实现”。这其实是给 agent 加了一层“流程护栏”避免它一拿到需求就直接往前冲。第七类验收定义。告诉它“什么状态算完成”。比如“单测通过 lint 通过 无回归 有变更记录”。对写文档类任务就是“包含步骤说明 包含示例 不含遗留 TODO”。第八类模块边界。哪些代码是核心逻辑改动时必须特别说明哪些是临时脚本改坏了也无所谓。这让 AI 知道轻重缓急不会把重构玩具脚本的时间和改核心逻辑的时间混为一谈。第九类沟通偏好。比如“讨论时用中文代码注释用英文”“在动手前先列任务清单让我过目”“当发现需求有歧义时主动列出你的假设”。这一点容易被忽略但非常影响整体体验。2.2 一个越写越短的迭代心法别指望第一版就写出完美手册。我的做法是每次 Claude Code 在一个任务上表现不佳或者做了一件需要我纠正的事我就会反问自己一句话——“如果这条规则在 CLAUDE.md 里下次是不是就不会犯”如果答案是“会”那就立刻把规则加进去。这样迭代几轮之后CLAUDE.md 会变得越来越“像个懂行的人”而不是越来越厚。真正稳定下来的版本往往很短因为大部分空泛话语都会被删掉只留下经受过实战检验的硬约束。我现在的几个主力项目CLAUDE.md 大概控制在 60 到 120 行之间没有冗余段落。3. 一份可以直接抄作业的 CLAUDE.md 模板与落地实录理论说了不少下面放一份真实可用的模板。它不追求普适而是以“Node.js TypeScript React”项目为例因为我发现这类项目最容易从 CLAUDE.md 中获益依赖多、命令多、模块边界容易模糊AI 犯错的空间也够大。这份模板是我从当前项目的文件里节选并脱敏以后的结果你可以直接复制到自己的项目里改也可以只挑走对你有用的段落# CLAUDE.md ## 项目总览 这是一个面向 B 端用户的报表配置平台前端使用 React TypeScript 后端是 Node.js Express数据库通过 Prisma 访问 PostgreSQL。 包管理器统一使用 pnpm禁止使用 npm / yarn。 ## 目录结构 - apps/web前端应用页面组件统一放在 src/pages 下 - apps/server后端服务路由按领域划分禁止把业务逻辑写进路由 - packages/shared前后端共享类型和工具函数不依赖任何框架 - scripts一次性脚本不得放入业务逻辑 ## 常用命令 - pnpm dev启动完整开发环境前后端并行 - pnpm test运行所有单元测试 - pnpm test:watch只监听当前改动文件对应的测试 - pnpm typecheck全量类型检查 - pnpm lint运行 eslint提交前必须通过 - pnpm build:server构建后端 ## 代码风格 - 组件统一使用函数式组件命名 PascalCase文件使用 kebab-case - 禁止在业务组件里直接写 fetch必须使用 packages/api/client 下的封装 - API 响应必须包裹在 ApiResponseT 类型中禁止裸返回 - 所有日期时间统一使用 dayjs 处理禁止输出本地时区字符串 - 不要给已有代码大规模重排减少与主分支无关的 diff ## 技术栈锁定 - React 18Vite 构建版本已锁定未经明确指示不要升级任何依赖 - Node.js 版本以项目根目录 .nvmrc 为准 - 新增依赖前必须先列出理由和体积估算由用户确认 ## 已知陷阱 - 测试环境使用内存数据库首次跑会有一点慢不是卡死 - 修改 Prisma schema 后必须先 pnpm exec prisma generate - .env.local 里的 mock 开关不要动数据展示单靠它区分 - 如果集成测试挂在了 “webhook” 相关用例先查看测试说明可能有模拟服务器依赖 ## 工作流 1. 接到任务后先列出任务拆解和关键假设 2. 改动前跑一次 pnpm test 确认基线通过 3. 每完成一个子任务就执行一次 pnpm typecheck 4. 全部完成后跑 pnpm lint pnpm test通过才算交付 5. 涉及 UI 改动时先简单描述改动区域再动手避免自由发挥 ## 沟通偏好 - 使用中文说明问题和方案代码与注释保留英文 - 收到需求时如果存在歧义不要猜测列出 2~3 种理解供选择3.1 为什么每个字段都要写成“可执行指令”注意我上面所有条目都没有写成“请务必保证代码质量”而是写成了一条条可以立刻落到命令行、文件路径、命名规范上的具体约束。原因很简单Claude Code 对“抽象要求”的响应非常不稳定。你说“高质量代码”它理解不了你的质量阈值你说“pnpm lint 必须通过”它至少知道跑完以后要检查退出码。这种写法的另一个好处是它等于给 AI 配了一把“自测尺子”。任务完成后它会主动跑pnpm typecheck跑完发现报错还会继续修直到通过。如果没有这把尺子它很可能改完业务代码就宣布完事把验证工作全部留给你。3.2 从“几乎不读”到“完全信任”的改版记录我最早写的版本只有 15 行内容全是“你是这个项目的 AI 助手”之类的话。后来第一轮遇到严重跑偏它在一个表单页面里新增了一个依赖理由是“为了更好的日期选择体验”结果那个库没人维护安全审计直接报警。我在复盘时就把“新增依赖前必须先确认”写了进去。第二轮是它把服务端的一个路由直接重构掉了原因是“把逻辑清晰化”。从代码质量角度可能没错但那块逻辑客户还依赖旧行为结果产生了一个线上问题。这件事之后我加了“核心业务逻辑改动前必须先说明影响范围”的条款。第三轮的问题比较隐蔽它测试通过后直接提交没有跑 lint导致 CI 挂了。这件事之后我就把“提交前跑 lint test”写进工作流固定成第一步。你可以看到每一轮教训都会沉淀成一条具体条款而条款一多AI 的自由发挥空间就被压缩了反而产出更稳定。4. 让 CLAUDE.md 真正生效加载机制、本地覆盖与常见误区CLAUDE.md 写好了还得知道它什么时候生效、在哪些场景下可能失效。很多人写了文件以后发现 AI 还是“不听话”于是得出结论“这功能没用”其实多半是没搞懂加载细节。Claude Code 在启动时会自动读取项目根目录和相关子目录里的 CLAUDE.md并把内容放进系统上下文。这意味着你可以在项目根目录放一份通用规则在某个特殊模块目录里放一份局部覆盖规则。比如根目录规定“测试用 Vitest”而某个旧模块是 Mocha 写的你可以在那个子目录里放一份 CLAUDE.md 说明“该模块测试沿用 Mocha不要自动迁移”。层级优先级上子目录的 CLAUDE.md 描述的信息离实际文件更近约束通常会覆盖根目录的通用规则。这一点我用过之后就再也不想回到单文件模式了尤其是 monorepo 场景下这种分层管理几乎是刚需。4.1 别指望它“实时重载”会话中间的变更需要手动确认有一次我中途在 CLAUDE.md 里加了一条“不要改 packages/shared 的公共接口”然后继续让 Claude Code 干活结果它照样改了公共接口。我一度以为是文件不生效后来才发现机制问题Claude Code 是在会话启动时读取 CLAUDE.md 的中途新增的内容不会自动注入当前上下文。解决办法有两个一是新开一个会话再发任务让全新上下文加载新版手册二是在当前会话里明确要求它“先重新读一遍根目录的 CLAUDE.md 再继续”。第二种办法通常也能奏效因为 Claude Code 有文件读取工具你让它再看一次它就会根据新规则修正后续行为。这个细节很容易被人忽略一旦知道了你就能在规则调整时做出正确的选择而不是对着一个“不听话”的 agent 发火。4.2 全局 CLAUDE.md 与项目 CLAUDE.md 的职责边界Claude Code 还支持在用户主目录放一份全局的 CLAUDE.md作为跨项目的基线习惯。我的建议是全局文件只放一些永远不变的原则比如“不主动执行破坏性 git 操作”“遇到无法确定的需求时先提问”等项目文件则放项目专属结构、命令和坑点。如果把项目专属信息写进全局文件会导致所有项目共享一份“大杂烩”上下文被无意义内容占满反而稀释了真正重要的项目规则。反过来如果只写项目文件不写全局文件跨项目的好习惯就得不到沉淀。两者配合才是一个完整的规则体系。4.3 规则冲突时的表现与排查路径当根目录和子目录的规则冲突时Claude Code 的行为需要实测。我遇到过的情况是根目录写着“禁止使用 any”子目录写着“本目录为历史遗留代码允许使用 any 以保持兼容”最终 agent 在子目录里优先采用了后者。这很符合“越靠近文件的指令越优先”的直觉但你不该只靠直觉最好在关键模块动手前先问一句“你依据的是哪条规则”。如果发现它选了你不想要的规则修复方式通常不是重写整个 CLAUDE.md而是在子目录的文件里把冲突规则改得更明确甚至加上“本规则优先级高于根目录中同名规则”这句话。5. 从规则手册升级为指挥手册任务切片、验收清单与自动迭代CLAUDE.md 写好了接下来可以做一件更有想象力的事把它从“规则手册”升级成“指挥手册”。也就是说让它不只告诉 AI 什么能做什么不能做还告诉它“接到一个任务后应该按照什么步骤切分、每一步的验收标准是什么”。我目前最常用的一种结构是在 CLAUDE.md 里内置任务工作流。比如要求它在拿到需求时先输出一份拆解清单格式是- 需求理解用三句话复述用户想要什么 - 影响面列出需要改动的文件与潜在风险 - 实现步骤分阶段列出每阶段包含验收方式一旦 Claude Code 开始按这个格式输出你会发现它的执行力变得非常可控。它不再是一上来就噼里啪啦写一堆代码而是先跟你对齐思路。你确认完后它再进入实现。这个过程看起来只是多了一步“解释”但实际上把返工成本降了一个量级。5.1 把验收清单写进 CLAUDE.md效果立竿见影我见过不少团队要求 Claude Code“做完以后自己检查”但没说清楚检查什么AI 当然无从下手。如果把“检查哪些文件、跑哪些命令、什么样的 diff 算干净”写进 CLAUDE.md它就真的会去做。我在实验项目里给 CLAUDE.md 加过一段验收清单pnpm typecheck必须通过、pnpm lint不允许有 error、改动区 diff 中不得出现格式化无关变更、组件 story 文件如果受影响必须同步更新。加完以后它提交产物的质量肉眼可见地上升很多以前要靠代码 review 阶段打回的问题在它自己生成阶段就被过滤器拦住了。5.2 利用项目内引用来实现“CDN 式”的轻量复用Claude Code 的 CLAUDE.md 支持通过语法引用项目内的其他文件。这意味着你不用把所有内容都堆在一个文件里可以把详细的样式规范放在docs/style-guidelines.md然后在 CLAUDE.md 里写“需要设计新页面时先阅读docs/style-guidelines.md”。这种“按需加载”模式非常实用。如果你把所有历史决策都堆进 CLAUDE.md上下文会越来越臃肿。而引用文件只会在任务真正相关时才会被读取既保留了手册的轻量又能在关键时刻引用详细规范。我踩过的一个教训是早期我把整个设计系统的说明全部复制进 CLAUDE.md导致每次对话都携带大量无关内容AI 对核心约束的注意力反而下降了。后来改成“CLAUDE.md 只保留红线与高频规则 低频详细规范使用引用”体感立刻清朗很多。5.3 让 CLAUDE.md 自己进化失败驱动的规则沉淀最后分享一个我多年养成的习惯每个周期结束后我都会把本周里 Claude Code 产生过的问题清单翻一遍逐条判断是否需要新增规则。比如“连续三次在同一类重构中漏改测试”就在 CLAUDE.md 里加一条“重构时必须同步更新受影响测试并在结果中列出改动测试清单”。这个习惯坚持下去你会发现 CLAUDE.md 其实不是一份静态文档它更像一个与 agent 共同演化的契约。刚开始它很粗糙但随着每次失败、每次返工、每次“明明跟它说过了但它还是犯了”的瞬间被转化为条款它就会越来越精准地代表你的开发意图。我曾经一度在会话里反复输入同样的纠正指令换来的是同样的问题改完再犯现在我把纠正直接沉淀到 CLAUDE.md几乎是“说一次管一辈子”。这种一劳永逸的快感是我认为 CLAUDE.md 最值得投入的原因——它不是放大模型的魔法而是把人的经验变成了项目资产让每次会话都站在上一次的肩膀上出发。真要靠这个文件把效率翻上百倍不需要什么神奇配方只需要你愿意花一个下午把脑海里那些默认常识一条一条落到这份小小的 markdown 里。