# Lesson 3: 主动管理上下文——让每个 token 都有价值

## 本课目标

- 掌握上下文检查与诊断工具（/context、/memory）
- 学会管理会话生命周期（--continue、--resume、--fork、/rename）
- 掌握回退操作的三种等价入口（双击 ESC、/rewind、/checkpoints）
- 掌握提高交互效率的快捷操作（/btw）
- 形成"主动管理"而非"被动清理"的上下文习惯

## 核心内容

### 从被动到主动：心态转变

上一课我们学了上下文窗口的基本概念和 `/clear`、`/compact`、`/cost` 三个基础命令——这是"被动清理"。

这一课升级到"主动管理"：**在问题出现之前就掌控局面。**

```
被动清理：上下文快满了 → /compact → 继续工作 → 又满了 → /clear
主动管理：提前检查占用 → 合理规划会话 → 高效交互 → 始终保持充裕
```

### 检查与诊断

#### /context — 看清 token 都花在了哪里

```bash
/context
```

`/context` 展示**上下文的占用结构**——不只是总量，而是每一块占了多少。

```
┌─────────────────────────────────────────────────┐
│  /context 输出示例                                │
│                                                  │
│  System prompt     ████░░░░░░░░░░░░░  12%       │
│  CLAUDE.md         ██░░░░░░░░░░░░░░░   4%       │
│  Rules             ███░░░░░░░░░░░░░░   6%       │
│  Skills (loaded)   █████░░░░░░░░░░░░  10%       │
│  MCP servers       ████████░░░░░░░░░  18%  ⚠️  │
│  Conversation      ██████████░░░░░░░  22%       │
│  Available         ░░░░░░░░░░░░░░░░░  28%       │
│                                                  │
│  总计：72% 已使用，28% 可用                        │
└─────────────────────────────────────────────────┘
```

**关键用途**：

| 场景 | /context 能告诉你什么 |
|------|---------------------|
| Claude 变慢或变蠢了 | 是不是上下文快满了？ |
| 装了很多 MCP 服务器 | MCP 占了多少上下文？需要精简吗？ |
| 读了很多文件 | 文件读取占比是否过高？ |
| 加载了很多 Skills | Skills 和 Rules 的常驻开销有多大？ |

**实操建议**：养成在长会话中定期检查的习惯。当可用空间低于 30% 时，考虑 `/compact` 或 `/clear`。

#### /memory — 确认加载了什么，记住了什么

```bash
/memory
```

`/memory` 回答两个关键问题：

**1. 哪些 CLAUDE.md 真的被加载了？**

你以为项目的 CLAUDE.md 生效了，但它真的加载了吗？`/memory` 列出当前会话实际加载的所有记忆文件和配置文件，让你确认无误。

```
/memory 输出示例：

已加载的项目指令：
  ✅ ~/project/CLAUDE.md
  ✅ ~/project/.claude/rules/security.md
  ✅ ~/project/.claude/rules/testing.md

自动记忆：
  ✅ ~/.claude/projects/<project>/memory/MEMORY.md (87 行)
```

**2. 开启和管理 auto memory**

Auto memory 是 Claude 的跨会话笔记本。通过 `/memory` 你可以：
- 确认 auto memory 是否开启
- 查看当前记忆了什么
- 主动让 Claude 记住或忘记信息

```bash
# 让 Claude 记住
"记住：这个项目用 pnpm，不要用 npm"

# 让 Claude 忘记
"忘记之前关于数据库配置的记忆，那已经过时了"

# 查看记忆
/memory
```

### 会话生命周期管理

上一课我们学了在**一个会话内**管理上下文。但真实工作跨越多天、多个会话。会话管理让你的工作连续性不被打断。

> **延伸阅读**：cc4pm 的 `session-start.js` 和 `session-end.js` Hook 会自动保存和恢复会话状态——包括当前任务、修改的文件、使用的工具等。这意味着即使你关掉终端，下次 `--continue` 时 AI 也能立刻知道"上次做到哪了"。详见 **Lesson 23（阶段 4）自动化工作流**中的 SessionStart/Stop Hooks。

#### claude --continue — 恢复最近会话

```bash
claude --continue
```

最常用的恢复方式。接上**最近一次会话**，继续未完成的工作。

```
场景：昨天让 Claude 做了一半的代码重构，今天继续

昨天：
  claude
  "帮我重构 auth 模块"
  → Claude 完成了 3 个文件，还剩 2 个
  → 下班了，关掉终端

今天：
  claude --continue
  → 自动恢复昨天的上下文
  "继续重构剩下的 2 个文件"
  → Claude 知道之前做了什么，无缝继续
```

#### claude --resume — 从历史会话列表中选择

```bash
claude --resume
```

当你有**多个未完成的会话**时，`--resume` 让你从列表中选择恢复哪一个。

```
$ claude --resume

最近会话：
  [1] 2h ago  — auth 模块重构（3/5 文件完成）
  [2] 1d ago  — PRD 创建：用户通知功能
  [3] 2d ago  — E2E 测试编写
  [4] 3d ago  — 代码审查：支付模块

选择要恢复的会话: _
```

