hooks-development

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Hooks Development

Hooks开发

Guide for developing Claude Code hooks with proper output visibility patterns.
关于开发具有正确输出可见性模式的Claude Code Hooks的指南。

When to Use This Skill

何时使用该技能

  • Creating a new PostToolUse or PreToolUse hook
  • Hook output is not visible to Claude (most common issue)
  • User asks about
    decision: block
    pattern
  • Debugging why hook messages don't appear
  • User mentions "Claude Code hooks" or "hook visibility"

  • 创建新的PostToolUse或PreToolUse Hook
  • Hook输出对Claude不可见(最常见问题)
  • 用户询问
    decision: block
    模式
  • 调试Hook消息不显示的原因
  • 用户提及“Claude Code Hooks”或“Hook可见性”

Quick Reference: Visibility Patterns

快速参考:可见性模式

Critical insight: PostToolUse hook stdout is only visible to Claude when JSON contains
"decision": "block"
.
Output FormatClaude Visibility
Plain textNot visible
JSON without
decision: block
Not visible
JSON with
decision: block
Visible
Exit code behavior:
Exit Codestdout BehaviorClaude Visibility
0JSON parsed, shown in verbose mode onlyOnly if
"decision": "block"
2Ignored, uses stderr insteadstderr shown to Claude
Otherstderr shown in verbose modeNot shown to Claude

关键要点:只有当JSON中包含
"decision": "block"
时,PostToolUse Hook的标准输出才会对Claude可见。
输出格式对Claude的可见性
纯文本不可见
不含
decision: block
的JSON
不可见
decision: block
的JSON
可见
退出码行为
退出码标准输出行为对Claude的可见性
0JSON被解析,仅在详细模式下显示仅当包含
"decision": "block"
时可见
2被忽略,改用标准错误输出标准错误输出会显示给Claude
其他标准错误输出在详细模式下显示不会显示给Claude

Minimal Working Pattern

最简可用模式

bash
/usr/bin/env bash << 'SKILL_SCRIPT_EOF'
#!/usr/bin/env bash
set -euo pipefail
bash
/usr/bin/env bash << 'SKILL_SCRIPT_EOF'
#!/usr/bin/env bash
set -euo pipefail

Read hook payload from stdin

Read hook payload from stdin

PAYLOAD=$(cat) FILE_PATH=$(echo "$PAYLOAD" | jq -r '.tool_input.file_path // empty')
[[ -z "$FILE_PATH" ]] && exit 0
PAYLOAD=$(cat) FILE_PATH=$(echo "$PAYLOAD" | jq -r '.tool_input.file_path // empty')
[[ -z "$FILE_PATH" ]] && exit 0

Your condition here

Your condition here

if [[ condition_met ]]; then jq -n
--arg reason "[HOOK] Your message to Claude"
'{decision: "block", reason: $reason}' fi
exit 0 SKILL_SCRIPT_EOF

**Key points**:

1. Use `jq -n` to generate valid JSON
2. Include `"decision": "block"` for visibility
3. Exit with code 0
4. The "blocking error" label is cosmetic - operation continues

---
if [[ condition_met ]]; then jq -n
--arg reason "[HOOK] Your message to Claude"
'{decision: "block", reason: $reason}' fi
exit 0 SKILL_SCRIPT_EOF

**关键点**:

1. 使用`jq -n`生成有效的JSON
2. 包含`"decision": "block"`以确保可见性
3. 以退出码0退出
4. “blocking error”标签仅为装饰性 - 操作会继续执行

---

TodoWrite Templates

TodoWrite模板

Creating a PostToolUse Hook

创建PostToolUse Hook

markdown
1. [pending] Create hook script with shebang and set -euo pipefail
2. [pending] Parse PAYLOAD from stdin with jq
3. [pending] Add condition check for when to trigger
4. [pending] Output JSON with decision:block pattern
5. [pending] Register hook in hooks.json with matcher
6. [pending] Test by editing a matching file
7. [pending] Verify Claude sees the message in system-reminder
markdown
1. [待处理] 创建带有shebang和set -euo pipefail的Hook脚本
2. [待处理] 使用jq从标准输入解析PAYLOAD
3. [待处理] 添加触发条件检查
4. [待处理] 输出带有decision:block模式的JSON
5. [待处理] 在hooks.json中通过匹配器注册Hook
6. [待处理] 通过编辑匹配文件进行测试
7. [待处理] 验证Claude在system-reminder中能看到消息

Debugging Invisible Hook Output

调试不可见的Hook输出

markdown
1. [pending] Verify hook executes (add debug log to /tmp)
2. [pending] Check JSON format is valid (pipe to jq .)
3. [pending] Confirm decision:block is present in output
4. [pending] Verify exit code is 0
5. [pending] Check hooks.json matcher pattern
6. [pending] Restart Claude Code session

markdown
1. [待处理] 验证Hook是否执行(向/tmp添加调试日志)
2. [待处理] 检查JSON格式是否有效(通过管道传递给jq .)
3. [待处理] 确认输出中包含decision:block
4. [待处理] 验证退出码为0
5. [待处理] 检查hooks.json中的匹配器模式
6. [待处理] 修改Hook后重启Claude Code会话

Reference Documentation

参考文档

  • Lifecycle Reference - All 10 hook events, diagrams, use cases, configuration pitfalls
  • Visibility Patterns - Full exit code and JSON schema details
  • Hook Templates - Copy-paste templates for common patterns
  • Debugging Guide - Troubleshooting invisible output

  • 生命周期参考 - 全部10种Hook事件、图表、使用场景、配置陷阱
  • 可见性模式 - 完整的退出码和JSON架构细节
  • Hook模板 - 可直接复制粘贴的常见模式模板
  • 调试指南 - 排查不可见输出问题的指南

Post-Change Checklist (Self-Evolution)

变更后检查清单(自我演进)

When this skill is updated:
  • Update evolution-log.md with discovery
  • Verify code examples still work
  • Check if ADR needs updating: PostToolUse Hook Visibility ADR

当本技能更新时:
  • evolution-log.md中记录更新内容
  • 验证代码示例仍可正常工作
  • 检查是否需要更新ADR:PostToolUse Hook可见性ADR

Related Resources

相关资源



Troubleshooting

故障排查

IssueCauseSolution
Hook output not visibleMissing decision:block in JSONAdd
"decision": "block"
to JSON output
JSON parse error in hookInvalid JSON syntaxUse
jq -n
to generate valid JSON
Hook not executingWrong matcher patternCheck hooks.json matcher regex matches tool name
Plain text output ignoredOnly JSON parsedWrap output in JSON with decision:block
Exit code 2 behaviorstderr used instead of stdoutUse exit 0 with JSON, or exit 2 for stderr messages
Session not seeing changesHooks cachedRestart Claude Code session after hook changes
Verbose mode not showingDisabled by defaultEnable verbose mode in Claude Code settings
jq command not foundjq not installed
brew install jq
问题原因解决方案
Hook输出不可见JSON中缺少decision:block在JSON输出中添加
"decision": "block"
Hook中出现JSON解析错误JSON语法无效使用
jq -n
生成有效的JSON
Hook未执行匹配器模式错误检查hooks.json中的匹配器正则表达式是否匹配工具名称
纯文本输出被忽略仅解析JSON将输出包装在带有decision:block的JSON中
退出码2的行为使用标准错误输出而非标准输出使用退出码0并输出JSON,或使用退出码2输出标准错误消息
会话未看到变更Hooks被缓存修改Hook后重启Claude Code会话
详细模式未显示默认处于禁用状态在Claude Code设置中启用详细模式
jq命令未找到未安装jq
brew install jq