返回列表

CLAUDE.md 完全指南:写好 Claude Code 的「员工手册」,从入门到精通

2026-03-03·16 分钟阅读·AI教程

前言

如果你只能为 Claude Code 写一个配置文件,那一定是 CLAUDE.md。

CLAUDE.md 是 Claude Code 的**「员工手册」**。它告诉 Claude "做什么"——项目怎么构建、代码风格是什么、有哪些坑要避开。而 settings.json 告诉 Claude "怎么做"——权限、模型、工具配置。两者搭配,才是完整的 Claude Code 配置体系。

很多人用 Claude Code 觉得"不够聪明"、"总是犯同样的错",大多数时候不是模型的问题,而是没有给够上下文。CLAUDE.md 就是解决这个问题的核心手段。

这篇文章把 CLAUDE.md 讲透——从文件层级到写作原则,从高价值内容到反模式,再到完整的实战示例。


一、CLAUDE.md 是什么

1.1 一句话定义

CLAUDE.md 是一个纯文本文件,放在项目中(或用户目录下),Claude Code 启动时自动读取,作为整个会话的背景指令。你写在里面的内容,Claude 会在每次对话中都"记住"。

把它想象成你给一个新同事写的入职文档:项目怎么跑、代码怎么写、有什么规矩。区别是这个"同事"每次上班都会从头读一遍这份文档。

1.2 和其他配置文件的区别

Claude Code 有四种配置文件,各司其职:

文件内容类型作用类比
CLAUDE.md自然语言项目知识、编码规范、工作流指令员工手册
settings.jsonJSON权限、工具、模型、环境变量IT 安全策略
.claude/commands/Markdown 模板可复用的 Prompt 模板SOP 操作手册
.claudeignoreGlob 模式排除文件/目录,不让 Claude 读取.gitignore

一个常见的误区是把所有东西都塞进 CLAUDE.md。记住分工:

  • "Claude 应该知道什么" → CLAUDE.md
  • "Claude 被允许做什么" → settings.json
  • "Claude 不该看什么文件" → .claudeignore
  • "常用操作怎么一键触发" → commands

1.3 为什么 CLAUDE.md 是最重要的配置文件

settings.json 控制的是"能不能",CLAUDE.md 控制的是"好不好"。

没有 settings.json,Claude Code 照样能工作(只是每次都要确认权限)。但没有 CLAUDE.md,Claude 就像一个什么都不知道的新人——它不知道你的项目用什么构建工具、测试怎么跑、代码风格有什么特殊要求。它只能靠猜,而猜错的概率很高。

CLAUDE.md 是你获得好结果最重要的杠杆。


二、文件层级与加载顺序

2.1 五个层级

CLAUDE.md 有五个层级,Claude Code 启动时会按顺序加载并合并:

① Enterprise(最高优先级,不可覆盖)
   ~/.claude/enterprise/CLAUDE.md

② 用户级(跨项目的个人偏好)
   ~/.claude/CLAUDE.md

③ 项目根目录(团队共享,提交到 Git)
   ./CLAUDE.md

④ 子目录级(特定模块的上下文)
   ./src/CLAUDE.md
   ./packages/api/CLAUDE.md

⑤ 项目用户级(个人项目笔记,不提交)
   ~/.claude/projects/<project-hash>/CLAUDE.md

2.2 层级详解

层级路径谁写是否提交 Git典型内容
Enterprise~/.claude/enterprise/CLAUDE.mdIT 管理员N/A公司级编码规范、安全要求
用户级~/.claude/CLAUDE.md个人N/A个人偏好(语言、风格)
项目根目录./CLAUDE.md团队构建命令、架构、约定
子目录级./src/CLAUDE.md团队模块特定的上下文
项目用户级~/.claude/projects/<hash>/CLAUDE.md个人N/A个人笔记、临时提醒

2.3 加载与合并行为

所有层级的 CLAUDE.md 内容会拼接在一起,作为 Claude 的系统上下文。不是覆盖,是拼接——所有层级的内容 Claude 都能看到。

最终上下文 = Enterprise
           + 用户级
           + 项目根目录
           + 当前工作目录的子目录级(如果有)
           + 项目用户级

关键细节:

  • 子目录级是动态的:Claude 只会加载当前工作目录路径上的子目录 CLAUDE.md。如果你在 packages/api/ 下工作,Claude 会加载 packages/api/CLAUDE.md,但不会加载 packages/web/CLAUDE.md
  • Enterprise 不可覆盖:其他层级无法"取消"Enterprise 层的指令。这是给企业 IT 管理员用的强制策略。
  • 内容冲突时:如果两个层级的指令矛盾,Claude 会倾向于遵循更具体的(子目录 > 项目根目录 > 用户级)。但最好避免冲突。

