CLAUDE.md:把团队规则写成机器可用上下文
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 成本。
| 内容类型 | 放在哪里 | 加载时机 | Token 成本 | 适用场景 |
|---|---|---|---|---|
| 命令和构建步骤 | CLAUDE.md |
每次会话 | 高(每次全量加载) | 所有项目都需要 |
| 全局架构规则 | CLAUDE.md |
每次会话 | 高 | 分层架构、编码规范 |
| 按路径的编码规则 | .claude/rules/ |
匹配路径时 | 中(按需加载) | monorepo 不同 package |
| 特定任务流程 | Skill | 触发任务时 | 低(仅任务期间) | 复杂工作流如部署 |
| 长脚本和模板 | Skill resources | 明确引用时 | 最低 | 代码生成模板、提示词 |
决策逻辑:
- 每个开发者都需要知道的(命令、架构、安全边界)→
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 遵守规则、不需要额外提醒的会话比例 | 跑 10 个任务,数一数需要手动纠正几次 | ≥ 80% |
| 重复提问率 | Claude Code 询问 CLAUDE.md 中已有答案的问题的比例 | 记录每次会话中的问题,检查是否已在 CLAUDE.md 中 | ≤ 10% |
| 越界率 | Claude Code 违反明确声明的边界(Safety 段落)的比例 | 检查修改的文件是否触达 Safety 列表 | ≤ 5% |
| 首次正确率 | 第一次生成就符合架构规则、不需要返工的代码比例 | 统计需要二次修改的原因,区分"需求不清"和"规则违反" | ≥ 70% |
度量方法不需要复杂工具。连续用 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 | 原因 |
|---|---|---|---|
| 编码风格(用 Tailwind、用 zod) | 主要位置 | 不需要 | 违反后果低,上下文提示足够 |
| 架构分层(route 不写逻辑) | 主要位置 | 可选补充 | 违反后果中等,CLAUDE.md 多数有效 |
| 文件保护(不改 schema、不改 .env) | 列出文件 | 必须配合 | 违反后果高,不能只靠模型自律 |
| 测试要求(改代码后跑测试) | 描述期望 | PostToolUse 提醒 | 双保险:上下文提示 + 事件触发 |
| 命令权限(不能跑 reset、drop) | 不需要 | 主要位置 | 后果严重且可枚举,直接阻断 |
| 工作流步骤(部署流程、发布检查) | 描述流程 | 不需要 | 流程性内容,上下文足够 |
核心原则:违反后果可接受的规则放 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 也要跟着更新。每次新增一个重要目录、变更测试框架、或者修改部署流程时,同步更新对应的段落。
评论
还没有评论
欢迎留下第一条评论,帮助这篇内容更快形成讨论。