CLAUDE.md:这不是写给人看的文档,而是写给 AI 的上下文

TL;DR:CLAUDE.md 不是给人读的文档,是给模型读的工程规格。它控制 Claude Code 的行为边界,每次会话都被全量加载到上下文。写得好,省掉反复提醒;写得差,浪费 Token 还不生效。
CLAUDE.md 是工程规格,不是文档
大多数团队第一次写 CLAUDE.md,会本能地抄一段 README 进去——项目介绍、技术栈、团队使命。这些信息对人有用,对模型几乎没用。模型不关心你们的愿景,它关心的是:跑什么命令、改哪些文件、遵守什么边界、不能碰什么东西。

CLAUDE.md 的本质是一份机器可读的行为规格。它有以下工程属性:
-
• 每次会话全量加载:无论任务大小,CLAUDE.md 的全部内容都会被注入上下文。这意味着每一行都在持续消耗 Token 预算。 -
• 层级覆盖:用户级 ~/.claude/CLAUDE.md→ 项目级./CLAUDE.md→ 子目录级subdir/CLAUDE.md,后者覆盖前者。跨项目通用的偏好放用户级,项目特定的放项目级。 -
• 支持文件导入: @other-file.md语法可以把外部文件内容内联进来。适合拆分长规则到独立文件。 -
• 不是强制策略:CLAUDE.md 是上下文,不是策略引擎。模型可能会忽略其中的规则。真正需要强制的安全边界要用 Hooks 实现(见第 22 篇)。
理解这一点很关键:CLAUDE.md 里的规则是建议,不是约束。你在里面写”不要改 .env”,模型多数时候会遵守,但不是 100%。如果某条规则违反了就必须中断操作,那它属于 Hooks 的管辖范围。
一个常见的误解是:CLAUDE.md 写得越详细,Claude Code 就越听话。实际上,CLAUDE.md 的效果遵循一个倒 U 型曲线——太少的信息让模型无从遵循,太多的信息让模型失去焦点。最佳区间在 60 到 120 行之间。低于 60 行,缺少关键约束;超过 120 行,规则之间互相干扰,遵循率开始下降。后文的 Token 预算分析和失败案例会展开这个论点。
另一个误解是:CLAUDE.md 可以替代 README。不能。README 是给人看的,描述项目是什么、为什么这么做;CLAUDE.md 是给模型看的,描述怎么操作、不能做什么。一个好的检验标准:如果删掉 CLAUDE.md 里某段话,模型的行为是否会改变?如果不会,那段话就不该在那里。
三个真实的 CLAUDE.md
不是模板,是实际在用的配置。三个项目,三种技术栈,三种关注点。
A. TypeScript API 服务
这个项目的核心需求是分层架构约束——Claude Code 必须知道每一层该干什么、不能干什么,否则它会在 route handler 里写业务逻辑。
# CLAUDE.md## Commands- Install: pnpm install- Dev: pnpm dev- Test: pnpm test (unit), pnpm test:e2e (integration)- Lint: pnpm lint- Typecheck: pnpm typecheck- DB migrate: pnpm prisma migrate dev## Architecture- src/routes/ — Express route handlers, thin layer, delegate to services- src/services/ — Business logic, no HTTP imports- src/repositories/ — Database access only, no business logic- src/models/ — Prisma-generated types only, never edit manually- src/utils/ — Shared helpers, no side effects## Rules- Routes MUST NOT contain business logic- Services MUST NOT import from express- Repositories are the only layer that touches prisma client- All new endpoints need integration tests in tests/e2e/- Use zod for request validation, never trust req.body directly## Safety- Do not edit prisma/schema.prisma without explicit approval- Do not modify migrations after they've been applied- Do not touch .env files- Do not run pnpm prisma migrate reset## Testing- Run relevant unit tests after editing service files- Run integration tests after adding endpoints- Test command for single file: pnpm vitest run src/services/user.test.ts
关键设计:Architecture 段落用一句话定义每个目录的职责和限制。Rules 用 MUST NOT 做硬边界声明。Testing 段落不只说”要测试”,而是明确给出什么操作触发什么测试。
B. React 前端(Next.js)
前端项目的关注点不一样:组件复用、样式约束、路由结构、SSR 边界。
# CLAUDE.md## Commands- Install: pnpm install- Dev: pnpm dev- Build: pnpm build- Lint: pnpm lint- Typecheck: pnpm typecheck- Test: pnpm test## Architecture- app/ — Next.js App Router, page.tsx + layout.tsx only- components/ui/ — Primitive components (Button, Input, Dialog), no business logic- components/features/ — Feature-specific composite components- lib/ — Shared utilities and hooks, no React components- lib/api/ — API client functions, generated from OpenAPI spec- styles/ — Global styles and Tailwind config## Rules- Use Tailwind classes only, no inline styles, no CSS modules- Import components from @/components/ui, never write raw<button> or<input>- Server Components by default, add "use client" only when state/effects needed- Data fetching in Server Components or Server Actions, not in useEffect- Form mutations use Server Actions, not API routes- Do not create new API routes unless explicitly asked## Safety- Do not edit tailwind.config.ts without approval- Do not modify next.config.js without approval- Do not install new UI libraries without checking if existing components suffice- Do not touch lib/api/ — it is auto-generated## Testing- Run pnpm test after modifying components- Test file colocated: ComponentName.test.tsx next to ComponentName.tsx- Prefer testing-library, no Enzyme
关键设计:Rules 段落明确”默认 Server Component,按需加 use client”——这是 Next.js 项目最容易出错的地方。Safety 里”不要装新 UI 库”防止 Claude Code 动不动引入 shadcn 新组件。
C. Python ML 服务
ML 项目有独特的约束:数据管线、模型文件、实验可复现性。
# CLAUDE.md## Commands- Install: pip install -e ".[dev]"- Dev: python -m src.main- Test: pytest tests/ -v- Lint: ruff check src/- Format: ruff format src/- Train: python -m src.train --config configs/default.yaml- Evaluate: python -m src.evaluate --checkpoint checkpoints/latest.pt## Architecture- src/data/ — Data loading and preprocessing pipelines- src/models/ — Model architectures, PyTorch nn.Module only- src/training/ — Training loops, loss functions, schedulers- src/evaluation/ — Metrics, visualization, report generation- configs/ — YAML config files, one per experiment- notebooks/ — Exploration only, never import from notebooks into src/## Rules- All data paths go through configs, no hardcoded file paths in source- Model changes must be backward compatible with saved checkpoints- Use PyTorch, not TensorFlow- Use type hints everywhere, run mypy before committing- Do not modify configs/default.yaml — create a new config for experiments- Keep notebooks stateless: clear all outputs before committing## Safety- Do not delete or modify files under checkpoints/- Do not run training without specifying a config file- Do not modify src/data/loader.py without running full pipeline test- Do not push large model files (>100MB) to git## Testing- Run pytest after modifying any src/ file- Test data pipeline separately: pytest tests/test_data/- Integration test after model changes: pytest tests/test_training/- Single file: pytest tests/test_data/test_loader.py -v
关键设计:ML 项目最大的坑是可复现性。Rules 里的”所有数据路径走 configs”和”模型变更必须向后兼容 checkpoint”直接防止 Claude Code 破坏实验可复现性。Safety 段落的”不要删 checkpoints 目录下的文件”看似简单,但这类规则如果只在 CLAUDE.md 里声明而没有 Hooks 兜底,一旦模型认为删除旧 checkpoint 是”清理空间”的合理操作,损失不可逆。
三个例子的共同模式
回看这三个配置,可以发现一个共同结构。每个 CLAUDE.md 都包含五个段落,每个段落的职责固定:
Commands 回答”怎么跑”。列出安装、开发、测试、lint、类型检查的完整命令。不给这些信息,Claude Code 会猜——它可能猜对(用 npm 代替 pnpm),也可能猜错(用 jest 代替 vitest)。一旦猜错,后续所有操作都建立在错误的工具链上。
Architecture 回答”东西在哪”。用一句话描述每个关键目录的职责和限制。这不是给人看的架构文档,是给模型的导航图。没有它,模型会通过搜索推断结构——读 ten 个文件来猜目录职责,浪费数千 tokens,还可能猜错。
Rules 回答”怎么写”。用 MUST / MUST NOT 做明确的约束声明。关键是具体:不要写”注意代码质量”,要写”Services MUST NOT import from express”。前者是人的价值观,后者是机器可执行的条件判断。
Safety 回答”不能碰什么”。列出所有禁止修改的文件和禁止执行的命令。这些规则需要 Hooks 兜底——CLAUDE.md 里列出是为了让模型理解原因,Hooks 里拦截是为了确保执行。
Testing 回答”怎么验证”。不只说”要测试”,而是明确什么操作触发什么测试命令。给单文件测试命令尤其重要——没有它,Claude Code 会跑全量测试,一个 2000 个测试的仓库等两分钟,消耗大量 Token 在测试输出上。
内容分层策略:什么放哪里
CLAUDE.md 不是唯一的行为配置点。Claude Code 有三层规则载体,各有不同的加载时机和 Token 成本。