2.4 每个层级的使用场景

Enterprise(~/.claude/enterprise/CLAUDE.md):

# 公司编码规范
 
- 所有代码必须通过 ESLint 检查后才能提交
- 不要使用 any 类型
- 所有 API 端点必须有错误处理
- 日志使用公司统一的 logger 库,不要用 console.log
- 敏感数据(API Key、密码)绝不能硬编码

这个文件由 IT 管理员部署到每台开发机器上,开发者无法修改。

用户级(~/.claude/CLAUDE.md):

# 个人偏好
 
- 回复使用中文
- 代码注释使用英文
- 优先使用函数式编程风格
- commit message 使用 Conventional Commits 格式

跨项目生效。适合放个人习惯和偏好。

项目根目录(./CLAUDE.md):

这是最重要的层级,下一节详细讲。

子目录级(./packages/api/CLAUDE.md):

# API 包约定
 
- 所有路由处理函数放在 routes/ 目录
- 使用 zod 做请求参数校验
- 错误响应统一使用 AppError 类
- ���据库查询使用 repository 模式
- 测试文件和源文件放在同一目录:user.service.ts → user.service.test.ts

适合 Monorepo 中不同包有不同约定的场景。

项目用户级(~/.claude/projects/<hash>/CLAUDE.md):

# 个人笔记
 
- 当前正在重构 auth 模块,注意不要改动 legacy/ 目录
- payments 模块的测试需要 mock Stripe API
- 本地开发用 port 3001(3000 被其他项目占了)

这个文件由 /memory 命��自动创建和管理,不提交到 Git。适合放个人的临时笔记和提醒。


三、该写什么:高价值内容指南

项目根目录的 CLAUDE.md 是最核心的文件。这一节讲清楚:什么内容值得写,怎么写效果最好。

3.1 构建 / 测试 / Lint 命令(最高价值)

这是 CLAUDE.md 中价值最高的内容。Claude 需要这些命令来验证自己的工作——写完代码后跑测试、跑 lint,确认没有破坏任何东西。

# 常用命令
 
- 构建:`npm run build`
- 开发服务器:`npm run dev`(端口 3000)
- 全量测试:`npm test`
- 单文件测试:`npm test -- path/to/file.test.ts`
- Lint:`npm run lint`
- 类型检查:`npx tsc --noEmit`
- 格式化:`npx prettier --write .`

为什么这是最高价值?

没有这些命令,Claude 只能写代码然后"希望"它是对的。有了这些命令,Claude 会在写完代码后主动运行测试和 lint,发现问题立即修复。这是从"写代码"到"交付可工作的代码"的关键跨越。

进阶写法——区分不同场景:

# 命令
 
