PRACTICAL EXPERIENCE / CORE HANDBOOK
项目大脑:CLAUDE.md 深度指南
在 Vibe Coding 时代,AI Agent 经常被抱怨"不听话"——每次新建会话都要重新交代规范,多轮对话后忘记项目约定,或者写出与项目完全不搭调的代码。 这一切问题的答案,都指向同一个文件:**`CLAUDE.md`**。 `CLAUDE.md` 是 Claude Code 官方支持的项目记忆文件。每次会话启动时,Claude Code 自动将其注入上下文,相当于给这位"会失忆的超级程序员"配备了一本永远摆在桌上的工作手册。本文结合官方文档与大型项目实战,全面解析 `CLAUDE.md` 的机制、写法与最佳实践。 --- ## 1. 两种互补的记忆机制 Claude Code 提供两种持久记忆机制,两者相互补充,在每次会话启动时都会被加载: * **CLAUDE.md 文件**:由**你编写**的规则与约束。内容是指令与规范,作用范围可以是项目、用户或整个组织。 * **自动记忆(Auto Memory)**:由 **Claude 自动写入**的笔记。Claude 根据你的纠正与偏好,自动在 `~/.claude/projects/返回 PPT:CLAUDE.md & AGENTS.md 最佳实践 ↗/memory/MEMORY.md` 中积累知识,无需你手动维护。 两者的核心区别如下表所示: | 维度 | CLAUDE.md 文件 | 自动记忆(Auto Memory) | | --- | --- | --- | | **谁来写** | 你 | Claude 自动写入 | | **写什么** | 指令与规范 | 学习到的习惯与偏好 | | **作用范围** | 项目、用户或组织 | 按仓库隔离,跨 Worktree 共享 | | **何时加载** | 每次会话启动 | 每次会话启动(最多前 200 行或 25KB) | | **适合放什么** | 编码规范、工作流、项目架构 | 构建命令、调试经验、Claude 发现的偏好 | > **重要区别**:CLAUDE.md 是约束层(你来主导),Auto Memory 是学习层(Claude 自动积累)。如果需要硬性阻止某个行为(如禁止直接 push main),应该用 Hook 或 Permission 而不是 CLAUDE.md。 ### 自动记忆(Auto Memory)的工作原理 Auto Memory 默认开启。每次会话中,当 Claude 发现值得记录的信息(如你纠正了一个命令、确认了一个编码偏好),它会自动保存到本地目录: ```text ~/.claude/projects/ /memory/ ├── MEMORY.md # 简洁索引,每次会话自动加载 ├── debugging.md # 调试模式的详细笔记 ├── api-conventions.md # API 设计决策 └── ... # Claude 自动创建的其他主题文件 ``` * `MEMORY.md` 是入口索引,每次会话自动加载其前 200 行或 25KB。 * 详细笔记会被拆分到专题文件(如 `debugging.md`),按需读取。 * 所有文件都是普通 Markdown,你可以随时编辑或删除。 使用 `/memory` 命令可以在会话中浏览和编辑所有记忆文件。 --- ## 2. CLAUDE.md 的四层作用域 `CLAUDE.md` 不是一个单一文件,而是一个**作用域层级系统**。不同位置的文件作用于不同范围,Claude Code 在启动时会按照从宽到窄的顺序依次加载它们,后加载的文件(更接近工作目录的文件)在上下文中排列靠后,优先级更高: | 作用域 | 文件位置 | 用途 | 是否共享 | | --- | --- | --- | --- | | **组织策略** | macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md` | IT/DevOps 管理的全公司规范 | 同机器所有用户 | | **用户个人** | `~/.claude/CLAUDE.md` | 个人偏好,适用于所有项目 | 仅自己 | | **项目共享** | `./CLAUDE.md` 或 `./.claude/CLAUDE.md` | 团队共享的项目规范 | 通过版本控制共享给团队 | | **本地私有** | `./CLAUDE.local.md` | 个人项目偏好,加入 `.gitignore` | 仅自己(当前项目) | ### 加载机制详解 Claude Code 从**当前工作目录向上遍历**目录树,加载所有层级的 `CLAUDE.md` 和 `CLAUDE.local.md`。所有文件会被**拼接注入上下文**,而不是互相覆盖。 * 子目录中的 `CLAUDE.md` 不在启动时全量加载,而是在 Claude 读取该子目录中的文件时**按需加载**。 * `CLAUDE.local.md` 始终在同目录 `CLAUDE.md` 之后追加,你的个人备注是最后被 Claude 读取的内容。 使用 `/context` 命令可以查看当前会话实际加载了哪些记忆文件。 --- ## 3. AGENTS.md 与 CLAUDE.md 的正确关系 Claude Code 读取的是 `CLAUDE.md`,**不读取** `AGENTS.md`。 如果你的项目已经维护了一个供 Cursor、Aider 等其他 Agent 工具使用的 `AGENTS.md`,推荐用以下方式让 Claude Code 也能读取它,同时添加 Claude 专属指令: ```markdown @AGENTS.md ## Claude Code 专属约束 - 对 `src/billing/` 下的改动,必须进入 Plan 模式先确认方案再执行。 - 禁止使用 `any` 类型,使用前必须在聊天中说明原因。 ``` 也可以简单创建一个符号链接(无需额外内容时): ```bash ln -s AGENTS.md CLAUDE.md ``` 运行后,执行 `/context` 确认 `CLAUDE.md` 出现在 **Memory files** 列表中即为成功。 > **注意**:`@path` 导入语法会在会话启动时将文件内容展开注入上下文。如果被导入的文件路径在工作目录之外(如家目录),首次使用时 Claude Code 会弹出授权确认对话框。 --- ## 4. 快速上手:用 /init 自动生成 CLAUDE.md 不知道从何写起?Claude Code 提供了 `/init` 命令,它会自动分析你的代码库,并生成包含构建命令、测试指令和项目约定的初始 `CLAUDE.md`: ```bash # 在项目根目录启动 Claude Code 后,输入: /init ``` * 如果项目中已有 `CLAUDE.md`,`/init` 会给出优化建议而不是覆盖。 * 设置环境变量 `CLAUDE_CODE_NEW_INIT=1` 可开启交互式多阶段初始化流程:先探索代码库,再通过问答填补信息空白,最后展示方案供你审阅后才写入文件。 * `CLAUDE_CODE_NEW_INIT=1` 模式下,`/init` 还会自动读取 `.cursor/rules/`、`.cursorrules`、`AGENTS.md` 等其他 Agent 工具的规则文件,将相关内容整合进来。 生成后,用 `/doctor` 命令可以让 Claude 检查 `CLAUDE.md` 是否过大,并提出裁剪建议(删除可以从代码库直接推断的内容,如目录结构、依赖列表等)。 --- ## 5. 应该包含哪些核心内容? 一个合格的 `CLAUDE.md` 只包含**模型无法从已有源码中自行推断出来的约束与规范**。官方建议控制在 **200 行以内**——超过这个长度,上下文消耗增大,Claude 的遵从度反而下降。 内容应聚焦在以下几个维度: ### 常用命令(Commands) 列出构建、运行、测试和 Lint 的具体 Shell 命令。Claude 有执行 Shell 命令的能力,写明这些命令后,它修改代码后会自行在终端验证,大幅降低人工介入频率。 ```markdown ## 常用命令 - 启动开发服务器: `npm run dev` - 构建项目: `npm run build` - 运行单测: `npm test` - 代码检查: `npm run lint` - 数据库迁移: `npx prisma db push` ``` ### 技术栈与架构约束(Architecture) 统一技术选型,防止 AI 引入不相关的依赖。告知目录规范和 API 契约: ```markdown ## 技术栈 - React 18 (Next.js App Router) + TypeScript strict 模式 + Tailwind CSS - 状态管理: Zustand - 组件库: shadcn/ui,位于 @/components/ui ## 架构约束 - 业务逻辑封装在 src/services/,页面组件只做渲染 - API 统一返回格式: { success: boolean, data: T, code: number, message: string } - 按钮/输入框/下拉框必须从 @/components/ui/ 导入,禁止手写基础 CSS ``` ### 编码风格(Code Style) 写具体可验证的规则,而不是模糊描述: ```markdown ## 编码风格 - 使用 2 空格缩进(不是 4 空格,也不是 Tab) - 命名: 文件与组件 PascalCase,函数与变量 camelCase - 禁止显式 any,所有 API 入参出参必须定义 Interface/Type - 异步请求必须包含 try-catch,错误统一调用 toast.error() ``` ### 避坑红线(DO NOTs) 记录项目绝对不能触碰的底线: ```markdown ## 禁止事项 - 严禁修改 prisma/schema.prisma 历史主键,新增字段必须通过 Migration - 禁止将 Token、密码或 API Key 硬编码在代码中,必须使用 .env.local - 禁止在组件内写超过 20 行内联 CSS - 修改接口时禁止删除已有参数,必须保持向下兼容 ``` ### 业务守恒原则(Preservation) 对重构与迁移任务设置最高优先级的业务完整性要求: ```markdown ## 业务守恒 - 重构或样式迁移时,必须 100% 保留: - 所有查询字段、重置按钮与页签默认过滤条件 - 权限控制标识(如 hasPermission('admin')) - 所有接口字段与数据契约,严禁凭空幻觉删减 ``` --- ## 6. 用 .claude/rules/ 实现精细化规则管理 当项目较大时,把所有规则堆在一个 `CLAUDE.md` 里很快会失控。官方提供了 `.claude/rules/` 目录来实现**模块化规则管理**: ```text your-project/ ├── CLAUDE.md # 主指引文件(简洁,控制在 50 行内) └── .claude/ └── rules/ ├── code-style.md # 编码风格规范 ├── testing.md # 测试约定 ├── security.md # 安全要求 └── frontend/ └── components.md # 组件专属规则 ``` ### 路径限定规则(Path-scoped Rules) 规则文件可以通过 YAML frontmatter 将作用范围限定到特定文件路径。只有当 Claude 读取匹配路径的文件时,该规则才会被加载,节省上下文空间: ```markdown --- paths: - "src/api/**/*.ts" - "lib/**/*.ts" --- ## API 开发规范 - 所有 API 端点必须包含输入校验 - 使用标准错误响应格式 { code, message, data } - 必须包含 OpenAPI 注释文档 ``` 常用的 glob 匹配模式: | 模式 | 匹配范围 | | --- | --- | | `**/*.ts` | 任意目录下所有 TypeScript 文件 | | `src/**/*` | src/ 目录下所有文件 | | `*.md` | 项目根目录的 Markdown 文件 | | `src/components/*.tsx` | 特定目录下的 React 组件 | --- ## 7. 完整模板:可直接复制使用 以下是一个通用的、控制在 200 行以内的 `CLAUDE.md` 标准模板,适合大多数前端项目: ```markdown # 项目核心指引 (CLAUDE.md) ## 常用命令 - 启动: `npm run dev` - 构建: `npm run build` - 测试: `npm test`(提交前必须通过) - Lint: `npm run lint` ## 技术栈 - React 18 + TypeScript (strict) + Tailwind CSS + Prisma - 状态管理: Zustand - UI 组件: shadcn/ui(@/components/ui) ## 架构约束 - 业务逻辑封装于 src/services/,禁止在组件内直接调用 API - API 返回格式: `{ success: boolean, data: T, code: number, message: string }` - 组件必须从 @/components/ui/ 导入,禁止手写内联样式基础组件 ## 编码规范 - 2 空格缩进,PascalCase 组件名,camelCase 函数名 - 禁止显式 any,所有 API 参数必须定义 Type - 异步操作必须 try-catch,错误调用 toast.error() ## 禁止事项 - 禁止修改 prisma/schema.prisma 的历史主键定义 - 禁止硬编码密钥,必须用 .env.local 环境变量 - 禁止修改接口时删除已有参数,保持向下兼容 - 修改后未通过单测,禁止提交 ## 业务守恒 - 重构/迁移时,100% 保留:查询字段、权限标识、接口契约 ## 导入补充规范 @docs/git-workflow.md ``` > **小技巧**:CLAUDE.md 中的 HTML 注释(``)会在注入上下文前被自动过滤,不消耗 Token。可以用来给人类维护者留下备注。 --- ## 8. 实战案例:长江电力 600+ 页面的约束体系 在"长江电力新一代生产经营管理系统"实战中,团队只有 4 名开发人员,却需要在 12 个异构协作团队共同参与的情况下,构建 **600+ 个页面**且保持 100% 规范一致。 核心解法就是将所有工程约束沉淀进 `AGENTS.md`(通过软链映射至 `CLAUDE.md`),建立了三层约束体系: ### 第一层:Skill 路由与任务分流 大型工程不能让一个通用 coding 助手干所有事。项目在 `AGENTS.md` 中明确了任务路由规则,将不同类型任务路由给专属的 Agent Skills: ```markdown ## Skill 路由规则 - 新增 Vue 业务页面 → 调用 `frontend-page-builder` Skill - 样式审查与迁移 → 调用 `design-review` Skill - 组件封装与复用 → 调用 `component-refactor` Skill ## 源码事实优先级(Fact Order) 组件状态表 > index.ts 导出 > Vue 源码 > Design Tokens > 业务页面 > 文档 ``` ### 第二层:公共组件基线绑定 为杜绝 AI 和开发者随意使用开源组件或手写内联 CSS,`AGENTS.md` 强制要求使用 stable 状态的 `Ds*` 规范库: ```markdown ## 组件基线约束 - 列表页面必须使用 DsPage + DsDataTable(禁止手搭分页逻辑) - 表单使用 DsFormGrid(禁止 flex/grid 手排布) - 状态标签使用 DsStatusTag(禁止自定义彩色标签) - 严禁内联 style,严禁硬编码颜色/圆角值,严禁覆盖 .ant-* 全局类 ``` ### 第三层:业务守恒硬约束 重构与迁移是最容易出错的场景。项目在 `AGENTS.md` 中设置了最高级别的业务守恒要求: ```markdown ## 业务守恒原则(最高优先级) 在重构或样式迁移时,下列内容必须 100% 保留,违反视为高优 Bug: - 所有查询字段与重置按钮的默认条件 - 所有权限按钮标识(v-permission, hasPermission) - 接口入参与响应字段契约,严禁凭空幻觉删减 - 页签、抽屉、弹窗的触发条件与数据绑定 ``` **结果**:在 `AGENTS.md` 的约束下,系统 1,156 个业务视图中有 1,021 个深度绑定了 `Ds*` 规范库,组件覆盖率高达 **88.3%**,整体研发周期从传统模式的 650 人天压缩至 **176 人天**。 --- ## 9. 日常演进:把 AI 犯错成本变成工程资产 `CLAUDE.md` 绝不是写完就束之高阁的文档,而是一个**与项目共同成长的 Living Doc**。 官方文档给出了最佳添加时机:当 Claude 犯了同样的错误第二次、代码审查发现了 Claude 应该已知的问题、或者你在聊天框里输入了和上次会话完全相同的纠正语句时,就应该立刻将其写入 `CLAUDE.md`。 核心心法是**"持续改进闭环"**: > AI 犯错 → 排查根因 → 把红线写进 CLAUDE.md → 下次会话自动遵守 每一次 AI 犯错,你不只是在修复一个 Bug,更是在**把修复成本变成项目永久的工程化资产**。只要这个规则在 `CLAUDE.md` 里,以后这个错误就不会再发生。 ### 排查指令速查 当你怀疑 Claude 没有读取 `CLAUDE.md` 规范时: ```bash # 在会话中检查哪些记忆文件被加载了 /context # 浏览和编辑所有记忆文件(CLAUDE.md + Auto Memory) /memory # 检查 CLAUDE.md 是否过大,获取裁剪建议 /doctor ``` 常见排查项: * 运行 `/context`,确认 `CLAUDE.md` 出现在 **Memory files** 列表中。 * 检查相关 `CLAUDE.md` 是否在 Claude Code 的加载路径中。 * 把指令写得更具体,例如"使用 2 空格缩进"比"格式化好看"有效得多。 * 检查多个 CLAUDE.md 文件之间是否存在相互矛盾的指令。 > 如果某个操作必须在特定时机强制执行(如提交前必须运行 Lint),应该使用 **Hook** 而不是 `CLAUDE.md`。Hook 以 Shell 命令形式在固定生命周期事件中执行,不依赖 Claude 的主观判断。