|
|
|
|
|
|
|---|---|---|---|---|
|
|
CLAUDE.md |
|
|
|
|
|
CLAUDE.md |
|
|
|
|
|
.claude/rules/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
决策逻辑:
-
• 每个开发者都需要知道的(命令、架构、安全边界)→ CLAUDE.md -
• 只有改某个目录时才需要知道的(UI 组件规范、API 风格)→ .claude/rules/ -
• 只有执行特定任务时才需要知道的(部署流程、数据迁移)→ Skill
错误做法:把所有规则都塞进 CLAUDE.md。一个 400 行的 CLAUDE.md 里可能有 200 行只在改某个子目录时才有用,但它们每次会话都在消耗 Token。详见后文失败案例。
正确做法:CLAUDE.md 保持精简(建议 120 行以内),路径特定规则拆到 .claude/rules/(见第 05 篇),任务流程封装为 Skill(见第 08 篇)。
Token 预算分析
CLAUDE.md 不是免费的。每次会话启动,它的全部内容都会被注入上下文。以下是基于实际使用估算的 Token 消耗:
CLAUDE.md 行数 → 大致 Token 消耗├── 30 行 → ~500 tokens├── 50 行 → ~800 tokens├── 80 行 → ~1200 tokens├── 120 行 → ~1800 tokens ← 推荐上限├── 200 行 → ~3000 tokens├── 400 行 → ~6000 tokens ← 已是负担└── 600+ 行 → ~9000+ tokens ← 严重影响任务空间
加上其他上下文开销:
总上下文预算构成(Claude Sonnet, 200K tokens)├── 系统提示词(内置) ~3K tokens├── 用户级 CLAUDE.md ~800 tokens(如果配置了)├── 项目级 CLAUDE.md ~1500 tokens(120 行)├── Rules 文件(按需加载) ~200-500 tokens(匹配的文件)├── Auto memory ~200-1000 tokens├── 用户消息 ~1K tokens├── 工具调用 + 结果 ~5K-50K tokens(任务复杂度决定)├── 历史对话 ~10K-100K tokens(会话长度决定)└── 剩余可用于任务推理 → 越多越好
关键洞察:CLAUDE.md 从 30 行增长到 120 行,Token 成本只从 500 增长到 1800,还在可接受范围。但从 120 行增长到 400 行,成本跳到 ~6000,而增加的 280 行规则(主要是一些低频场景的注意事项)被模型遵循的概率反而下降了——因为规则太多,模型无法在大量指令中维持对每一条的注意力。
建议上限:CLAUDE.md ≤ 120 行,控制 Token 消耗在 2000 以内。 超出的内容考虑拆到 .claude/rules/ 或 Skill。
这里有一个反直觉的发现:Token 消耗的增长是线性的,但规则遵循率的下降是指数级的。从 80 行增加到 120 行,遵循率可能只从 88% 降到 82%;但从 120 行增加到 200 行,遵循率可能从 82% 骤降到 65%。原因是注意力稀释——模型面对 200 行指令时,很难在前 80 行的架构规则和后 120 行的边缘场景注意事项之间合理分配注意力权重。结果往往是高频规则被正确遵循,低频规则被完全忽略,而中间地带(比如测试要求)处于不确定状态。
这意味着 CLAUDE.md 优化的核心不是”怎样塞更多规则”,而是”怎样让最重要的规则最突出”。实用的做法:把最关键的 5-8 条规则放在 Rules 段落的前三行。模型对指令列表的开头部分注意力最高。
质量度量:怎么知道你的 CLAUDE.md 有没有用
CLAUDE.md 不是写了就完了。它是一份运行中的工程规格,需要度量效果。以下是四个可操作的指标:
|
|
|
|
|
|---|---|---|---|
| 遵循率 |
|
|
|
| 重复提问率 |
|
|
|
| 越界率 |
|
|
|
| 首次正确率 |
|
|
|
度量方法不需要复杂工具。连续用 Claude Code 完成一周的任务,记录每次需要手动纠正的情况,就能得到这些指标的粗略估计。更简单的方法:让 Claude Code 在每个任务结束时输出一份简短的”规则遵循自检”——它认为自己遵循了哪些规则、违反了哪些规则、有哪些规则不确定怎么执行。虽然自检不完全可靠,但它的”不确定”项通常指向 CLAUDE.md 里表述模糊的段落。
诊断规则:
-
• 遵循率低 → 规则表述太模糊,Claude Code 不知道怎么执行。改写为具体指令。 -
• 重复提问率高 → CLAUDE.md 缺少关键信息。把被反复问到的问题补充进去。 -
• 越界率高 → Safety 规则只在 CLAUDE.md 里,没有被 Hooks 强制。把最关键的边界移到 Hooks。 -
• 首次正确率低 → Architecture 描述不准确或不完整。让 Claude Code 复述架构,看它理解了什么。
CLAUDE.md vs Hooks:边界决策
CLAUDE.md 是建议层,Hooks 是执行层。一条规则放在哪里,取决于违反后果的严重程度。

