OFFICIAL SOURCE ANALYSIS

上下文体系

Claude 怎么「知道」你的项目?CLAUDE.md、Rules、Auto Memory、Skills、MCP 的加载机制与最佳实践。

Part 1: 上下文体系

Claude Code 的上下文不是一个单一的「记忆」,而是由多个来源、多种加载时机、多层优先级构成的复合系统。以下按加载优先级从高到低排列。

1. CLAUDE.md — 用户规则文件

CLAUDE.md 是你与 Claude Code 之间最重要的「合约」。它是一个纯文本文件,内容会在每次会话启动时被注入到 system prompt 中,相当于你在每次对话开始前先说了一段话。

两个层级

层级路径作用范围典型内容
项目级 ./CLAUDE.md(项目根目录) 仅在该项目目录下的会话中生效 技术栈说明、代码规范、提交规则、测试命令、架构约定
用户级 ~/.claude/CLAUDE.md 在所有项目的所有会话中生效 全局偏好、通用规则(如「所有回复用中文」「不要用 emoji」)
加载时机:每次会话启动时自动加载。不需要手动 import,不需要配置。只要文件存在于正确位置,Claude 就能看到。修改后的内容在下一次会话启动时生效。

最佳实践

控制在 200 行以内

CLAUDE.md 的全部内容都会被注入 system prompt,直接占用上下文窗口。太长会:

  • 浪费宝贵的上下文空间,挤占实际对话内容
  • 包含太多信息时,重要规则的「权重」会被稀释
  • 增加 auto-compact 触发频率

如果超过 200 行:拆分到 .claude/rules/ 目录中,利用路径匹配按需加载。把最核心、最通用的规则留在 CLAUDE.md 中。

内容组织建议
  • 优先级最高的放最前面:Claude 对靠前内容的遵循度更高
  • 用命令式语气:「使用 TypeScript strict mode」比「我们一般用 TypeScript strict mode」效果更好
  • 避免解释性文字:CLAUDE.md 不是文档,是「指令集」。不需要解释为什么,只需要说怎么做
  • 分节用 Markdown 标题:便于 Claude 定位特定规则
CLAUDE.md 示例结构 示例
# 项目概览
这是一个 Next.js 14 + TypeScript + Prisma 的全栈项目。

# 代码规范
- 使用 TypeScript strict mode
- 函数参数超过 3 个时使用对象解构
- 所有组件使用 named export,不用 default export
- 测试文件放在 __tests__ 目录,用 Vitest

# Git 规范
- commit message 用中文
- 不要自动 push
- 每次 commit 前运行 pnpm lint

# 运行命令
- 开发: pnpm dev
- 测试: pnpm test
- 构建: pnpm build
- lint: pnpm lint

