刚把 Claude Code 装好的那几天,我跟很多人一样,满怀期待地把它指向一个攒了三年的老项目,然后问它:"这个项目的架构是怎么组织的?帮我梳理一下。"结果它给我回了一份看起来非常专业的答案,把目录结构讲得头头是道,里面却有一半是它自己脑补的——把两个已经废弃的模块当成了核心依赖,还热情地建议我把构建工具从 Webpack 换成 Vite。问题不在模型不够聪明,而在于它在打开代码之前,根本不知道这个项目经历过什么、定过什么规矩。这就是 CLAUDE.md 存在的意义:它是 Claude Code 在每次会话启动时自动加载的上下文文件,相当于给 AI 提前交底的"项目说明书"。今天这篇文章,我把自己配置 CLAUDE.md 的整套流程、内容模板和踩过的坑整理出来,给正在折腾 Claude Code 配置的朋友一条能直接走的路。
1. 先把加载机制搞清楚:CLAUDE.md 不是配置文件
很多人一听到"配置"两个字,就默认它跟 settings.json 是同一类东西,以为要在里面放 API Key、模型参数。我第一次也是这么理解的,结果往里写了一堆环境变量,完全没生效。后来才弄明白,CLAUDE.md 在 Claude Code 的体系里属于"上下文记忆"层,它跟传统意义上的配置是两个维度的东西。这个认知不建立起来,后面写多少内容都是白搭。
1.1 CLAUDE.md 与 settings.json 的分工
Claude Code 的配置体系其实由两部分组成。settings.json 管理运行时参数:你连哪个 API 端点、走什么模型、用多少并发、哪些目录要忽略、有哪些权限控制,这些是"程序怎么跑"的问题。而 CLAUDE.md 管理的是"AI 如何看待你的项目":项目是干什么的、代码里有什么约定、测试要跑哪个命令、哪些事情绝对不能做。前者是给工具看的,后者是给模型看的。
这两个文件的分工一定要在脑子里立住,否则很容易出现一种尴尬情况:你在 CLAUDE.md 里写了"调用外部服务时走统一出口",但 Claude Code 根本不会去解析这种指令,它只会把这段话当作项目背景信息的一部分。真正控制工具行为的是 settings.json 里的权限配置。我见过有人把 CLAUDE.md 当万能配置文件用,结果该生效的没生效,不该生效的却因为描述太模糊产生了一堆副作用。
1.2 三个层级的加载顺序与优先级
CLAUDE.md 不是只有一个。Claude Code 在启动时会按固定顺序加载三个层级的上下文文件,后加载的内容会叠加在先加载的基础上,而不是覆盖。第一层是用户级,位于~/.claude/CLAUDE.md,适合放你个人的通用偏好,比如"回应尽量用中文""在给出代码前先解释思路""不要使用 emoji"这些跨项目都成立的规则。第二层是项目级,位于项目根目录,这是绝大多数人最需要维护的文件,承载的是这个项目独有的技术栈、架构和约定。第三层是子目录级,位于项目内任意子目录,比如src/backend/CLAUDE.md只会在模型处理这个目录下的文件时被加载。
这个机制的意义在于分层治理:个人习惯、项目约定、模块细节互不污染。我见过有些团队把所有内容一股脑塞进根目录的 CLAUDE.md,结果文件越写越长,AI 的上下文被大量无效信息占用,反而模糊了重点。更合理的做法是:根目录写"在这个项目里必须知道的整体规则",子目录再写"这个模块特有的注意事项",让 AI 按需读取,而不是一次全量灌入。
1.3 命名、位置与生效方式
文件名就是全大写的 CLAUDE.md,放在对应目录的根下,扩展名是 .md。不需要任何注册步骤,Claude Code 每次会话启动时都会自动读取。如果你在会话中途创建或修改了这个文件,用/clear重建当前会话上下文,新会话启动时会重新加载,不用重启整个终端。
一个小技巧是把最关键的约定放在文件前几行。从我实际使用的体感来看,模型对上下文开头部分的注意力明显高于中间部分,一份一万字的 CLAUDE.md,真正被严格执行的往往就是开头那几屏。我自己的习惯是第一行直接写项目一句话简介,然后紧跟三条"绝不违反"的规则,这样即使后面内容再多,AI 也能精准抓住红线。
2. 内容骨架:一份能真正改变 AI 行为质量的 CLAUDE.md
加载机制理解了,真正的重点是写什么。我踩过两次"写了等于没写"的坑,第一次是写得非常宏观,全是"请遵守最佳实践""注意代码质量"这种废话,AI 读完毫无反应;第二次是写得过于琐碎,把每行代码的格式要求都列了进去,AI 反而抓不住主干。后来我把内容收敛成五个模块,每个模块都遵循"具体、可执行、说人话"的原则。
2.1 项目身份:一句话让 AI 知道自己在哪里
文件开篇只需要两到三段文字,把项目是什么、为谁服务、现在处于什么阶段讲清楚。不需要长篇大论,但信息密度要高。比如:
这是一个面向中小电商团队的订单处理服务,核心职责是同步多平台订单、执行库存扣减、触发售后流程。项目已上线运行三年,当前处于稳定维护期,重构需谨慎,优先保证兼容性。
这段话比"这是一个订单系统"强太多了。AI 看到之后,很多决策会立刻变得靠谱:它不会建议你大刀阔斧改存储结构,因为知道项目在稳定维护期;它不会把订单和库存的概念混淆,因为明确了核心职责。千万别觉得这种"背景介绍"没什么技术含量,它往往是 AI 行为质量最重要的决定因素。我见过太多人跳过这一步,结果 AI 把内部管理系统当成对外 SaaS 来设计,方案完全跑偏。
2.2 事实清单:技术栈、命令与不可违背的约定
第二部分要写这个项目的"客观事实"。这些内容最好是 AI 无法靠读代码就能百分百确定的,或者即使能确定也需要花很大代价才知道的:
- 核心技术栈:语言版本、框架、关键依赖。比如"Python 3.12 + FastAPI + SQLAlchemy 2.0,消息队列用的是 Redis Stream"
- 命令真相:build、dev、test、lint 分别是什么。很多项目的实际命令和默认习惯不一致,直接写出来能省 AI 大量试探时间
- 环境依赖:有没有需要外部服务(数据库、Redis、第三方 API)才能跑起来的前提
- 分支与发布约定:比如"main 分支必须是可发布的,feature 分支从 dev 切出"
这里有一个很关键的写作原则:不要写模糊的"最佳实践",要写确定的事实。比如"代码需要测试"这句话没有信息量;"新增业务逻辑必须至少补充一个针对核心路径的单元测试,运行pytest tests/ -m unit通过后才算合格"这句话才是 AI 能执行的事实。命令这东西最容易出错,因为模型训练数据里的通用命令和你们项目的真实命令经常不一样,你必须在文件里给出"正确答案"。
2.3 架构地图:给 AI 一张不迷路的导航图
大型代码库对 AI 来说最大的问题是"不知道哪些文件是核心、哪些是历史遗留"。你可以写一段目录导航,帮它快速建立全局认知:
核心代码在 src/core/,包括 orders.py(订单聚合)、inventory.py(库存扣减)、webhook.py(外部回调)。src/legacy/ 下的代码不推荐扩展,能不动就不动。测试在 tests/integration,运行较慢,修改核心逻辑后必须跑。
这段内容特别适合有一定历史包袱的项目。AI 有了这张地图之后,被问"订单状态流转在哪里实现"时,不会像无头苍蝇一样全库搜文件。如果你连自己都不太确定架构应该怎么描述,可以先让 Claude Code 分析一遍项目结构,再把它的梳理结果人工校准后写回 CLAUDE.md——它干这种事效率很高,你只需要负责判断和修订。校准的时候要注意,AI 可能会把一些它自己脑补出来的"职责"也写进去,你有必要把每个目录的实际用途核实一遍。
2.4 代码风格与约定:把团队的"潜规则"明说出来
每个团队都有自己的潜规则,比如"函数要写中文 docstring""数据库迁移必须先生成 review 脚本""接口返回结构统一是{code, message, data}"。这些规则新人要靠问才知道,但 AI 是完全不会问的,你不写它就只能靠猜。
我在这一节用了"正面清单 + 负面清单"的组合。正面清单说明要求做什么,负面清单说明禁止做什么。从我的实测效果来看,负面清单往往更有效,因为 AI 在开放式生成时,限制比要求更能约束行为。举几个例子:
- "不要在 service 层写原生 SQL,一律走 repository 封装"
- "禁止在业务代码里直接 log.Print,统一走 logger 模块并带上 request_id"
- "Controller 层只做参数校验和响应组装,不写业务逻辑"
- "不要用枚举字符串做状态比较,统一引用 status 包下的常量"
这些条目不需要解释原因,AI 不需要理解动机,它只需要遵守。写得越具体越不会出歧义,这也意味着你要舍得花时间把团队里最常被违反的那几条规则挑出来,优先写进去,而不是贪多求全。
2.5 一个可直接套用的基础模板
我把以上内容整理成一个模板,你直接复制过去改就可以了。注意,这份模板的核心不是格式好看,而是每一条都足够具体、能被验证。
# 项目名称:一句话简介 ## 项目背景 (1-3句话说明项目是什么、为谁服务、当前所处的阶段) ## 技术栈与命令 - 语言/框架:(如 Go 1.22 + Gin + GORM) - 启动开发服务:go run ./cmd/server - 运行全部测试:go test ./... - 代码格式化:gofmt -l .(提交前必须通过,不能有输出) - 数据库迁移:make migrate-up / make migrate-down ## 架构速览 (列出核心目录和职责,特别是历史遗留目录,务必标出"别动"区域) ## 代码约定 ### 必须 - (列出正面要求) ### 禁止 - (列出负面清单) ## 常见任务 - 新增一个 API:router 注册 → handler 写参数校验 → service 写业务逻辑 → repository 写数据访问 → 补测试 - 修改表结构:先写迁移脚本 → 本地跑 migrate-down/up 验证 → 更新 README 中的数据字典这个模板的价值在于,它把"AI 每次都要重新摸索的信息"一次性固化了。等你写到第五次的时候就会明显感觉,Claude Code 的第一次回答命中率提升了不止一个档次。而且你会发现,写 CLAUDE.md 的过程本身就是在梳理项目——很多团队规范你可能从来没清晰成文过,借着写这个文件把它们沉淀下来,对团队也是一种贡献。
3. 踩坑实录:信息过期、指令冲突与上下文失控
好文件是改出来的,不是写出来的。我在这套流程上踩过几个比较深的坑,说给你听,能少走很多弯路。
3.1 写太长等于没写:上下文不是无限泳池
第一次给一个中大型项目写 CLAUDE.md,我抱着"信息越多 AI 越懂我"的想法,把 API 文档、历史决策记录、模块改动说明全塞了进去,文档一度接近一万字。结果效果反而变差了:AI 的回答开始变得"泛",因为真正关键的指令被淹没在大量背景信息里,模型对中间段落的注意力本来就相对弱,核心约束反而捕捉不到。
后来我给自己定了一条硬规则:CLAUDE.md 的文件体量控制在 300 到 800 行以内,新加一条内容就必须删掉一条旧内容。超过这个阈值,就说明信息该拆到子目录的 CLAUDE.md,或者放到 docs/ 目录下用引用代替全文粘贴。记住一个原则:这个文件的目标是"让 AI 快速建立准确认知",而不是"把项目文档全部搬进去"。你觉得重要的每一条都"舍不得删",最后就等于什么都没写。
3.2 静态文档与真实代码的冲突:让 AI 自己去验证
CLAUDE.md 是静态的,代码是动态的。依赖升级、函数改名、目录重构之后,文件里的描述很容易过期。最典型的一次,项目把包管理器从 npm 换成了 pnpm,CLAUDE.md 里还写着"npm run build",结果 AI 在会话里反复给出错误命令,我还以为是模型笨,后来才发现是文件没更新。
解决这个问题有两个思路。第一是每次项目依赖或命令真正变化时,顺手同步更新 CLAUDE.md,把这件事当作切换工具链的一部分,而不是可做可不做的收尾。第二是在文件里明确告知 AI:"如果本文件中的命令与代码实际情况冲突,以 package.json 的 scripts 字段为准,并提示我更新本文件。"这相当于给 AI 装了一个自我纠错机制,它不会盲目相信静态文件,而是会交叉验证。这个动作很重要,因为你的团队不可能永远记得更新文档,但 AI 可以帮你兜底。
3.3 指令冲突的优先级:谁说了算
多层级的 CLAUDE.md 各自独立,指令之间可能冲突。比如用户级的规则说"所有回答使用中文",但项目级的规则说"API 错误信息统一输出英文"。这时候 AI 怎么选?根据我的实测,作用范围更精确的层级优先级更高——项目级会覆盖用户级,子目录级会覆盖项目级。但这个规律不是绝对的,你最好在文件里主动声明。
如果遇到同层级内部的冲突,那就只能靠你在文件里写明优先级。比如同时存在"测试必须快"和"核心逻辑必须有完整测试覆盖"两条规则,你可以明确写:
当本文件中多条规则冲突时,按以下顺序判断:安全性和数据正确性 > 性能要求 > 代码风格 > 执行速度。在"测试必须快"与"完整测试覆盖"冲突时,优先保证核心路径的完整覆盖,允许用 mock 替代外部服务来提速。
这种显式的优先级声明,比让 AI 自己权衡要可靠得多。你也可以在开头用一句话声明兜底:"当规则冲突时,以项目目标为最终判断标准:本项目的首要目标是保证线上稳定。"
3.4 别把密钥和敏感信息写进去
这个坑看似低级,但我真见人踩过。有人为了方便,在 CLAUDE.md 里写了测试服务器的地址、账号,甚至一段数据库连接串。CLAUDE.md 如果提交进 git,这些信息就会进入版本历史,即使后面删了也能在 history 里翻到,这是一个很难挽回的失误。
正确做法是:一切密钥、token、数据库密码、外部服务账号都放环境变量或 .env 文件,CLAUDE.md 里只写"环境变量名称"和"从哪里获取",比如"DB_CONN_STR 从团队密码管理器的 Production 条目获取"。这样既给了 AI 足够的信息,又不至于泄露敏感内容。顺便说一句,如果你之前已经把 CLAUDE.md 提交过带敏感信息的版本,别只删文件,记得要清理 git 历史,或者干脆轮换那几个凭据。
4. 进阶思路:把 CLAUDE.md 变成团队共同的"活文档"
如果你已经能写出不错的 CLAUDE.md,下一步是把它从一个"个人笔记"升级成"团队资产"。这一步做的事并不多,但收益会指数级上升。
4.1 纳入版本控制:CLAUDE.md 是代码的一部分
我看到有不少人把 CLAUDE.md 放在 .gitignore 里,理由是"这是我的个人配置,不想污染仓库"。我的建议恰恰相反:项目级的 CLAUDE.md 应该提交进 git,而且应该像代码一样走 review 流程。
理由很简单:Claude Code 不只会被你一个人用。团队里任何一个人打开这个项目,AI 的行为质量都应该是一致的。项目级 CLAUDE.md 承载的是公共知识,它不该依赖某个人的本地文件。把它纳入版本控制后,每次修改都有记录,新成员 clone 项目就能直接获得全套上下文,这个收益远大于"仓库多了一个 markdown 文件"的成本。你甚至可以把它当作新人入职文档的一部分,让 AI 先读 CLAUDE.md,再带着新同事跑通第一个需求。
唯一需要管理的风险是敏感信息。前面说过,密钥绝对不写,涉及内部基础设施的地址如果团队要求保密,也要用相对描述替代,比如"部署在内网,如需连接信息问 infra 组"。这样既能指导 AI,又不越界。
4.2 与子目录 CLAUDE.md 搭配:大型项目的拆分法
当项目的核心业务横跨多个模块时,根目录的 CLAUDE.md 很容易膨胀。这时候可以启用子目录级的 CLAUDE.md,做一个"总—分"结构:根目录只放全局规则,每个子模块在自己的目录里放专有约定。
比如一个中台服务,根目录 CLAUDE.md 写技术栈、全局命令、必须遵守的质量红线;src/payment/CLAUDE.md写支付模块特有的对账规则、幂等约束、回调签名校验方法;src/user/CLAUDE.md写账号体系的数据权限模型。AI 在修改支付模块时,会自动把子目录的 CLAUDE.md 纳入上下文,而在处理全局问题时不会受到这些模块细节的干扰。这既节省了上下文空间,又提高了指令的精准度。
4.3 用引用代替搬运:跟 docs/ 目录联动
有些项目的约束文档已经写得很完善了,不需要在 CLAUDE.md 里重复造轮子。你可以直接引导 AI 去读外部文档,而不是把整篇文档粘贴进来。比如这样写:
数据库设计规范参考 docs/database-guide.md,涉及表结构变更必须先阅读该文档再动手。最关键的一条:所有表必须有 created_at 和 updated_at,由 ORM 自动维护,不写在迁移脚本里。
这里要注意两点。一是路径要准确,写相对路径时最好从仓库根目录算起,减少 AI 猜路径的概率。二是别把引用当成万能药,如果那份文档特别长(比如上千行),AI 未必会全部读完。你得在 CLAUDE.md 里同时写上一两句"最常被忽略的关键规则",相当于一个摘要指针,让它在不读全文的情况下也能抓住要点。
4.4 维护节奏:让文件跟着项目一起进化
CLAUDE.md 最大的敌人不是第一次写不好,而是写着写着就没人管了。项目三个月前换了框架,文件里还写着旧框架的目录名,这种情况我见过太多。文件一旦和现实脱节,AI 给出的建议就会从"基本靠谱"退化成"看着专业实际全错",而人往往比 AI 更难发现这种错误,因为你潜意识里会信任一份"写得很认真"的文档。
我现在的做法是把"更新 CLAUDE.md"纳入任务收尾清单,每当完成一个涉及架构调整或命令变化的任务,就顺手在文件里同步改动。同时每季度抽出半小时专门过一遍:哪些描述已经过时,哪些模块已经不存在,哪些新约定还没写进去。这个习惯看起来不酷,但它保证了一点——AI 在项目里的表现不会随着时间推移而劣化,反而会越来越懂你的项目。
另外,分享一个实用小技巧:你可以定期把"最近和 Claude Code 协作中它犯过的代表性错误"记下来,反向补充进 CLAUDE.md。它不是一次性写入的文档,而是持续进化的系统。就像你带新人一样,每一次纠偏都是一次上下文校准。当 Claude Code 犯错的频率越来越低,你就知道这份 CLAUDE.md 已经完成它的使命了。