Claude Code 输出被上下文截断

Claude Code 长回复半句话被切掉。最快的办法:让它「从最后一句继续」。真正的原因多半是 auto-compact、单轮输出上限、或者某次工具输出把预算吃光了。

你让 Claude Code 写一份详尽的总结、一个长计划、或者一份多章节报告。它写到一半就停了——没报错、没提示继续、看不出原因。或者下一轮带着一个「Context low · run /compact」的提示(自动 compaction)出现、原来的细节没了。

最快的修法(约 80% 情况有效):直接输入 continue from the last sentence 回车。半截答案还在 context 里,所以 Claude Code 会接着写、而不是从头来。如果它每次都卡在同一个地方,那真正的原因就是下面几个桶之一——最常见的是某一次巨大的工具结果把回复的空间挤没了。

为什么会发生:Claude Code 跑在一个固定大小的 context window 里(截至 2026 年 6 月,Opus 4.7 和 Sonnet 4.6 都是 1,000,000 token)。工具结果、文件读取、之前的轮次、system prompt 全都和你这次回复挤在同一个 window 里。能切断回复的其实是两个独立的上限——单轮输出上限(模型给单次回答设的天花板)和 context window(总预算,快满时触发 auto-compaction)。截断几乎都能追到这两者之一。

你属于哪个桶

