大模型应用
在 Claude Code 中开发/调试 hooks 时…
当需要为 Claude Code 创建、注册、调试或测试 hooks,并确保阻断、上下文注入和自动化行为正确时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 Claude Code 中开发/调试特定
解决思路
- 根据事件用途选择 hook:PreToolUse 在工具执行前触发,可阻断,用于阻断/修改工具调用。
- PostToolUse 在工具完成后触发,可部分阻断,用于响应工具结果。
- UserPromptSubmit 在用户发送提示时触发,可阻断,用于验证/注入上下文。
- PermissionRequest 在权限对话框显示时触发,可阻断,用于自动批准/拒绝。
- SessionStart 在会话开始时触发,不可阻断,用于加载上下文、设置环境变量。
- SessionEnd 在会话结束时触发,不可阻断,用于清理/保存状态。
- Stop 在 agent 完成时触发,可阻断,用于强制继续。
- SubagentStart 在子代理生成时触发,不可阻断,用于模式协调。
- SubagentStop 在子代理完成时触发,可阻断,用于强制继续。
- PreCompact 在压缩前触发,不可阻断,用于保存状态。
- Notification 在通知发送时触发,不可阻断,用于自定义提醒。
- 选择 hook 类型:type 为 "command" 时执行 bash;type 为 "prompt" 时使用 LLM 评估。
- PreToolUse 输入解析字段:session_id、transcript_path、cwd、permission_mode、hook_event_name、tool_name、tool_input、tool_use_id。
- PreToolUse 输出 JSON 使用 hookSpecificOutput.hookEventName="PreToolUse"、permissionDecision="allow|deny|ask"、permissionDecisionReason、updatedInput,并可包含 continue、stopReason、systemMessage、suppressOutput。
- PreToolUse 用 exit code 2 阻断工具,stderr 展示给 Claude。
- PreToolUse 常用 matchers:Bash、Edit|Write、Read、Task、mcp__.*。
- PostToolUse 输入中响应字段是 tool_response,不是 tool_result;其中可包含 filePath、success、output、exitCode。
- PostToolUse 输出 JSON 可设置 decision="block"、reason、hookSpecificOutput.hookEventName="PostToolUse"、additionalContext、continue、stopReason、suppressOutput。
- PostToolUse 用 "decision": "block" 加 "reason" 提示 Claude 解决问题。
- PostToolUse 常用 matchers:Edit|Write、Bash。
- UserPromptSubmit 输入解析字段:prompt。
- UserPromptSubmit 纯文本 stdout 会加入 Claude 上下文。
- UserPromptSubmit 输出 JSON 可设置 decision="block"、reason、hookSpecificOutput.hookEventName="UserPromptSubmit"、additionalContext。
- UserPromptSubmit 的 "decision": "block" 会擦除 prompt,只向用户显示 reason,不向 Claude 显示。
- UserPromptSubmit 用 exit code 2 阻断 prompt,只向用户显示 stderr。
- PermissionRequest 输入解析 tool_name、tool_input 等;输出 hookSpecificOutput.hookEventName="PermissionRequest"、decision.behavior="allow|deny"、updatedInput、message、interrupt。
- SessionStart 输入解析 source="startup|resume|clear|compact";使用 CLAUDE_ENV_FILE 写入 export VAR=value 以持久化环境变量。
- SessionStart 输出纯文本或 JSON;纯文本 stdout 作为上下文;JSON 可包含 hookSpecificOutput.hookEventName="SessionStart"、additionalContext、suppressOutput。
- SessionEnd 输入解析 reason="clear|logout|prompt_input_exit|other";不能影响会话,仅用于清理。
- Stop 输入解析 stop_hook_active;必须检查 stop_hook_active: true 以防止无限循环。
- Stop 输出 "decision": "block" 和 "reason" 强制 Claude 继续,reason 作为提示。
- SubagentStart 输入解析 agent_id;仅能注入上下文,不能阻断。
- SubagentStop 输入解析 stop_hook_active;输出同 Stop。
- PreCompact 输入解析 trigger="manual|auto"、custom_instructions;matchers 为 manual、auto;输出 continue、systemMessage。
- Notification 输入解析 message、notification_type="permission_prompt|idle_prompt|auth_success|elicitation_dialog";matchers 为 permission_prompt、idle_prompt、auth_success、elicitation_dialog、*;输出 continue、suppressOutput、systemMessage。
- 在 settings.json 中注册 hooks:使用 {"hooks":{"EventName":[{"matcher":"ToolPattern","hooks":[{"type":"command","command":"$CLAUDE_PROJECT_DIR/.claude/hooks/my-hook.sh","timeout":60}]}]}}。
- Matcher 模式:Bash 精确匹配 Bash 工具;Edit|Write 匹配 Edit 或 Write;Read.* 正则匹配 Read*;mcp__.*__write.* 匹配 MCP 写入工具;* 匹配所有工具。
- Matcher 大小写敏感:Bash 不等于 bash。
- 需要 matcher 的事件:PreToolUse、PostToolUse、PermissionRequest、Notification(可选)、SessionStart(startup|resume|clear|compact)、PreCompact(manual|auto)。
- 不需要 matcher 的事件可直接在 hooks 数组中注册 command,例如 UserPromptSubmit。
- Command hooks 使用 type: "command",执行 bash 命令或脚本,并指定 command、timeout。
- Prompt-based hooks 使用 type: "prompt",用 LLM(Haiku)做上下文感知决策,最适合 Stop/SubagentStop;指定 prompt、timeout;prompt 中可用 $ARGUMENTS;响应 schema 包含 decision="approve"|"block"、reason、continue、stopReason、systemMessage。
- MCP 工具命名使用 mcp__<server>__<tool>;例如 mcp__memory__.*、mcp__.*__write.*、mcp__github__.*。
- 所有 hooks 可用环境变量:CLAUDE_PROJECT_DIR、CLAUDE_CODE_REMOTE;CLAUDE_CODE_REMOTE 为 "true" 表示 remote/web,空表示 local CLI。
- SessionStart 专用环境变量:CLAUDE_ENV_FILE,用于写入 export VAR=value 行。
- Plugin hooks 专用环境变量:CLAUDE_PLUGIN_ROOT,插件目录绝对路径。
- 退出码 0:成功,处理 JSON,忽略 stderr。
- 退出码 2:阻断错误,stdout 被忽略,stderr 作为错误消息。
- 其他退出码:非阻断错误,忽略 stdout,stderr 在 verbose 模式显示。
- 按 hook 使用 exit code 2:PreToolUse 阻断工具,stderr 给 Claude;PostToolUse stderr 给 Claude(工具已运行);UserPromptSubmit 阻断 prompt,stderr 只给用户;Stop 阻断停止,stderr 给 Claude。
- Shell wrapper 模式:bash 脚本中 set -e,cd "$CLAUDE_PROJECT_DIR/.claude/hooks",cat | npx tsx src/my-hook.ts;或 bundled 时 cd "$HOME/.claude/hooks",cat | node dist/my-hook.mjs。
- TypeScript handler 模式:定义 HookInput 接口,readStdin 使用 readFileSync(0, 'utf-8'),main 中 JSON.parse(readStdin()),处理输入后用 console.log(JSON.stringify(output)),并 main().catch(console.error)。
- 手动测试 hooks:用 echo JSON 管道输入脚本,例如 PostToolUse (Write)、PreToolUse (Bash)、SessionStart、SessionEnd、UserPromptSubmit 的命令。
- TypeScript 编辑后重建:cd .claude/hooks;npx esbuild src/my-hook.ts --bundle --platform=node --format=esm --outfile=dist/my-hook.mjs。
- 阻止危险文件(PreToolUse)模式:Python 读取 stdin,取 tool_input.file_path,若包含 .env、secrets.json、.git/ 则输出 JSON hookSpecificOutput.hookEventName="PreToolUse"、permissionDecision="deny"、permissionDecisionReason,否则输出 {}。
- 自动格式化文件(PostToolUse)模式:bash 读取 INPUT,用 jq -r '.tool_input.file_path // empty' 取文件路径,若为 .ts 或 .tsx 则 npx prettier --write "$FILE" 2>/dev/null,最后 echo '{}'。
- 注入 Git 上下文(UserPromptSubmit)模式:bash 输出 Git status 和 Recent commits,使用 git status --short 与 git log --oneline -5,失败时输出 fallback。
- 强制测试验证(Stop)模式:Python 读取 stdin,若 stop_hook_active 则输出 {} 并退出;运行 npm test,若 returncode != 0 输出 "decision": "block"、"reason": "Tests are failing. Please fix before stopping.",否则输出 {}。
- 调试清单:检查 hook 是否注册在 settings.json。
- 调试清单:检查 shell 脚本有 +x 权限。
- 调试清单:TS 变更后重新构建 bundle。
- 调试清单:使用 tool_response 而不是 tool_result。
- 调试清单:输出是有效 JSON 或纯文本。
- 调试清单:Stop hooks 中检查 stop_hook_active。
- 调试清单:路径使用 $CLAUDE_PROJECT_DIR。
- 关键学习:字段名重要,tool_response 不是 tool_result。
- 关键学习:阻断输出格式使用 "decision": "block" 加 "reason"。
- 关键学习:exit code 2 的 stderr 去 Claude/用户,stdout 被忽略。
- 关键学习:重建 bundles,TypeScript 源码编辑不会自动生效。
- 关键学习:手动测试,先用 echo '{}' | ./hook.sh 再依赖。
- 关键学习:先检查输出,编辑代码前 ls .claude/cache/。
- 关键学习:detached spawn 隐藏错误,添加 logging 调试。
- 参考 /debug-hooks 调试工作流和 .claude/rules/hooks.md hook 开发规则。
适用边界 · 注意事项
- 非 Claude Code 环境或未启用 hooks 的项目不适用。
- 无法在 settings.json 注册 hooks、不能执行 shell,或不能使用 LLM prompt 的受限/沙箱环境不适用。
- 需要与其他 agent 框架 hook 完全兼容的场景不适用,因为 schema、事件名和退出码语义不同。