跳到主要内容

Claude Code上下文窗口为什么越用越乱

一个 Claude Code 会话刚开始时,模型往往能牢牢记住目标。它读了几十个文件、跑了几轮测试、改了几次方案以后,早期约束可能开始被遗漏,搜索也会重复,回答还会越来越慢。

很多小伙伴会把原因归结成“Token 快满了”。窗口容量确实重要,信息质量同样会影响结果。窗口里塞着过期日志、重复文件和已经推翻的判断,即使还有剩余空间,模型也要在噪声中寻找当前任务需要的内容。

我通常把问题拆成两部分:窗口装了什么,以及这些内容现在还有没有用。

上下文窗口是当前推理的工作区

模型每次生成下一步动作时,只能使用本轮请求带给它的信息。会话历史、工具返回、规则和 Skill 都要重新进入请求,模型不会在请求之间保留一个隐藏的项目大脑。

上下文窗口因此更像一张正在使用的工作台。桌面大小有限,东西摆得越多,找到当前那张设计图就越费劲。

这个类比有两个边界:

  • 窗口里的文字会被模型整体处理,不等同于 JVM 中可以按地址精确读取的对象;
  • 窗口容量增加能容纳更多材料,却不能保证长文本中每个细节都被同等关注。

Claude Code上下文组成图

一次模型请求里有哪些开销

上下文占用可以分成启动开销和运行增量。

启动开销

会话开始时,Claude Code 已经需要准备一批信息:

内容作用特点
系统指令定义 Claude Code 的行为和工具使用方式每轮都需要
工具描述告诉模型有哪些工具、参数怎样写工具越多,开销通常越大
CLAUDE.md项目和个人长期约定会话启动时加载相应层级
无路径限制的 Rules对所有文件生效的项目规则启动时进入上下文
Auto Memory 索引以前沉淀的项目经验入口默认加载 MEMORY.md 前 200 行或 25KB
Skill 元数据告诉模型有哪些按需能力正文通常在调用后加载

项目规则写得过长、MCP Server 接得过多,任务还没开始,窗口余量已经被吃掉一部分。

运行增量

任务推进时,下面这些内容会持续增长:

  • 用户补充的需求和纠正;
  • Claude 的计划、解释与中间结论;
  • Read 返回的源文件;
  • Grep、Glob 等搜索结果;
  • Bash、测试、构建和日志输出;
  • Edit/Write 等工具调用记录;
  • 当前加载过的 Skill 正文;
  • Subagent 返回的结论;
  • Hook 注入的 additional context。

同样聊 20 轮,只讨论概念和每轮都跑测试,窗口占用差别会很大。工具结果往往是 Coding Agent 会话里增长最快的部分。

可以用一个概念公式理解预算:

当前可用余量
≈ 模型窗口上限
- 启动上下文
- 对话历史
- 工具调用及结果
- 为后续输出与压缩保留的空间

这个公式用于理解组成,不适合反推出某个版本的精确阈值。Claude Code 会迭代压缩策略、模型窗口和保留预算,面试里死背内部常量很容易过时。

哪些内容最容易把窗口撑大

下面几类内容在工程会话里增长得最快,也最容易被当成“反正还在窗口里”而反复保留。

全量测试日志

几千行成功日志的价值很低,真正有用的通常是失败用例、异常栈和复现命令。可以让测试工具减少普通输出,或者只保留失败摘要。

重复读取同一批文件

Agent 忘了自己查过什么,或者压缩后没有明确线索,就可能重新搜索和读取。文件内容确实可以再取,但频繁重复会抬高成本,也说明任务状态记录得不够好。

无边界的仓库调查

“帮我看看这个项目”会让 Agent 在目录之间不断展开。把范围改成“只调查库存预占和订单关闭链路”,搜索结果会少很多。

过长的规则与说明书

把部署 SOP、代码审查清单、UI 规范全塞进 CLAUDE.md,每轮都要付出这笔上下文成本。低频流程更适合做成 Skill,局部规则更适合放带 paths.claude/rules/

工具注册过多

多个 MCP Server 可能暴露几十甚至上百个工具。工具描述占空间,名称相似还会增加误选概率。连接真正需要的 Server,并定期清理闲置工具,比单纯扩大窗口更有用。

Lost in the Middle讲的是什么

长文本中的信息位置会影响模型使用效果。关键限制出现在开头,当前问题出现在结尾,中间夹着大量工具结果时,中间位置的细节更容易被漏掉,这类现象常被称为 Lost in the Middle。

