---
title: "02 · 一次能看多少代码"
description: "上下文窗口不是记忆，是一张会满的工作台。100 万 token 听起来巨大，但用了 78% 你就会觉察 Claude 变笨——理解这张桌子怎么运作、怎么管，操作上的困惑就全解开了。"
canonical: "https://xiangyugongzuoliu.com/tag/claude-code"
verifiedAt: "2026-05-08"
---

Aaron用 Claude Code 的头一个月，有时候它分析得头头是道，有时候聊着聊着就**变笨了**。翻了文档才发现，这不是智力波动，是工作台被堆满了。搞清楚这张工作台的运作方式之后，很多操作上的困惑就全解开了。——Aaron

> [!NOTE]
> **这一篇用 13 分钟换什么**：上一篇 [01](/docs/claude-code/understanding/01-what-is-claude-code) 我们理解了 Claude Code 的核心是**位置**——AI 住在你电脑里。这一篇拆它怎么**看**你的项目：通过上下文窗口，把代码摊在一张大桌子上。理解了桌子怎么满、怎么管，后面的 CLAUDE.md、Skills、SubAgents 才有清晰的位置感。

## 1. 从最简单的情况开始

想象你面前有一张桌子。你和 Claude 在这张桌子上协作——你把文件摊开，它看了之后给你建议。

**这张桌子就是上下文窗口（context window，会话工作台）**。

最简单的情况是这样的：桌子是空的，你问了一个问题，Claude 回答了。桌上放了两样东西——你的问题和它的回答。很轻松，空间绰绰有余。

这是所有人最开始用 Claude Code 的体验：反应快、回答精准、感觉什么都能搞定。

但随着工作推进，事情会发生变化。我们用一个具体的会话场景往下走——**今天你要修一个支付回调的 bug**：

> [!NOTE]
> **👤 你**：账户充值后金额没到账，支付回调日志在 `/logs/payment.log`，可能跟 webhook 重试有关，帮我查一下。

> [!TIP]
> **🤖 Claude**：好，我先看 `payment.log` 和 webhook 处理代码 *(读 8 个文件：`logs/payment.log` 最近 200 行、`controllers/webhook.ts`、`services/payment.ts`、`models/transaction.ts`、`queue/retry.ts` ……)*

这个场景会贯穿整篇——从干净的桌子，一路跑到桌子被堆满，再到我们决定怎么处理。

## 2. 桌子上的东西越来越多

刚才那个支付 bug 调查继续推进：你让 Claude 看了 8 个文件，每个几百行；它跑了一次 webhook 重试测试，输出了 600 行日志；你和它来回讨论了十几轮，每轮分析至少 200 字……桌上已经堆了不少。

还有一些你看不到但确实存在的东西也在桌上：Claude Code 自身的系统提示（大约 50 条内置指令）、你的 CLAUDE.md 配置文件、Auto Memory（自动记忆）的 MEMORY.md 前 200 行。这些在每次会话开始时就自动上桌了。

```mermaid
flowchart TB
    Desk["📋 上下文窗口<br/>（你的工作台）"]

    System["🧠 系统级内容<br/>会话开始自动上桌"]
    User["💬 你说的话<br/>每条消息、每个追问"]
    AI["🤖 Claude 的回答<br/>通常比你的提问更长"]
    Files["📁 读取的文件<br/>500 行 ≈ 5000-7000 token"]
    Cmd["⚡ 命令执行输出<br/>测试 / 编译 / 安装日志"]

    System --> Desk
    User --> Desk
    AI --> Desk
    Files --> Desk
    Cmd --> Desk

    Desk -.->|持续累积| Full["⚠️ 桌子被堆满<br/>表现开始下降"]

    style Desk fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
    style Full fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
    style AI fill:#fee2e2,stroke:#ef4444
```

**通俗讲**：想象你在开一个长会。每个人说的话都在往白板上写——你说的、对方说的、中途查的资料、打开的文件。白板很大，但**不是无限大**。如果会开得够久，白板总会写满。

回到支付 bug 的会话。10 轮对话后，桌上已经堆了：

- 8 个源文件 ≈ 4 万 token
- 600 行日志 ≈ 8000 token
- Claude 的 10 段分析 ≈ 1.5 万 token
- 你的提问 + 系统提示 + CLAUDE.md ≈ 3000 token

加起来 7 万 token——感觉**写满了**？还差得远。继续往下读。

## 3. 这张桌子有多大

现在给桌子加一个数字：**100 万 token**（1 million token，词元）。

1 个 token 大约是 4 个英文字符（约 0.75 个英文单词），中文大约 2 个 token 对应 1 个汉字。所以 100 万 token 约等于 **50 万中文字**——5 到 6 本长篇小说的篇幅。

换算到代码场景：

