ECC Hook 故障规避实战指南:Claude Code 上游 Hook 相关 Bug 的高信号修复方案
导读:本文围绕 ECC(Everything Claude Code)仓库中 docs/hook-bug-workarounds.md 记录的社区验证型规避方案展开,聚焦 Claude Code 上游行为对 Hook 重度使用场景造成的五类干扰:误报的
Hook Error标签、比预期更早发生的上下文压缩、压缩后 MCP 认证看似存活实则失效、Hook 修改不热重载,以及高负载下的反复529 Overloaded。读完本文,你将掌握每类问题的可落地操作步骤、正确的 Hook 退出码语义、相关环境变量的取值与作用,以及如何借助 ECC 的strategic-compact技能和 Token 优化配置降低问题触发概率。
1. 先厘清问题边界:上游 Claude Code 行为,而非 ECC 缺陷
ECC 是一套为 Claude Code、Codex、Opencode、Cursor 等 Agent Harness 提供 skills、instincts、memory、security 与 research-first 开发能力的插件体系。由于 ECC 大量使用 Hook 做自动化守卫(详见仓库根的 hooks/README.md),Claude Code 自身的任何 Hook 相关缺陷都会被放大。
本文记录的五类问题有一个共同前提:它们是上游 Claude Code 的行为,不是 ECC 的 Bug(原文表述为 "upstream Claude Code behaviors, not ECC bugs")。因此在修复思路上不应对 ECC 本身做破坏性改动,而是采用"临时规避 + 等待上游修复"的策略。与 docs/TROUBLESHOOTING.md 中更宽泛的排障面不同,本页面刻意保持窄聚焦,只收录社区验证过的高信号操作修复,不重复投机性、无依据的配置建议。
这些规避方案源自社区在 issue #644 中汇总的生产实测报告,测试环境为 Claude Code v2.1.79(macOS、重度 Hook 使用、启用 MCP 连接器),可作为方案适用性的参考前提。
何时使用本页:当你正在调试以下任一具体症状时——
- 本来执行成功的 Hook 却被错误标记为
Hook Error; - 上下文压缩比预期发生得更早;
- MCP 连接器界面显示已认证,但压缩后调用失败;
- 修改 Hook 后没有热重载生效;
- 在 Hook/工具调用高压下反复收到
529 Overloaded响应。
2. 高信号规避方案一:处理"假" Hook Error 标签
2.1 症状与根因
Hook 实际执行成功,但 Claude Code 仍会在转录(transcript)中显示 Hook Error。根据仓库 hooks/README.md 对 Hook 工作流的定义,Claude Code 会向 Hook 进程通过 stdin 传入 JSON,并期望进程按约定消费输入、以规定的退出码结束。当 shell Hook 没有消费 stdin 管道时,父进程会观测到"未被消费的管道",从而误判为异常。
2.2 推荐做法(四项规则)
- 在 Hook 开头立即消费 stdin:shell Hook 用
input=$(cat);Node 等语言 Hook 则监听 stdin 数据并在end事件中处理(后文给出 JS 示例)。 - 对简单的 allow/block Hook 保持 stdout 安静:除非 Hook 实现明确需要结构化 stdout,否则不要向 stdout 输出;把人类可读的诊断信息发送到 stderr。
- 对无关紧要的子进程 stderr 做重定向:当子进程的报错不可操作时,将其丢弃,避免干扰 Hook 的判定。
- 使用正确的退出码:
0表示放行(allow),2表示阻止(block),其他非零退出码一律被当作错误处理。
2.3 标准示例:阻止并附原因
# 好做法:消费 stdin → stderr 输出诊断 → exit 2 阻止
input=$(cat)
echo "[BLOCKED] Reason here" >&2
exit 2
这一退出码约定与仓库中 Hook 架构规范完全一致:rules/common/hooks.md 明确 PreToolUse Hook 可阻止(exit code 2)或警告(仅 stderr 不阻止),hooks/README.md 亦将退出码总结为:0 成功继续、2 阻止工具调用(仅 PreToolUse)、其他非零视为错误(记录但不阻止)。
2.4 Node Hook 对应的写法
ECC 的 Hook 逻辑大量以 Node.js 实现以保证跨平台(见 hooks/README.md 的 Cross-Platform Notes)。等价写法如下:
// my-hook.js —— 消费 stdin,输出诊断到 stderr,回写原数据到 stdout
let data = '';
process.stdin.on('data', chunk => data += chunk);
process.stdin.on('end', () => {
const input = JSON.parse(data);
const toolName = input.tool_name; // "Bash"、"Edit"、"Write"...
const toolInput = input.tool_input; // 工具专属参数
console.error('[Hook] Warning message shown to Claude'); // 警告(不阻止)
// process.exit(2); // PreToolUse 阻止时使用
console.log(data); // 原样回写 stdout
});
排查验证:可手动把一条工具调用 JSON 通过管道喂给 Hook 脚本,确认退出码与输出符合预期,例如:
echo '{"tool_name":"Bash","tool_input":{"command":"echo test"}}' | bash path/to/hook.sh
echo "exit code: $?"
3. 高信号规避方案二:压缩比预期更早发生
3.1 症状与反直觉行为
在部分当前 Claude Code 构建版本中,降低 CLAUDE_AUTOCOMPACT_PCT_OVERRIDE 非但没有延后自动压缩,反而让压缩更早发生("Lowering causes compaction to happen sooner, not later")。
从仓库证据看,这个变量在 ECC 的 Token 优化推荐里默认被设为 50(默认行为为 95),见 README.md 的推荐 settings;但 docs/token-optimization.md 特别添加了"Community note on auto-compaction overrides":部分新版 Claude Code 中该覆盖值只能下调压缩阈值,即低于默认值会提前压缩。
3.2 推荐做法
- 如果你希望获得更多工作空间,直接移除
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE,不要试图通过把它设得更低来延后压缩。 - 在自然的任务边界手动执行
/compact,掌握压缩时机的主动权。 - 改用 ECC 的
strategic-compact指导,而不是强制压低自动压缩阈值(详见第 6 节)。
3.3 在哪里配置 / 移除
该变量位于 ~/.claude/settings.json 的 env 块,或当前 shell 环境变量:
{
"model": "sonnet",
"env": {
"MAX_THINKING_TOKENS": "10000",
"CLAUDE_CODE_SUBAGENT_MODEL": "haiku"
}
}
即从 env 中删去 "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE" 一行即可让 Claude Code 回到原生压缩行为。
4. 高信号规避方案三:MCP 认证看似存活、压缩后却失败
4.1 症状
以 Gmail、Google Drive 等 MCP 工具为例:会话压缩之后工具调用开始报错,但连接器在界面中仍然显示已认证。这属于压缩后认证态失效的恢复问题,而非永久性损坏。
4.2 推荐做法
- 压缩后将该连接器关闭再重新打开(toggle off / back on),强制刷新认证状态。
- 如果当前 Claude Code 构建支持
PostCompact事件,可添加一个轻量级提醒 Hook,在每次压缩后提醒你复查连接器认证。仓库的插件清单测试已把PostCompact纳入受支持的 Hook 事件枚举,见 tests/plugin-manifest.test.js。 - 把它当作"恢复提醒"而非"永久修复"——上游修复落地前,每次压缩后都需人工或靠提醒 Hook 复查。
一个轻量提醒 Hook 的示意(写入你的 Claude Code settings,或用 ECC 插件方式注册):
{
"hooks": {
"PostCompact": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "echo \"[ECC] After compaction, re-check MCP connector auth state (toggle off/on if needed)\""
}
],
"description": "PostCompact reminder to re-verify MCP connector auth"
}
]
}
}
说明:ECC 自身的
PreCompactHook 承担的是压缩前保存状态的职责(见 hooks/hooks.json 中pre:compact条目与 hooks/README.md 的 Lifecycle Hooks 表),与上述"压缩后提醒"的诉求互补。Hook 输入均为 JSON 且通过 stdin 传入、stdout 输出 JSON,符合第 2 节描述的统一契约。
5. 高信号规避方案四:Hook 修改不热重载
5.1 症状
修改 settings.json 中的 Hook 后不生效,直到重启会话。这与 Claude Code 会话加载 Hook 配置的时机有关——Hook 定义在会话启动阶段被读取。
5.2 推荐做法
- 修改 Hook 后重启 Claude Code 会话,这是文档确认的可靠手段。
- 高级用户有时会借助 shell 本地重载辅助手段(例如在
/reload命令周围封装kill -HUP $PPID),但 ECC 没有内置这样的脚本——因为这类做法与 shell、平台强相关(原文:"ECC does not ship that because it is shell-dependent and not universally reliable")。请不要期待在 ECC 中找到一键重载命令。
5.3 如何避免频繁手改 Hook 配置
ECC 推荐用环境变量做运行时控制而非每次编辑 hooks.json(详见 hooks/README.md 的 Runtime Hook Controls 小节):
# 主开关。显式环境值优先于插件偏好。
export ECC_HOOKS_ENABLED=true
# minimal | standard | strict(默认:standard)
export ECC_HOOK_PROFILE=standard
# 按逗号分隔禁用指定 Hook ID
export ECC_DISABLED_HOOKS="pre:bash:tmux-reminder,post:edit:typecheck"
# 在 setup/恢复期间单独关闭 GateGuard
export ECC_GATEGUARD=off
# 限制 SessionStart 附加上下文(默认 8000 字符)
export ECC_SESSION_START_MAX_CHARS=4000
# 完全关闭 SessionStart 附加上下文
export ECC_SESSION_START_CONTEXT=off
# 保留上下文/范围/循环警告,仅关闭 API 费率成本估算提示
export ECC_CONTEXT_MONITOR_COST_WARNINGS=off
Windows PowerShell 设置用户级环境变量:
[Environment]::SetEnvironmentVariable('ECC_CONTEXT_MONITOR_COST_WARNINGS', 'off', 'User')
Hook profile 含义(同样来自 hooks/README.md):
minimal—— 只保留必要生命周期与安全 Hook;standard—— 默认档,均衡的质量 + 安全检查(suggest-compact等 Hook 在此档激活);strict—— 额外提醒与更严格的护栏。
插件安装场景可直接在 hooks/hooks.json 中看到这些 Hook 的注册方式:例如 pre:edit-write:suggest-compact 通过 run-with-flags.js 限定在 standard,strict 档生效。注意:手动安装场景下不要把仓库内的原始 hooks.json 直接粘贴进 ~/.claude/settings.json,请使用 ECC 安装器(bash ./install.sh --target claude --modules hooks-runtime --enable-hooks 或 Windows 的 pwsh -File .\install.ps1 ...),安装器会把 Hook 命令重写到你的真实 Claude 根目录(hooks/README.md 的 Installing Hooks Manually 一节)。
6. 高信号规避方案五:反复出现 529 Overloaded
6.1 症状
在 Hook/工具调用/上下文高压下,Claude Code 开始频繁返回 529 Overloaded。本质是单请求的"工具定义 + 隐藏思考 Token + 上下文"压力过大,导致服务端过载或配额紧张。
6.2 推荐做法(按优先级)
| 手段 | 配置 | 作用原理 / 出处 |
|---|---|---|
| 降低工具定义压力 | ENABLE_TOOL_SEARCH=auto:5(若你的构建支持) |
减少每次暴露给模型的工具定义数量,前提是你的 Claude Code 版本开放该开关 |
| 例行工作降低思考预算 | MAX_THINKING_TOKENS=10000(默认 31,999) |
Extended Thinking 每请求最多预留 31,999 个输出 Token 做内部推理,调低约可削减 ~70% 隐藏成本(README.md、docs/token-optimization.md) |
| 子代理路由到廉价模型 | CLAUDE_CODE_SUBAGENT_MODEL=haiku(若暴露该旋钮) |
Subagent(Task 工具)用 Haiku 跑探索、读文件、跑测试,成本约低 ~80% |
| 按项目禁用无用 MCP 服务器 | 运行 /mcp 关闭,或用 ECC_DISABLED_MCPS |
每个启用的 MCP 服务器都会向上下文加入工具定义;docs/token-optimization.md 提醒每项目启用数尽量控制在 10 个以下,优先用 CLI(gh、aws)替代 MCP |
| 在自然断点手动压缩 | 手动 /compact |
避免等自动压缩在任务中途触发,降低峰值上下文压力(详见第 7 节) |
一个贴合 ECC 推荐的整体配置(加入 ~/.claude/settings.json):
{
"model": "sonnet",
"env": {
"MAX_THINKING_TOKENS": "10000",
"CLAUDE_CODE_SUBAGENT_MODEL": "haiku"
}
}
对应快捷命令:/model sonnet(日常主力)、/model opus(复杂架构推理)、/clear(无关任务之间)、/compact(逻辑断点)、/cost(监控花费)。
6.3 关于 MCP 的补充细节
- 运行时即时开关请使用
/mcp命令(Claude Code 会把运行时禁用持久化在~/.claude.json);不要在.claude/settings.json/.claude/settings.local.json里试图禁用已加载的 MCP 服务器。 ECC_DISABLED_MCPS仅影响 ECC 在安装/同步流程(如install.sh、npx ecc-universal install、Codex MCP 合并)中生成的 MCP 配置输出,不是运行时的 Claude Code 开关。- ECC 自带的
memoryMCP 默认被配置但当前不被任何 skill/agent/hook 使用,可考虑禁用。
7. 纵深:用 strategic-compact 取代"强制压低阈值"
ECC 为"何时压缩"提供了比手动经验更精确的实现:skills/strategic-compact/ 中的 suggest-compact.js 脚本在 PreToolUse(Edit/Write)上运行,综合两个信号给出 /compact 建议:
- 上下文体积(主信号):读取会话转录中最新
usage记录,求和input_tokens + cache_read_input_tokens + cache_creation_input_tokens(该轮的真实上下文大小),并按窗口缩放阈值触发建议——200K 窗口约 160K Token,1M 窗口约 250K Token(从[1m]模型标记检测,或当观测 Token 已超 200K 时推断),之后每再增长 60K Token 重复提醒。 - 工具调用次数(次信号):统计会话内工具调用,默认达到 50 次给出首次建议,此后每 25 次再提醒。
其插件侧注册可见于 hooks/hooks.json:pre:edit-write:suggest-compact(Hook ID 同名字段,激活于 standard 与 strict 档)。相关可调环境变量:
| 变量 | 含义 | 默认 |
|---|---|---|
COMPACT_THRESHOLD |
首次建议前的工具调用次数 | 50 |
COMPACT_CONTEXT_THRESHOLD |
上下文建议触发的 Token 阈值(0 关闭该信号) |
200K 窗口 160000 / 1M 窗口 250000 |
COMPACT_CONTEXT_INTERVAL |
重复提醒的额外 Token 增长量 | 60000 |
COMPACT_STATE_TTL_DAYS |
临时目录中过期会话状态文件的清理天数 | 14 |
ECC_CONTEXT_WINDOW_TOKENS |
显式指定上下文窗口 Token 数,覆盖自动检测 | 未设置 |
CLAUDE_CODE_AUTO_COMPACT_WINDOW |
Claude Code 原生窗口大小覆盖(前项未设时的回退) | 未设置 |
压缩决策速查(何时该压缩 / 何时不该):
- 该压缩:研究 → 规划完成后;里程碑完成后;调试结束、转向新工作前;大上下文切换前。
- 不该压缩:多文件相关改动实现中途;正在调试活跃问题时;多文件重构期间。
压缩前务必把重要状态写入文件或 memory(CLAUDE.md 指令、磁盘文件、Git 状态、memory 文件在压缩后保留;中间推理、已读过的文件内容、多轮对话上下文会丢失)。这条纪律与第 3 节"移除自动压缩覆盖 + 手动断点压缩"互为补充,共同构成 ECC 语境下对抗过早/无序压缩的完整策略。
8. 一张速查表:症状 → 首选动作
| 症状 | 首选动作 | 次选/补充动作 |
|---|---|---|
假 Hook Error |
Hook 开头 input=$(cat) 消费 stdin |
stdout 保持安静;诊断走 stderr;只用 0/2/其他非零对应放行/阻止/错误 |
| 压缩过早 | 移除 CLAUDE_AUTOCOMPACT_PCT_OVERRIDE |
任务边界手动 /compact;用 strategic-compact 提示 |
| MCP 压缩后失效 | 压缩后 toggle 连接器 off/on | 加 PostCompact 提醒 Hook;当作恢复提醒而非永久修复 |
| Hook 不热重载 | 重启 Claude Code 会话 | 用 ECC_* 环境变量做运行时控制,减少改配置频率 |
反复 529 Overloaded |
ENABLE_TOOL_SEARCH=auto:5 |
降 MAX_THINKING_TOKENS;子代理用 haiku;按项目关无用 MCP;手动断点压缩 |
关键原则回顾:上述全部属于上游 Claude Code 行为,ECC 侧的正确动作是"临时规避",等待上游修复;不要用删除/重写 ECC Hook 文件的方式来"修"这些上游问题。若修改过 ECC 安装或 Hook 后出现漂移,可先运行 ecc doctor / ecc repair 这类 ECC 自身的诊断修复命令进行核对(详见 docs/TROUBLESHOOTING.md)。
9. 延伸阅读(仓库内)
- docs/TROUBLESHOOTING.md —— 更完整的 ECC 排障面(本页对应的较完整版本,含 Dashboard、OpenCode/Termux、Cyber Safeguards 等更多主题);
- docs/token-optimization.md —— Token 优化与上下文管理设置详解(含 MCP 管理、成本提示开关);
- hooks/README.md —— ECC 的 Hook 生命周期、退出码约定、运行时环境变量与自定义 Hook 编写规范;
- hooks/hooks.json —— ECC 实际注册的 Hook 图(含
pre:compact、pre:edit-write:suggest-compact等条目); - skills/strategic-compact/ —— 战略压缩技能与其 Hook 实现说明;
- rules/common/hooks.md —— Hook 架构层面规范(PreToolUse/PostToolUse/Stop、权限与 TodoWrite 最佳实践);
- scripts/hooks/ —— 各类 Hook 脚本的实际实现目录;
- README.md —— Token 优化推荐设置与日常命令速查。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00