Hook 退出码裁决台
Hook 的退出码是它的语言:0 放行、2 拦截且 stderr 成为给模型的理由、其余非零是非阻断错误——动作照常继续(fail-open)。切一条命令和一个脚本出口,看 block-rm.sh 这道 rm 防线怎么裁决:exit 2 是唯一拦截码、连 JSON 的 allow 都压不过;而机器上没装 jq 时,脚本表面正常收工,防线已经敞开。
纯前端确定性模拟:预设 block-rm.sh(stdin 收事件 JSON → grep rm -rf → exit 2 / exit 0),退出码语义、JSON 决定优先级与 fail-open 哲学逐字对齐知识库《Hooks:事件驱动的确定性控制》动手节十五行 rm 防线,零 API、零随机。
预设一条 PreToolUse Bash hook:block-rm.sh——从标准输入拿事件详情, 命令含 rm -rf 就 exit 2 并把理由写到 stderr,否则 exit 0。切一条命令和一个脚本出口,单步看这次 Hook 怎么裁决—— 重点盯「未装 jq」:脚本表面正常,防线已经敞开。
.claude/hooks/block-rm.sh · 十五行的 rm 防线
挂在 PreToolUse · matcher: Bash#!/bin/bashinput=$(cat) # stdin:事件详情 JSONcommand=$(echo "$input" | jq -r '.tool_input.command')if echo "$command" | grep -q 'rm -rf'; then echo "拦截:rm -rf 禁止执行(红线规则)" >&2 exit 2 # 退出码 2 = 拦截,stderr 是给模型的理由fiexit 0 # 放行,其余走正常权限流
高亮行是本次执行的分支走向;把鼠标悬在行上看每行的角色。
① 命令内容(工具调用)红线命令:block-rm.sh 的 grep -q 'rm -rf' 等的就是它——防线存在的意义
② 脚本出口(脚本运行时发生了什么)四个出口互相独立,与命令任意组合
③ stdout JSON 输出exit 0 的 stdout 若为合法 JSON,读取结构化决定
单步流水 · 一次 Hook 裁决的四步
拦截 · 理由回填模型① stdin · 事件详情通过 · Claude Code → 脚本
事件详情以 JSON 从标准输入喂给脚本:工具名、完整参数(含命令文本)都在里面
{"tool_name":"Bash","tool_input":{"command":"rm -rf /tmp/x"}}② 脚本分支 · block-rm.sh命中 · grep -q 'rm -rf'
命令文本命中 rm -rf——走拦截行:stderr 写理由,exit 2
③ 退出码命中 · exit 2 · 拦截
退出码 2:该事件的行为被阻止,stderr 成为给模型的拦截理由
exit 2 stderr: 拦截:rm -rf 禁止执行(红线规则)
④ 终局命中 · 拦截 · 理由回填模型
拦截 · 理由回填模型——工具调用在执行前被拒,模型收到 stderr 里的理由并会另想办法(比如改用更精确的删除路径)。
退出码表 · Hook 的语言,三种出口一张表记住
| 退出码 | 含义 | 动作走向 | 给模型的反馈 |
|---|---|---|---|
| 0 | 成功/放行 | 继续执行 | stdout 是 JSON 则读取结构化决定;部分事件纯文本会进上下文 |
| 2 | 拦截 | 该事件的行为被阻止(连 JSON allow 也压不过) | stderr 成为拦截理由 |
| 其他非零 | 脚本出错 | 无有效 JSON 输出时动作照常继续(fail-open),界面显示 hook error;若 stdout 带合法 JSON 决定,仍按 JSON 裁决 | 转写进调试日志 |
exit 2 是唯一拦截码0 放行、2 拦截、其余非零记为非阻断错误——且 exit 2 连 stdout 里 JSON 的 allow 都压不过:这是「机器说了算」的最后保障,别在脚本里输出互相矛盾的决定。
崩溃默认放行退出码非 0 非 2 时动作照常进行,只显示一条 hook error——拦截脚本自己崩了,防线是敞开的。这是 fail-open:系统宁可放过错报,也不让一个坏脚本卡死整场会话。
安全脚本要显式 fail-closed把「任何意外都退出 2」写成显式逻辑:解析失败或变量为空就 exit 2,把失败关在门外——未装 jq 的坑就是这么漏的。格式化类脚本则可以接受 fail-open:格式化失败不该拦住写文件。
与权限工具分工「权限裁决漏斗」和「Headless 权限矩阵」裁决的是权限系统——Hook 只是多层漏斗里的一关;本工具把 Hook 本体拆开:退出码这台裁决机自己怎么工作、崩了之后系统怎么兜。