症状大概率原因跳到
每次都停在一个整数附近(Sonnet 约 64K、Opus 约 128K)单轮输出上限原因 1
截断前刚跑过一个超大的 Bash/Read单次工具结果吃光窗口原因 2
看到过 /compact 或「Context low」横幅auto-compaction原因 3
还没发第一条 prompt,/context 就显示 40K+ tokensystem block 臃肿(MCP/skill)原因 4
会话很长、堆满旧代码 dumphistory 太啰嗦原因 5
回复就这么结束了、看着也还算完整模型自己写完了(end_turn原因 6

常见原因

按命中率从高到低。

1. Assistant 回复撞单轮输出上限

这个和 context window 是两码事:每一次单独的回复都有一个由模型设定的最大输出长度。截至 2026 年 6 月,Claude Code 单轮最多能吐 Sonnet 4.6 的 64K 输出 tokenOpus 4.7 最高 128K。你的 prompt 邀请的是 20 万 token 的回答,那不管 context window 还剩多少空,回复都会在这个天花板处断掉。

怎么判断:回复很长,而且每次重发同一条 prompt 都停在差不多的体积。截断后跑 /context——如果总 context 离满还远、回复却照样停了,那就是撞单轮输出上限、不是窗口满了。

2. 单次工具结果把窗口吃光

一次 Bash 调用吐出 20 万字符、或者 Read 一个超大文件,留给 assistant 思考和回复的空间就没了。

怎么判断:看截断之前最近那次 tool_result,如果体积巨大,就是它。

3. auto-compaction 中途启动了

窗口用量越过 auto-compact 阈值(截至 2026 年 6 月默认 95%)时,Claude Code 会把旧轮总结成一段压缩 recap、再从那里接着写。compact 之后那一轮可能丢了它原本依赖的细节,所以一个长答案明明是从摘要重建出来的、读起来却像「被截断」。Claude Code 还会在窗口顶部留一段 buffer(大约 33K token、约 10%),所以可用预算比标称的 1M 略低一点。

怎么判断:你看到过「Context low · run /compact」横幅或一行 checkpoint,或者 transcript JSON 里截断那一轮前面有一条 summary record。

4. System prompt + skills + tools 不知不觉膨胀了

每个插件、Skill、MCP server 在你打字之前就往 system block 里加 token。原本不大的 prompt 现在前面可能顶着 40K+ token 的 overhead,留给回复的更少、也更快把你推向 compaction 阈值。

怎么判断:跑 /context(或一开始就 claude --debug),看 system / tools / MCP 的 token 拆分。那里数字意外高的话能解释很多事。

5. 之前的 assistant 轮太啰嗦、一直占着 context

早先几轮要是吐了大段代码,那些都还留在 context window 里。几轮下来就把你预算占完了。

怎么判断:往上翻。会话里全是几千行的代码 dump,预算就没了。

6. 模型确实没更多东西要说

有时候看着像被截、其实模型本来就想停在那。「半句话」的感觉可能是个该有却没产生的句号。

怎么判断:打开 transcript JSONL 里那条 assistant record,看它的 stop_reasonend_turn 是模型自己选择停下;max_tokens 是撞到了单轮输出上限。

开始前

  • 大致记下被截断回复的长度(行数或字符数)。
  • 能访问 ~/.claude/projects/ 下最近的 transcript 文件。
  • 想清楚你是只要一次完整输出、还是反复都要长输出。
  • 必要时准备把 prompt 拆小。

需要收集的信息

  • Claude Code 版本:claude --version
  • 触发截断的那条 prompt 原文。
  • 截断后立刻拍一张 /context 快照(system、tools、MCP、messages 的拆分)。
  • 截断点前最后几条 tool result。
  • transcript JSON 里的 summary / compaction record。
  • 当前模型(/model),因为 Sonnet 4.6 和 Opus 4.7 的单轮输出上限不一样。

一步一步修复

Step 1:用 /context 看预算

在会话里跑:

/context

它会把当前装进来的东西显示出来——system prompt、tools、MCP server、消息历史——以及各占窗口的比例。总用量接近 95% 就快 auto-compact 了;用量很低、长回复却照样停了,那就是撞了单轮输出上限。要看原始 transcript,JSONL session 文件在 ~/.claude/projects/ 下:

ls -lt ~/.claude/projects/*/*.jsonl | head -3

每一行是一条 record;一次 compaction 会在被重建那一轮的前面显示为一条 summary record。

Step 2:缩小前面那次工具输出

截断前的 Bash 或 Read 结果太大,就改用更窄的范围重跑:

# 不要 dump 整个文件,改成:
sed -n '100,200p' big-file.log

或者写到磁盘、让模型读一份摘要。

Step 3:让模型从断点继续

简单一句「从最后一句话继续」通常就行,因为之前的 context 还留着半截答案。别让它从头重来,那是双倍 token 开销。

Step 4:把任务拆章节

要长结构化输出,每次只要一段:

只写第 1 节:架构概览。这一节写完就停。

下一轮再要第 2 节。每一轮都舒舒服服地装在上限以内。

Step 5:在长回复之前主动 compact

会话里堆了一堆无关的工具调用,在要那个大答案之前先自己跑一下 /compact 把它们总结掉、给接下来的回复腾出 token。可能会丢细节,所以 recap 要看一眼。如果意外的 auto-compaction 才是真问题,可以调高触发点或干脆关掉:

# 把 auto-compact 触发点压低、让它更早触发(默认 95):
export CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=80

# 或者彻底关掉 auto-compaction(会写进 ~/.claude.json):
claude config set -g autoCompactEnabled false

也可以在 /config 里切换「Auto-compact」开关。关掉之后,你会撞到一个硬性的「Context low」停止、而不是一次静默重建,这往往更好判断。

Step 6:关掉用不到的 MCP server 和 skill

每个 MCP server 和 skill 都往 system prompt 里加 token,/context 会把这笔账显示给你。这次会话用不到的就关掉:

claude --strict-mcp-config --mcp-config '{}'   # 启动时一个 MCP server 都不加载

--strict-mcp-config 会忽略你的配置文件、只加载 --mcp-config 传进来的东西;空对象就是一个都不加载。或者临时从 .mcp.json / 设置里把 server 挪掉。连着的 server 越少,system block 越小、留给回复的空间越大。

Step 7:反复要长输出,就写到文件

让 agent 把长输出用 Write 写进 markdown 文件,对话里只回路径加摘要:

把完整报告写到 /tmp/report.md,回复时只给路径加 5 条 bullet 的总结。

这样根本不会撞对话里的 token 上限。

怎么验证修好了

  • 用修好的方式再发一次同样的 prompt,能拿到一份停在完整句子上的回复。
  • 回复后跑 /context,用量稳稳低于 95% 的 auto-compact 线。
  • 后面几轮不再蹦出意外的「Context low · run /compact」横幅。
  • 写文件那条路下,磁盘上的目标文件是完整的、就算对话里回复短——打开看一眼最后一行。

长期预防

  • 工具输出尽量小,多用 headtailsed range、grep,少用全量 dump。
  • 长结果一律写盘、用路径引用,别贴进对话。
  • 盯着 /context,会话过了窗口约 70% 时自己跑 /compact,别等 auto-compact 在 95% 处把答案写一半时触发。
  • 审一下当前激活的 skill 和 MCP server,平时不用的关掉,让 system block 保持小。
  • 反复要的报告,用一个每次只要一章的 prompt 模板。

容易踩的坑

  • 截断后让模型「从头再生成一遍」——token 直接翻倍、同一个上限照样可能撞。
  • 读整个 log 文件、而不是 grep 出相关行。
  • 让 auto-compaction 静默丢掉之前重要的决策;它产生的 recap 要看一眼。
  • 五个 MCP server 都连着、其实只用一个;用 /context 查查这笔开销。
  • 把每个短回复都当成截断,其实模型只是写完了这一轮。

常见问答

  • Claude Code 的 context window 多大? 截至 2026 年 6 月,Opus 4.7 和 Sonnet 4.6 都是 1,000,000 token(从原来的 200K 涨上来的)。扣掉 system prompt、tools、history 和约 33K token 的预留之后,实际可用预算略低一点。
  • 为啥 /context 显示还剩很多空间、我的长答案还是停了? 你撞的是单轮输出上限,它和窗口是两码事。Sonnet 4.6 单轮最多吐 64K 输出 token、Opus 4.7 最高 128K。把答案拆成几节就能绕过。
  • 为啥对话自己 compact 了我没让它做? Claude Code 在窗口用量到默认 95% 时会自动 compact。可以用 CLAUDE_AUTOCOMPACT_PCT_OVERRIDE 调低触发点、自己更早跑 /compact、或者用 claude config set -g autoCompactEnabled false 关掉。
  • 怎么直接让一段被截断的答案接着写? 输入 continue from the last sentence。半截文字还在 context 里,所以 Claude Code 会从断点接上、不用为重启再花 token。
  • 写文件算 context 用量吗? Write 这个工具调用本身占一些 token,但文件内容不会留在窗口里——这正是把长输出导到磁盘的全部意义。
  • 要不要总把没用的 MCP server 关掉? 长会话该关,每个连着的 server 都在撑大 system block;临时的一次性小活儿一般无所谓。

相关

标签: #Claude Code #排查 #agent #排查