我扒了 Claude Code 的源码,画出了 Token 是怎么涨涨涨然后崩的
你有没有好奇过:为什么用 Claude Code 聊了一会儿之后,突然间它说「正在压缩对话」,然后好像失忆了一段?
这背后藏着一套精密的上下文管理机制。我翻了 Claude Code 的完整源码,把每一轮对话中 token 数量的变化规律画成了一张图。
先看一眼这张图

图里展示的是一次从头到尾的真实会话。横轴是第几轮对话,纵轴是当前占用的 token 数。
你会看到:折线不断爬升,然后突然垂直下坠,然后再爬升,再下坠。 一共经历了 5 种不同的「压缩」事件。
为什么 token 数一直在涨?
很多人以为「input tokens」就是你发的那条消息。错了。
每次你发一条消息,Claude 收到的实际上是:
input = 系统提示(~8K) + 工具定义(~12K) + 所有历史对话 + 内存附件(CLAUDE.md) + 你当前这条消息
整个对话历史,每轮都完整发一遍。
这就是为什么图里的折线永远向右上方走——你每多说一句话,下一次 API 调用就多带一句话的历史。
而且,不同操作对 token 的消耗量差距巨大:
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
💡 一次 Read 大文件,抵得上 10 轮正常对话的 token 消耗。
五种「崩」法,各有各的原因
图里的每次下坠,对应的机制不一样。从左到右:
① Session Memory Compact(青色,局部压缩)
这是最轻量的一种。当 token 开始逼近警戒线,Claude Code 会先尝试只压缩内存附件部分(CLAUDE.md 等动态注入的内容),历史对话基本保留。降幅约 15~25K,像是给上下文做了个局部瘦身。
对应源码:trySessionMemoryCompaction(),它在触发重量级压缩之前优先运行。
② Auto Compact #1(红色,全量压缩)
这是最常见的大崩。源码里写死的阈值:
有效窗口 = 200K - 20K(输出预留) = 180K 触发线 = 180K - 13K(buffer) = 167K(约 83%)
触发后,Claude Code 会启动一个独立的 forked agent,把整段对话历史总结成一份摘要,然后用摘要替换原来的所有历史。压缩完再自动恢复最多 5 个最常用的文件(上限 50K token)。
图里看到的那条垂直下坠线,就是从 ~167K 跳到 ~33K。整个摘要的生成费用当然也得计入……是的,压缩本身也要花钱。
③ Auto Compact #2(橙色,连环二次压缩)
压缩后的对话重新开始积累,不可避免地再次触到 167K。第二次触发时,源码会标记 isRecompactionInChain=true,说明这是连环压缩。摘要对摘要,信息损耗更大。
④ Circuit Breaker(红叉,断路器)
这是最危险的情况。如果上下文里有某条工具返回内容本身就超长,那么压缩会失败——摘要输出超过限制,API 报 prompt_too_long。
连续失败 3 次后,断路器触发:
MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3 // BQ 2026-03-10: 全球每天 ~250K 次无效 API 调用被浪费 // 1,279 个 session 有 50+ 次连续失败
Anthropic 工程师把真实 BigQuery 数据写进了注释。断路器触发后,自动压缩永久停用,只能靠用户手动 /compact 救场。
⑤ Manual /compact(紫色,手动救场)
用户主动触发,通常是断路器启动后的最后手段。机制和自动压缩一样,但由人决策。
还有一件事:Prompt Cache
系统提示和工具定义这 ~20K 的静态内容,第一次调用时写入 prompt cache(cache_creation,额外收 25% 费用),后续每次读取缓存(cache_read,打 9 折,便宜 90%)。
这意味着:你的每次 API 调用,实际新计费的部分只是历史对话的增量,系统提示和工具定义几乎白嫖。但历史对话不会进 cache——每轮新增的内容都按原价计费。
实用结论
如果你是 Claude Code 的重度用户,这张图告诉你几件事:
1. 最贵的操作是读大文件,不是问复杂问题。 一次 Read 整个大文件,比 10 轮对话还费钱。能 grep 就别 Read 全文。
2. Bash 输出要加截断。 如果命令可能输出很多行,加 | head -50 之类的截断,否则工具结果会把上下文撑爆。
3. 第一次 compact 之后,session 就开始信息损耗。 如果在意连贯性,及时开新 session 比一直压缩要更可靠。
4. 断路器触发是个警告信号。 说明你的某次工具调用产生了无法被压缩的超长内容,需要手动清理再继续。
图中的数据基于 claude-code 开源源码(autoCompact.ts / compact.ts / tokens.ts 等),阈值为 claude-sonnet-4-6 在 200K 上下文下的真实配置。
夜雨聆风