Claude Code 长会话变慢变贵的解决办法
每轮都会重发全部上下文,会话越长越慢越贵。先读 /context 看占用,削减固定开销,再用 clear 和 compact 按意图清理。
如何让长时间 Claude Code 会话保持快速和便宜
长时间的 Claude Code 会话会变慢、变贵,因为每一轮都会重新发送全部上下文,而上下文只会越来越大。解决办法是按固定顺序进行清理。运行 /context 查看是什么在占满窗口,删掉每次请求都要重复付出的内容,然后在不相关的任务之间使用 /clear,在同一个长任务中用 /compact 配合一条指令。保持连续工作,因为冷启动的提示缓存会把本应廉价读取的内容变成对全部历史的完整重写。
至于为什么会有计量,参见 智能体会话背后的令牌计量机制。
在做任何修改之前先读取 /context
不要猜测窗口里装的是什么。Claude Code 会告诉你。
/context [all] 把当前上下文用量绘制成彩色网格,并对占用大量上下文的工具和内存膨胀给出优化建议;all 在全屏模式下展开每个项目的明细。把结果看作五个桶。
- 系统提示。 Claude Code 自身的运行框架指令。在整个会话期间是固定的。
- 工具定义。 智能体可以调用的每个工具的 schema,包括每个已连接的 MCP(模型上下文协议)服务器。
- 内存文件。
CLAUDE.md和自动内存,在会话开始时加载。 - 文件和工具结果。 每个被读取的文件,以及你的命令回显的所有内容。
- 消息历史。 你的轮次和它的回复。
前三个是固定开销,在会话生命周期内的每个请求都要支付。后两个会增长。固定开销只在开始时削减一次;增长的部分要持续管理。
有两个字符串告诉你窗口已满:
Context exceeds the 200k-token limit by 94k tokens — run /compact or /clear to continue.
Context is 94k tokens past the 200k-token compaction window — run /compact to reduce usage.第一个是硬性上限,请求会被拒绝;对应的 API(应用程序编程接口)错误信息是 Prompt is too long。第二个是压缩窗口,在 100 万 token 的模型上,它可能低于模型真实的上下文窗口。超过它之后请求仍然会成功,所以它只是一个警告,而不是拒绝。
在付费计划上,/usage 补上另一半,标记诸如长上下文或缓存未命中之类的行为,并把最近的使用量归属到各个技能、子智能体和 MCP 服务器上。
CLAUDE.md 是一笔持续开销,请保持精简
你的 CLAUDE.md 在会话开始时被加载到上下文中,并一直保留。如果它包含详细的部署流程,那么在你修复测试文件中的拼写错误时,这些 token 依然占用着空间。Anthropic 的建议是只保留关键内容,并将文件控制在 200 行以内。
将流程移到技能中。技能仅在被调用时加载,因此一周只运行两次的工作流在其余日子里不消耗任何开销。技能在压缩之后有独立的预算:内容体会被重新注入,单个技能上限为 5,000 token,总计上限为 25,000 token,最旧的优先丢弃。截断会保留文件的起始部分,因此请将最重要的指令放在 SKILL.md 的顶部。
压缩后能存活下来的内容,决定了一条指令应该放在哪里。
- 系统提示和输出风格保持不变,因为它们不属于消息历史。
- 项目根目录的
CLAUDE.md、未限定作用域的规则以及自动记忆会从磁盘重新注入。 - 带
paths:frontmatter 的规则会丢失,直到再次读取匹配的文件。 - 子目录中的嵌套
CLAUDE.md会丢失,直到再次读取该子目录中的某个文件。 - Hooks 不受影响,因为 hook 以代码形式运行,从不进入上下文。
因此,你所依赖的规则应放在项目根的 CLAUDE.md 中:Claude Code 先清理较早的工具输出,然后再进行总结,因此会话早期的指令可能会丢失。使用 /memory 编辑记忆。Claude Code 持有它在会话开始时加载的副本,因此会话中途的修剪会保留提示缓存,并且要等到下一次 /clear、/compact 或重启才会生效。
在任务之间使用 /clear,在单个任务内使用 /compact
这两个看起来可以互换,但成本差异很大。
/clear [name] 以空上下文开启新对话。它不发送任何请求,因此不产生费用。可以传入一个名称,用于在 /resume 选择器中标记上一个对话;/reset 和 /new 是别名。在切换到无关任务的那一刻使用它,因为旧任务否则会在新任务的每条消息中被重新发送并重新计费。
/compact [instructions] 在继续同一对话的同时释放上下文:它会总结到目前为止的历史并替换它。在单个长任务内部使用,此时你仍然需要保持连续性。
始终给 /compact 一个指令。 一个裸的 /compact 会针对一个默认提示进行总结,该提示并不知道你还需要工作的哪一部分。带指令的则能保留它:
/compact focus on the auth bug fix
/compact keep only the plan and the diff如果你每次都出于同样的原因进行压缩,请在项目的 CLAUDE.md 中以 # Compact instructions 标题的形式放置一条常设指令。在新会话中 /compact 打印 Not enough messages to compact.,这只表示还没有历史记录。
这里混淆了两种成本。总结请求共享你的前缀,因此它读取现有缓存而不是重新处理历史,并且其大部分时间用于生成总结。压缩大型上下文仍然是一个大型请求,因为被总结的对话就是输入。压缩之后的下一轮并不是慢的部分:它是为一个更短的提示重建缓存。
存在两个更便宜的命令。/rewind [description] 将代码和对话回滚到检查点;对于想要完全放弃的路径,它优于压缩,因为它截断回一个已经缓存的前缀。/recap 将总结作为命令输出追加,而不是替换历史,因此缓存的前缀保持不变。
自动压缩反复触发会打印如下内容:
Autocompact is thrashing: the context refilled to the limit...压缩成功,但一个文件或工具输出连续多次重新填满了窗口,因此 Claude Code 停止重试。通过按行范围读取过大的文件、运行带有丢弃大输出焦点的 /compact、将该工作移交给子代理,或者如果早期对话已完成则使用 /clear 来恢复。
MCP 服务器是固定开销
每连接一个 MCP 服务器,都会在整次会话中为每个请求增加开销。无论你是否调用它,都要付出代价。
Claude Code 对此有所缓解。MCP 工具定义默认是延迟加载的,因此只有工具名称会进入上下文,直到 Claude 实际使用某个具体工具。运行 /context 可以查看各个服务器的真实成本,运行 /mcp disable <name> 可以移除今天不会用到的服务器。如果你在 VPS 上自建 MCP 服务器,同样的算术也限制了一个服务器应该暴露多少个工具。
在会话开始时执行此操作。只要定义保持延迟加载,连接或断开服务器只会追加到对话中,缓存仍然有效。如果定义加载到前缀中(例如工具搜索关闭,或某个服务器被排除在延迟加载之外),同样的更改会导致下一次请求重新读取所有内容。
在工具输出进入上下文之前过滤冗长内容
工具结果就是输入,而输入会在之后每一轮中重新发送。一次测试运行如果输出 20,000 个 tokens,那不是一次性成本:在它离开上下文窗口之前,每一轮都要再次承担这部分开销。
在源头过滤。在 Claude 看到之前,通过 hook 把测试运行缩减到只剩失败部分,这样那一墙输出在本轮以及之后每一次重新发送时,都只剩下几百个 tokens:
npm test 2>&1 | grep -E "FAIL|Error:" | head -40Hook 本身永远不会进入上下文,因为它们以代码形式运行。对于任何输出超过一屏的工具,都应该这样做。同样的逻辑也适用于 3,000 行的文件:只请求你需要的行范围,因为文件一旦进入上下文,整个文件就会一直留在窗口里。
限定代理读取范围,并把嘈杂的工作委托出去
明确写出文件名和症状的提示词只会读取那个文件。一个开放式的“整理一下项目”的请求会让代理自行决定读取哪些内容,而每一次读取都会留在上下文窗口里。
把冗长的任务委托给子代理。测试运行和日志处理都会消耗真实的上下文;子代理把那些输出留在自己的窗口里,只返回摘要。代价是:子代理在第一次调用时构建自己的缓存,没有任何命中,并且即使在订阅制下也使用五分钟的缓存生命周期。委托能可靠地保护你的主上下文,但并不总能降低总 token 数。
缓存时钟:按连续段工作
提示词缓存让重发变得便宜:读取前缀的费率是基础输入的 0.1 倍,而写入是 1.25 倍,使用一小时生命周期时写入是 2 倍。每次使用都会刷新条目,且不产生额外费用,因此计时从最近一次使用开始算。
你能获得哪种生命周期取决于你的认证方式,这也是“一刀切地说你的缓存会在五分钟后过期”这种说法站不住脚的原因。
- 使用 Claude 订阅时,Claude Code 会自动请求一小时生命周期。
- 一旦超出套餐额度并开始使用用量积分,由于这部分用量要计费,生命周期就会回退到五分钟。
- 使用 API 密钥或云服务商时,生命周期保持五分钟。
ENABLE_PROMPT_CACHING_1H=1选择启用一小时生命周期,FORCE_PROMPT_CACHING_5M=1则强制将其降回五分钟。
无论哪种情况,节奏建议都一样:按连续段工作,因为一旦空闲时间超过生命周期,下一轮就要重写整个累积的前缀。tmux 中分离的 Claude Code 会话在空闲时不产生费用,而空闲时间所放弃的正是已暖好的缓存。
在你仍在工作时,有些操作会直接丢弃缓存:切换模型、调整 effort 等级、开启 fast mode、连接或断开 MCP 服务器、启用或禁用插件、整组拒绝某个工具、压缩上下文,以及升级 Claude Code。/model 是最常见的意外,因为每个模型都有自己的缓存,所以即使内容完全相同,下一次请求也会在没有缓存命中的情况下读取整个历史。
编辑文件、编辑 CLAUDE.md、调用技能和命令、运行 /recap、回退,以及派生子代理,都会保留缓存。缓存的作用域限定在一台机器和一个目录,因此不同目录中的两个会话互相无法命中对方的缓存。
要查看缓存是否生效,请读取 current_usage。cache_creation_input_tokens 按缓存写入费率写入;cache_read_input_tokens 以大约标准输入费率十分之一的费率被读取。读取与创建的比值较高是健康的。如果创建量一轮接一轮居高不下,说明你的前缀里有什么东西一直在变化。
更大的上下文窗口能解决此问题吗?
部分可以。当前几个模型支持 1 百万 token 的上下文窗口,上限扩大后压缩机制的工作方式不变。成本结构不变,因为完整提示词每一轮都会被重新发送并计费。更大的窗口决定何时被迫采取行动;清理习惯决定成本。如果问题出在账单而不是上限,哪个 Claude 套餐适合你的使用方式 决定你是在花美元还是在消耗套餐额度。
API 中的上下文编辑与压缩是不同的功能
如果你正在 基于 Messages API 构建自己的智能体,则不存在斜杠命令,需要自行实现。服务器端有两项功能可以完成这项工作,它们不是同一项功能。
上下文编辑(Context editing)会在对话历史增长时选择性地清除其中的特定内容,并将每个被清除的结果替换为占位文本,这样 Claude 就知道有内容被移除了。它目前是 beta 版:发送 anthropic-beta: context-management-2025-06-27 并在 context_management.edits 下配置策略。clear_tool_uses_20250919 用于清除工具结果,clear_thinking_20251015 用于管理思考块。其 trigger 默认为 100,000 个输入 token,keep 默认为最近 3 次工具调用,clear_tool_inputs 默认为 false,因此输入会保留,只有结果会被清除。
压缩(Compaction)会生成一份摘要,并用该摘要替换完整的对话历史。它同样是 beta 版:发送 anthropic-beta: compact-2026-01-12 并使用编辑类型 compact_20260112。触发阈值默认为 {"type": "input_tokens", "value": 150000},且该值必须至少为 50,000。
压缩有一条交接规则,会悄无声息地破坏智能体。响应以一个包含摘要的 compaction 内容块开始,随后是普通的文本块。你必须在后续请求中把那个块原样传回,API 随后会丢弃它之前的所有内容块。实际操作中:把 response.content 的全部内容追加回去,而不只是其中的文本。
Anthropic 的文档将服务器端压缩称为管理长对话上下文的主要策略,将上下文编辑视为对清除内容进行更精细控制的选项。请先检查模型支持情况。当前的 Opus、Sonnet 和 Fable 模型支持压缩,claude-haiku-4-5 不支持,压缩页面提供最新的支持列表。这两项 beta 都不会驱动 Claude Code 自身的 /compact,其文档将其描述为客户端发送的一次性摘要请求。
FAQ
为什么我的 Claude Code 会话运行得越久越慢、成本越高?
因为每次轮次都会重新发送整段对话,所以在已经开了一整天的会话里提一个一行的问题,也会带着一整天的内容一起发出。提示缓存能让它在缓存命中时保持低价,命中读取的费率是基础输入的 0.1x;一旦某一轮未命中缓存,同样的前缀会以 1.25x 的费率重新写入。运行 /context 可以看到是什么在占满窗口,并阅读 Claude Code 会话是如何向你计费的 来了解其机制。
Claude Code 中 /clear 和 /compact 有什么区别?
/clear 以空上下文开始一个新对话。它不发送任何请求,因此不产生任何费用,是无关任务之间的正确选择。/compact 保留同一个对话,但用一段摘要替换历史记录,因此适合在一个长任务的内部使用。给它一个焦点,例如 /compact keep only the plan and the diff,因为指令决定了哪些内容会被保留。
如何查看是什么占满了我的 Claude Code 上下文窗口?
运行 /context,或运行 /context all 获取每个项目的完整明细。它会以彩色网格的形式展示系统提示、工具定义、MCP 服务器、记忆文件和历史记录,并针对占用上下文较多的工具和膨胀的记忆给出建议。在付费套餐下,/usage 还会将最近的使用量归因到各个 skill、子代理和 MCP 服务器。
我应该使用 100 万 token 的上下文窗口来代替压缩吗?
更大的窗口只是延缓问题,而不是解决问题。目前有多个模型支持 100 万 token 的上下文窗口,Opus 4.8 和 Sonnet 5 都在其中,压缩在该窗口下的行为方式也相同。每一次轮次仍然会重新发送完整的提示,并仍然为其计费,所以一次 400,000 token 的对话,无论是否能装进窗口,都是昂贵的。
Claude API 中,上下文编辑(context editing)和压缩(compaction)有什么区别?
上下文编辑会选择性地清除旧内容(主要是工具结果),并在每个被清除的位置留下占位文本,以便 Claude 知道那里原本有内容被移除。压缩则会生成一段摘要,并用这段摘要替换完整的历史记录。Anthropic 的文档将压缩称为长时运行对话的主要策略,并将上下文编辑定位为更细粒度的选项。两者都是各自带有独立 Header 的 beta 功能,并且都与 Claude Code 的 /compact 是分开的。