Devotd Github
新发现评测

second-time-is-a-bug-book/book-companion — 钩子 fail closed 修正

second-time-is-a-bug-book/book-companion 文档化的 Cursor 钩子包装示例已改为 fail-closed 形式,只在退出码为 0 时才允许。

仓库信息second-time-is-a-bug-book/book-companion ↗

second-time-is-a-bug-book/book-companion 文档化的 Cursor 钩子包装示例已改为 fail-closed 形式,只在退出码为 0 时才允许。

GitHub 项目说明: Companion code for the book "The Second Time Is A Bug"

星标
★ 2
复刻
0
语言
TypeScript
许可证
MIT
查看原始来源 ↗在 GitHub 查看 ↗

second-time-is-a-bug-book/book-companion 是收录书籍《The Second Time Is A Bug》示例代码的仓库。2026 年 10 月 27 日的提交 b0a04d5 只改动了一个文件 docs/tool-wiring.md(新增 4 行,删除 4 行)。其内容是颠倒了包裹 Cursor 钩子的 shell 包装示例的判定顺序。以前守卫只在退出码为 2 时拒绝,其余情况一律放行;现在只在退出码为 0 时允许,其他所有情况都拒绝。

钩子(hook)是 Cursor 的一项功能,在智能体执行 shell 命令之前插入用户编写的脚本,用来判断是允许还是拒绝。文档说明在 .cursor/hooks.json 中设置 "version": 1,当 preToolUse 匹配到 Shell 时传入 tool_input.command,beforeShellExecution 传入 command。退出码 2 默认会阻止,但如果钩子没有指定 "failClosed": true,脚本崩溃或超时时会转为放行。示例调用 guards/destructive-command.ts 来检查命令,并以 JSON 输出判断结果,但文档并未说明输出不是合法 JSON 时会被阻止,也未说明空输出会被允许。因此该示例需要 jq。

颠倒判定的理由很简单。在「不是 2 就允许」的规则下,脚本失败反而会让执行通过;而在「不是 0 就拒绝」的规则下,失败本身就导致阻止。文档因此建议同时在钩子上指定 failClosed。不过,实际的守卫脚本并不在这个仓库里。注释中也写明 .cursor/hooks/guard.sh 是简写示例,不包含在此仓库中。能够确认的只是文档所主张的配置方向发生了变化;钩子实际如何运作,仅凭这一次提交还无法判断。依据是 GitHub 提交 b0a04d5(2026-10-27)。