## 测试
- 全量测试:`npm test`
- 单元测试:`npm run test:unit`
- 集成测试:`npm run test:integration`(需要先启动数据库:`docker compose up -d db`
- 单文件测试:`npx vitest run path/to/file.test.ts`
- 测试覆盖率:`npm run test:coverage`
 
## 构建
- 开发构建:`npm run build:dev`
- 生产构建:`npm run build`(会执行类型检查)
 
## 代码质量
- Lint:`npm run lint`
- Lint 自动修复:`npm run lint:fix`
- 类型检查:`npx tsc --noEmit`
- 格式化检查:`npx prettier --check .`

3.2 代码风格和约定

只写非显而易见的、和默认不同的约定。Claude 已经知道通用的编码规范,你不需要教它"函数名用 camelCase"(除非你的项目偏偏不用)。

好的写法:

# 代码风格
 
- 使用具名导出(named export),不用默认导出(default export)
- React 组件用 arrow function,不用 function declaration
- 状态管理统一用 Zustand,不要引入 Redux
- CSS 使用 Tailwind,不写自定义 CSS 文件
- 错误处理用 Result 模式(neverthrow 库),不用 try-catch
- 文件命名:组件用 PascalCase(UserProfile.tsx),工具函数用 kebab-case(format-date.ts)

不好的写法:

# 代码风格
 
- 使用 TypeScript(← 项目已经是 TS,Claude 能看到 tsconfig.json)
- 缩进用 2 空格(← .prettierrc 里已经配了)
- 使用 ESLint(← package.json 里已经有了)
- 变量命名用 camelCase(← 这是 JS/TS 的默认约定)

3.3 架构概览

保持简短。Claude 能读代码,不需要你把整个架构文档复制过来。只需要给它一个"地图",让它知道去哪里找什么。

# 项目架构
 
Monorepo(pnpm workspace):
- `packages/api/` — Express 后端,REST API
- `packages/web/` — Next.js 前端
- `packages/shared/` — 共享类型和工具函数
- `packages/db/` — Prisma schema 和数据库迁移
 
API 路由结构:
- `routes/` — 路由定义(thin controller)
- `services/` — 业务逻辑
- `repositories/` — 数据库访问
- `middleware/` — Express 中间件
 
数据流:Route → Service → Repository → Prisma

3.4 重要警告和陷阱

这类信息价值极高——它们是 Claude 不可能从代码中推断出来的"隐性知识"。

# 重要警告
 
- `users` 表的 `email` 字段有唯一约束,但 `profiles` 表没有——不要假设 profile.email 是唯一的
- `legacy/` 目录下的代码不要修改,它会在 Q3 被移除
- 环境变量 `DATABASE_URL` 在本地和 CI 中格式不同(本地用 localhost,CI 用 Docker 网络名)
- `payment.service.ts` 中的金额计算必须用 Decimal.js,不要用浮点数
- 修改 `schema.prisma` 后必须运行 `npx prisma generate`,否则类型不会更新

3.5 Git 和工作流约定

# Git 约定
 
- 分支命名:`feat/xxx``fix/xxx``refactor/xxx`
- Commit message 格式:`type(scope): description`
  - 例:`feat(auth): add OAuth2 login`
  - 例:`fix(api): handle null response from payment gateway`
- 提交前必须通过:lint + 类型检查 + 相关测试
- 不要直接 push 到 main,走 PR 流程
- PR 标题和 commit message 格式一致

3.6 测试约定

# 测试约定
 
- 测试文件放在 `__tests__/` 目录,命名为 `xxx.test.ts`
- 使用 Vitest + React Testing Library
- Mock 外部服务,不 mock 内部模块
- 测试描述用中文:`describe('用户登录')` / `it('应该返回 JWT token')`
- 每个 PR 必须包含对应的测试
- 集成测试使用 testcontainers 启动真实数据库

3.7 技术栈摘要

当项目技术栈不是"一眼能看出来"的时候,写一个简短的摘要很有帮助:

# 技术栈
 
- Runtime: Node.js 20 + TypeScript 5.4
- 前端: Next.js 16 (App Router) + Tailwind CSS v4
- 后端: Express 5 + tRPC
- 数据库: PostgreSQL 16 + Prisma ORM
- 缓存: Redis 7(用于 session 和 rate limiting)
- 测试: Vitest + Playwright(E2E)
- CI/CD: GitHub Actions
- 部署: Docker + AWS ECS

四、写作原则

知道该写什么之后,还要知道怎么写。CLAUDE.md 的写法直接影响 Claude 的理解效果。

4.1 简洁直接,用祈使语气

CLAUDE.md 是给 Claude 的指令,不是给人读的文档。用祈使语气,像给同事发 Slack 消息一样。

不好的写法好的写法
在我们的项目中,我们通常倾向于使用具名导出而不是默认导出,因为这样有利于重构和自动导入。使用具名导出,不用默认导出。
当你需要运行测试的时候,你可以使用以下命令...测试命令:npm test
我们的团队约定是在提交代码之前先运行 lint 检查,以确保代码质量。提交前运行 npm run lint

4.2 优先高信号信息

把最重要的信息放在最前面。Claude 对文件开头的内容权重更高。

推荐的内容顺序:

1. 构建/测试/lint 命令(Claude 最常用)
2. 重要警告和陷阱(避免犯错)
3. 代码风格约定(保持一致性)
4. 架构概览(导航地图)
5. Git/工作流约定(协作规范)
6. 其他补充信息

4.3 不要重复代码里已有的信息

Claude 能读 package.jsontsconfig.json.eslintrc.prettierrc 等配置文件。不需要在 CLAUDE.md 里重复这些信息。

不需要写的:

  • "项目使用 TypeScript"(tsconfig.json 已经说明了)
  • "缩进用 2 空格"(.prettierrc 里配了)
  • "使用 ESLint"(.eslintrc 存在就说明了)
  • "依赖包括 React、Next.js..."(package.json 里有)

需要写的:

  • 配置文件里看不出来的约定
  • 团队的隐性知识
  • 工具链的非标准用法

4.4 增量更新,用 /memory 命令

不要试图一次写出完美的 CLAUDE.md。在日常使用中,当你发现 Claude 犯了某个错误或不知道某个约定时,用 /memory 命令把它记下来。

你:/memory 修改 prisma schema 后要运行 npx prisma generate
Claude:已保存到项目记忆。

这条信息会被保存到项目用户级的 CLAUDE.md(~/.claude/projects/<hash>/CLAUDE.md)。积累一段时间后,你可以把高频出现的条目整理到项目根目录的 CLAUDE.md 中,提交给团队共享。

4.5 提交到版本控制

项目根目录的 CLAUDE.md 应该提交到 Git。它是团队共享的项目知识,和 README.md、.eslintrc 一样是项目的一部分。

git add CLAUDE.md
git commit -m "docs: add CLAUDE.md for Claude Code"

好处:

  • 新成员 clone 项目后立即获得完整上下文
  • CLAUDE.md 的变更可以在 PR 中 review
  • 版本历史可追溯

4.6 Monorepo 用子目录 CLAUDE.md

在 Monorepo 中,不要把所有包的约定都塞进根目录的 CLAUDE.md。利用子目录层级:

my-monorepo/
├── CLAUDE.md                    # 全局约定(构建命令、Git 规范)
├── packages/
│   ├── api/
│   │   └── CLAUDE.md            # API 特定约定
│   ├── web/
│   │   └── CLAUDE.md            # 前端特定约定
│   └── shared/
│       └── CLAUDE.md            # 共享库约定

Claude 会根据当前工作目录自动加载对应的子目录 CLAUDE.md,不会把无关的上下文混进来。

4.7 控制篇幅

CLAUDE.md 的内容会占用上下文窗口。过长的文件会:

  • 浪费 token(花更多钱)
  • 稀释重要信息(Claude 可能忽略关键指令)
  • 增加冲突概率(内容越多越容易自相矛盾)

建议控制在 500 行以内。 如果超过了,考虑:

  • 把模块特定的内容拆到子目录 CLAUDE.md
  • 删除 Claude 能从代码中推断的信息
  • 用"详见 docs/xxx.md"引用外部文档,而不是复制内容

五、反模式:不该做什么

知道该写什么很重要,知道不该写什么同样重要。以下是常见的 CLAUDE.md 反模式。

5.1 不要写小说

# ❌ 反模式:2000 行的 CLAUDE.md
 
## 项目背景
这个项目始于 2023 年,当时我们的团队只有 3 个人。最初我们选择了 React 作为前端框架,
因为团队成员对 React 比较熟悉。后来随着项目规模扩大,我们引入了 Next.js 来解决 SSR
的需求。在 2024 年初,我们进行了一次大规模重构,将状态管理从 Redux 迁移到了 Zustand...
(后面还有 1500 行)

Claude 不需要知道你的项目历史。它需要的是当前的、可操作的信息。2000 行的文件浪费大量 token,而且 Claude 很可能会忽略其中的关键信息。

修正: 只保留当前有效的指令,删除历史叙述。

5.2 不要写显而易见的

# ❌ 反模式:重复已有信息
 
- 本项目使用 TypeScript
- 包管理器是 pnpm
- 使用 React 18
- 使用 Next.js 16
- 使用 Tailwind CSS

Claude 能读 package.jsontsconfig.json。这五行信息它自己就能推断出来,写了等于没写,还浪费 token。

修正: 只写 Claude 推断不出来的信息,比如"用 pnpm,不要用 npm 或 yarn"(如果这是一个强制约定的话)。

5.3 不要自相矛盾

# ❌ 反模式:矛盾的指令
 
## 测试
- 测试文件放在 `__tests__/` 目录
 
## 代码规范
- 测试文件和源文件放在同一目录

Claude 遇到矛盾指令时会困惑,可能随机选择一个遵循。定期审查 CLAUDE.md,确保没有冲突。

修正: 统一约定,删除矛盾的条目。

5.4 不要包含密钥或凭证

# ❌ 反模式:硬编码密钥
 
## 环境配置
- API Key: sk-xxxxxxxxxxxx
- Database URL: postgresql://admin:password123@prod-db.example.com/mydb

CLAUDE.md 通常会提交到 Git。即使不提交,密钥也不应该出现在任何纯文本文件中。

修正: 用占位符或环境变量名代替。

# ✅ 正确写法
 
## 环境配置
- API Key 从环境变量 `API_KEY` 读取
- 数据库连接字符串在 `.env.local` 中配置(参考 `.env.example`

5.5 不要微管理代码格式

# ❌ 反模式:格式微管理
 
- 花括号放在同一行
- 逗号后面加空格
- 字符串用单引号
- 行尾不加分号
- 对象最后一个属性加尾逗号
- import 语句按字母排序

这些事情应该交给 Prettier、ESLint 等工具。在 CLAUDE.md 里写格式规则是低效的——Claude 可能遵循也可能不遵循,而且你已经有工具来强制执行了。

修正: 配置好 Prettier/ESLint,在 CLAUDE.md 里只写"提交前运行 npm run lint:fix"。如果你配了 Hooks,连这句都不用写——Hook 会自动格式化。

5.6 不要当文档用

# ❌ 反模式:把 CLAUDE.md 当 README
 
## 安装步骤
1. 克隆仓库
2. 安装依赖:npm install
3. 复制环境变量:cp .env.example .env.local
4. 启动开发服务器:npm run dev
5. 打开浏览器访问 http://localhost:3000
 
## API 文档
### GET /api/users
返回用户列表...

CLAUDE.md 是给 Claude 的指令,不是给人读的文档。安装步骤放 README.md,API 文档放 Swagger/OpenAPI。

修正: 只保留 Claude 需要的命令(npm run devnpm test),删除面向人类的教程内容。

5.7 不要放动态或频繁变化的信息

# ❌ 反模式:动态信息
 
- 当前 Sprint 目标:完成用户模块重构
- 待修复 Bug:#123, #456, #789
- 下次发布日期:2026-03-25

这些信息很快就会过时。过时的信息比没有信息更糟糕——它会误导 Claude。

修正: 动态信息放在 Issue Tracker 或项目管理工具中。如果需要 Claude 知道当前任务,在对话中直接告诉它。


六、CLAUDE.md 与 Memory 系统

6.1 /memory 命令

Claude Code 有一个内置的记忆系统,通过 /memory 命令使用:

你:/memory 这个项目的测试需要先启动 Docker
Claude:已保存到项目记忆。

/memory 命令会把信息保存到项目用户级 CLAUDE.md:

~/.claude/projects/<project-hash>/CLAUDE.md

这个文件:

  • 按项目隔离(不同项目有不同的 hash)
  • 不提交到 Git(是你的个人笔记)
  • 每次会话自动加载

6.2 自动记忆建议

除了手动 /memory,Claude 有时会主动建议保存某些信息。比如当你纠正了 Claude 的一个错误时,它可能会说:

Claude:明白了,这个项目用 Vitest 而不是 Jest。要我把这个保存到记忆中吗?
你:好的
Claude:已保存。下次我会记住使用 Vitest。

这个机制让 CLAUDE.md 可以渐进式完善——你不需要一开始就写出完美的文件,在日常使用中逐步积累就好。

6.3 会话上下文 vs 持久记忆

理解三种"Claude 知道的信息"的区别:

类型来源生命周期优先级
会话上下文当前对话中你说的话会话结束即消失最高
CLAUDE.md各层级的 CLAUDE.md 文件持久存在
代码上下文Claude 读取的代码文件按需加载最低

优先级规则: 如果你在对话中说"用 Jest 测试",但 CLAUDE.md 里写的是"用 Vitest 测试",Claude 会遵循你在对话中的指令。聊天指令 > CLAUDE.md > 代码推断。

6.4 什么时候用哪种方式

场景推荐方式原因
团队统一的编码规范项目根目录 CLAUDE.md提交到 Git,团队共享
个人编码偏好用户级 CLAUDE.md跨项目生效
项目中你个人的笔记/memory 命令不影响团队
临时的一次性指令直接在对话中说不需要持久化
模块特定的约定子目录 CLAUDE.md按需加载,不污染全局
公司强制规范Enterprise CLAUDE.md不可覆盖

6.5 从 Memory 到 CLAUDE.md 的工作流

推荐的渐进式工作流:

1. 日常使用中,用 /memory 记录发现的问题和约定
2. 定期(比如每周)review ~/.claude/projects/<hash>/CLAUDE.md
3. 把高频出现的、团队通用的条目移到项目根目录 CLAUDE.md
4. 提交 PR,让团队 review
5. 清理项目用户级中已经移到根目录的条目

这样 CLAUDE.md 就是一个活的文档,随着项目演进不断完善。


七、实战示例:Next.js 全栈项目

7.1 项目背景

假设你在一个 Next.js 全栈项目中工作:

  • 技术栈:Next.js 16 (App Router) + Prisma + tRPC + Tailwind CSS v4
  • Monorepo 结构(pnpm workspace)
  • 团队 4 人,使用 GitHub 协作
  • 前后端在同一个仓库

7.2 项目根目录 CLAUDE.md(团队共享)

./CLAUDE.md(提交到 Git,约 60 行):

# 项目指令
 
## 命令
- 安装依赖:`pnpm install`
- 开发服务器:`pnpm dev`(端口 3000)
- 全量测试:`pnpm test`
- 单文件测试:`pnpm test -- --run path/to/file.test.ts`
- Lint:`pnpm lint`
- 类型检查:`pnpm typecheck`
- 数据库迁移:`pnpm db:migrate`
- 数据库 seed:`pnpm db:seed`
- 生成 Prisma Client:`pnpm db:generate`
 
## 架构
Monorepo(pnpm workspace):
- `apps/web/` — Next.js 16 前端(App Router)
- `apps/api/` — tRPC 路由和业务逻辑
- `packages/db/` — Prisma schema、迁移、seed
- `packages/ui/` — 共享 UI 组件(Tailwind CSS v4)
- `packages/shared/` — 共享类型和工具函数
 
## 代码风格
- 使用具名导出,不用默认导出(Next.js page/layout 除外)
- React 组件用 arrow function
- 服务端组件优先,只在需要交互时用 'use client'
- 状态管理用 Zustand(不用 Context 做全局状态)
- 表单用 react-hook-form + zod 校验
- 日期处理用 date-fns,不用 moment
 
## 重要警告
- 修改 `packages/db/prisma/schema.prisma` 后必须运行 `pnpm db:generate`
- `apps/web/app/` 下的 page.tsx 和 layout.tsx 必须用默认导出
- tRPC router 定义在 `apps/api/src/routers/`,不要在 web 端定义
- 环境变量分两种:`NEXT_PUBLIC_*`(客户端可见)和普通变量(仅服务端)
- Tailwind v4 不用 tailwind.config.js,配置在 CSS 文件中
 
## Git 约定
- 分支:`feat/xxx``fix/xxx``refactor/xxx`
- Commit:`type(scope): description`(英文)
- scope 用包名:`feat(web): add login page`
- 提交前确保 `pnpm lint``pnpm typecheck` 通过
 
## 测试
- 使用 Vitest + React Testing Library
- 测试文件:`xxx.test.ts(x)`,放在 `__tests__/` 目录
- Mock 外部 API,不 mock 内部模块
- 数据库相关测试用 `@testcontainers/postgresql`

7.3 子目录 CLAUDE.md(API 特定约定)

./apps/api/CLAUDE.md

# API 约定
 
## 路由结构
- `src/routers/` — tRPC router 定义
- `src/services/` — 业务逻辑(一个 service 对应一个领域)
- `src/repositories/` — 数据库查询(封装 Prisma 调用)
 
## 数据流
Router(输入校验)→ Service(业务逻辑)→ Repository(数据库)
 
## 规范
- 每个 router 文件导出一个 `xxxRouter`
- 输入校验用 zod schema,定义在 router 文件中
- Service 方法不直接调用 Prisma,通过 Repository
- 错误处理用 `TRPCError`,不要 throw 普通 Error
- 所有数据库查询必须有 `select``include`,不要 `select: undefined`(防止返回敏感字段)
 
## 新增 API 的步骤
1.`src/routers/` 创建或修改 router
2.`src/services/` 实现业务逻辑
3.`src/repositories/` 实现数据库查询
4.`src/routers/_app.ts` 注册 router
5. 运行 `pnpm test -- --run apps/api/` 确认测试通过

7.4 用户级 CLAUDE.md(个人偏好)

~/.claude/CLAUDE.md

# 个人偏好
 
- 回复使用中文
- 代码注释使用英文
- commit message 使用英文
- 优先使用函数式风格,避免 class
- 解释技术决策时给出简短理由

7.5 项目用户级 Memory(个人笔记)

~/.claude/projects/<hash>/CLAUDE.md(由 /memory 命令创建)��

# 项目笔记
 
- 本地 PostgreSQL 跑在 Docker 里:`docker compose up -d db`
- payments 模块正在重构,暂时不要改 `src/services/payment.legacy.ts`
- 跑 E2E 测试前需要 seed 数据库:`pnpm db:seed`
- 张三负责 auth 模块,有问题找他

7.6 合并后的效果

当你在 apps/api/ 目录下工作时,Claude 看到的完整上下文:

[用户级] 回复中文、代码注释英文、函数式风格...
[项目根目录] pnpm install、Monorepo 架构、代码风格、Git 约定...
[子目录级] tRPC 路由结构、数据流、API 规范...
[项目用户级] 本地 Docker、payments 重构中...

当你切换到 apps/web/ 目录工作时,子目录级的内容会自动切换为 apps/web/CLAUDE.md(如果存在的话),API 的约定不会干扰前端的工作。

这就是多层 CLAUDE.md 的威力:全局约定统一,局部上下文精准,个人偏好不影响团队。


八、进阶模式

8.1 条件指令

你可以在 CLAUDE.md 中写条件性的指令,让 Claude 在特定场景下遵循特定规则:

# 条件指令
 
写测试时:
- 总是先写测试描述(describe/it),再写实现
- 每个测试只验证一个行为
- 使用 Arrange-Act-Assert 模式
 
写 API 路由时:
- 总是添加输入校验(zod schema)
- 总是处理错误情况
- 总是返回统一的响应格式
 
做代码审查时:
- 关注安全问题(SQL 注入、XSS、敏感数据泄露)
- 检查错误处理是否完整
- 检查是否有性能问题(N+1 查询、不必要的重渲染)
 
重构时:
- 不要改变公共 API 的签名
- 每次只重构一个模块
- 重构后运行完整测试套件

Claude 会根据当前任务的上下文自动匹配相关的条件指令。

8.2 引用外部文档

当某个主题的信息太多,不适合全部放在 CLAUDE.md 中时,用引用的方式:

# 架构
 
整体架构概览见本文件。详细的架构决策记录(ADR)在 `docs/adr/` 目录。
 
数据库 schema 设计见 `packages/db/prisma/schema.prisma`
 
API 接口文档见 `docs/api.md`
 
部署流程见 `docs/deployment.md`

Claude 在需要时会主动去读这些文件。你不需要把内容复制到 CLAUDE.md 中——只需要告诉 Claude 去哪里找。

8.3 团队入职加速

CLAUDE.md 的一个隐藏价值是加速新成员入职

新成员 clone 项目后,CLAUDE.md 立即提供:

  • 怎么构建和运行项目
  • 代码风格和约定
  • 架构概览
  • 常见陷阱

这比口头传授或翻阅 Wiki 高效得多。而且 Claude Code 可以基于这些信息回答新成员的问题:

新成员:这个项目怎么跑测试?
Claude:(读取 CLAUDE.md)运行 `pnpm test`。单文件测试用 `pnpm test -- --run path/to/file.test.ts`。
        注意:数据库相关的测试需要先启动 Docker:`docker compose up -d db`。

8.4 CI/CD 集成

Claude Code 支持 headless 模式(非交互式),可以在 CI/CD 流水线中使用。在这种模式下,Claude 同样会读取 CLAUDE.md。

# .github/workflows/claude-review.yml
name: Claude Code Review
on: [pull_request]
 
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Claude Review
        run: |
          claude --headless "Review the changes in this PR. \
            Check for code style violations, potential bugs, \
            and missing tests." \
            --settings .claude/ci-settings.json

CLAUDE.md 中的约定会指导 Claude 的 review 标准。比如你写了"错误处理用 Result 模式",Claude 在 review 时就会检查是否有人用了 try-catch。

8.5 Monorepo 策略

大型 Monorepo 的 CLAUDE.md 策略:

monorepo/
├── CLAUDE.md                     # 全局:workspace 命令、Git 约定、CI 流程
├── apps/
│   ├── web/
│   │   └── CLAUDE.md             # 前端:组件规范、路由约定、状态管理
│   ├── mobile/
│   │   └── CLAUDE.md             # 移动端:平台差异、导航结构
│   └── admin/
│       └── CLAUDE.md             # 管理后台:权限模型、表格组件用法
├── packages/
│   ├── api/
│   │   └── CLAUDE.md             # API:路由结构、认证、错误处理
│   ├── db/
│   │   └── CLAUDE.md             # 数据库:迁移流程、命名约定
│   └── ui/
│       └── CLAUDE.md             # UI 库:组件 API 设计原则、样式约定

根目录 CLAUDE.md 的原则:

  • 只放全局通用的信息
  • 不超过 100 行
  • 引导 Claude 去子目录找具体约定

子目录 CLAUDE.md 的原则:

  • 只放该模块特有的信息
  • 不重复根目录已有的内容
  • 包含该模块的构建/测试命令(如果和全局不同)

8.6 版本控制最佳实践

把 CLAUDE.md 当作代码一样管理:

# 在 PR 中 review CLAUDE.md 的变更
 
## 好的 PR 示例
标题:docs(claude): add API error handling convention
变更:在 apps/api/CLAUDE.md 中添加错误处理约定
 
## Review 检查清单
- [ ] 新增的指令是否和现有指令冲突?
- [ ] 是否有可以从代码推断的冗余信息?
- [ ] 篇幅是否合理?
- [ ] 是否包含敏感信息?

推荐的 Git 工作流:

  1. 在日常使用中通过 /memory 积累改进点
  2. 定期整理,提交 CLAUDE.md 的更新 PR
  3. 团队 review——CLAUDE.md 的变更和代码变更一样重要
  4. 合并后,所有人的 Claude Code 立即生效

九、常见问题

Q1:CLAUDE.md 和 README.md 有什么区别?

README.md 是给读的——项目介绍、安装步骤、使用说明。CLAUDE.md 是给 Claude 读的——编码指令、构建命令、项目约定。

两者可能有少量重叠(比如构建命令),但目的完全不同。不要把 CLAUDE.md 当 README 写,也不要用 README 代替 CLAUDE.md。

Q2:CLAUDE.md 支持什么格式?

纯 Markdown。支持标题、列表、代码块、表格等标准 Markdown 语法。Claude 对 Markdown 的理解很好,合理使用格式可以提高可读性。

不支持的:

  • 图片(Claude 不会渲染 Markdown 中的图片链接)
  • HTML 标签(会被当作纯文本)
  • 动态内容(不支持变量替换或模板语法)

Q3:CLAUDE.md 有大小限制吗?

没有硬性限制,但有实际限制——它会占用上下文窗口。建议:

层级建议行数原因
项目根目录50-150 行核心信息,每次都加载
子目录级20-50 行模块特定,按需加载
用户级10-30 行个人偏好,简短即可
项目用户级10-30 行临时笔记,定期清理
所有层级合计< 500 行控制总 token 消耗

如果你的项目根目录 CLAUDE.md 超过 200 行,认真考虑拆分到子目录或删除冗余内容。

Q4:多人协作时 CLAUDE.md 冲突怎么办?

和代码冲突一样处理——Git merge 时解决。因为 CLAUDE.md 通常是追加式修改(添加新条目),冲突概率不高。

减少冲突的技巧:

  • 每个条目独占一行
  • 用清晰的分节(## 标题)
  • 避免频繁修改已有条目
  • 大的变更走 PR review

Q5:Claude 真的会遵循 CLAUDE.md 里的所有指令吗?

大部分情况下会。但有几个注意点:

  • 指令越具体,遵循率越高。"用 Vitest 测试"比"写好测试"有效得多。
  • 指令越靠前,权重越高。把最重要的放在文件开头。
  • 矛盾的指令会降低遵循率。Claude 遇到矛盾时可能随机选择。
  • 对话中的指令优先级更高。如果你在对话中说了和 CLAUDE.md 矛盾的话,Claude 会遵循对话。
  • 过长的文件会稀释重要指令。500 行以内效果最好。

Q6:可以在 CLAUDE.md 中引用其他文件吗?

不能直接 #includeimport。但你可以写"详见 docs/xxx.md",Claude 在需要时会主动去读取那个文件。

# 架构详情见 docs/architecture.md
# 数据库 schema 见 packages/db/prisma/schema.prisma
# API 错误码定义见 packages/shared/src/error-codes.ts

这是一种"懒加载"模式——CLAUDE.md 提供索引,Claude 按需读取详细内容。

Q7:项目用户级的 CLAUDE.md 路径中的 hash 是怎么算的?

hash 基于项目的绝对路径生成。你不需要手动管理这个路径——/memory 命令会自动处理。如果你想查看或编辑它,可以在 Claude Code 中问"我的项目记忆文件在哪里"。

Q8:从零开始,CLAUDE.md 应该先写什么?

如果你刚开始使用 Claude Code,按这个优先级写:

# 第一步:只写命令(5 分钟搞定)
- 构建:`npm run build`
- 测试:`npm test`
- Lint:`npm run lint`
 
# 第二步:加上关键警告(遇到问题时补充)
- 修改 schema 后要运行 generate
- 不要改 legacy/ 目录
 
# 第三步:逐步完善(日常使用中积累)
- 用 /memory 记录 Claude 犯的错
- 定期整理到 CLAUDE.md

不要试图一次写出完美的 CLAUDE.md。先写 5 行,比不写强 10 倍。


总结

CLAUDE.md 的核心就三件事:

  1. 写对的内容——构建命令、关键警告、非显而易见的约定。这些是 Claude 无法从代码中推断的高价值信息。
  2. 用对的方式写——简洁、直接、祈使语气。不写小说,不重复已有信息,控制在 500 行以内。
  3. 用对的层级——团队约定放项目根目录(提交 Git),个人偏好放用户级,临时笔记用 /memory,模块细节放子目录。

记住:CLAUDE.md 是你获得好结果最重要的杠杆。先写 5 行命令,然后在日常使用中逐步完善。


推荐阅读