第 04 章 CLAUDE.md 与上下文入门
版本基准:2026-07-08 / v2.1.202+
1. 结论先行
CLAUDE.md 是 Claude Code 的持久上下文文件——你把项目的「技术栈、代码规范、常用命令、架构约束、安全红线」一次性写进去,之后每一次对话都会自动加载。它的价值不是配置本身,而是工程纪律的第一块基石:让 Agent 不用你每次重复说明就能在同一套规则下工作。
本章解决三个问题:CLAUDE.md 怎么分层加载、怎么写好一份、怎么与 Claude Code 的另一套记忆系统(Auto Memory)协作。
2. 为什么需要持久上下文
每次对话重复说明的代价
Claude 是无状态的——每一次新对话、每一次 /clear 之后,模型对你项目的认知归零。如果没有持久上下文,你必须每次重复告诉它:
- 「我们用的是 NestJS 10 + TypeORM + PostgreSQL 16」
- 「数据库操作放 Repository,Controller 只做参数校验」
- 「测试用 Jest,单测跑
npm test -- --testPathPattern=auth」 - 「不要用
.then(),用 async/await」
这些信息每多重复一次,就消耗一次 token、增加一轮误解的概率。更严重的是,Agent 在不被告知约束时会按通用习惯行事——它可能写出 .then() 链、把 SQL 拼接进 Controller、用原生 Error——而这些恰恰是你最不希望的。
CLAUDE.md 预加载的收益
写一份 CLAUDE.md 之后:
- 首次启动即知情:Claude 进入项目目录就知道技术栈、目录结构、验证命令,省去 5–10 分钟的探索。
- 规则统一:所有对话在同一套代码规范下生成,不再出现「这次让用 async/await、下次又冒出
.then()」的摇摆。 /clear后不丢规则:清空上下文只清对话历史,不清 CLAUDE.md。规则跨会话持久。- 多人协作对齐:把 CLAUDE.md 提交到 Git,团队成员的 Claude 都加载同一份规则,相当于「机器可读的编码规范」。
工程上的核心价值:把约束写下来,比每次口头强调更可靠。这与人类团队里「写进 CONTRIBUTING.md」的逻辑一致——口头规则会随人员变动失效,文档规则不会。
3. 两套记忆系统
Claude Code 有两套记忆系统,职责不同,必须分清。
| 维度 | CLAUDE.md(手写指令) | Auto Memory(自动记录) |
|---|---|---|
| 存储位置 | 项目根 ./CLAUDE.md、~/.claude/CLAUDE.md 等四级层级 | ~/.claude/projects/<project>/memory/ |
| 内容性质 | 你主动写下的规则、约束、命令 | Claude 在对话中学习到的事实、决策、用户偏好 |
| 加载方式 | 每次启动全量加载到上下文 | MEMORY.md 为索引,首 200 行或 25KB 加载 |
| 维护方式 | 人工编辑,提交到 Git | Claude 自动写入,用户可 /memory 查看/切换 |
| 适合内容 | 稳定的项目规则、代码规范、架构 | 易变的项目状态、用户习惯、踩坑记录、决策原因 |
| 生命周期 | 项目级,长期 | 跨会话累积,可手动清理 |
什么时候用哪个
写进 CLAUDE.md:当信息是「规则」——你希望 Claude 每次都遵守的硬约束。例如:
- 「数据库操作必须用参数化查询,禁止字符串拼接」
- 「改
src/后必须跑python src/rag.py "测试问题"验证」 - 「API 响应格式统一为
{ code, data, message }」
交给 Auto Memory:当信息是「事实」或「偏好」——Claude 在工作中观察到的、不需要你每次重复的。例如:
- 「用户偏好用 cursor-based pagination 而非 offset」
- 「上次重构决策记录在
docs/adr/002.md」 - 「测试数据库连接串在
.env.test,不要改」
简单判断法:能写成团队规范的进 CLAUDE.md,只在某次对话中成立的临时状态留给 Auto Memory。
注意:Auto Memory 不应记录代码规范(代码规范写在 CLAUDE.md 里更稳定)。它的价值是记录那些「代码推导不出来、但对话中反复有用」的非显而易见信息。
4. CLAUDE.md 分层加载
Claude Code 按四级层级加载 CLAUDE.md,从广到细,后者补充(而非简单覆盖)前者。
四级层级与加载顺序
1. Managed policy /Library/Application Support/ClaudeCode/CLAUDE.md
(企业/组织级,最高优先级,通常由 IT 部署)
↓
2. User ~/.claude/CLAUDE.md
(用户全局,所有项目共享,个人偏好与通用纪律)
↓
3. Project ./CLAUDE.md 或 ./.claude/CLAUDE.md
(项目级,提交到 Git,团队共享)
↓
4. Local ./CLAUDE.local.md
(本地级,gitignore,个人临时覆盖)四份文件全部都会加载,不是「后者覆盖前者」。它们在上下文里按层级拼接,Claude 同时看到所有层级的内容。当规则冲突时,更细粒度(更靠近 Local)的指令优先;但默认情况下四级应该互补,不冲突。
各级该放什么
| 层级 | 放什么 | 典型示例 |
|---|---|---|
| Managed policy | 组织强制规则、合规要求、安全红线 | 「禁止把生产数据写入测试环境」「所有 PR 必须有 SAST 扫描通过」 |
| User | 跨项目通用的个人偏好、沟通风格、思维原则 | 「结论先行」「代码用英文、对话用中文」「禁止谄媚废话」 |
| Project | 项目级技术栈、代码规范、架构、命令、目录 | 「NestJS 10 + TypeORM + PostgreSQL」「测试命令 npm test」 |
| Local | 本机临时覆盖、个人实验、未定稿 | 「今天先用 Node 18 测试,正式用 20」「我本机的 db host 是 localhost:5433」 |
核心原则:越靠下的层级越个人化、越易变;越靠上的层级越稳定、越共享。User 级写你这个人是谁、怎么沟通;Project 级写这个项目怎么干活;Local 级写你本机的临时差异。
进入子目录时的加载
当你在项目根目录下进入子目录工作(例如 cd src/modules/auth),Claude 会额外加载该子目录的 CLAUDE.md(如果存在)。子目录级规则只在该目录下生效,适合给特定模块加专属约束。例如:
src/modules/payment/CLAUDE.md ← 支付模块的专属规则(PCI 合规、加密要求)
src/modules/auth/CLAUDE.md ← 认证模块的专属规则(JWT 过期、刷新策略)5. 高级语法
5.1 @import 引用其他文件
CLAUDE.md 支持用 @path/to/file 引用其他文件,被引用文件的内容会一并加载到上下文。
# CLAUDE.md
@docs/architecture.md
@docs/coding-standards.md
@docs/api-conventions.md适合把长规则拆成多个文件,按主题组织。例如把「API 设计规范」「Git 工作流」「数据库迁移规则」分别维护,在 CLAUDE.md 里统一 import。
递归深度限制:@import 支持嵌套,最深 4 层递归。即 A 引用 B、B 引用 C、C 引用 D 是允许的;再深一层会被截断。设计时避免过深的引用链——四层嵌套通常意味着规则组织得太碎,应该合并。
5.2 .claude/rules/ 条件规则
对于只在特定路径下生效的规则,用 .claude/rules/ 目录下的规则文件,通过 frontmatter 的 paths 字段做 glob 匹配。
.claude/
rules/
frontend.rules.md ← 只对前端文件生效
backend.rules.md ← 只对后端文件生效
test.rules.md ← 只对测试文件生效frontend.rules.md 示例:
---
paths:
- "web/src/**"
- "*.tsx"
- "*.ts"
---
# 前端规则
- 使用函数组件 + Hooks,禁止 class 组件
- 样式用 Tailwind CSS,不写自定义 CSS
- API 调用统一走 web/src/api/,不在组件里直接 fetch
- 状态管理用 Zustand,不用 Reduxbackend.rules.md 示例:
---
paths:
- "server/**/*.go"
---
# 后端规则
- 遵循 Effective Go
- 错误用 fmt.Errorf + %w 包装,禁止吞错误
- 数据库操作放 repository 层
- 所有 SQL 用参数化查询条件规则的好处:前端规则不污染后端上下文。全栈项目里前端和后端规则经常冲突(例如前端用 camelCase、后端用 snake_case),全量加载会让 Claude 困惑;按路径加载让规则只在相关文件上生效。
5.3 AGENTS.md 兼容
Claude Code 兼容开源的 AGENTS.md 规范。两种使用方式:
方式一:@AGENTS.md 导入
如果项目已有 AGENTS.md(其他工具也在用),在 CLAUDE.md 里引用即可:
# CLAUDE.md
@AGENTS.md方式二:符号链接
ln -s AGENTS.md CLAUDE.md让 CLAUDE.md 直接指向 AGENTS.md,两者完全同步。适合团队同时用 Claude Code 和其他支持 AGENTS.md 的工具(如 Cursor、Codex),只维护一份规则文件。
6. 该写什么 / 不该写什么
该写
- 项目概述:一两句话说明这是什么项目、给谁用。
- 技术栈:版本要写具体,因为不同版本 API 差异大(NestJS 8 和 10 的写法不同)。
- 常用命令:开发、测试、构建、迁移、lint——给完整可复制的命令。
- 代码规范:命名、错误处理、分层职责、禁止的写法。
- 架构约束:模块边界、通信方式、认证要求、分页策略。
- 目录结构:每个关键目录的职责,避免 Claude 把文件放错位置。
- 安全注意:密钥处理、SQL 注入防护、用户输入校验。
不该写
- 代码片段:CLAUDE.md 不是代码仓库。具体实现放代码文件里,规则只写「应该怎么做」。
- 可从代码推导的文件路径:写「
config.py是唯一配置入口」有用;写「src/utils/format.ts里有formatDate函数」没用——Claude 自己能搜到,而且这种信息会过时。 - 临时状态:「今天在修 bug #123」「正在重构 auth 模块」——这种是 Auto Memory 的职责,写进 CLAUDE.md 会在 bug 修完后变成过时信息。
- 完整文档:API 文档、设计文档不该塞进 CLAUDE.md,用
@import引用即可。 - 密钥、Token、连接串:绝对禁止。CLAUDE.md 通常提交到 Git,密钥进了 Git 历史就无法清除。
建议长度:每个文件 < 200 行
CLAUDE.md 每次启动全量加载到上下文,过长会持续占用 token 预算。建议:
- 单个 CLAUDE.md 控制在 200 行以内。
- 超过就拆分:长规则拆到
docs/下用@import引用;模块专属规则拆到.claude/rules/。 - 一份好的 CLAUDE.md 读起来像「新人入职第一天的 README」——精炼、可执行、不啰嗦。
7. /init 自动生成 + /memory 查看
/init:一键生成初始 CLAUDE.md
进入一个新项目,先跑:
/initClaude 会分析项目结构(package.json、go.mod、目录树、配置文件、已有文档),自动生成一份初始 CLAUDE.md,包含:
- 检测到的技术栈
- 推断的常用命令
- 目录结构概述
- 基础代码规范建议
这份初始文件是草稿,不是终稿。生成后你应该手动修正:
- 删掉 Claude 猜错的部分
- 补充项目特有的架构约束
- 加入安全红线和验证闭环要求
- 调整为团队习惯的命名和分层
/init适合冷启动。已有 CLAUDE.md 的项目不用再跑——它不会智能合并,而是覆盖。
/memory:查看所有加载文件
/memory执行后会列出当前会话加载的所有上下文文件:
- 四级 CLAUDE.md 的实际路径(哪些存在、哪些缺失)
@import引用的所有文件.claude/rules/下生效的条件规则- Auto Memory 的状态(开/关、当前项目记录条数)
/memory 还可以切换 Auto Memory 开关。当你发现 Claude 把不该记的东西写进 Auto Memory,或者 Auto Memory 内容过时干扰判断时,可以临时关闭。
调试上下文问题的第一步永远是 /memory。如果 Claude 行为异常(不遵守规则、规则冲突、加载了奇怪的内容),先看 /memory 确认实际加载了什么,再决定是改 CLAUDE.md 还是清理 Auto Memory。
8. 完整 CLAUDE.md 示例
以下是一个 SaaS 数据分析平台项目的完整 CLAUDE.md,涵盖该写的所有要素。可直接复制修改使用。
# CLAUDE.md
## 1. 项目概述
B2B SaaS 数据分析平台,支持自定义看板、实时数据流和多人协作。
面向企业数据团队,多租户架构,按 workspace 隔离。
## 2. 技术栈
- Frontend: React 18 + TypeScript 5 + Tailwind CSS + Zustand
- Backend: Go 1.22 + Gin + GORM
- Database: PostgreSQL 16(业务库) + ClickHouse(分析查询)
- Queue: Kafka 3.5
- Cache: Redis 7
- Testing: Vitest(前端) + Go testing(后端)
- Deploy: Docker Compose + Kubernetes
## 3. 常用命令
```bash
# 前端
cd web && npm run dev # 开发服务器
cd web && npm test # 全量前端测试
cd web && npm test -- auth # 单模块测试
cd web && npm run build # 构建
# 后端
cd server && go run ./cmd/api # 开发服务器
cd server && go test ./... # 全量后端测试
cd server && go test ./internal/auth/... # 单包测试
# 全局
make test # 跑前后端所有测试
make migrate # 数据库迁移
make lint # 全量 lint
docker compose up -d # 本地起依赖(PG/ClickHouse/Redis/Kafka)
```
## 4. 代码规范
- TypeScript: strict mode,禁止 any,禁止 @ts-ignore
- Go: 遵循 Effective Go,错误用 fmt.Errorf + %w 包装,禁止 _ = err
- React: 函数组件 + Hooks,禁止 class 组件;状态用 Zustand,不用 Redux
- API 响应格式统一: `{ code: number, data: T, message: string }`
- 变量命名: 代码用 camelCase,数据库字段用 snake_case
- 错误处理: 不吞错误,不裸 panic,业务错误用自定义 AppError
## 5. 架构约束
- 模块间通过接口通信,不直接 import 其他模块的 Service 实现
- 所有 API 端点需要认证(除 /auth/login 和 /auth/register)
- 分页统一用 cursor-based,不用 offset
- Controller 层只做参数校验和响应格式化,业务逻辑在 Service 层
- 数据库操作只在 Repository 层,禁止在 Controller/Service 里写 SQL
- 跨 workspace 的查询必须带 workspace_id 过滤
## 6. 目录结构
```
web/src/
pages/ 页面组件
hooks/ 自定义 Hooks
api/ API 调用层(统一入口,组件不直接 fetch)
stores/ Zustand stores
components/ 通用组件
server/
cmd/api/ 程序入口
internal/
handler/ HTTP 处理器
service/ 业务逻辑
repository/ 数据库操作
model/ 数据模型
middleware/ 中间件(auth、logging、ratelimit)
migrations/ 数据库迁移脚本
```
## 7. 验证闭环
- 改 server/ 代码后:`cd server && go test ./...` 必须通过
- 改 web/ 代码后:`cd web && npm test && npm run build` 必须通过
- 改数据库 schema 后:`make migrate` 必须成功,且向后兼容
- 禁止「只改不验」,禁止用 @ts-ignore 或 _ = err 绕过报错
## 8. 安全注意
- API Key、数据库连接串、JWT secret 只从环境变量读,禁止硬编码
- 所有 SQL 必须参数化,禁止字符串拼接
- 用户输入在 handler 层校验(用 validator)
- 日志禁止打印用户密码、token、PII 数据
- 跨 workspace 操作必须校验权限
- .env 文件不提交 Git,仅保留 .env.example这份 CLAUDE.md 约 80 行,覆盖了所有该写的要素。它能让 Claude 在进入项目时立即知道:用什么技术、怎么跑命令、怎么写代码、哪些事不能做、改完怎么验证。
9. 失败边界
CLAUDE.md 不是越多越好。三种典型失败模式:
9.1 过长,持续占用上下文
CLAUDE.md 每次启动全量加载,长文件持续吃 token。一份 500 行的 CLAUDE.md 可能占用数千 token,每轮对话都付出成本。
症状:对话后期 Claude 开始「忘记」你刚才说的话——因为上下文被 CLAUDE.md 占满,留给对话历史的窗口变小。
对策:
- 单文件 < 200 行。
- 长规则拆到
docs/用@import引用。 - 模块专属规则拆到
.claude/rules/,按路径加载。 - 定期用
/memory检查实际加载了多少。
9.2 过时信息误导
CLAUDE.md 写了「用 NestJS 8」,但项目已经升级到 10——Claude 会按 8 的写法生成代码,导致编译错误或用了废弃 API。
症状:Claude 生成的代码引用了不存在的 API、用了已废弃的写法、放错了文件位置。
对策:
- 规则变更顺序:先改 CLAUDE.md,再改代码实践。升级依赖时第一时间同步 CLAUDE.md。
- 把会变的具体版本号写清楚(「NestJS 10」比「NestJS」好),升级时强制 review CLAUDE.md。
- 删掉所有「可从代码推导」的内容——版本号升级时代码会变,但 CLAUDE.md 不会自动更新,这种信息是过时的温床。
- 把易变的临时状态交给 Auto Memory,不写进 CLAUDE.md。
9.3 把密钥写进去
这是最严重的失败。CLAUDE.md 通常提交到 Git,密钥一旦进入 Git 历史,即使后续删除也永久留存,需要 force push 清理——而 force push 本身就是高风险操作。
症状:Git 历史里出现 ANTHROPIC_API_KEY=sk-...、数据库连接串带密码、JWT secret 明文。
对策:
- CLAUDE.md 里只写规则(「密钥从环境变量读」),不写值。
- 用
.env.example给模板,真实值放.env(gitignore)。 .gitignore必须包含.env、CLAUDE.local.md、*.local.json。- 如果已经泄露,立即轮换密钥——清理 Git 历史无法撤销已发生的泄露。
小结
CLAUDE.md 的本质是把「每次都要重复说的规则」沉淀成文件。它不是配置,是工程纪律——你写得多认真,Claude 就有多稳定。掌握三个要点即可:
- 分层:四级层级各司其职,User 管个人偏好,Project 管项目规则,Local 管临时覆盖。
- 精炼:单文件 < 200 行,长规则拆
@import,模块规则拆.claude/rules/。 - 闭环:规则变更先改 CLAUDE.md 再改代码;改完代码必须跑 CLAUDE.md 里写的验证命令。
下一章将进入 Hooks 与自动化——如何让 Claude Code 在特定事件触发时自动执行命令,把「验证闭环」从口头规则变成强制执行的系统。