☰
如何为项目写一份高效的CLAUDE.md?AI编程协作实战指南
2026/10/5 15:48:57 网站建设 项目流程

给项目配一份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类型与工具函数)、infra(Docker 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起的PostgreSQL;shared目录被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 7(Docker 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 -- --name=xxx` 与 `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 checklist
AI不遵守否定指令表述不够绝对改成"禁止""不要""不允许"等强否定句

我自己的体会是,CLAUDE.md这种文件的本质,是把和AI协作时的隐性知识显性化。写完AQ-Chat这份文件之后,最明显的变化不是少打了几行字,而是AI每次进入项目都像同一个老同事——它知道你跑服务的顺序、知道代码放哪、知道哪些是不能碰的红线,你只需要告诉它"把AQ-Chat的AI回复流改成SSE格式",它就知道该去server/src/ai里找哪几个文件、改完怎么验证。最后再分享一个小技巧:写完之后,故意开一个全新会话,丢给它一个中等复杂度的任务,看它第一轮的行为是否符合预期。这一轮试跑能暴露出CLAUDE.md里所有你自以为写清楚了但实际含糊的地方,比读十遍文档都管用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询