CLAUDE.md 编写最佳实践技术分析
一、概述
1. 简介
A. 是什么
CLAUDE.md 是 Claude Code 的高杠杆配置点,也是每个会话中默认注入的唯一文件。学习如何编写高质量的 CLAUDE.md(或 AGENTS.md)是代理驱动软件工程的关键技能。
B. 为什么重要
- LLM 是无状态函数,每个会话开始时对代码库一无所知
- CLAUDE.md 是让 Claude 了解代码库的主要方式
- 编写质量直接影响 AI 代理的工作效率
C. 学完能做什么
- 编写简洁有效的 CLAUDE.md 文件
- 使用渐进式信息披露原则优化上下文
- 避免常见陷阱,最大化 Claude Code 的效能
2. 核心原理
LLM 的权重在推理时被冻结,不会随时间学习。模型对代码库的了解完全取决于输入的 token。因此:
- 每次会话开始时,编码代理对代码库一无所知
- 必须在每次会话中告诉代理重要信息
- CLAUDE.md 是实现这一目标的首选方式
二、LLM 的无状态特性
1. 无状态函数
LLM 是无状态的,模型权重在推理时冻结。这意味着:
- 模型不会跨会话学习
- 每个会话都是独立的
- 所有知识必须通过上下文提供
2. 代理记忆管理
编码代理框架(如 Claude Code)通常需要显式管理代理记忆。CLAUDE.md 是默认进入每个对话的唯一文件。
graph LR
A[新会话开始] --> B[CLAUDE.md 注入]
B --> C[系统提示加载]
C --> D[用户消息]
D --> E[代理生成响应]
E --> F[会话结束]
F --> A3. 三层含义
- 代理在每次会话开始时对代码库一无所知
- 必须在每次会话开始时告诉代理代码库的重要信息
- CLAUDE.md 是实现这一目标的首选方式
三、CLAUDE.md 的核心作用
1. 代码库入职引导
CLAUDE.md 应该将 Claude 接入代码库,高层面上应覆盖:
- WHAT:技术栈、项目结构、代码库地图
- WHY:项目目的、各部分功能
- HOW:工作方式、验证方法、测试运行
2. 内容组成
mindmap
root((CLAUDE.md))
WHAT
技术栈
项目结构
代码库地图
monorepo 布局
WHY
项目目的
各部分功能
设计意图
HOW
运行命令
测试方法
类型检查
编译步骤
验证变更3. 编写原则
不要试图将所有可能需要的命令都塞进 CLAUDE.md,这会导致次优结果。
四、Claude 对 CLAUDE.md 的处理机制
1. 系统提醒包装
Claude Code 在系统提醒中包装 CLAUDE.md 内容:
<system-reminder>
IMPORTANT: this context may or or may not be relevant to your tasks.
You should not respond to this context unless it is highly relevant to your task.
</system-reminder>2. 忽略机制
当 Claude 认为 CLAUDE.md 内容与当前任务不相关时,会忽略这些内容。文件中不普遍适用的信息越多,Claude 越可能忽略指令。
3. 设计原因
许多用户将 CLAUDE.md 作为添加行为热修复的方式,附加了大量不普遍适用的指令。通过告诉 Claude 忽略不良指令,框架实际上产生更好的结果。
五、编写高质量 CLAUDE.md 的原则
1. 少即是多
A. 指令跟随能力研究
- 前沿思考型 LLM 可以合理跟随约 150-200 条指令
- 较小模型的能力衰减更快,呈现指数级衰减
- 较大模型呈现线性衰减
B. 注意力偏向
LLM 倾向于关注提示边缘的指令:
- 最开始:Claude Code 系统消息和 CLAUDE.md
- 最结尾:最近的用户消息
C. 指令数量影响
随着指令数量增加,指令跟随质量均匀下降。模型不会只忽略新指令,而是开始均匀忽略所有指令。
graph XY
x-axis["指令数量"] --> 0 --> 50 --> 100 --> 150 --> 200 --> 250
y-axis["指令跟随质量"] --> 0.0 --> 0.2 --> 0.4 --> 0.6 --> 0.8 --> 1.0
line["小模型(指数衰减)"] : [0, 1.0] : [50, 0.6] : [100, 0.3] : [150, 0.1] : [200, 0.05] : [250, 0.02]
line["大模型(线性衰减)"] : [0, 1.0] : [50, 0.85] : [100, 0.7] : [150, 0.55] : [200, 0.4] : [250, 0.25]D. Claude Code 系统提示
Claude Code 的系统提示包含约 50 条独立指令,这已接近代理可可靠跟随指令的三分之一。
2. 文件长度与适用性
A. 上下文窗口原则
当上下文窗口充满专注、相关的上下文(示例、相关文件、工具调用、工具结果)时,LLM 在任务上的表现更好。
B. 普遍适用性要求
由于 CLAUDE.md 进入每个会话,应确保其内容尽可能普遍适用。
C. 长度建议
- Anthropic 没有官方建议长度
- 一般共识:少于 300 行最佳,越短越好
- HumanLayer 的根 CLAUDE.md 少于 60 行
3. 渐进式信息披露
A. 概念
编写简洁的 CLAUDE.md 文件可能具有挑战性,特别是在大型项目中。渐进式信息披露原则确保 Claude 只在需要时看到任务或项目特定的指令。
B. 实现方式
将任务特定的指令保存在单独的 markdown 文件中:
agent_docs/
|- building_the_project.md
|- running_tests.md
|- code_conventions.md
|- service_architecture.md
|- database_schema.md
|- service_communication_patterns.mdC. 引用机制
在 CLAUDE.md 中包含这些文件的列表及简要描述,指示 Claude 决定哪些文件相关并在开始工作前阅读它们。
D. 指针优于副本
尽可能不要在这些文件中包含代码片段,它们会很快过时。相反,应包含 file:line 引用以指向权威上下文。
graph TD
A[CLAUDE.md 主文件] -->|引用| B[agent_docs/]
B --> C[构建文档]
B --> D[测试文档]
B --> E[代码规范]
B --> F[架构文档]
C -->|file:line 引用| G[实际代码文件]
D -->|file:line 引用| G
E -->|file:line 引用| G
F -->|file:line 引用| G4. Claude 不是昂贵的 linter
A. 常见错误
最常见的做法之一是在 CLAUDE.md 中放入代码风格指南。
B. 问题分析
- LLM 相比传统 linter 和 formatter 昂贵且缓慢
- 代码风格指南会添加大量指令和大多不相关的代码片段
- 降低 LLM 性能和指令跟随能力,占用上下文窗口
C. 正确做法
- 始终在可能时使用确定性工具
- LLM 是上下文学习者,会倾向于遵循现有代码模式和约定
- 可以设置 Claude Code Stop 钩子运行 formatter 和 linter
- 创建包含代码指南的斜杠命令
D. 推荐工具
使用可以自动修复问题的 linter(如 Biome),仔细调整规则以实现最大(安全)覆盖。
5. 避免自动生成
A. 高杠杆点
CLAUDE.md 进入每个会话,是框架的最高杠杆点之一。
B. 影响层次
- 一行不良代码只是一行不良代码
- 实施计划中的一行不良代码可能创建大量不良代码
- 研究中的一行不良代码可能误解系统工作方式,导致计划中的大量不良行
- CLAUDE.md 影响工作流程的每个阶段和每个工件
C. 杠杆作用分析
graph LR
A[CLAUDE.md] -->|影响| B[研究阶段]
A -->|影响| C[计划阶段]
A -->|影响| D[实施阶段]
B -->|产生| E[研究文档]
C -->|产生| F[实施计划]
D -->|产生| G[代码变更]
E -->|指导| F
F -->|指导| GD. 建议
不要使用 /init 或自动生成 CLAUDE.md,应该仔细 crafting 其内容以获得最佳结果。
六、最佳实践总结
1. 核心要点
- CLAUDE.md 用于将 Claude 接入代码库,应定义项目的 WHY、WHAT 和 HOW
- 少即是多,应包含尽可能少的合理指令
- 保持内容简洁且普遍适用
- 使用渐进式信息披露,告诉 Claude 如何找到重要信息
- Claude 不是 linter,应使用 linter 和代码 formatter
- CLAUDE.md 是框架的最高杠杆点,避免自动生成
2. 实施建议
- 仔细考虑放入的每一行内容
- 使用单独的文档文件存储任务特定信息
- 优先使用 file:line 引用而非代码副本
- 利用钩子和斜杠命令处理特定任务
- 保持文件简短(少于 60 行理想)
3. 常见陷阱
- 塞入过多命令和指令
- 包含不普遍适用的代码风格指南
- 自动生成而不仔细审查
- 忽略渐进式信息披露原则
- 将 CLAUDE.md 作为行为热修复机制
七、实际应用建议
1. monorepo 项目
在 monorepo 中,CLAUDE.md 尤为重要。应该:
- 说明有哪些应用
- 说明有哪些共享包
- 说明每个部分的用途
- 帮助 Claude 知道在哪里查找内容
2. 验证方法
告诉 Claude 如何验证其变更:
- 如何运行测试
- 如何执行类型检查
- 如何执行编译步骤
3. 工具链集成
- 使用 bun 而非 node 等特定工具
- 项目特定的构建命令
- 自定义脚本和工具
八、进阶技巧
1. 钩子机制
使用 Claude Code 的 Stop 钩子:
- 在每次变更时运行 formatter 和 linter
- 将错误呈现给 Claude 进行修复
- 实现代码质量自动化
2. 斜杠命令
创建专用斜杠命令:
- 包含代码指南
- 指向版本控制中的变更
- 指向 git status
- 分离实施和格式化
3. 文档组织
project_root/
|- CLAUDE.md(主文件,<60 行)
|- agent_docs/
|- building_the_project.md
|- running_tests.md
|- code_conventions.md
|- service_architecture.md九、案例对比
1. 不良示例
# CLAUDE.md - 过于冗长
## 项目概述
这是一个使用 React、TypeScript、Node.js、MongoDB、Redis、
Kubernetes、Docker... 的项目...
## 代码风格
- 使用 2 空格缩进
- 使用单引号
- 函数名使用 camelCase
- 类名使用 PascalCase
- 常量使用 UPPER_SNAKE_CASE
...(100 行代码风格指南)
## 数据库模式
- users 表包含...
- orders 表包含...
...(50 行数据库模式)
## API 端点
- GET /api/users...
- POST /api/orders...
...(80 行 API 文档)2. 良好示例
# CLAUDE.md - 简洁有效
## 项目概述
E-commerce 平台,前端使用 React + TypeScript,
后端使用 Node.js + Express,数据存储为 MongoDB。
## 项目结构
- frontend/:React 前端应用
- backend/:Node.js API 服务
- shared/:共享类型定义
- infra/:Kubernetes 配置
## 如何运行
详见 agent_docs/building_the_project.md
## 测试
详见 agent_docs/running_tests.md
## 架构
详见 agent_docs/service_architecture.md