Prompt cache 与上下文预算
把 prompt cache 用满、把上下文预算分配清楚的实战策略,结合 Claude Code 实际数据讲清"省钱"和"省时间"两个目标
装包失败 / 权限报错 / API 限流 / context 超限 / hook 死循环等终端 Agent 高频问题的快速定位与处置
内容摘要
跑过一段时间 Claude Code、Codex CLI、Gemini CLI 之后,你会发现一件事:**CLI Agent 的报错和普通命令行工具的报错是两种生物**。一条 `git status` 出错,问题大概率就在 git 自己;但一条 `claude` 卡住几十秒不动,原因可能在网络、可能在订阅状态、可能在某个挂着的 MCP server,也可能是你昨天写的 PreToolUse hook 进入了死循环。**Agent 是一条长链路**,链路上任何一段坏掉都会让你看到一个含糊的"卡住""超时""报错"。
跑过一段时间 Claude Code、Codex CLI、Gemini CLI 之后,你会发现一件事:CLI Agent 的报错和普通命令行工具的报错是两种生物。一条 git status 出错,问题大概率就在 git 自己;但一条 claude 卡住几十秒不动,原因可能在网络、可能在订阅状态、可能在某个挂着的 MCP server,也可能是你昨天写的 PreToolUse hook 进入了死循环。Agent 是一条长链路,链路上任何一段坏掉都会让你看到一个含糊的"卡住""超时""报错"。
要把排错做高效,得先建立分层定位的思维。一次失败的 Agent 调用,按照"从外到内、从便宜到昂贵"的顺序去查,效率最高:
把这五层记牢,遇到任何"Agent 不对劲"先按顺序往下走,能避免 80% 的盲目重装、盲目重启、盲目改配置。
| 要素 | 说明 |
|---|---|
| 分层定位 | 网络 → 认证 → 配额 → 上下文 → Agent 自身,由外到内排查 |
| 诊断命令 | claude doctor / /status / /context / /doctor 是 Claude Code 内置体检入口;gemini --debug / RUST_LOG=debug codex 是 Gemini / Codex CLI 的对应入口 |
| 可重现最小用例 | 报 bug 前先把环境变量、模型、prompt 缩到最小,区分"我的环境问题"和"工具 bug" |
| 日志位置 | Codex CLI 写 ~/.codex/logs/codex-tui-*.log;Claude Code 用 /feedback 自动带 transcript;Gemini CLI 通过 --debug 输出到 stderr |
| 回滚而非重装 | 配置类问题重装基本无效,优先 /rewind、/clear、注释掉新加的 hook,再决定是否动安装 |
下面这张表覆盖 Claude Code / Codex CLI / Gemini CLI 在 2026 年 4 月之前最常见的 12 类报错。出问题先来这里查一遍,90% 的情况能直接拿到处置方法。
| # | 典型表现 / 报错 | 一眼定位 | 修复方法 |
|---|---|---|---|
| 1 | command not found: claude | PATH 里没有 ~/.local/bin | echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc |
| 2 | npm install -g 报 EACCES: permission denied | 全局目录归 root 所有 | 不要用 sudo。改用官方 curl -fsSL https://claude.ai/install.sh | bash,或 npm config set prefix '~/.npm-global' |
| 3 | Killed during install on Linux | 内存不足,OOM killer 干掉了安装进程 | 加 2G swap:sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile |
| 4 | unable to get local issuer certificate / SELF_SIGNED_CERT_IN_CHAIN | 公司代理在做 TLS 检查,Node 不认它的根证书 | export NODE_EXTRA_CA_CERTS=/path/to/corp-ca.pem,必要时加 NODE_OPTIONS="--use-openssl-ca" |
| 5 | API Error: 401 / Invalid API key / OAuth token expired | 旧的 ANTHROPIC_API_KEY 抢了 OAuth | unset ANTHROPIC_API_KEY 后 /logout && /login;用 /status 确认当前生效的 credential |
| 6 | API Error: 403 Forbidden 登录后 | 订阅过期 / 公司账号没分到 Claude Code 角色 / 代理挡了 | 查 claude.ai/settings;公司账号找 admin 加角色;代理场景去 /en/network-config 查白名单 |
| 7 | API Error: 429 · Rate limited 或 You've hit your session limit | 撞到模型限流或订阅周限额 | /status 看 credential 是不是订阅;/model 切到更小模型;降并发 CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY=2;等 /usage 显示的重置时间 |
| 8 | Prompt is too long / Autocompact is thrashing | 上下文窗口塞满,自动压缩失败 | /context 看占用;/compact keep only the plan and the diff 带焦点压缩;关闭未用的 /mcp disable <name>;上下文已塞死就 /clear |
| 9 | API Error: 529 Overloaded | 该模型全局过载,已自动重试到上限 | /model 切到不同模型(容量分模型计算);隔几分钟再试;查 status.claude.com |
| 10 | MCP server 启动后"沉默失败",工具列表里没有 | 路径含空格 / 启动慢被 60s 默认超时 / config 没装载 | claude doctor 看 MCP 报错;用 claude mcp add -s user <name> <cmd> 重加;长启动设 MCP_TIMEOUT=120000 |
| 11 | Stop hook 死循环,Agent 反复"再试一次" | Stop hook 没看 stop_hook_active 字段 | 在 hook 脚本头部加 guard:[ "$(jq -r '.stop_hook_active // false')" = "true" ] && exit 0;卡住时 Ctrl+C 两次或 kill -9 当前 claude 进程 |
| 12 | API Error: 400 due to tool use concurrency issues | tool_use / tool_result / thinking 块顺序错乱 | /rewind 或 Esc 两下回到上一个 checkpoint,从那里继续 |
急救 1:突然 401 / 403,先确认到底用的哪条 credential。
# 在出错的同一个 shell 里跑,看 ANTHROPIC_API_KEY 是否被某个 .env / 旧 zshrc 偷偷设了
env | grep ANTHROPIC
# 如果看到一行 ANTHROPIC_API_KEY=sk-... 但你本意是用订阅,就清掉
unset ANTHROPIC_API_KEY
# 重新登录 + 在 Claude Code 内核对
claude
> /status # 看 Active credential 是 OAuth (Pro/Max) 还是 API key
> /logout
> /login
急救 2:429 / context too long 同时出现,说明上下文撑爆了 + 在硬撞限流。
# 在 claude 会话里
/context # 先看哪一块占大头:system / tools / memory / messages
/mcp # 列出当前挂载的 MCP,哪些其实这次任务用不到
/mcp disable obsidian # 用不到的先停,工具定义就不会再占 context
/compact keep only the latest plan, diff, and unresolved errors
# 如果还是不行,直接重置
/clear
急救 3:MCP server 死活连不上,开 debug 看真实错误。
# Claude Code:内置体检
claude doctor
# 如果 doctor 显示 MCP "configured but failed to start",
# 把 server 命令拎出来手动跑一遍,看真实 stderr
npx -y @modelcontextprotocol/server-filesystem /Users/me/Desktop
# 启动慢的 server(如要下载模型 / 拉资源)记得抬高超时
export MCP_TIMEOUT=120000
claude
# 如果是 ~/.claude/mcp.json 不被加载,改用 CLI 命令重加(更可靠)
claude mcp add -s user filesystem npx -- -y @modelcontextprotocol/server-filesystem /Users/me/Desktop
预期行为:执行 claude doctor 后,正常状态会逐项打勾(Installation / Search / MCP / Settings / Auto-update);任何一项红字基本就是你这次问题的源头。
不同 CLI Agent 的诊断入口不一样,但思路是相通的。下表收束三家最常用的"开 debug、看日志、查健康"的入口,方便互相迁移经验:
| 维度 | Claude Code | OpenAI Codex CLI | Google Gemini CLI |
|---|---|---|---|
| 体检命令 | claude doctor / /doctor(内嵌检测安装、Search、MCP、Settings、Auto-update) | 无统一 doctor 命令,靠 --version + 日志判断 | 无统一 doctor 命令,issue 模板要求附 gemini --debug 输出 |
| 状态命令 | /status(看 credential、模型、配额)/ /usage / /context | 会话内 /feedback 收集 Request ID | 通过 --debug 输出请求详情 |
| 详细日志开关 | claude --debug --verbose(限交互调试时) | RUST_LOG=debug codex 或 RUST_LOG=trace codex,可加 RUST_LOG_FORMAT=json | gemini --debug "..." 2>&1 | tee bug.txt 或 DEBUG_MODE=1 |
| 日志落盘位置 | 默认不持久化日志,需 /feedback 把 transcript 自动打包发回 | ~/.codex/logs/codex-tui-*.log,自动轮转 | 默认 stderr,无固定文件路径 |
| 上下文压缩 | /compact(带焦点参数)/ /clear / /rewind | /clear / /compact(视版本) | 重新启动会话或缩短 prompt |
| 限流定位 | /status 看 credential,错误信息会写"this may be a temporary capacity issue" | 错误体含 rate_limit_exceeded,需自己读 stderr | 报 You exceeded your current quota,需查 Google AI Studio 配额面板 |
| 上报方式 | /feedback 一键带 transcript 发到 Anthropic(Bedrock/Vertex 不可用) | /feedback + Request ID | 需手动开 GitHub issue 附 --debug 日志 |
核心区别用一句话:
claude doctor、/status、/context、/usage、/feedback 互相补位,能在 30 秒内把"我哪儿出问题"答出来。tail -f、grep ERROR,但需要自己拼 RUST_LOG,不太适合非工程背景用户。--debug 现场抓,所以排错门槛最高。这意味着:学会 Claude Code 的排错命令,迁移到另两家时只需要换"日志怎么开"这一处,分层定位的思维和顺序是通用的。
| 误区 | 准确理解 |
|---|---|
| 把模型 429 / 529 当成"Agent 卡死",疯狂 Ctrl+C 重启 | 429 / 529 是 API 层面的限流和过载,重启 Agent 改变不了限额。正确动作是 /status 确认 credential、/model 切模型、降并发或等 /usage 显示的重置时间 |
看到任何报错都先 npm install -g 重装一遍 | 配置类问题(hook 死循环、MCP 没启动、ANTHROPIC_API_KEY 串了、上下文撑爆)重装一次都解决不了。先 claude doctor + /status 才是正确顺序 |
| Stop hook 写了"keep working",结果 Agent 反复触发陷入死循环却没及时 kill | Stop hook 的输入里有 stop_hook_active 字段,guard 在脚本第一行就要写:[ "$(jq -r '.stop_hook_active // false')" = "true" ] && exit 0。卡住时 Ctrl+C 两次仍不退就 pkill -9 claude |
| 用 sudo 解决 npm 全局安装权限问题 | sudo npm install -g 会让后续所有更新、卸载、postinstall 都需要 sudo,并且引入安全隐患。官方推荐用原生安装脚本或 npm config set prefix '~/.npm-global' |
公司代理报 SSL 错误就直接 NODE_TLS_REJECT_UNAUTHORIZED=0 | 这等于把整条 Agent ↔ API 的 TLS 校验全关掉,等于裸奔。正确做法是从 IT 拿 corp-ca.pem,设 NODE_EXTRA_CA_CERTS,TLS 链路依然受信 |
| 觉得 Claude Code 给的报错文字不准就忽略它 | 错误文本里通常带"do this next"的提示,例如 Run /rewind to recover / Press esc twice to go back / Run /context,照着做一次再判断,不要看见英文就下意识忽略 |
| 把 MCP server 静默失败误判为"协议有 bug" | 大概率是路径含空格、启动超过 60s 默认超时、config 没生效。先 claude doctor 看 MCP 段落,再把 server 命令手动跑一遍 验证它本身能起来 |
排错路径有三种:自己按速查表排、直接问 Agent 自己、提工单。三者各有适用场景,混用才是高效姿势。
| 路径 | 优势 | 劣势 |
|---|---|---|
| 自助排错(看速查表 / 文档) | 10 秒定位高频问题;不消耗 token;不留私域信息外泄 | 需要预先建立"分层定位"的肌肉记忆;遇到全新问题没有线索 |
| 直接问 Agent 自己(在会话里描述报错) | Agent 知道自己内置的诊断命令,能引导你跑 /doctor、/status;对常见问题给出修复 patch | 撞到限流 / 401 / 上下文超限时 Agent 本身就答不动;可能编造不存在的命令;transcript 越长越烧 token |
提工单 / GitHub issue(/feedback 或手动) | 复杂 bug、版本回归类问题最终只能靠官方查;/feedback 自动带 transcript 是最高效的上报姿势 | 周期以天为单位;要把问题缩小到可重现的最小用例;公司账号要小心 transcript 里的代码片段 |
实际经验上的最优组合:
/status 输出贴回去,让 Agent 引导跑 claude doctor、/context,70% 的中频问题能解决。/feedback 一键带 transcript 上报;同时 GitHub 搜一下报错关键词,看是不是已知 issue。切忌一上来就提工单——等回复的时间足够你自己解决三轮问题。
claude,提示 API Error: 403 Forbidden。订阅明明是有效的,怎么定位?参考答案:
按"分层定位"的顺序走:
env | grep ANTHROPIC。99% 概率会发现一行 ANTHROPIC_API_KEY=sk-... 是从旧 .zshrc、旧项目 .env、direnv、或公司脚手架里继承下来的。这个 key 可能属于一个早就被禁用的 Console org,于是订阅 OAuth 被它压住,API 直接回 403。unset ANTHROPIC_API_KEY,并把 ~/.zshrc / ~/.bashrc / ~/.profile 里的 export ANTHROPIC_API_KEY=... 行删掉,否则下次重开 shell 又会复发。claude 进入会话,跑 /status,确认 Active credential 显示成你的订阅(OAuth),而不是 API key。整个流程不超过 2 分钟,关键是不要直接重装 Claude Code,重装解决不了 credential 串台。
参考答案:
为什么会死循环:Claude 收到 stop 信号 → 你的 hook 检查测试失败 → 返回 block 让 Claude 继续 → Claude 回了一段话又触发 stop → 你的 hook 又 block → 无限循环。
救场(必须先做):
pkill -f claude 或 ps aux | grep claude 拿到 PID 后 kill -9 <pid>,把进程一棒打死。settings.json 注释掉再启动 claude,否则一进去又复发。正确的写法(避免再次发生):在 Stop hook 入口先读 stop_hook_active 字段做 guard——如果 Claude 已经因为这个 hook 被 block 过一次了,就让它真的停。
#!/bin/bash
INPUT=$(cat)
ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false')
# guard:已经在 stop loop 里了,直接放行
if [ "$ACTIVE" = "true" ]; then
exit 0
fi
# 真正的检查逻辑:如果测试失败,让 Claude 再修一轮
if ! npm test --silent; then
echo '{"decision":"block","reason":"tests still failing"}'
exit 0
fi
exit 0
配套防御:给所有可能 block 的 hook 设合理的 timeout(默认到点会被 kill 当成非阻塞失败),以及在 settings 里明确写 "timeout": 30000 一类的硬上限,防止哪天 hook 自己卡死又拖死 Agent。
优先展示同分类且标签更接近的内容,方便继续串联学习。
把 prompt cache 用满、把上下文预算分配清楚的实战策略,结合 Claude Code 实际数据讲清"省钱"和"省时间"两个目标
高危权限治理:dangerously-skip-permissions / 容器隔离 / CI 场景 / 团队规范的成体系做法,含真实事故案例