如何为项目写一份高效的CLAUDE.md?AI编程协作实战指南
给项目配一份CLAUDE.md这事听起来特别像写文档但实际做起来完全是另一码事。我做AQ-Chat一个把实时聊天和大模型对话揉在一起的应用时被Claude Code坑过很多次——不是它能力不行而是它每次进到我的代码仓库里都像一个第一天入职且没人带的新人不知道项目用什么技术栈、不知道构建命令是什么、不知道代码规范放哪、甚至不知道哪条分支才算主干。后来我花了一整个下午把这份CLAUDE.md For AQ-Chat写好再让它干活效果完全是两个级别。这篇文章就围绕这份文件的产生过程来写包括我踩过的坑、沉淀下来的写法、以及一份可以直接抄走的模板。1. 项目概述AQ-Chat是什么CLAUDE.md要解决什么问题1.1 AQ-Chat项目的基本盘先交代一下AQ-Chat本身。它是一个实时消息与AI助手对话的混合型聊天应用前端用React 18 TypeScript Vite搭建后端是Node.js 20 Express数据库用PostgreSQL Redis实时通信走Socket.IO另外有一个独立的AI模块负责把用户提问转发到大模型接口并流式返回回答。整个仓库由四个目录组成web前端、server后端、shared前后端共享的TypeScript类型与工具函数、infraDocker Compose、Nginx配置和部署脚本。这类项目有个特点目录多、命令多、约定多。web和server各有各的package.json、各有各的lint规则shared里的类型改动会同时影响两端AI模块还涉及API Key和环境变量管理。任何一个新人或AI初次进入仓库光靠翻代码很难在短时间内搞清楚改哪里、怎么跑、怎么测、怎样才算符合规范。我最初把Claude Code放进这个仓库时它连npm run dev:web和npm run dev:server要分开跑都不知道还经常拿web目录的命令去跑server的代码折腾得我一度想放弃。事后想明白了问题出在我这边——我没给它一份干活的说明书。1.2 CLAUDE.md的真实定位很多人在项目里第一个想到的是README。但README是给人看的它讲项目的意义、功能亮点、安装方式恨不得写成宣传册。而CLAUDE.md是给Claude Code这类AI编程工具看的运行手册它不讲情怀只讲事实。AI不需要知道AQ-Chat致力于打造流畅的对话体验它需要知道的是前端dev server跑在5173端口后端跑在3001端口Redis必须先用Docker起起来。换句话说CLAUDE.md解决的是AI进入一个陌生代码库后如何正确地合作这个问题。它把项目的技术栈、目录结构、常用命令、代码规范、开发流程、禁忌事项固化成一个文件让AI每次进入会话时都能快速加载不用我在对话里反复交代。对我来说最大的价值是省时间以前每次开新会话都要重新口头讲背景讲得再详细下一次会话照样忘得一干二净。有了这份文件背景知识变成仓库的一部分随代码一起提交、一起演进谁来接手都不会丢。1.3 为什么选择用CLAUDE.md来管理AI协作可能有人会问为什么不直接在对话里告诉它或者写个.cursorrules我在实践里的感受是对话里的指令是一次性的上下文一滚动就没了.cursorrules绑定在特定编辑器生态里团队其他人用别的工具就指望不上。CLAUDE.md的意义在于它把项目级AI协作规范做成了一种事实标准——被Claude Code原生支持放在仓库根目录就能自动读取。你还可以在子目录里放更细粒度的CLAUDE.md做局部约束。这套机制比我试过的任何靠嘴交代都靠谱。当然写CLAUDE.md不是把README抄一遍就完事。它有自己的内容组织逻辑、表达方式和维护节奏。下面我拆开细讲。2. 内容架构动笔之前先想清楚放什么2.1 五个核心模块我写CLAUDE.md时会严格按以下几个模块来组织内容顺序基本固定模块解决的问题典型内容项目概况与技术栈让AI快速建立认知一句话项目介绍、核心框架、语言版本、关键依赖常用命令让AI能把项目跑起来dev/build/test/lint/migration等命令及端口号目录结构与代码约定让AI知道去哪改、怎么改目录职责、命名规范、类型约束、接口规范开发工作流让AI遵守团队协作方式分支策略、PR要求、提交信息格式、schema变更流程禁忌与注意让AI不踩坑不要改哪些文件、不要提交什么、哪些操作有副作用这个顺序不是拍脑袋定的。AI读取CLAUDE.md时有上下文上限靠前的内容会被优先记住所以越重要的越靠前。项目概况放第一段是让AI先建立全局背景命令放第二是因为它后面做任何操作都得用到规范与工作流放主体是它干活时高频查询的内容禁忌放最后但我会在概况或命令里用一两句强约束提前点出来防止AI在前面章节的引导下做出危险操作。2.2 写给AI看的文档和写给人类看的文档有什么不同我踩过最大的坑就是用写README的思维写CLAUDE.md。写README你可以说后端服务通过npm启动人看了能理解AI看了会纠结到底是npm start还是npm run dev在哪个目录执行端口多少所以面向AI的文档核心原则是可执行、无歧义、少修饰。具体来说有三点。第一命令必须完整写从工作目录到执行命令再到预期结果一条条列清楚例如在仓库根目录执行npm run dev:web前端dev server启动在http://localhost:5173。第二规则要写成条件句例如如果新增了数据库字段必须先创建migration文件再提交而不是泛泛的注意数据库变更。第三不要堆形容词AI理解不了高效的优雅的但能理解禁止使用any函数必须显式标注返回类型。我还会刻意把否定指令写上。AI在自由发挥时很容易跑偏到它认为合理但不符合项目现实的做法。例如我明确写过不要使用nodemon重启后端统一用ts-node-dev因为它确实会在某些场景自己安装额外的工具。把这些写在纸上比在后面对它反复说别这样要高效得多。2.3 顺序与优先级的设计CLAUDE.md的每一行都在占用AI的上下文窗口内容一定要贵精不贵多。我的做法是先写一个完整版本然后反复压缩能合并的条目合并能删掉的铺垫删掉最终目标是让全文在AI一次加载时不至于把其他信息挤出去。优先级上我认为会跑偏的规范 常用的命令 详细的架构描述。也就是说与其花500字给AI讲AQ-Chat的微服务拓扑不如先用200字告诉它不要直接改shared里的类型改完必须同步更新两侧引用。因为AI大部分时候在做具体的编码任务而不是在做架构级推演你给它讲清楚边界和红线比给它画全景图更有用。3. AQ-Chat的CLAUDE.md实操编写流程3.1 第一步把项目里能挖的信息全部挖出来动笔之前我先把仓库里所有会暴露事实的文件过一遍。这个环节不需要AI人工很快就能做完但值得认真做因为里面很多内容平时根本不会留意。我习惯这样收集素材读根目录的package.json记录所有scripts包括dev、build、test、lint、typecheck、migration相关命令读README的开发章节看看维护者自己认为哪些步骤是标准动作看docker-compose.yml明确DB、Redis等服务怎么启动、端口怎么映射翻目录结构确认每个一级目录的职责边界翻.env.example或config目录了解有哪些环境变量、哪些是必填项翻最近几条commit message感受团队实际的提交风格。我把结果整理成一张速查表作为编写素材。以AQ-Chat为例我记录下来的关键事实包括前端命令集中在web/package.json根目录的npm scripts只做了个转发后端数据库连接依赖环境变量DATABASE_URL本地开发用docker-compose起的PostgreSQLshared目录被web和server同时以workspace依赖引用所以改shared里的代码必须保证两端TypeScript编译都通过。这些细节如果没有提前挖出来写出来的CLAUDE.md就会漏洞百出。3.2 第二步逐模块填写核心内容下面贴一份我实际使用的CLAUDE.md简化版保留了完整骨架你可以直接当模板参考# CLAUDE.md 本文件为Claude Code提供AQ-Chat项目的开发指南。请先通读本文件再执行任何代码变更。 ## 项目概述 AQ-Chat是一个实时聊天应用支持Web端消息收发与AI助手对话。 - 前端React 18 TypeScript Vite目录 web/ - 后端Node.js 20 Express TypeScript目录 server/ - 数据库PostgreSQL 15 Redis 7Docker Compose管理配置在 infra/ - 实时通信Socket.IO后端事件前缀 chat: 和 ai: - AI模块通过OpenAI兼容接口调用大模型相关代码集中在 server/src/ai ## 常用命令 - 首次安装依赖在仓库根目录执行 npm install - 启动基础设施在 infra/ 目录执行 docker compose up -d - 启动前端dev server在仓库根目录执行 npm run dev:web端口5173 - 启动后端dev server在仓库根目录执行 npm run dev:server端口3001 - 类型检查npm run typecheck会同时检查web与server - 运行测试npm test使用Jest配置文件在 server/jest.config.ts - 代码规范检查npm run lint 与 npm run lint:fix - 数据库迁移npm run migration:generate -- --namexxx 与 npm run migration:run ## 目录结构与变更规范 - web/前端代码按页面功能拆分子目录新页面组件放 web/src/pages - server/后端代码路由统一挂载在 /api/v1 前缀下业务逻辑放在 server/src/services避免堆在controller里 - shared/前后端共享的TypeScript类型与工具函数修改后必须在web和server同时跑 npm run typecheck - infra/Docker Compose、Nginx配置与部署脚本禁止直接修改已上线的compose文件 ## 开发工作流 - 分支命名feat/描述、fix/描述、refactor/描述 - 提交信息使用Conventional Commits例如 feat(web): 增加消息已读状态 - PR合并必须通过CI全部检查项至少一人review - 涉及数据库schema变更时必须先创建migration文件不允许直接改已有的migration ## 代码风格与约束 - TypeScript使用严格模式禁止使用 any如确需绕过需在代码中加 // eslint-disable-next-line typescript-eslint/no-explicit-any 并说明原因 - 组件命名使用PascalCase文件名与被导出组件同名 - 后端接口返回统一使用 { code, data, message } 结构 - 日志使用项目封装的logger禁止直接 console.log - 不要修改 web/src/styles/global.css 的基础变量如需新增主题色先在 theme.ts 中定义 ## 禁忌与注意 - 不要删除或重命名 server/src/ai 下已存在的prompt模板文件AI模块的动态prompt依赖文件命名 - 不要直接改 shared/ 的类型后再手工同步两端应使用 npm run typecheck 校验 - 不要在 web/ 或 server/ 单独执行不确定的安装命令依赖新增必须从仓库根目录统一管理 - 所有涉及真实用户数据的改动必须在测试环境验证禁止在生产环境直接操作数据库这份文件的每一节都可以找到对应刚才说的五个模块。特别要说的是代码风格与约束这一块我把禁止使用any和不要直接console.log写成明确的否定句而不是建议避免。AI对否定句的执行力比我预想的要强得多。如果你在实践里发现它老在某些细节上反复踩线多半就是你的约束句子还不够绝对。3.3 第三步分层放置与引用CLAUDE.md不一定要写成一个文件。如果AQ-Chat里某个子系统的复杂度特别高比如server/src/ai下面有大量prompt模板、模型调用策略、流式返回逻辑全塞进根目录文件会把上下文撑爆。所以我会在根目录放一份全项目级别的CLAUDE.md再在复杂的子目录里放一份局部的子目录CLAUDE.md。子目录的CLAUDE.md只覆盖该目录内的工作内容比如server/src/ai/CLAUDE.md就写这个目录下几个模块分别做什么、新增模型接入要改哪几个文件、prompt版本管理用什么命名方式。Claude Code读取时会自动把子目录文件与根目录文件合并于是AI既有全局背景又有局部细节。更深层的用法是通过路径语法在对话里手动导入特定文档片段但对我来说大多数场景根目录加子目录两层已经够了。3.4 第四步提交前自检与后续维护CLAUDE.md写完之后不要急着提交先做一次自检。我对着文件问三个问题。第一这里面的每一条指令AI是否能直接执行如果某句话还需要咀嚼那就重写。第二是否与仓库当前事实一致如果package.json里的命令已经变了文件就必须同步更新过期的说明比没有更糟。第三有没有冗余内容如果某段描述80%的会话都用不上直接删掉。维护节奏上我把它当成代码的一部分每当我新增一个npm script、改一次目录结构、换一个技术选型都会顺手更新CLAUDE.md。我甚至会在PR描述里加一个checklist提醒自己检查CLAUDE.md是否需要同步。正是这种随手维护的习惯让AI每次读取到的都是当前仓库的真实状态而不是一份过期的考古文献。4. 常见问题与排查技巧实录4.1 CLAUDE.md没有被AI读取或遵循最常遇到的情况是我明明写了CLAUDE.md但Claude Code的行为完全不像读过它。排查顺序一般是这样的。先确认文件是否在正确的路径——必须是仓库根目录的CLAUDE.md名字全大写小写claude.md在某些大小写敏感的环境下不会被自动加载。再看文件编码和格式如果开头有奇怪的BOM头或空行偶尔会导致解析异常。最后是权限问题文件至少要有可读权限。如果加载正常但规则没生效那多半是规则写得不够明确或者太靠后导致AI没记住。我的解决办法是把最高优先级的红线比如不要改shared的类型在文件开头用两三句强约束重复一次并且把冲突类规则写得更细。规则越具体遵从度越高。4.2 文件太长导致AI注意力分散CLAUDE.md不是越长越好。我早期犯的错是写了一份3000字的说明书结果AI在长任务里经常忘记后面的内容甚至会因为前面几条互相冲突的表述而产生错误决策。后来我强制把根目录文件压到1000字以内把细节下沉到子目录CLAUDE.md效果立刻改善。压缩技巧有三个。第一把背景说明删掉只留动作指令第二把相似规则合并成一条列举句比如接口返回统一使用{ code, data, message }结构就比为了让前端统一处理错误我们设计了一套响应结构包括...省不少字且无信息损失第三能用表格说清楚的事不用散文比如端口号、目录职责这种表格一眼就能扫完。4.3 指令与实际代码库冲突还有一类典型问题CLAUDE.md本身写得没问题但仓库实际代码并没有完全遵守文件里的约定。比如我说组件命名使用PascalCase可代码库里其实混着一堆kebab-case的老组件。这种情况下AI会陷入两难听文件的还是听现有代码的我的经验是在CLAUDE.md里明确优先级新代码必须遵守本文件约定老代码在不影响功能的前提下可以按需重构但不要大范围改动存量文件。同时把确实无法统一的地方列成已知例外。这样做既保持AI的前后一致性也避免它为了统一规范而擅自重写大量代码导致review成本暴涨。4.4 常见问题速查表症状可能原因处理办法AI不执行跨目录命令命令没写工作目录每条命令明确在哪个目录执行AI频繁安装多余依赖没有写依赖管理约束加统一从根目录管理依赖的强约束AI修改了不该改的文件未声明文件边界用目录级白名单/黑名单说明上下文被大量文档占用CLAUDE.md过长拆分到子目录或压缩到1000字以内规则互相冲突条目表述自相矛盾定期审查保证优先级一致新功能跑了旧命令命令未随项目更新把CLAUDE.md纳入PR checklistAI不遵守否定指令表述不够绝对改成禁止不要不允许等强否定句我自己的体会是CLAUDE.md这种文件的本质是把和AI协作时的隐性知识显性化。写完AQ-Chat这份文件之后最明显的变化不是少打了几行字而是AI每次进入项目都像同一个老同事——它知道你跑服务的顺序、知道代码放哪、知道哪些是不能碰的红线你只需要告诉它把AQ-Chat的AI回复流改成SSE格式它就知道该去server/src/ai里找哪几个文件、改完怎么验证。最后再分享一个小技巧写完之后故意开一个全新会话丢给它一个中等复杂度的任务看它第一轮的行为是否符合预期。这一轮试跑能暴露出CLAUDE.md里所有你自以为写清楚了但实际含糊的地方比读十遍文档都管用。