#### claude --continue --fork — 分叉会话，探索不同方案

```bash
claude --continue --fork
```

这是一个高级技巧：从已有会话的**同一起点分叉**，探索不同的实现方案。

```
┌─────────────────────────────────────────────────┐
│                                                  │
│  原始会话：重构 auth 模块                         │
│  ├── 探索阶段（已完成）                           │
│  ├── 方案制定：3 种候选方案                       │
│  │                                               │
│  ├── --continue --fork → 分支 A                  │
│  │   └── 用 JWT 方案实现                          │
│  │                                               │
│  └── --continue --fork → 分支 B                  │
│      └── 用 Session 方案实现                      │
│                                                  │
│  两个分支独立工作，对比结果后选最优方案             │
│                                                  │
└─────────────────────────────────────────────────┘
```

**典型用例**：
- 探索阶段完成后，分叉尝试不同实现方案
- 对比两种架构设计的优劣
- 保留一个"安全版本"，在另一个分支上做激进实验

#### /rename — 给会话起个好名字

```bash
/rename auth-refactor-jwt
```

默认会话名是时间戳，很难从列表中识别。`/rename` 让你给会话起一个有意义的名字，配合 `--resume` 使用时一目了然。

```
重命名前：
  [1] 2h ago  — session-1719384729
  [2] 1d ago  — session-1719298329

重命名后：
  [1] 2h ago  — auth-refactor-jwt
  [2] 1d ago  — notification-prd
```

**命名建议**：用 `功能-阶段` 格式，如 `auth-refactor`、`prd-notification`、`e2e-payment`。

### 交互效率技巧

#### 回退操作——三个等价入口

Claude Code 提供了三种方式做同一件事：**撤销上一轮对话及其文件改动，回到上一条输入重新编辑**。

| 入口 | 操作方式 | 效果完全相同 |
|------|---------|-------------|
| **双击 ESC** | 快速按两次 ESC 键 | 撤销上一轮 + 回到输入状态 |
| **/rewind** | 输入斜杠命令 | 撤销上一轮 + 回到输入状态 |
| **/checkpoints** | 输入斜杠命令 | 撤销上一轮 + 回到输入状态 |

三种方式效果一样——都是回退到上一个状态点（包括撤销 Claude 修改的文件），然后让你重新编辑那条输入。选哪个纯看个人习惯，**双击 ESC 最快**。

#### 双击 ESC / /rewind / /checkpoints — 回退并重新编辑

```
双击 ESC 键（快速按两次 ESC）
```

走偏了或者上一句话没说清楚？不用 `/clear` 重来，直接双击 ESC 回到上一条输入重新编辑。

```
场景：你发出了一条不够精确的提示词

你："帮我改一下登录功能"
Claude：（开始大规模重写整个登录页面）
你：等等，我只是想改验证逻辑！

❌ 低效做法：等 Claude 做完 → 纠正 → 浪费上下文
✅ 高效做法：双击 ESC → 回到上一条输入
            修改为 "只修改 src/auth/validate.ts 中的邮箱验证逻辑"
            → 精确执行，零浪费
```

**和单击 ESC 的区别**：

| 操作 | 效果 |
|------|------|
| 单击 ESC | 打断 Claude 当前操作（Claude 已经执行的部分保留） |
| 双击 ESC | **回到上一条输入**重新编辑，改完重发 |

双击 ESC 改完重发比开新会话更省事——你保留了之前积累的上下文，只修正了最后一条指令。

#### ESC + 记忆组合技——防止重复犯错

当 Claude 反复犯同一个错误时，不要只是 ESC 打断——**打断后立即用 # 写入记忆**：

```bash
# Claude 又在生成你不要的 console.log
# 按 ESC 打断

# 然后用 # 写记忆
# "永远不要在代码中添加 console.log 调试语句"
```

这个组合技的威力在于：ESC 只阻止了这一次，但 # 写入的记忆会在**所有未来会话**中生效。下次 Claude 不会再犯同样的错误。

#### /btw — 不打断主任务的侧问题

```bash
/btw 这个函数的参数类型是什么？
```

有时候工作到一半，突然想问一个小问题——但不想打断当前的任务流。

`/btw` 就是为这个场景设计的：
- 答案出现在**可关闭的覆盖层**中
- **永远不会进入对话历史**
- 不增加上下文噪音
- 关掉覆盖层后，主任务继续

```
场景：你正在让 Claude 重构 auth 模块

你："重构 auth 模块，提取公共验证逻辑"
Claude：（正在分析文件...）

突然想知道：这个项目用的什么测试框架？

/btw 这个项目用的什么测试框架？
→ 弹出覆盖层：Jest + React Testing Library
→ 关闭覆盖层
→ 主任务继续，上下文完全不受影响
```

**/btw vs 直接问的对比**：

| | 直接问 | /btw |
|--|-------|------|
| 是否进入对话历史 | 是 | 否 |
| 是否消耗上下文 | 是 | 否 |
| 是否打断当前任务 | 是 | 否 |
| 适合什么 | 与当前任务相关的问题 | 与当前任务无关的快速查询 |

### 主动管理速查表

