你让 Claude Code 写一份详尽的总结、一个长计划、或者一份多章节报告。它写到一半就停了——没报错、没提示继续、看不出原因。或者下一轮带着一个「context compacted」的标记出现、原来的细节没了。Claude Code 工作在一个固定大小的 context window 里。工具调用、文件读取、之前的 assistant 轮、system prompt 全都和你这次回复挤在同一个 window 里。预算紧了,模型可能被 max_tokens 卡住、对话可能被自动 compact、单次工具输出可能把这一轮的预算吃光。修复方法看你撞上了哪种压力点。
常见原因
按命中率从高到低。
1. Assistant 回复撞 max_tokens 上限
每一轮 assistant 回复都有 token 数上限。你的 prompt 邀请的是 20k token 的回答、上限是 8k,那回复就在 8k 处断掉。
怎么判断:数一下被截断回复的 token 数。卡在 8192 或 16384 这种整数附近,就是撞上限了。
2. 单次工具结果把窗口吃光
一次 Bash 调用吐出 20 万字符、或者 Read 一个超大文件,留给 assistant 思考和回复的空间就没了。
怎么判断:看截断之前最近那次 tool_result,如果体积巨大,就是它。
3. 对话 compaction 中途启动了
用量上去之后,Claude Code 可能把旧轮自动 compact 成总结。compact 之后那一轮新的 assistant 回复可能丢了它原本依赖的细节。
怎么判断:transcript 里截断那一轮的前面找找有没有「compacted」或「summarized」标记。
4. System prompt + skills + tools 不知不觉膨胀了
每个插件、Skill、MCP server 都给 system block 加 token。原本不大的用户 prompt 现在前面顶着 40k token 的 overhead,留给回复的就不多了。
怎么判断:跑 claude --debug 看报出来的 system token 数。意外高的话能解释很多事。
5. 之前的 assistant 轮太啰嗦、一直占着 context
早先几轮要是吐了大段代码,那些都还留在 context window 里。几轮下来就把你预算占完了。
怎么判断:往上翻。会话里全是几千行的代码 dump,预算就没了。
6. 模型确实没更多东西要说
有时候看着像被截、其实模型本来就想停在那。「半句话」的感觉可能是个该有却没产生的句号。
怎么判断:看 API 响应里的 stop reason。stop_reason: end_turn 是模型主动停;max_tokens 是被卡住。
开始前
- 大致记下被截断回复的长度(行数或字符数)。
- 能访问
~/.claude/projects/下最近的 transcript 文件。 - 想清楚你是只要一次完整输出、还是反复都要长输出。
- 必要时准备把 prompt 拆小。
需要收集的信息
- Claude Code 版本:
claude --version。 - 触发截断的那条 prompt 原文。
- 这一轮结束时显示的 token 使用量(如果看得到)。
- 截断点前最后几条 tool result。
- transcript JSON 里的 compaction 标记。
claude --debug报出来的 system prompt 大小。
一步一步修复
Step 1:确认 stop reason
打开最近的 session transcript:
ls -lt ~/.claude/projects/*/sessions/ | head -3
找到被截断那一轮,看 stop_reason。max_tokens 就是撞上限;end_turn 就是模型自己停的。
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。注意可能会丢细节。
Step 6:关掉用不到的 MCP server 和 skill
每个 MCP server 和 skill 都往 system prompt 里加 token。这次会话用不到的就关掉:
claude --no-mcp
或者临时从 settings.json 里挪掉。
Step 7:反复要长输出,就写到文件
让 agent 把长输出用 Write 写进 markdown 文件,对话里只回路径加摘要:
把完整报告写到 /tmp/report.md,回复时只给路径加 5 条 bullet 的总结。
这样根本不会撞对话里的 token 上限。
怎么验证修好了
- 用修好的方式再发一次同样的 prompt,能拿到完整回复。
- transcript 里 stop reason 从
max_tokens变成end_turn。 - 后面几轮不再触发意外 compaction。
- 文件输出方式下,磁盘文件内容是完整的、就算对话里回复短。
长期预防
- 工具输出尽量小,多用 head、tail、sed range、grep,少用全量 dump。
- 长结果一律写盘、用路径引用。
- 会话用到窗口 50% 以上时主动
/compact。 - 审一下当前激活的 skill 和 MCP server,平时不用的关掉。
- 反复要的报告,prompt 模板里固定拆章节。
容易踩的坑
- 截断后让模型「从头再生成一遍」——token 直接翻倍、上限照样撞。
- 读整个 log 文件、而不是 grep 出相关行。
- 让 compaction 静默丢掉之前重要的决策;compaction 摘要要看一眼。
- 五个 MCP server 都连着、其实只用一个;system prompt 巨大。
- 把每个短回复都当成截断,其实模型只是 end_turn。
常见问答
- Claude Code 的 context window 多大? 看模型。Sonnet 和 Opus 是 200k token,但扣掉 system prompt、tools、history 之后,实际回复预算小得多。
max_tokens到底是啥? assistant 回复 token 数的上限。和总 context 大小是独立的。- 能调大 max_tokens 吗? 有的版本能在 settings 里设、或者换模型,但更稳的办法是拆 prompt。
- 为啥对话自己 compact 了我没让它做? Claude Code 在用量接近上限时会自动 compact。也能手动
/compact。 - 写文件算 context 用量吗? Write 调用本身占一些 token,但文件内容不占——这正是它的优势。
- 要不要总把没用的 MCP 关掉? 长会话该关、短会话无所谓。每个连着的 server 都耗 token。
相关
- Claude Code 到一半因 usage limit 停下
- Claude Code token 预算开太大
- Claude Code subagent 结果回传不到主会话
- Claude Code 上下文断裂
- Claude Code 输出和 prompt 对不上
- Claude Code 半执行后卡住
标签: #Claude Code #排查 #agent #排查