2. Rules (.claude/rules/*.md)

Rules 是 CLAUDE.md 的扩展机制。当你的规则太多、或者某些规则只在特定场景下需要时,Rules 系统比把所有内容塞进一个 CLAUDE.md 要优雅得多。

两种类型

类型配置方式加载时机适用场景
无条件规则 直接放在 .claude/rules/ 目录下的 .md 文件,没有 frontmatter 每次会话启动时自动加载(和 CLAUDE.md 一样) 通用但不适合放在 CLAUDE.md 里的补充规则
路径匹配规则 .md 文件中包含 YAML frontmatter,声明 paths 字段 仅当 Claude 操作的文件路径匹配 paths 中的模式时才加载 特定子目录或文件类型的专属规则

paths 字段的匹配方式

Glob 模式匹配

paths 字段使用 glob 语法匹配文件路径。当 Claude 读取或修改的文件匹配到某条规则的 paths 模式时,该规则会被动态注入到上下文中。

路径匹配规则示例 示例
---
paths:
  - "src/components/**/*.tsx"
  - "src/components/**/*.ts"
---

# React 组件规范
- 所有组件使用函数式写法
- Props 类型单独定义,命名为 XxxProps
- 使用 forwardRef 包装需要 ref 的组件
- CSS 使用 Tailwind,不写内联样式对象

这个规则只有在 Claude 操作 src/components/ 下的 .tsx.ts 文件时才会被加载。操作其他目录的文件时,这些规则不会浪费上下文空间。

另一个实用示例:数据库迁移规则 示例
---
paths:
  - "prisma/**"
  - "src/db/**"
---

# 数据库操作规范
- 修改 schema 后必须运行 npx prisma generate
- 每次迁移都要写明确的迁移名称
- 不要直接修改已有的 migration 文件
- 添加字段时考虑默认值和 nullable
规则拆分策略:把 CLAUDE.md 想象成「宪法」(核心原则),Rules 是「法律」(具体领域的详细规定)。宪法简短且始终生效,法律详尽但按需适用。

3. Auto Memory — 自动记忆系统

CLAUDE.md 和 Rules 是你手动维护的。Auto Memory 是 Claude 自己维护的——它会从对话中自动提取重要信息并持久化保存。

记忆的存储结构

MEMORY.md 索引文件

每个项目的 .claude/ 目录下会有一个 MEMORY.md 文件,作为记忆的索引和主存储。

  • 大小限制:前 200 行或 25KB(取较小者)会被加载到上下文
  • 超过限制的部分:不会被加载,等于不存在
  • 格式:Markdown,每条记忆通常是一个简短的要点
按主题拆分的 Topic Files

当 MEMORY.md 变得太大,或者某个主题的记忆特别多时,Claude 会自动创建主题文件:

  • 存放在 .claude/memory/ 目录下
  • 按主题命名,如 testing.mddeployment.md
  • MEMORY.md 中会包含指向这些主题文件的引用
  • 加载时根据当前上下文相关性决定是否加载具体主题文件
项目级记忆目录

记忆分为两个级别:

  • 用户级记忆:~/.claude/ 下的 MEMORY.md 和 memory/ 目录,跨项目共享
  • 项目级记忆:项目 .claude/ 下的 MEMORY.md 和 memory/ 目录,仅在该项目中生效

记忆的触发方式

触发方式说明
自动提取 Claude 在对话中发现值得记住的模式或偏好时,自动写入记忆
/memory 命令 打开交互式面板,手动查看、编辑或添加记忆
对话中明确要求 你说「记住这个」或「以后都这样做」时,Claude 会将其写入记忆
记忆 vs CLAUDE.md:CLAUDE.md 是你的「显式指令」,内容完全由你控制。Memory 是 Claude 的「学习笔记」,是它从交互中自动归纳的。两者互补:CLAUDE.md 适合写规则,Memory 适合记录偏好和项目事实。

4. Skills 的两层加载

Skills 是 Claude Code 的能力扩展机制。但如果所有 Skill 的完整内容都在启动时加载,上下文会被撑爆。所以 Skills 使用了一个巧妙的两层加载策略。

Layer 1: 名字 + 描述(system prompt 常驻)
Layer 2: 完整内容(按需加载)

Layer 1: 摘要层

始终在 system prompt 中
  • 每个 Skill 只占用约 100 tokens
  • 包含:Skill 名称、一句话描述、触发条件
  • 作用:让 Claude 知道「有这个能力存在」,以便在合适的时机调用
  • 即使有 50 个 Skills 安装,Layer 1 总共也只占约 5000 tokens

Layer 2: 完整内容层

仅在使用时加载
  • 每个 Skill 的完整内容约 2000 tokens(有的更多)
  • 包含:详细指令、工作流步骤、配置参数、示例
  • 触发:当 Claude 决定使用某个 Skill 时,通过 Skill 工具调用加载完整内容
  • 加载后的内容会进入当前对话上下文,直到 compact 或 clear
设计哲学:这就像一本书的「目录」和「正文」的关系。目录(Layer 1)始终在手边,方便快速查找;正文(Layer 2)只在需要时翻到对应章节。这个设计让 Claude Code 可以安装大量 Skills 而不压垮上下文窗口。
实际流程示例 流程
用户: "帮我把这个 PDF 拆成两部分" 1. Claude 看到 system prompt 中的 Skill 列表(Layer 1) → 找到: pdf - "Use this skill whenever the user wants to do anything with PDF files..." 2. Claude 调用 Skill 工具 → skill: "pdf" 3. Skill 完整内容被加载到上下文(Layer 2) → 包含 PDF 操作的详细指令、工具链、代码模板 4. Claude 根据完整指令执行 PDF 拆分操作

5. MCP 工具的延迟装配

MCP(Model Context Protocol)工具是外部服务通过标准协议暴露给 Claude 的能力。和 Skills 类似,MCP 工具也不是一次性全部加载的。

两阶段加载

启动时:加载工具名列表
使用时:按需加载完整 schema
阶段一:启动时

Claude Code 连接到已配置的 MCP Server,获取所有可用工具的名称和简短描述。这些信息被写入 system prompt 的 deferred tools 列表中。

  • 占用极少的 tokens(每个工具仅名称 + 一句话)
  • 让 Claude 知道「这个工具存在,可以调用」
  • 但此时 Claude 不知道工具的参数结构
阶段二:使用时

当 Claude 决定调用某个 MCP 工具时,会先通过 ToolSearch 工具获取完整的 JSON Schema 定义。

  • 包含:参数名称、类型、是否必填、描述、默认值
  • 获取后 Claude 才能构造正确的调用参数
  • Schema 会留在当前对话上下文中,后续调用同一工具不需要重复获取
ToolSearch 的查询方式 技术细节

ToolSearch 支持三种查询形式:

  • select:Read,Edit,Grep — 按名称精确匹配,一次获取多个工具的 schema
  • notebook jupyter — 关键字搜索,返回最相关的工具(最多 max_results 个)
  • +slack send — 要求名称中包含「slack」,再按其他关键字排序

这个设计让 Claude 能高效地按需发现和使用 MCP 工具,而不需要在启动时把所有工具的完整定义都塞进上下文。

和 Skills 的区别:Skills 是 Claude Code 原生的能力扩展,内容是 Markdown 指令。MCP 工具是外部服务暴露的可调用接口,内容是 JSON Schema。两者的延迟加载策略类似,但执行方式不同:Skill 加载后 Claude 按指令行动;MCP 工具加载后 Claude 构造 JSON 调用外部服务。

6. 为什么 Claude 有时像「忘了以前说过的话」

这是新用户最困惑的体验之一:你明明十分钟前告诉了 Claude 一件事,它现在却好像完全不记得了。这不是 bug,而是上下文管理机制的副作用。

三个主要原因

原因 1:/compact 和 auto-compact 替换了历史 最常见

当对话长度接近上下文窗口上限时,系统会自动触发 compact(你也可以手动执行 /compact)。Compact 的工作方式是:

  • 让模型生成一份最多 2000 token 的对话摘要
  • 用这份摘要替换所有之前的对话消息
  • 替换是彻底的——原始对话内容不再存在于上下文中

后果:如果你在之前的对话中提到过某个偏好或细节,但它没有被包含在摘要中,Claude 就「忘了」。摘要毕竟只有 2000 token,不可能保留所有细节。

好消息:原始对话会保存在 .transcripts/ 目录,不会真正丢失。但 Claude 在当前会话中确实无法访问了。

原因 2:内容没有被持久化

只存在于对话历史中的内容,生命周期仅限于当前会话。一旦 compact 或开新会话,就会丢失。只有写入以下位置的内容才能跨会话存活:

  • CLAUDE.md — 手动维护的规则
  • .claude/rules/ — 分类规则文件
  • MEMORY.md / .claude/memory/ — 自动或手动记忆

建议:如果一个信息很重要且需要跨会话保留,主动告诉 Claude「把这个记住」或者自己手动写入 CLAUDE.md。

原因 3:权重稀释

即使信息仍在上下文中,当上下文非常长时,模型对单条信息的「注意力」会下降。这是大语言模型的固有特性:

  • 靠前的内容(system prompt、CLAUDE.md)权重较高
  • 中间的内容权重最低(「迷失在中间」效应)
  • 靠后的内容(最近的对话)权重较高

实际影响:如果你在会话早期提到过一条规则,随着对话变长,Claude 可能会「忽略」它——不是真的忘了,而是其他更近的信息抢占了注意力。

诊断工具

命令作用何时使用
/memory 查看和编辑 Claude 的自动记忆 怀疑 Claude 没有记住某个偏好时
/context 查看当前加载的所有上下文来源 想确认 CLAUDE.md、Rules、Memory 是否被正确加载
/compact 手动压缩对话,可以附带自定义提示来控制摘要内容 觉得对话太长影响质量时,主动压缩并强调关键信息
/cost 查看当前上下文 token 消耗 想判断是否快要触发 auto-compact
常见误区:很多人以为 Claude 「记住了上次会话的所有内容」。事实上,每个新会话只加载 CLAUDE.md + Rules + Memory + Skills 摘要。上次会话中的具体对话内容不会自动带到新会话(除非你用 /resume 恢复会话)。

上下文全景图

所有上下文来源在一次会话中的加载方式:

会话启动 │ ├── 始终加载 (system prompt) │ ├── CLAUDE.md(项目级 + 用户级) │ ├── .claude/rules/ 无条件规则 │ ├── MEMORY.md 索引(前 200 行 / 25KB) │ ├── Skills Layer 1(名字 + 描述,~100 tok/skill) │ └── MCP 工具名列表 │ ├── 按需加载 │ ├── .claude/rules/ 路径匹配规则 → 操作匹配路径的文件时 │ ├── Memory topic files → 上下文相关时 │ ├── Skills Layer 2(完整内容)→ 调用 Skill 工具时 │ └── MCP 工具 schema → 调用 ToolSearch 时 │ └── 对话中积累 ├── 用户消息 + Claude 回复 ├── 工具调用结果 └── 文件读取内容 │ ↓ 接近上下文上限时 auto-compact: 摘要替换全部历史