自动化 · Hooks 让它按规矩来Automate · Hooks Make It Follow the Rules.
有些事你不想靠「希望模型记得」:每次改完自动跑 formatter、提交前必须过 lint、绝不允许它碰生产库、每次收尾发个通知。这些不能是建议,得是规矩。Hooks 就是规矩:它们是你在特定时机(工具调用前后、会话结束时)自动执行的脚本 —— 由 harness 执行,不由模型自觉,所以它跳不过。这一章讲 hooks 能钉住哪些行为、几个真正值得设的(安全闸、质量门、通知),以及它和 CLAUDE.md「叮嘱」的根本区别:一个是请求,一个是硬约束。Some things you don't want to leave to 'hoping the model remembers': run the formatter after every edit, pass lint before every commit, never let it touch the production database, ping you when it wraps up. These can't be suggestions — they have to be rules. Hooks are the rules: scripts that fire automatically at set moments (before/after a tool call, at session end) — executed by the harness, not by the model's goodwill, so it can't skip them. What hooks can pin down, the few genuinely worth setting (a safety gate, a quality gate, a notification), and how they differ fundamentally from a CLAUDE.md reminder: one is a request, the other a hard constraint.
9 分钟 · 初稿 2026.079 Min · Drafted 2026.07
有些事你不想靠「希望模型记得」:每次改完文件跑格式化,提交前必须过 lint,生产配置绝对不许碰,收工时给你发条通知。写进 CLAUDE.md,它十次里九次照做 —— 而这四件事你要的是十次里十次。差的那一次,不能靠更大的字体解决。这一章讲 hooks:不求模型自觉、由 harness 到点必然执行的规矩。Some things you refuse to leave to 'hoping the model remembers': format after every file edit, lint before every commit, never touch production config, ping me when you wrap up. Write them in CLAUDE.md and it complies nine times in ten — but for these four you need ten in ten. The missing tenth can't be fixed with bolder fonts. This chapter is about hooks: rules the harness executes at the appointed moment, no model goodwill required.
— I
请求与规矩的分界线The Line Between a Request and a Rule.
这本书已经两次踩到这条线:第 3 章说记忆是「上下文,不是强制配置」3注 3Note 3Claude Code Docs · Memory —— CLAUDE.md 与 auto memory 是「上下文,不是强制配置」;要不论模型怎么决定都拦住某个动作,用 PreToolUse hook。截至 2026-07-17。Claude Code Docs · Memory — CLAUDE.md and auto memory are 'context, not enforced configuration'; to block an action regardless of what the model decides, use a PreToolUse hook. As of 2026-07-17.,第 4 章说 skill 由模型理解执行、结果可能有出入。hooks 站在线的另一侧 —— 定义原话:「用户定义的 shell 命令、HTTP 端点或 LLM 提示,在 Claude Code 生命周期的特定时点自动执行」。2注 2Note 2Claude Code Docs · Hooks reference —— 定义原话:「hooks 是用户定义的 shell 命令、HTTP 端点或 LLM 提示,在 Claude Code 生命周期的特定时点自动执行」;事件约三十个,含 PreToolUse、PostToolUse、Stop、SessionStart、SessionEnd、Notification、UserPromptSubmit、SubagentStop 等;能力包括拦下工具调用、改写工具输入输出、注入上下文、发通知。截至 2026-07-17。Claude Code Docs · Hooks reference — the definition verbatim: 'hooks are user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code's lifecycle'; roughly thirty events, including PreToolUse, PostToolUse, Stop, SessionStart, SessionEnd, Notification, UserPromptSubmit, and SubagentStop; capabilities include blocking tool calls, rewriting tool input/output, injecting context, and emitting notifications. As of 2026-07-17.关键词是自动:hook 由 harness 在事件上触发,不经过模型的判断,它想跳也跳不过。官方把分工说得很干脆:必须每次发生、零例外的动作,用 hooks;CLAUDE.md 是建议,hooks 是确定。4注 4Note 4Claude Code Docs · Best practices —— 「hooks 用于必须每次发生、零例外的动作」,CLAUDE.md 的指令是建议性的,hooks 才是确定性的;可以直接让 Claude 替你写 hook;Stop hook 把检查设为收工硬门,连续拦 8 次后放行。截至 2026-07-17。Claude Code Docs · Best practices — 'use hooks for actions that must happen every time with zero exceptions'; CLAUDE.md instructions are advisory, hooks are deterministic; you can ask Claude to write the hook for you; a Stop hook gates the end of a turn on your check, releasing after 8 consecutive blocks. As of 2026-07-17.This book has stepped on the line twice already: chapter 3 called memory 'context, not enforced configuration,'3注 3Note 3Claude Code Docs · Memory —— CLAUDE.md 与 auto memory 是「上下文,不是强制配置」;要不论模型怎么决定都拦住某个动作,用 PreToolUse hook。截至 2026-07-17。Claude Code Docs · Memory — CLAUDE.md and auto memory are 'context, not enforced configuration'; to block an action regardless of what the model decides, use a PreToolUse hook. As of 2026-07-17. and chapter 4 said skills are interpreted by the model, so outcomes vary. Hooks stand on the other side — the definition verbatim: 'user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code's lifecycle.'2注 2Note 2Claude Code Docs · Hooks reference —— 定义原话:「hooks 是用户定义的 shell 命令、HTTP 端点或 LLM 提示,在 Claude Code 生命周期的特定时点自动执行」;事件约三十个,含 PreToolUse、PostToolUse、Stop、SessionStart、SessionEnd、Notification、UserPromptSubmit、SubagentStop 等;能力包括拦下工具调用、改写工具输入输出、注入上下文、发通知。截至 2026-07-17。Claude Code Docs · Hooks reference — the definition verbatim: 'hooks are user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code's lifecycle'; roughly thirty events, including PreToolUse, PostToolUse, Stop, SessionStart, SessionEnd, Notification, UserPromptSubmit, and SubagentStop; capabilities include blocking tool calls, rewriting tool input/output, injecting context, and emitting notifications. As of 2026-07-17. The key word is automatically: the harness fires hooks on events, no model judgment in the path — it couldn't skip one if it wanted to. The official division is blunt: actions that must happen every time with zero exceptions go in hooks; CLAUDE.md advises, hooks determine.4注 4Note 4Claude Code Docs · Best practices —— 「hooks 用于必须每次发生、零例外的动作」,CLAUDE.md 的指令是建议性的,hooks 才是确定性的;可以直接让 Claude 替你写 hook;Stop hook 把检查设为收工硬门,连续拦 8 次后放行。截至 2026-07-17。Claude Code Docs · Best practices — 'use hooks for actions that must happen every time with zero exceptions'; CLAUDE.md instructions are advisory, hooks are deterministic; you can ask Claude to write the hook for you; a Stop hook gates the end of a turn on your check, releasing after 8 consecutive blocks. As of 2026-07-17.
— II
装第一条:通知 + 格式化Your First Two: a Notification and a Formatter.
hooks 住在 settings 文件里(~/.claude/settings.json 归你,.claude/settings.json 随仓库),结构三层:事件名 → matcher 筛工具 → 要跑的命令。下面这份配置装了两条最常用的:改完文件自动 prettier,Claude 等你输入时发桌面通知 —— 后者治好的病叫「盯终端」:Hooks live in settings files (~/.claude/settings.json is yours, .claude/settings.json travels with the repo), in three layers: event name → matcher to filter tools → the command to run. This configuration installs the two most common: prettier after every file edit, and a desktop notification when Claude is waiting on you — the latter cures the disease called watching the terminal:
读法:PostToolUse 是「工具跑完之后」这个时点;matcher Edit|Write 表示只在编辑或写文件后触发;命令从 stdin 收到这次事件的 JSON,用 jq 取出文件路径喂给 prettier。1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.不想手写 JSON 也行,这活可以派:直接说「写一个每次编辑后跑 eslint 的 hook」,让 Claude 自己给自己立规矩。4注 4Note 4Claude Code Docs · Best practices —— 「hooks 用于必须每次发生、零例外的动作」,CLAUDE.md 的指令是建议性的,hooks 才是确定性的;可以直接让 Claude 替你写 hook;Stop hook 把检查设为收工硬门,连续拦 8 次后放行。截至 2026-07-17。Claude Code Docs · Best practices — 'use hooks for actions that must happen every time with zero exceptions'; CLAUDE.md instructions are advisory, hooks are deterministic; you can ask Claude to write the hook for you; a Stop hook gates the end of a turn on your check, releasing after 8 consecutive blocks. As of 2026-07-17.装好后用 /hooks 面板核对 —— 它是只读的浏览器,改动仍走 settings 文件。1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.How to read it: PostToolUse is the moment after a tool finishes; the matcher Edit|Write fires only after file edits or writes; the command receives the event's JSON on stdin and uses jq to hand the file path to prettier.1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17. You needn't hand-write the JSON either — delegate it: say 'write a hook that runs eslint after every file edit' and let Claude legislate for itself.4注 4Note 4Claude Code Docs · Best practices —— 「hooks 用于必须每次发生、零例外的动作」,CLAUDE.md 的指令是建议性的,hooks 才是确定性的;可以直接让 Claude 替你写 hook;Stop hook 把检查设为收工硬门,连续拦 8 次后放行。截至 2026-07-17。Claude Code Docs · Best practices — 'use hooks for actions that must happen every time with zero exceptions'; CLAUDE.md instructions are advisory, hooks are deterministic; you can ask Claude to write the hook for you; a Stop hook gates the end of a turn on your check, releasing after 8 consecutive blocks. As of 2026-07-17. Then verify in the /hooks panel — a read-only browser; changes still go through settings files.1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.
— III
时点地图与否决权The Map of Moments, and the Veto.
生命周期上有约三十个可挂的事件,不用全记 —— 先认四个:PreToolUse,动手之前,唯一能拦下动作的时点;PostToolUse,动完之后,放质量动作;Stop,它想收工时,放验收闸;SessionEnd,会话结束,放通知和清理。2注 2Note 2Claude Code Docs · Hooks reference —— 定义原话:「hooks 是用户定义的 shell 命令、HTTP 端点或 LLM 提示,在 Claude Code 生命周期的特定时点自动执行」;事件约三十个,含 PreToolUse、PostToolUse、Stop、SessionStart、SessionEnd、Notification、UserPromptSubmit、SubagentStop 等;能力包括拦下工具调用、改写工具输入输出、注入上下文、发通知。截至 2026-07-17。Claude Code Docs · Hooks reference — the definition verbatim: 'hooks are user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code's lifecycle'; roughly thirty events, including PreToolUse, PostToolUse, Stop, SessionStart, SessionEnd, Notification, UserPromptSubmit, and SubagentStop; capabilities include blocking tool calls, rewriting tool input/output, injecting context, and emitting notifications. As of 2026-07-17.hook 和 harness 的对话协议是退出码:exit 0 放行;exit 2 否决 —— 动作被拦下,你写进 stderr 的理由会交还给 Claude,它读了会调整做法。1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.要更细的裁决(允许、询问、改写输入),exit 0 加一段 stdout JSON。1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.The lifecycle offers roughly thirty attachable events; don't memorize them — meet four: PreToolUse, before the act, the only moment that can block it; PostToolUse, after, for quality actions; Stop, when it wants to finish, for the acceptance gate; SessionEnd, for notification and cleanup.2注 2Note 2Claude Code Docs · Hooks reference —— 定义原话:「hooks 是用户定义的 shell 命令、HTTP 端点或 LLM 提示,在 Claude Code 生命周期的特定时点自动执行」;事件约三十个,含 PreToolUse、PostToolUse、Stop、SessionStart、SessionEnd、Notification、UserPromptSubmit、SubagentStop 等;能力包括拦下工具调用、改写工具输入输出、注入上下文、发通知。截至 2026-07-17。Claude Code Docs · Hooks reference — the definition verbatim: 'hooks are user-defined shell commands, HTTP endpoints, or LLM prompts that execute automatically at specific points in Claude Code's lifecycle'; roughly thirty events, including PreToolUse, PostToolUse, Stop, SessionStart, SessionEnd, Notification, UserPromptSubmit, and SubagentStop; capabilities include blocking tool calls, rewriting tool input/output, injecting context, and emitting notifications. As of 2026-07-17. The hook-to-harness protocol is exit codes: exit 0 proceeds; exit 2 vetoes — the action is blocked and the reason you wrote to stderr is handed back to Claude, which reads it and adjusts.1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17. For finer rulings (allow, ask, rewrite the input), exit 0 plus a JSON verdict on stdout.1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.PreToolUse 有一个值得单独记住的性质:它跑在权限模式检查之前 —— 一条返回 deny 的 hook,连 bypassPermissions 模式也拦得住。1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.这意味着 hooks 是比权限模式更硬的一层:模式管的是「问不问你」,hook 管的是「许不许做」。第 2 章那句「信不过的点用规矩钉死」,钉子就是它。PreToolUse has one property worth remembering on its own: it runs before the permission-mode check — a hook that returns deny blocks the call even under bypassPermissions.1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17. That makes hooks a harder layer than modes: modes govern whether you get asked; hooks govern whether it's allowed at all. Chapter 2's 'pin the points you don't trust with rules' — this is the pin.
— IV
真值得设的三类:安全闸、质量门、通知The Three Worth Setting: Safety Gate, Quality Gate, Notification.
别一口气挂三十个事件。多数人长期真正在用的是三类:Don't festoon all thirty events. What most people actually keep running is three kinds:
改完跑 lint;检查不过不许收工Lint after edits; no finishing until the check passes
通知Notification
Notification / SessionEnd
等输入、收工时提醒你,人离开终端Ping you when it waits or wraps — you leave the terminal
安全闸的写法在文档里就有现成样:一个脚本核对目标路径,命中保护清单就 exit 2 并在 stderr 里说明为什么 —— Claude 收到理由,换路走。1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17.质量门的顶配是 Stop hook,第 9 章已经预告过:收工前跑你的检查,不过不放行;也记得它的边界 —— 连续拦 8 次后 harness 会放行,它是门,不是牢,兜底仍在测试和 CI。4注 4Note 4Claude Code Docs · Best practices —— 「hooks 用于必须每次发生、零例外的动作」,CLAUDE.md 的指令是建议性的,hooks 才是确定性的;可以直接让 Claude 替你写 hook;Stop hook 把检查设为收工硬门,连续拦 8 次后放行。截至 2026-07-17。Claude Code Docs · Best practices — 'use hooks for actions that must happen every time with zero exceptions'; CLAUDE.md instructions are advisory, hooks are deterministic; you can ask Claude to write the hook for you; a Stop hook gates the end of a turn on your check, releasing after 8 consecutive blocks. As of 2026-07-17.The safety gate has a ready template in the docs: a script checks the target path and, on hitting the protected list, exits 2 with the why on stderr — Claude receives the reason and routes around.1注 1Note 1Claude Code Docs · Hooks guide —— hooks 提供确定性控制,「保证某些动作必然发生,而不是依赖 LLM 选择去做」。配置放 settings 文件的 hooks 块:事件名 → matcher(如 Edit|Write)→ type: command 的命令;/hooks 面板只读浏览,增改要编辑 settings 或让 Claude 代写。协议:事件数据以 JSON 进 stdin;exit 0 放行,exit 2 拦下且 stderr 作为反馈交还给 Claude 让它调整;更复杂的决定用 exit 0 + stdout JSON(如 PreToolUse 的 permissionDecision: deny)。PreToolUse 在权限模式检查之前执行 —— 返回 deny 的 hook 连 bypassPermissions 也拦得住。示例即文档所载:PostToolUse 用 jq 取 file_path 交给 prettier;PreToolUse 脚本对 .env、.git/ 等保护路径 exit 2。截至 2026-07-17。Claude Code Docs · Hooks guide — hooks provide deterministic control, 'ensuring certain actions always happen rather than relying on the LLM to choose to run them.' Configuration lives in a settings file's hooks block: event name → matcher (e.g. Edit|Write) → a type: command entry; the /hooks panel is read-only — add or change by editing settings or asking Claude to write it. Protocol: event data arrives as JSON on stdin; exit 0 proceeds, exit 2 blocks with stderr fed back to Claude so it can adjust; richer decisions use exit 0 + JSON on stdout (e.g. PreToolUse's permissionDecision: deny). PreToolUse runs before permission-mode checks — a hook that denies blocks the call even under bypassPermissions. The examples are the docs' own: PostToolUse piping file_path via jq to prettier; a PreToolUse script exiting 2 on protected paths like .env and .git/. As of 2026-07-17. The quality gate's top form is the Stop hook, previewed in chapter 9: run your check before it finishes, no pass no release — and remember its boundary too: after 8 consecutive blocks the harness releases, so it's a gate, not a jail; the backstop remains tests and CI.4注 4Note 4Claude Code Docs · Best practices —— 「hooks 用于必须每次发生、零例外的动作」,CLAUDE.md 的指令是建议性的,hooks 才是确定性的;可以直接让 Claude 替你写 hook;Stop hook 把检查设为收工硬门,连续拦 8 次后放行。截至 2026-07-17。Claude Code Docs · Best practices — 'use hooks for actions that must happen every time with zero exceptions'; CLAUDE.md instructions are advisory, hooks are deterministic; you can ask Claude to write the hook for you; a Stop hook gates the end of a turn on your check, releasing after 8 consecutive blocks. As of 2026-07-17.动手 · 一晚上装齐三类:Hands-on · install all three kinds in an evening:
装上面的通知 hook,从此让终端叫你,而不是你守终端。Install the notification hook above — from now on the terminal calls you, not the other way.
把你仓库里最不可碰的路径(.env、migrations)写成 PreToolUse 安全闸,亲手触发一次确认它真拦。Turn your repo's most untouchable paths (.env, migrations) into a PreToolUse gate, and trip it once yourself to confirm it really blocks.
把第 9 章那条验收检查升级成 Stop hook —— 从「你记得看」变成「不过不收工」。Promote chapter 9's acceptance check into a Stop hook — from 'you remember to look' to 'no pass, no finish.'
叮嘱是请求,
hook 是规矩.
A reminder is a request;
a hook is a rule.
Aklman Library
— 讨论Discussion
讨论Discussion.
评论区初始化中…Initializing comments…
01 / 01
没有匹配结果No matches.
换个关键词,或按 Esc 回到页面Try another keyword, or press Esc to return