你有没有遇到过这种情况:昨天开会刚跟 AI 编程助手交代清楚项目的目录结构、命名规范和不能碰的模块,今天打开新会话,它又一脸茫然地问“这个项目是做什么的”,甚至敢直接在核心模块里乱改代码。我刚开始用 AI 编程工具那阵,几乎每天都在重复解释同一件事,气得我一度以为这玩意儿就是个“金鱼脑”。后来试了 CLAUDE.md,整个体验彻底变了——它就相当于在项目根目录下放了一张“入职员工手册”,AI 每次开工前先读一遍,自然就记住你定下的所有“潜规则”。
CLAUDE.md 是 Anthropic 为 Claude Code 这类编程智能体设计的项目级指令文件,也是当前 AI 编程实践里最值得推广的一个工程化手段。它本身就是一个普通的 Markdown 文件,但位置固定在项目根目录,AI 在每次会话开始时都会默认读取它,相当于给大模型注入了“项目记忆”。这篇文章不打算讲太多虚的,我会把实际使用中总结出来的内容规划、编写套路、避坑技巧全部整理出来,适合所有在项目里用 AI 编程工具、受够了反复交代背景的人参考。
1. 为什么 AI 总是“转头就忘”:CLAUDE.md 要解决的问题
我第一次接触 CLAUDE.md 的时候,其实挺困惑的:项目里不是已经有 README.md 了吗,为什么还要搞一个专门给 AI 看的文件?后来踩了几次坑才明白,这俩东西服务的对象完全不同,解决的是 AI 编程落地时最要命的问题——跨会话记忆。
1.1 AI 编程工具的“金鱼记忆”困境
大模型处理任务依赖上下文窗口,哪怕是最新的模型,上下文长度也是有限的。更关键的是,上下文是跟着会话走的,只要会话一关、窗口一清,AI 对这个项目的所有理解就会归零。我之前做过一个小型 Web 应用,前后端加起来几十个文件,有一次跟 AI 连续聊了四个小时,把业务逻辑交代得清清楚楚,AI 也把数据模型设计得有模有样。结果第二天打开新会话,让它加一个接口,它居然按自己想象的表结构去写,跟数据库里实际的字段对不上,白费了半天功夫。
这种痛苦用过 AI 编程的人应该都有体会。AI 不是不聪明,它是真的“记不住”。你可以在每次对话开头重新贴一遍项目背景,但项目稍微复杂一点,那段背景文字就长得吓人,既浪费 token 又影响 AI 的理解质量。CLAUDE.md 的出现,就是为了解决这个问题:把项目里那些“长期有效、默认适用、不太变化”的信息,单独抽出来做成一个持久化文件,让 AI 每次开机先读一遍。打个比方,它就像是公司给新员工准备的入职手册,而不是某个项目组成员临时写的工作说明。
1.2 CLAUDE.md 的工作方式与定位
从功能定位上看,CLAUDE.md 不是给人看的文档,而是给 AI 看的“工作规范”。它通常放在项目根目录,Claude Code 在启动时会自动识别并读取,文件里的内容会作为系统提示词的一部分注入到每一次会话的上下文中。也就是说,只要 AI 开始工作,它就会默认知道你在文件里写的那些规则,不需要你反复强调。
这个定位跟 README.md 有本质区别。README 主要是给开发者看的,介绍项目是什么、怎么安装、怎么使用,用词可以轻松随意,甚至可以带点个人风格。但 CLAUDE.md 是给 AI 看的操作手册,需要更精确、更结构化、更偏向“可执行指令”。我在维护老项目的时候,经常看到有人把 CLAUDE.md 写成了一篇散文,AI 读完还是不知道该干什么,那就是把定位搞混了。
另外,现在市面上很多 AI 编程工具也都有类似机制,比如一些编辑器插件会读取 .cursorrules 之类的文件,宗旨是一样的:把项目的“潜规则”沉淀成文件,让 AI 照着执行。原理都有相似之处,掌握了 CLAUDE.md 的写法,换成别的工具也能很快上手。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 设计 CLAUDE.md 的核心思路:先定规则,再谈内容
很多人第一次写 CLAUDE.md,上来就噼里啪啦写一大堆,把项目背景、技术栈、代码片段全塞进去。这样做不能说完全没用,但效率很低——AI 的注意力是有限的,信息太杂反而容易把真正关键的规则淹没。
2.1 一份好 CLAUDE.md 的三个衡量标准
站在我自己的使用经验上,判断一份 CLAUDE.md 好不好,就看这三个指标:
- 信息密度高:每一条内容都能直接影响 AI 的行为,不写废话。比如“本项目使用 pnpm 作为包管理器”就是高密度信息,“请努力工作”就是废话。
- 指令明确可执行:规则要写得像“操作规程”,而不是“价值宣言”。与其写“代码质量要高”,不如写“所有新增函数必须有 JSDoc 注释,并标明返回值类型”。
- 更新及时:CLAUDE.md 不是写一次就完事的,项目结构变了、技术栈换了、踩了大坑,都要及时同步进去。我见过最夸张的例子,是有人把半年前的 CLAUDE.md 原封不动地放在新项目里,AI 照着旧规则写代码,跟现在的代码风格完全对不上。
这三点听起来简单,但真正做到其实需要刻意练习。我刚开始写的时候,经常会忍不住把想法一股脑全倒进去,后来发现 AI 的执行效果反而变差了。后来我做了一件事:每次想往 CLAUDE.md 里加内容,先问自己一句“这条规则如果 AI 不知道,会出什么严重问题?”,如果答案是不会,就不加。用这个办法删掉了很多冗余内容,文件一下子清爽了很多。
2.2 内容模块拆分与编写优先级
CLAUDE.md 的内容虽然根据项目不同会有所差异,但大体上可以拆分成几个核心模块。我常用的模块和优先级如下:
| 模块 | 核心内容 | 编写优先级 |
|---|---|---|
| 项目身份 | 项目名称、一句话简介、核心目标 | 必写 |
| 技术栈 | 主要语言、框架、关键依赖、包管理器 | 必写 |
| 目录结构 | 关键目录作用、不得修改的目录 | 必写 |
| 命令速查 | 安装、启动、测试、构建、lint 等命令 | 必写 |
| 编码规范 | 命名风格、注释要求、组件写法、错误处理 | 高 |
| 明确约束 | 禁止做的事、不能碰的模块、性能红线 | 高 |
| 偏好设置 | 接口风格、日志规范、提交信息格式 | 中 |
| 常用任务 | 高频任务的标准做法、参考示例 | 中 |
优先级的意思是:当文件已经很长、不得不删减时,优先保留下方的、只留高优内容。实际上这个表格本身也可以作为你规划 CLAUDE.md 的骨架,我一般会先按这个框架列出二级标题,再逐个往里面填内容,避免写到一半漏掉关键模块。
2.3 篇幅与 token 的取舍
CLAUDE.md 不是越长越好。Claude Code 每次都要把文件内容塞进上下文里,太多会挤占任务处理的空间;太少又起不到约束作用。我个人的经验是控制在 2,000 到 5,000 token 之间,大约相当于一个 30 到 80 行的 Markdown 文件。超过这个规模之后,AI 对规则的遵守率反而会下降,因为核心指令会被淹没在大量背景信息里。
如果你的项目实在庞大,有一些取舍技巧:把最核心、最不可违反的规则放最前面,AI 对开头内容的注意力会更高;把“为什么这么写”的背景解释尽量压缩,只保留“怎么做”的结论;协议和技术细节如果系统里有现成文档,可以写“具体参数详见 docs/xxx.md”,让 AI 在需要时读取,而不是全部摊在 CLAUDE.md 里。这里面的道理很像给新人布置任务,解释太多反而容易让人无所适从。
3. 从零到一:手写一份可复用的 CLAUDE.md 模板
说实话,市面上关于 CLAUDE.md 的现成模板不少,但拿过来直接用大概率是水土不服的。因为每个项目的“潜规则”差别极大,我自己也是在一次次踩坑中,慢慢沉淀出了一套自己的写法。下面我把这套方法拆解开,从基础骨架讲到真实示例,再到维护节奏,一次性说清楚。
3.1 基础框架与逐段拆解
先上一个我用了很久的基础框架,你可以直接复制到项目里,再根据实际情况调整:
markdown复制# 项目名称
一句话描述项目目标。
## 技术栈
- 语言:TypeScript
- 前端框架:Vue 3
- 后端:Node.js + Express
- 包管理器:pnpm
## 常用命令
- 安装依赖:`pnpm install`
- 开发启动:`pnpm dev`
- 单元测试:`pnpm test`
- 构建产物:`pnpm build`
- 代码检查:pnpm lint
## 目录结构
- `src/`:主业务代码
- `src/api/`:接口请求层,禁止直接调用第三方 HTTP 库
- `src/components/`:通用组件,必须使用 composition API 写法
- `server/`:Node 服务端代码
- `server/routes/`:路由定义,只做参数校验和响应返回
- `server/services/`:核心业务逻辑,必须写单元测试
- `tests/`:测试文件,目录结构与 src 保持一致
## 编码规范
- 函数名使用 camelCase,组件名使用 PascalCase
- 任何外部接口请求必须放在 `src/api` 层,禁止在组件内直接 fetch
- 所有异步函数必须有 catch 处理,禁止裸抛异常
- 组件内禁止使用 any 类型,确实无法避免时要写注释说明原因
- 新增第三方依赖前必须进行体积和性能评估
## 明确约束
- 不允许修改 `server/migrations/` 下已提交的数据库迁移文件
- 不允许直接在配置文件里写明文密钥
- 不允许在 `server/controllers/` 中编写超过 200 行的函数
- 所有涉及数据库增删改的操作必须经过 service 层
## 偏好设置
- 前端组件优先使用 Option 式写法,不强制
- 日志规范:错误使用 console.error,普通信息使用 console.info
- git 提交信息格式:类型(模块): 描述,例如 fix(user): 修复登录页按钮样式
## 常见任务参考
- 新增一个前端页面:新建路由 -> 创建组件 -> 编写 api 函数 -> 接入状态管理
- 新增一个服务端接口:创建 service -> 创建 route -> 编写测试 -> 手动验证
这个骨架看起来简单,但每一段都有它存在的意义。技术栈部分能避免 AI 用错包管理器或者错误的框架写法;常用命令让 AI 不需要靠猜测去执行构建;目录结构是最容易忽视却又最重要的——很多乱改代码的“事故”,根源就在于 AI 不知道哪个目录能碰、哪个不能碰。明确约束部分是整个文件的压舱石,宁可少写背景,也一定把红线写足。
3.2 实战示例:一个真实项目的 CLAUDE.md 长什么样
光讲骨架比较抽象,我拿一个自己做过的数据可视化后台项目的 CLAUDE.md 来举例。这个项目前后端分离,前端用 Vue 3 + TypeScript + ECharts,后端用 Node.js + TypeScript + MySQL,图表配置很复杂,团队踩了不少坑,所以我把容易出问题的点都写进了约束里:
markdown复制# 数据可视化后台
面向运营人员的数据分析后台,主要功能包括用户行为分析、实时数据看板和报表导出。
## 技术栈
- 语言:TypeScript(严格模式)
- 前端:Vue 3 + Pinia + Vue Router + ECharts
- 后端:Node.js + Express + MySQL
- 包管理器:pnpm
- 图表:ECharts 5.4
## 常用命令
- 本地开发:`pnpm dev`
- 后端调试:`pnpm dev:server`
- 数据库迁移:`pnpm db:migrate`
- 运行测试:`pnpm test`
- 构建:`pnpm build:all`
## 目录结构
- `frontend/src/views/`:页面级组件,每个页面一个目录
- `frontend/src/components/charts/`:图表封装组件,必须接收 `option` 和 `data` 两个 props
- `frontend/src/stores/`:Pinia 状态管理,按业务域拆分
- `backend/src/controllers/`:请求入口,只做参数校验
- `backend/src/services/`:业务逻辑,禁止直接操作数据库
- `backend/src/models/`:数据库模型定义,使用 Drizzle ORM
## 编码规范
- 组件命名使用大驼峰,文件命名使用小驼峰
- 所有图表配置必须使用 `deepCompare` 判断是否更新,避免无限重渲染
- 后端错误处理统一使用自定义的 `AppError` 类,禁止直接返回 500
- SQL 查询必须使用参数化查询,禁止字符串拼接
- 所有金额字段使用 Number 类型,禁止使用 Float
## 明确约束
- 禁止修改 `frontend/src/components/charts/baseChart.vue` 中的图表生命周期逻辑
- 禁止在 service 层直接调用 req 或 res 对象
- 数据库表结构变更必须通过迁移文件,禁止手动改表
- 前端拉取接口数据时,必须处理 loading 和 empty 状态,禁止只处理成功态
- ECharts 的 option 对象禁止直接修改,必须通过 `setOption` 传入新对象
## 偏好设置
- 接口返回格式统一为 `{ code, data, message }`
- 日期时间统一使用 UTC 时间戳,前端展示时再转时区
- git 提交信息使用 Angular 规范
- 组件内不使用 console.log 调试
## 常用任务参考
- 新增一个图表组件:创建组件文件 -> 定义 props -> 初始化 ECharts -> 监听数据变化更新 option -> 注册到 charts/index.ts
- 新增一个导出任务:在 services 中创建 exportJob -> 写入任务表 -> 使用 BullMQ 处理队列 -> 生成文件后上传 OSS
你可以看到,这份文件里有些规则非常具体,比如“必须使用 deepCompare 判断是否更新”,这其实是当时团队真实踩过的一个坑——ECharts 实例在数据没变化时也会通过 setOption 强制刷新,导致用户体验很差。把这种踩坑经验写进 CLAUDE.md,AI 从一开始就会避开这个问题,而不是等踩坑之后再修。
3.3 更新与维护节奏
CLAUDE.md 写完之后,最难的是保持同步。项目是活的,代码不断变化,如果文件跟不上,AI 就会照着过期的规则做事,有时候比没有规则还糟糕。
我的维护节奏有三条:每次踩坑后立刻补一条规则,比如 AI 在某处乱改了不该改的文件,就把这个文件路径写进约束模块;每周抽十分钟整体过一遍,看看有没有已经不适用或可以合并的条目;把 CLAUDE.md 纳入 Git 管理,提交时附带说明,这样一旦更新出了问题可以方便回溯。我还见过有人把 CLAUDE.md 的更新写成脚本,检测到文件被 AI 意外修改时自动恢复,不过一般团队用不上这么重的机制,手动维护已经够用。
4. 常见问题与排查技巧实录
在实际使用 CLAUDE.md 的过程中,我遇到过不少问题,有些是文件本身写得不好,有些是工具行为理解不到位。这里挑了最典型的几个,做成速查表给各位参考。
4.1 问题速查表
| 问题现象 | 根本原因 | 解决办法 |
|---|---|---|
| AI 不遵守 CLAUDE.md 里的规则 | 规则写得模糊、位置太靠后、与用户对话中的指令冲突 | 将最关键规则前移,用命令式短句,明确不接受的备选行为 |
| 放了很多内容,但 AI 只记住前半段 | 上下文过长,注意力被稀释 | 精简到核心,背景信息挪到项目 doc 文件供按需读取 |
| 更新文件后,AI 行为没有变化 | 新会话没有重新读取,或者读取的是旧缓存 | 确认文件在项目根目录,检查工具版本,必要时重启会话 |
| 规则之间有冲突 | 不同模块的内容互相矛盾 | 增加冲突消解规则,比如“约束模块优先级最高” |
| 同一句规则,不同场景下 AI 解读不一致 | 表述有歧义,缺少示例 | 用“必须/禁止”的强指令,必要时附正反示例 |
| CLAUDE.md 被 AI 误修改 | 工具在某些操作中错误地覆盖了文件 | 用 Git 跟踪,上线前检查 diff,必要时设置只读权限 |
4.2 我的独家避坑经验
这些问题里,最常出现的其实是“AI 不遵守规则”,特别是规则跟用户当前对话里的临时指令冲突时。比如 CLAUDE.md 里明明写着“不允许直接调用第三方 HTTP 库”,但对话里你随口说了一句“这块用 axios 调一下”,AI 就会优先执行你最新的指令。所以在设计规则时,我会刻意写明“这是项目长期约束,除非用户明确要求临时绕过,否则必须遵守”。这样能大幅提高长期规则的优先级。
另一个经验是:CLAUDE.md 里尽量少用“不要”“别”这类否定词,多写正向指令。比如与其写“不要在组件里写样式”,不如写“样式文件统一放在 src/styles/ 目录,组件内只允许使用 class 引用”。原因是肯定句比否定句更容易被模型执行,尤其是复杂规则,能用“做什么”就不用“不要做什么”。
最后,不要把所有希望都寄托在一个文件上。对于特别复杂的项目,我还会在 docs/ 目录下放一些细分文档,然后在 CLAUDE.md 里写“涉及支付逻辑时,先阅读 docs/payment-flow.md”。这样既保证了文档的可维护性,又不会让 CLAUDE.md 变成一个臃肿的巨型文件。
我在实际项目中使用 CLAUDE.md 半年多,最深的一个体会是:它真正的价值不在于“多了一个配置文件”,而在于逼着我把项目里那些“只可意会不可言传”的经验,一点点转化成了可执行的规则。这个沉淀过程,对团队协作和 AI 编程体验的提升都很大。如果你刚开始接触,建议别急着一次写完美,先搭一个最简骨架,然后在日常使用中不断往里补规则。大概两三周之后,你会发现 AI 对整个项目的理解能力有了质的飞跃。另外,每个人、每个团队的写作风格都不一样,这套框架只是抛砖引玉,最重要的还是结合你自己的项目去调整。