```
┌─────────────────────────────────────────────────┐
│           主动管理上下文·速查表                     │
├─────────────────────────────────────────────────┤
│                                                  │
│  📊 检查与诊断                                    │
│  /context          token 占用结构分析             │
│  /memory           确认加载的配置和记忆            │
│  /cost             token 消耗和费用               │
│                                                  │
│  🔄 会话生命周期                                  │
│  claude --continue        恢复最近会话            │
│  claude --resume          从历史列表选择           │
│  claude --continue --fork 分叉探索不同方案        │
│  /rename                  重命名方便查找           │
│                                                  │
│  ⏪ 回退（三种等价入口）                            │
│  双击 ESC / /rewind / /checkpoints                │
│                 回退上一轮，撤销文件改动            │
│                                                  │
│  ⚡ 交互效率                                      │
│  双击 ESC          回到上一条输入重新编辑          │
│  /btw              侧问题，不污染上下文            │
│  单击 ESC          打断当前操作                    │
│                                                  │
│  🧹 清理与压缩（复习 Lesson 2）                   │
│  /clear            清空重新开始                    │
│  /compact           智能压缩保留关键信息           │
│                                                  │
└─────────────────────────────────────────────────┘
```

### 演示案例：体验完整的会话管理流程

```bash
# 1. 启动一个新会话
cd cc4pm
claude

# 2. 给会话起个名字
/rename cc4pm-explore

# 3. 做一些探索工作
"分析 agents/ 目录的代理分类"

# 4. 检查上下文占用
/context

# 5. 用 /btw 问一个侧问题（不打断主任务）
/btw hooks.json 有多少个 hook？

# 6. 退出会话（Ctrl+C 或 exit）

# 7. 第二天恢复
claude --resume
# → 从列表中选择 "cc4pm-explore"
# → 无缝继续

# 8. 分叉一个新方向
claude --continue --fork
/rename cc4pm-explore-v2
"换一个角度，按工作流阶段重新分类这些代理"
```

### 动手试试

**练习 1：检查上下文结构**

```bash
cd cc4pm
claude

# 先做一些操作，让上下文有内容
"读一下 CLAUDE.md 和 agents/planner.md"

# 然后检查
/context
# → 观察各部分的占比
# → 特别注意 System prompt 和 Rules 占了多少

/memory
# → 确认加载了哪些配置文件
```

**练习 2：体验双击 ESC**

```bash
claude

# 输入一条模糊的提示词
"改一下这个项目的结构"
# → Claude 开始执行

# 双击 ESC 回到上一条输入
# 修改为更精确的版本：
"读取 agents/ 目录结构，只告诉我有哪些文件，不要修改任何东西"
```

**练习 3：体验 /btw**

```bash
claude

# 先开始一个主任务
"分析 cc4pm 的 rules/common/ 下所有规则文件的主题和内容"

# 在 Claude 工作过程中，用 /btw 问侧问题
/btw 这个项目有多少个 skill？

# → 侧问题的回答不会打断主任务
# → 关闭覆盖层，主任务继续
```

## 常见问题

**Q: --continue 和 --resume 有什么区别？**

A: `--continue` 直接恢复**最近一次**会话，零交互；`--resume` 弹出**历史列表**让你选。日常工作用 `--continue`，多线程工作用 `--resume`。

**Q: --fork 分叉后，原始会话会受影响吗？**

A: 不会。分叉创建的是完全独立的副本。你在分支上做的任何操作不会影响原始会话。两个会话可以各自独立发展。

**Q: /btw 的回答会影响 Claude 的后续行为吗？**

A: 不会。`/btw` 的问答完全不进入对话历史，Claude 在后续回复中不会"记得"你通过 `/btw` 问过什么。它就像在便签纸上写了个答案然后撕掉。

**Q: 我应该多频繁地检查 /context？**

A: 在长会话中（超过 20 个来回），建议每隔 5-10 个交互检查一次。在短会话中不需要刻意检查。如果感觉 Claude 的回复质量下降了，第一件事就是 `/context` 看看是不是上下文快满了。

**Q: /rename 支持中文吗？**

A: 支持，但建议用英文短横线格式（如 `auth-refactor`），因为在终端中显示更友好，且 `--resume` 列表对齐更美观。

## 相关概念

- **Context Window**（Lesson 2）— Session Management 是对上下文窗口的主动管理策略
- **Agent Loop 11 Steps**（Lesson 1.1）— 会话生命周期嵌套在 Agent Loop 的执行流程中
- **Git Worktree**（Lesson 3.2）— 比 /fork 更彻底的并行开发方式，每个 worktree 独立会话

## 下一步

请调用 `AskUserQuestion` 展示以下选项，让学习者点击选择；从每条中提炼 1-5 个词作为 label，其余写入 description，不要要求输入数字：

- 进入下一课：Lesson 3.1 - Status Line：你的实时仪表盘
- 返回主菜单
- 退出学习

---
*阶段 1 | Lesson 3/26 (阶段内 3/10) | 上一课: Lesson 2.1 - Token 与语言税 | 下一课: Lesson 3.1 - Status Line*
