Skip to content

Hooks 失败也能拦住:onFailure 设为 block ​

团队用 hooks 做门禁:危险命令要过脚本检查,敏感操作要打 HTTP 审批。问题是——钩子自己挂了怎么办?脚本路径错了、服务超时、进程异常退出,旧行为往往是:钩子没跑成,动作照样放行。门禁形同虚设。

CLI 2.1.295 给命令型和 HTTP hooks 加了 onFailure: "block":钩子启动失败、超时、或以非预期退出码结束时,会阻止目标动作,而不是默默放行。

默认放行为什么危险 ​

常见事故链:

  1. 写了 PreToolUse 脚本,禁止未审批的 rm -rf 或生产库写入;
  2. 同事改了脚本路径,或审批服务临时 502;
  3. 钩子起不来或超时,旧逻辑把这当成「没意见」——命令直接执行。

你以为有闸门,实际闸门坏了还开着。CI、无人值守会话尤其危险:没人盯着终端里的钩子报错。

onFailure: "block" 的含义 ​

配置后,下列情况都会拦住动作:

  • 钩子根本启动不了(命令不存在、权限不够、配置写错);
  • 钩子超时;
  • 钩子以非预期退出码结束(具体哪些码算「非预期」,以你 hooks 配置约定为准)。

也就是说:「没检查到」不再等于「可以做」。检查链路不可用时,默认偏安全侧。

示意(字段名以你本机 hooks 配置为准,核心是加上失败即拦):

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "./scripts/check-dangerous-bash.sh",
            "onFailure": "block"
          }
        ]
      }
    ]
  }
}

HTTP 审批类钩子同理:审批服务挂了,宁可先拦,再修服务,也不要静默通过。

适合开、不适合开 ​

适合:

  • 生产目录、密钥、支付相关操作的 PreToolUse;
  • 必须经外部审批才能执行的工具调用;
  • 组织托管设置里的强制门禁(和用户自选钩子不同,失败放行代价更高)。

要谨慎:

  • 本地随便写的辅助钩子(格式化提示、统计)——失败就拦会打断正常工作流;
  • 依赖不稳定外网的非关键钩子——网络抖一下就全停。

原则很简单:这道门坏了是否比误拦更可怕?是,就 block;否,保持默认或修好可靠性再开。

和 2.1.294 指令型 hooks 修复的关系 ​

紧挨着的 2.1.294 修了另一类问题:写成自然语言指令的 prompt / agent hooks(例如「Block commands that…」)有时该拦却没拦住。那是「判断错了」;本次是「钩子挂了还放行」。两条线一起,门禁才靠谱:

  • 指令写对了,真的会拦;
  • 钩子挂了,也可以选择不放行。

同版本还加了终端 Program Status Protocol(OSC 7501):支持该协议的终端能显示 Claude Code 是在工作、等你,还是已结束。和 hooks 无关,但对长时间会话更直观。

小结 ​

  • 2.1.295 起,命令 / HTTP hooks 可设 onFailure: "block"。
  • 启动失败、超时、异常退出时阻止动作,避免「门禁坏了却当通过」。
  • 关键门禁建议打开;非关键辅助钩子按体验权衡。
  • 升级后顺带确认 2.1.294+:指令型 prompt/agent hooks 的拦截判断也更准了。

用 claude --version 确认 ≥ 2.1.295,再给团队真正在意的门禁钩子加上 onFailure: "block",并做一次「故意弄坏脚本路径」的演练,看危险命令是否被拦住。

Claude-cn.org,专注于 Claude Code 中文教程