|
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
核心原则:违反后果可接受的规则放 CLAUDE.md,违反后果不可接受的规则必须用 Hooks 兜底。
很多团队的现状是只在 CLAUDE.md 里写了”不要改生产数据库”,但没有 Hooks 拦截。这在 90% 的情况下够用,因为模型确实会遵守写在 Safety 段落里的规则。但那 10% 的失败场景——模型认为某个任务”显然”需要改数据库、绕过了 CLAUDE.md 的建议——造成的后果可能远超你愿意承受的范围。所以判断标准不是”模型通常会遵守吗”,而是”如果模型不遵守,后果有多严重”。严重到不可接受的,必须加 Hooks。
举个例子:你在 CLAUDE.md 里写了”不要改 .env 文件”。大部分时候 Claude Code 会遵守。但偶尔它会认为某个任务必须修改 .env 才能完成,然后就改了。如果你真的不能承受 .env 被修改的后果,就在 Hooks 里加一个 PreToolUse 拦截:
{ "hooks": { "PreToolUse": [ { "matcher": "Write|Edit", "command": "bash -c 'echo \"$TOOL_INPUT\" | jq -r .file_path | grep -q \"\\.env\" && echo BLOCK: .env files are protected || true'" } ] }}
这样即使模型”决定”要改 .env,Hooks 也会在写入前拦截。CLAUDE.md 是提示,Hooks 是保障。
失败案例:400 行的 CLAUDE.md
这是一个真实的场景。一个 8 人团队在 monorepo 里维护前端(Next.js)、后端(NestJS)、共享组件库和数据库迁移四个 package。他们把所有规则都写进根目录的 CLAUDE.md,大概 400 行,包括:

-
• 前端组件规范(只在改 packages/ui/时有用) -
• 后端 API 设计指南(只在改 apps/api/时有用) -
• 数据库迁移流程(只在改 packages/db/时有用) -
• 部署步骤(只有发布时有用) -
• Code Review 检查清单(只有提 PR 时有用) -
• 通用编码规范(任何时候都有用)
问题出在两个层面:
Token 浪费:400 行 CLAUDE.md 消耗约 6000 tokens。一个”修前端按钮样式”的任务,不需要后端 API 设计指南、数据库迁移流程和部署步骤,但这些内容全被加载了。
规则遵守率下降:更严重的问题是,规则太多之后 Claude Code 的遵循率反而下降。测试数据:40 行 CLAUDE.md 时遵循率约 85%,400 行时降至约 60%。原因不是模型能力不够,而是信号稀释——400 条指令里找到和当前任务相关的 20 条,比 40 条里找到 20 条困难得多。模型在大量无关规则中无法维持对所有规则的注意力。
修复方案:
修改前:根 CLAUDE.md 400 行(所有规则混在一起)修改后:根 CLAUDE.md 80 行(命令、全局架构、通用安全边界)├── .claude/rules/frontend.md — 前端组件规范(匹配 apps/web/**, packages/ui/**)├── .claude/rules/backend.md — 后端 API 设计指南(匹配 apps/api/**)├── .claude/rules/database.md — 数据库迁移流程(匹配 packages/db/**)├── .claude/rules/deploy.md — 部署步骤(匹配 deploy/**, scripts/**)└── Skill: code-review — Code Review 检查清单(触发时加载)
修改后,常规前端任务的上下文加载:根 CLAUDE.md(1200 tokens)+ frontend rules(400 tokens)= 1600 tokens。相比之前的 6000 tokens,节省了 73%。遵循率回升到约 80%。
教训:CLAUDE.md 的价值不在于写了多少规则,而在于当前任务相关的规则有多突出。 规则越多不等于越好。精简、分层、按需加载才是正确策略。
更深一层的教训是:这个团队犯的错误不是”写了太多规则”,而是”没有对规则做优先级排序”。400 行里的每一条单独看都是合理的,但它们没有区分”每次都需要”和”偶尔需要”。当一个前端开发者让 Claude Code 改按钮颜色时,它不应该被后端数据库迁移流程干扰。分层加载的本质是把”谁在什么时候需要什么”这个工程判断显性化。
如果你正在评估自己团队的 CLAUDE.md 是否过长,可以做一个简单测试:随机选一个任务,跑之前先问 Claude Code”根据 CLAUDE.md,这个任务需要注意哪些规则?”如果它列出了很多和你当前任务无关的规则,说明 CLAUDE.md 需要拆分。
落地检查清单
按顺序执行:
-
• [ ] CLAUDE.md≤ 120 行。如果超过,把路径特定的规则拆到.claude/rules/(见第 05 篇) -
• [ ] 包含五个核心段落:Commands、Architecture、Rules、Safety、Testing -
• [ ] Commands 段落覆盖:安装、开发、测试、类型检查、lint -
• [ ] Architecture 段落用一句话描述每个关键目录的职责和限制 -
• [ ] Rules 段落用 MUST NOT / MUST 做明确约束,不用”应该””尽量” -
• [ ] Safety 段落列出所有不能碰的文件和不能跑的命令 -
• [ ] Testing 段落明确什么操作触发什么测试,附上单文件测试命令 -
• [ ] 让 Claude Code 复述项目结构,确认准确(验证 Architecture 段落是否有效) -
• [ ] 跑三个任务,统计重复提问率和越界率 -
• [ ] Safety 里的关键规则已用 Hooks 兜底(见第 22 篇) -
• [ ] 没有 README 级别的背景描述——项目介绍、团队愿景、技术选型理由不属于 CLAUDE.md
交叉引用
-
• 第 05 篇(rules):路径特定规则的写法和组织方式,CLAUDE.md 超长时的拆分目标位置 -
• 第 22 篇(hooks):确定性控制层,Safety 规则的强制执行机制,CLAUDE.md 建议的兜底保障 -
• 第 00 篇(运行时模型):四层架构中的记忆层定位,CLAUDE.md 在上下文预算中的具体位置和压缩行为
一个实际的工作流
把以上内容串起来,一个团队从零开始配置 CLAUDE.md 的推荐流程:
第一步:让 Claude Code 自助生成草稿。在一个已有项目里运行”阅读仓库结构,生成一份 CLAUDE.md 草稿,包含 Commands、Architecture、Rules、Safety、Testing 五个段落”。它会基于实际代码给出一个合理的起点。
第二步:人工审查和修正。Claude Code 生成的草稿通常在 Commands 和 Architecture 上比较准确(因为它真的读了代码),但在 Rules 和 Safety 上往往遗漏团队的隐性约定。把那些”所有人都知道但没人写下来”的规则补进去。
第三步:验证。跑三个不同类型的任务(修 bug、加功能、重构),观察 Claude Code 是否遵循规则。如果它反复违反某条规则,不是它不听话,是那条规则表述不够具体。改写后重新验证。
第四步:度量。一周后检查遵循率、重复提问率、越界率。如果越界率超过 5%,把对应的 Safety 规则加到 Hooks。
第五步:迭代。项目在演进,CLAUDE.md 也要跟着更新。每次新增一个重要目录、变更测试框架、或者修改部署流程时,同步更新对应的段落。
夜雨聆风