例如会话第 2 轮写着“对账金额必须使用银行回单值”,第 35 轮已经出现多次日志查询、SQL 输出和代码修改。模型可能重新使用订单表中的金额,虽然那条约束仍在历史里。

在后面重复一遍只能短暂提醒模型。长期有效的项目规则应该写进 CLAUDE.md 或正式文档;当前任务关键约束要进入计划、测试和交接文件;需要强制执行的边界放到权限、Hook 或 CI。

Context Rot为何比窗口用满更早出现

Context Rot 可以理解为上下文质量随着会话推进而下降。常见信号包括:

  • 已经排除的方案又被提出来;
  • 搜索同一个符号,却不使用上一轮结论;
  • 忘记用户明确说过的修改边界;
  • 任务还没完成就开始写收尾说明;
  • 新证据与旧猜测冲突,回答却把两者一起保留;
  • 对下一步说得越来越笼统,例如只说“继续优化相关逻辑”。

这些信号没有统一百分比阈值。网上常见的“40% 后一定变笨”更像某些任务与模型下的经验线,无法替代当前会话观测。模型、工具结果大小和信息组织方式都会改变退化时机。

上下文质量随噪声增长的示意图

Prompt Cache能不能解决窗口压力

Prompt Cache 主要降低重复输入的费用和延迟。相同的系统指令、工具定义和历史前缀命中缓存后,服务端可以复用计算。

缓存并不会把这些内容从上下文窗口移走。它们仍属于本轮请求的输入,也会继续占用窗口容量。可以把它理解成“同样的数据读得更便宜”,不能理解成“数据不再占空间”。

这也是面试里很容易混的一点:成本优化和上下文治理有关联,解决目标并不相同。

/context应该怎么看

Claude Code 的 /context 命令用来查看当前窗口被什么占用。实际界面会随版本变化,通常可以看到模型窗口、已用空间和系统提示、工具、Memory、消息、Skills 等分类。

我会关注三件事:

  1. 固定开销是否异常,例如工具与规则刚启动就占了很大比例;
  2. 运行增量里哪类内容增长最快,是文件、日志还是长对话;
  3. 当前阶段结束后,哪些材料已经可以丢弃或写到文件外化。

ClaudeCode的Context命令

怎样减少低价值上下文

我的处理原则是让模型看到当前决策真正需要的材料,其余内容保留可重新获取的入口。

给探索设置边界

把目录、目标和禁止动作写清楚。先找符号和入口,再读关键文件,避免把整个仓库一次性展开。

控制命令输出

测试命令尽量使用简洁模式。日志分析先按时间、请求 ID 或错误码过滤,再打开关键上下文。

阶段结束就沉淀结论

探索结束后,把确认的调用链和方案写进计划。实现结束后,把变更和验证写进交付记录。旧搜索结果随后即使被清理,也不会丢掉当前决策。

把支线交给Subagent

日志归因、跨目录搜索和独立审查会产生很多一次性材料。Subagent 在独立窗口里完成过程,只把结论和证据带回主会话,可以明显减少主线污染。

把内容放到正确的载体

信息合适位置
当前正在看的代码片段会话上下文
每次会话都要遵守的项目规则CLAUDE.md
只影响某类路径的规则.claude/rules/
可复用的多步骤流程Skill
当前任务状态与决策Plan、Spec、Issue或交接文件
可在源码中重新查到的事实需要时重新查询
必须强制执行的限制权限、Hook、Sandbox、CI

上下文变长时先做什么

看到占用升高,不用马上清空会话。可以按下面顺序处理:

  1. 停止无边界搜索,确认当前阶段目标;
  2. 把关键约束、决策、失败用例和下一步写进任务状态;
  3. 清理或避免继续产生全量日志与重复结果;
  4. 阶段边界使用 /compact 压缩历史;
  5. 压缩后复述目标、已改文件、待办和验证命令;
  6. 多次压缩仍然接不上时,写 handoff 并换新会话。

压缩能释放空间,也会丢掉原始细节。真正稳定的长任务需要让重要状态离开聊天历史,进入可以重新读取的文件、测试和 Git diff。

面试回答可以这样组织

Claude Code 的上下文由启动开销和运行增量组成。系统指令、工具定义、规则与Memory索引构成起步成本;文件内容、搜索结果、测试日志和对话会持续增长。窗口变长后,模型可能出现Lost in the Middle和Context Rot,表现为漏约束、重复探索和使用旧判断。Prompt Cache能降低重复输入的成本与延迟,不能释放窗口。工程上要限制探索范围、控制工具输出、把任务状态写到文件、用Subagent隔离支线,并在阶段边界压缩会话。

参考资料

🎁优惠