| 单位 | 大约 token | 实际大小 | 直觉对照 |
|------|------|------|------|
| **1 行代码** | 10-15 | — | 1 个完整语句 |
| **1 个中型源文件** | 3000-7000 | 200-500 行 | 一个 controller / service |
| **20 万 token**（旧版上限）| 200,000 | 1.5 万行代码 | 能看一个模块的几个文件 |
| **100 万 token**（Sonnet 4.6 / Opus 4.7 当前）| 1,000,000 | 7-8 万行代码 | 能看完一个中型项目全部源码 |

> [!NOTE]
> **事实基准**：Opus 4.7、Opus 4.6、Sonnet 4.6 都支持 1M context window（[官方说明](https://code.claude.com/docs/en/model-config#extended-context)）。Max / Team / Enterprise 套餐 Opus 自动启用 1M。其它套餐 / Sonnet 1M 可能需要额外用量。模型别名加 `[1m]` 后缀显式启用：`/model opus[1m]`。

回到支付 bug 的场景。我们刚才算了 7 万 token——这张桌子用了 **7%**。剩下 93 万 token 还能装很多东西。

但**能装很多东西**不等于**应该装很多东西**。这就引出了下一个问题。

100 万 token 和 20 万 token 的区别**不只是大了 5 倍**。当你能同时看到整条链路时，**你能发现的问题类型发生了质变**——路由传了 `userId` 但控制器期望 `user_id` 这种跨文件的字段不匹配，只看一个文件永远发现不了。**100 万 token 让一类原本不可能发现的问题变得可以发现**。

20 万 token 像是只能透过钥匙孔看房间——你能看清某个角落，但看不到全貌。100 万 token 像是打开了房门走进去——你能同时看到家具之间的空间关系。**找一件东西的效率完全不同，不是快了 5 倍，而是从碰运气变成了一眼看到**。

## 4. 桌子一定会满

下一个自然的问题：**它会满吗？**

答案是：**看你怎么用**。如果你只做简单问答——问个问题、得到回答、再问一个——100 万 token 可以聊很久很久。

但实际工作中不是这样。继续支付 bug 的故事——你越查越深，桌子从 7% 一路膨胀到 78%：

### 第 1-10 轮：7% 占用

读 8 文件 + 跑测试 + 讨论。桌上：源码 + 日志 + Claude 的初步分析。


### 第 11-25 轮：18% 占用

让 Claude 重读相关 controller 全部测试。又加了 12 个文件 + 测试输出。


### 第 26-40 轮：28% 占用

检查支付网关 SDK 源码。SDK 整个 `src/` 目录 ≈ 6 万 token 进入工作台。


### 第 41-60 轮：55% 占用

让 Claude 写修复代码 + 跑全量测试。大量长 diff + 测试日志。


### 第 61-80 轮：78% 占用

反复改 + 验证 + 联调。所有历史持续累加，没东西被释放。


### 第 81+ 轮：接近上限

你开始觉察 Claude 回答**变慢**、**变笨**——它需要扫描的桌面太大了。


**关键点**：上下文窗口**不是一个装东西的桶**——东西放进去就静静待着。它更像一个**每轮都要翻一遍的工作台**。每一轮交互，Claude 都要把桌上所有东西扫一遍才能回答。**桌上东西越多，每轮扫描越慢、成本越高**。所以**能用多少就用多少**不是最优策略，**只放需要的东西**才是。

而且有一个容易忽略的点：**上下文消耗不是线性的**。随着对话深入，Claude 需要回顾之前的内容来保持连贯——这意味着每轮新交互，**实际处理的信息量都在增长**。

**为什么 Claude 在 78% 时会"变笨"**：模型每轮都要扫一遍桌上所有内容才能决定下一步动作。桌子越满，扫描越慢、注意力越分散、关键信息越容易被淹。这跟人开会到第 4 小时记不清前面讨论一个道理——不是脑子坏了，是认知带宽被堆满。**1M token ≠ 1M 都好用**——经验上 60-70% 占用就开始触发降级（Anthropic 的 prompt cache 机制对前缀重读有缓存，但全局注意力代价是真实的）。

所以问题不是会不会满，而是**满了怎么办**。

## 5. 满了怎么办：三种策略

Claude Code 提供了三种应对策略，它们适用场景完全不同。先用一张决策树判断该走哪条路：

```mermaid
flowchart TD
    Start["⚠️ 觉察上下文接近上限<br/>Claude 回答变慢 / 变笨"]
    Q1{"接下来的工作<br/>跟之前有关联吗？"}
    Q2{"任务本身能不能拆<br/>成多个独立步骤？"}
    Compact["✨ /compact<br/>压缩当前对话保留精华"]
    Clear["🧹 /clear<br/>清空重来"]
    Split["🪓 拆分任务<br/>每步用独立会话"]

    Start --> Q1
    Q1 -->|有关联，要继续| Q2
    Q1 -->|完全无关，换主题| Clear
    Q2 -->|可以拆| Split
    Q2 -->|不能拆，必须连续做| Compact

    style Compact fill:#dcfce7,stroke:#22c55e
    style Clear fill:#dbeafe,stroke:#3b82f6
    style Split fill:#fef3c7,stroke:#f59e0b
    style Start fill:#fee2e2,stroke:#ef4444
```

三种策略各自的细节看下面的 tab：

<details>
<summary>/compact 压缩</summary>

**原理**：让 Claude 回顾当前对话，把核心信息提炼成精简摘要，然后用这个摘要替代原来那一大堆内容。

**比喻**：开了两小时的会，有人站起来说要总结一下刚才讨论的要点，然后**擦掉白板上的细节，只留下几条关键结论**。白板腾出了空间，核心决策没丢。

**回到支付 bug**：已经查到 78%，但 bug 还没修完，正在反复联调。这时候用 `/compact`：Claude 把前 60 轮浓缩成一段 webhook 重试丢失幂等键、已修 4 文件、测试还缺一轮，桌子从 78 万 token 缩回 8 万。**继续干活，不丢上下文**。

**进阶用法**：指定压缩重点。

```bash
/compact 保留 webhook 幂等性相关的所有讨论
```

**自动触发**：Claude Code 在上下文接近上限时会**自动**触发压缩，你不需要时刻盯着 token 数。但提前手动压缩 / 清空仍然更聪明。

✅ **适合**：任务还在进行 + 不能丢上下文
❌ **不适合**：下一步跟前面无关

</details>

<details>
<summary>/clear 清空</summary>

**原理**：直接清空整个对话历史，回到一张干净的桌子。

**比喻**：擦掉整块白板，重新开会。

**回到支付 bug**：bug 修完了，你接下来要写一个新功能用户邮件订阅设置页——这两件事**完全不相关**。继续在同一个会话里干，前面的 webhook / 幂等性讨论就是噪音。`/clear` 比 `/compact` 更省 token。

**和 /compact 的本质区别**：

- `/compact` = 压缩但**保留**核心信息
- `/clear` = **全部丢弃**

判断标准很简单——问自己：接下来的任务跟刚才聊的有没有关系？有关联用前者，无关联用后者。

✅ **适合**：切换到完全不同的任务
❌ **不适合**：当前任务还要继续

</details>

<details>
<summary>拆分任务</summary>

**原理**：第三种不是命令，是**工作方式**。把大任务拆成多个小任务，每个用一个独立会话完成。

**回到支付 bug**：其实它一开始就可以拆——

- **会话 1**（30 分钟）：分析 webhook + 幂等性，输出根因报告 + 修复方案，保存到 `docs/bug-payment-webhook-analysis.md`
- **会话 2**（20 分钟，干净桌子）：读分析文件，实施第一部分修复（修 `controllers/webhook.ts`）
- **会话 3**（30 分钟，干净桌子）：读分析文件 + 修改后的 controller，写测试 + 跑全量回归

每个会话都从一张干净的桌子开始，**只放当前步骤需要的东西**。

**为什么高效**：一个任务的每个阶段需要的信息是不同的。**分析阶段**需要看很多文件但不需要之前的对话记录；**实施阶段**需要方案文件和目标文件但不需要分析过程。把所有阶段塞进一个会话，大量空间被已经过时的中间信息占据。

✅ **适合**：任务很大 + 阶段之间能传递文件
❌ **不适合**：必须强连续上下文的紧密任务

</details>

> [!TIP]
> **速记**：三种策略不是互相替代——`/compact` 保留精华继续干，`/clear` 清桌子换任务，**拆分任务**从一开始就别让桌子堆满。

**新手最常踩的坑：等 95% 才 /compact**。他们盯着进度条，到 95% 才动手压缩——这时候 Claude 已经"变笨" 半小时了，前面的判断质量大打折扣。正确做法是 **60-70% 主动 /compact**，趁还没明显降级时把桌子腾干净；或者更早就用"拆分任务"从源头避免堆积。

另一个常见误区：**以为 /compact 是免费操作**。压缩本身要让 Claude 把整张桌子读一遍再总结——这一轮本身就消耗大量 token + 时间。所以 /compact 不是"想压就压"，是"任务还要继续 + 上下文确实满了"才用。简单换主题直接 `/clear` 更省。

## 6. 一个容易混淆的地方

到这里你可能注意到了：我一直在说**桌子**，没有说**记忆**。这是故意的。

很多人把上下文窗口类比成记忆力——100 万 token 就是记忆力超强，能记住很多东西。这个类比有一个**致命的偏差**：记忆是可以长期保留的，**但上下文不是**。

**一句话理解**：上下文窗口是 AI 在一次会话中**同时能看到**的信息总量，**不是它能永久记住**的东西。你一旦关掉这次会话，桌上的东西全部清空。下次打开，桌子是空的。

**看到**和**记住**是两件事。你看一本书的时候，翻开的那些页面你都看到了——但合上书之后你不一定记住了。**上下文窗口决定的是 Claude 能同时翻开多少页面，不是它能永久记住多少内容**。

那 AI 怎么记住你的习惯和项目信息？那是另一套系统——**长期记忆**。下一篇 [03 · 怎么记住你的习惯](/docs/claude-code/understanding/03-memory) 会拆。

## 7. 回头看全貌

把前面所有内容串起来，形成一个**可操作的心智模型**：

| 阶段 | 桌子状态 | 你该做什么 |
|------|---------|---------|
| **开始任务** | 空（仅 CLAUDE.md + Auto Memory 摘要）| 放心让 Claude 读文件、跑命令 |
| **工作进行中** | 持续累积 | 有意识关注趋势：Claude 回答变慢 / 变笨 = 上下文快满信号 |
| **觉察到信号** | 接近上限 | 走 §5 决策树：`/compact` / `/clear` / 拆分 |
| **整个过程** | — | 一个会话一个主题——上下文管理最省心的方式 |

**底层逻辑**：上下文管理的核心原则——**让桌子上永远只有当前最需要的东西**。不是追求桌子多大，而是追求桌子多干净。

## 8. 检验你真懂了吗

费曼说，检验你是不是真的理解一件事，试试能不能解释给朋友听。

| # | 试着用自己的话回答 | 对应章节 |
|:-:|------|------|
| 1 | 有人说 100 万 token 就是记忆力好——你能解释这说法错在哪？上下文和记忆的本质区别是什么？ | §6 |
| 2 | 上下文从 20 万扩到 100 万，为什么是质变不是量变？举一个只有看全貌才能发现的问题类型。 | §3 |
| 3 | **动手题** ⭐：在你下次 Claude Code 会话开始前，先想清楚这次任务要分几步：① 调研 ② 设计 ③ 实现 ④ 测试。每步是同一个会话连着干，还是开新会话？写下你的拆分理由。提示：如果四步会议中前一步的代码片段对后一步**不直接相关**，就该开新会话——这就是 §5 拆分任务的核心。 | §4 + §5 |

> [!TIP]
> **过关标准**：能用一句话说清——**上下文窗口是 AI 一次会话能同时看到的信息总量，不是永久记忆；桌子会满，所以要主动管理。**

<details id="glossary">
<summary>📖 本篇术语速查表</summary>

| 英文 / 缩写 | 中文 | 一句话解释 |
|-------------|------|-----------|
| context window | 上下文窗口 | AI 一次会话中同时能看到的信息总量，本篇主角 |
| token | 词元 | 模型读 / 写文本的最小单位，1 个中文字大约 2 token |
| 1M / 100 万 token | 100 万词元 | Sonnet 4.6 / Opus 4.6 / Opus 4.7 当前的最大上下文 |
| `/compact` | 压缩命令 | 把当前对话提炼成精简摘要替换原内容，腾出桌面空间 |
| `/clear` | 清空命令 | 直接清空整个对话历史，回到干净桌子 |
| CLAUDE.md | 项目记忆文件 | 写给 Claude 的长期指令，会话开始自动上桌（详见 03 篇）|
| Auto Memory | 自动记忆 | Claude 自动维护的项目学习笔记，存在 MEMORY.md（详见 03 篇）|
| MEMORY.md | 自动记忆主文件 | 启动时只加载前 200 行或 25KB（取较小）|
| prompt caching | 提示缓存 | 重复前缀缓存机制，省 token 不省桌面空间 |

</details>

## 官方资料

- [How Claude Code works](https://code.claude.com/docs/en/how-claude-code-works)
- [Explore the context window](https://code.claude.com/docs/en/context-window)
- [Manage costs effectively](https://code.claude.com/docs/en/costs)

## 接下来去哪

<Cards>
  <Card title="➡️ 03 · 怎么记住你的习惯" href="/docs/claude-code/understanding/03-memory">
    上下文是一次性的，关机就没。CLAUDE.md + Auto Memory 双轨记忆系统怎么让 Claude 跨会话记住你的项目和偏好。
  </Card>
  <Card title="04 · 怎么和 AI 说话" href="/docs/claude-code/understanding/04-prompting">
    同样的意思，不同的表达，消耗的 token 天差地别。提示词不是模板游戏，是信息密度游戏。
  </Card>
  <Card title="01 · Claude Code 是什么（上一篇）" href="/docs/claude-code/understanding/01-what-is-claude-code">
    复习一下：AI 住在你电脑里这个根基，是怎么决定后面所有功能能不能成立的。
  </Card>
</Cards>

不用按顺序全读。挑你最好奇的那条线走就行。
