跳转至

ECC Hook 修复 — 2026-04-21

摘要

Windows 上的 Claude Code CLI v2.1.116 所有 Bash 工具 Hook 调用均失败,报错:

PreToolUse:Bash hook error
Failed with non-blocking status code:
C:\Program Files\Git\bin\bash.exe: C:\Program Files\Git\bin\bash.exe:
cannot execute binary file

PostToolUse:Bash hook error  (同上)

结果:observations.jsonl 在 2026-04-20T23:03:38Z 之后停止更新(最后一条记录是之前 stdin 带 BOM 问题导致的 parse_error)。

根本原因

C:\Users\sugig\.claude\settings.local.json 存在两个缺陷:

缺陷 1 — UTF-8 BOM + CRLF 行尾

文件以 EF BB BF(UTF-8 BOM)开头,并使用 CRLF 行结束符。 这是 PowerShell ConvertTo-Json | Out-File 的默认行为,也是 patch_settings_cl_v2_simple.ps1 重写文件后留下的结果。

00000000: efbb bf7b 0d0a 2020 2020 2268 6f6f 6b73  ...{..    "hooks

缺陷 2 — 双重包装的 bash.exe 调用

命令字符串显式再次调用了 bash.exe:

"command": "\"C:\\Program Files\\Git\\bin\\bash.exe\" \"C:\\Users\\sugig\\.claude\\skills\\continuous-learning\\hooks\\observe-wrapper.sh\""

当 Claude Code 在 Windows 上启动该命令时,参数拆分无法正确保留 带引号的 "C:\Program Files\..." 标记。Program Files 中的空格会拆分 argv[0],导致 bash.exe 最终把自己当作脚本文件传入,产生:

bash.exe: bash.exe: cannot execute binary file

之前可用的形态(供参考)

在 patch_settings_cl_v2_simple.ps1 运行之前,命令只是:

"command": "C:\\Users\\sugig\\.claude\\skills\\continuous-learning\\hooks\\observe.sh"

Windows 上的 Claude Code 会检测 .sh 并通过 Git Bash 本身调用它——无需 手动包装 bash.exe。

修复

C:\Users\sugig\.claude\settings.local.json 已重写为 UTF-8(无 BOM)、LF 行尾,命令直接指向包装器 .sh,并将 Hook 阶段作为普通参数传入:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "C:/Users/sugig/.claude/skills/continuous-learning/hooks/observe-wrapper.sh pre"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "C:/Users/sugig/.claude/skills/continuous-learning/hooks/observe-wrapper.sh post"
          }
        ]
      }
    ]
  }
}

附带好处:pre / post 参数现在会路由到 observe.sh 的 HOOK_PHASE 变量,因此事件会被正确记录为 tool_start 或 tool_complete(之前所有事件都被记录为 tool_complete)。

验证

直接调用新命令格式,模拟两个 Hook 阶段:

# PostToolUse path
echo '{"tool_name":"Bash","tool_input":{"command":"pwd"},"session_id":"post-fix-verify-001","cwd":"...","hook_event_name":"PostToolUse"}' \
  | "C:/Users/sugig/.claude/skills/continuous-learning/hooks/observe-wrapper.sh" post
# exit=0

# PreToolUse path
echo '{"tool_name":"Bash","tool_input":{"command":"ls"},"session_id":"post-fix-verify-pre-001","cwd":"...","hook_event_name":"PreToolUse"}' \
  | "C:/Users/sugig/.claude/skills/continuous-learning/hooks/observe-wrapper.sh" pre
# exit=0

observations.jsonl 新增:

{"timestamp":"2026-04-21T05:57:54Z","event":"tool_complete","tool":"Bash","session":"post-fix-verify-001",...}
{"timestamp":"2026-04-21T05:57:55Z","event":"tool_start","tool":"Bash","session":"post-fix-verify-pre-001","input":"{\"command\":\"ls\"}",...}

两个阶段现在都会生成类型正确的事件。

关于实时 CLI 验证的说明: 设置更改会在下一次 claude CLI 会话启动时生效。重启 CLI 并运行一次 Bash 工具调用,以确认 实际 CLI 会话在 observations.jsonl 中出现新行。

涉及文件

  • C:\Users\sugig\.claude\settings.local.json — 已重写
  • C:\Users\sugig\.claude\settings.local.json.bak-hookfix-20260421-145718 — 修复前备份

已知上游 Bug(此处未修复)

  • install_hook_wrapper.ps1 — 在步骤 [3/4] 处停止,从未到达 [4/4]。
  • patch_settings_cl_v2_simple.ps1 — 会用 UTF-8-BOM + CRLF 覆盖 settings.local.json,并重新引入双重包装的 bash.exe 命令。 应替换为输出 UTF-8(无 BOM)、LF 和直接 .sh 路径的补丁程序。

分支

claude/hook-fix-20260421

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC