claude-hook-writer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClaude Hook Writer
Claude Hook 编写指南
Status: Production Ready
Version: 2.0.0 (Optimized with progressive disclosure)
Last Updated: 2025-12-17
状态:可用于生产环境
版本:2.0.0(采用渐进式披露优化)
最后更新:2025-12-17
Overview
概述
Expert guidance for writing secure, reliable, and performant Claude Code hooks. This skill validates design decisions, enforces best practices, and prevents common pitfalls.
这是编写安全、可靠且高性能Claude Code hooks的专业指南。该指南可验证设计决策、推行最佳实践并避免常见陷阱。
When to Use This Skill
适用场景
- Designing a new Claude Code hook
- Reviewing existing hook code
- Debugging hook failures
- Optimizing slow hooks
- Securing hooks that handle sensitive data
- Publishing hooks as PRPM packages
- 设计新的Claude Code hook
- 审核现有hook代码
- 调试hook故障
- 优化运行缓慢的hook
- 保护处理敏感数据的hook
- 将hook发布为PRPM包
Core Principles
核心原则
1. Security is Non-Negotiable
1. 安全是底线
Hooks execute automatically with user permissions and can read, modify, or delete any file the user can access.
ALWAYS validate and sanitize all input. Hooks receive JSON via stdin—never trust it blindly.
For complete security patterns: Load when implementing validation or securing hooks.
references/security-requirements.mdHook会以用户权限自动执行,可读取、修改或删除用户能访问的任何文件。
务必验证并清理所有输入。Hook通过标准输入接收JSON数据——绝不能盲目信任。
完整安全模式参考:实现验证或安全防护时,可加载。
references/security-requirements.md2. Reliability Over Features
2. 可靠性优先于功能
A hook that works 99% of the time is a broken hook. Edge cases (Unicode filenames, spaces in paths, missing tools) will happen.
Test with edge cases before deploying.
For reliability patterns: Load when handling errors or edge cases.
references/reliability-performance.md99%时间能正常运行的hook仍属于故障hook。边缘情况(如Unicode文件名、路径含空格、依赖工具缺失)一定会出现。
部署前务必测试边缘情况。
可靠性模式参考:处理错误或边缘情况时,可加载。
references/reliability-performance.md3. Performance Matters
3. 性能至关重要
Hooks block operations. A 5-second hook means Claude waits 5 seconds before continuing.
Keep hooks fast. Run heavy operations in background.
For performance optimization: Load when optimizing hook speed.
references/reliability-performance.mdHook会阻塞操作。一个耗时5秒的hook意味着Claude需要等待5秒才能继续执行。
保持hook轻量化,将重型操作放在后台运行。
性能优化参考:优化hook速度时,可加载。
references/reliability-performance.md4. Fail Gracefully
4. 优雅处理故障
Missing dependencies, malformed input, and disk errors will occur.
Handle errors explicitly. Log failures. Return meaningful exit codes.
依赖缺失、输入格式错误、磁盘错误等情况一定会发生。
显式处理错误,记录故障信息,返回有意义的退出码。
Hook Design Checklist
Hook设计检查表
Before writing code, answer these questions:
编写代码前,请先回答以下问题:
What Event Does This Hook Target?
该Hook针对什么事件?
- - Before tool execution (modify input, validate, block)
PreToolUse - - After tool completes (format, log, cleanup)
PostToolUse - - Before user input processes (validate, enhance)
UserPromptSubmit - - When Claude Code starts (setup, env check)
SessionStart - - When Claude Code exits (cleanup, persist state)
SessionEnd - - During alerts (desktop notifications, logging)
Notification - /
Stop- When responses finish (cleanup, summary)SubagentStop - - Before context compaction (save important context)
PreCompact
Common mistake: Using PostToolUse for validation (too late—tool already ran). Use PreToolUse to block operations.
- - 工具执行前(修改输入、验证、阻止操作)
PreToolUse - - 工具执行后(格式化、记录日志、清理)
PostToolUse - - 用户输入处理前(验证、增强)
UserPromptSubmit - - Claude Code启动时(初始化、环境检查)
SessionStart - - Claude Code退出时(清理、持久化状态)
SessionEnd - - 告警触发时(桌面通知、日志记录)
Notification - /
Stop- 响应结束时(清理、生成摘要)SubagentStop - - 上下文压缩前(保存重要上下文)
PreCompact
常见错误:使用PostToolUse进行验证(时机太晚——工具已执行)。应使用PreToolUse来阻止操作。
Which Tools Should Trigger This Hook?
哪些工具应触发该Hook?
Be specific. runs on every tool call.
matcher: "*"Good matchers:
- - Only file writes
"Write" - - File modifications
"Edit|Write" - - Shell commands
"Bash" - - All GitHub MCP tools
"mcp__github__*"
Bad matchers:
- - Everything (use only for logging/metrics)
"*"
请明确指定。会在每次工具调用时运行。
matcher: "*"推荐的匹配规则:
- - 仅针对文件写入操作
"Write" - - 针对文件修改操作
"Edit|Write" - - 针对Shell命令
"Bash" - - 针对所有GitHub MCP工具
"mcp__github__*"
不推荐的匹配规则:
- - 针对所有操作(仅用于日志/指标统计场景)
"*"
What Input Does This Hook Need?
该Hook需要什么输入?
Different tools provide different input. Check what's available:
bash
undefined不同工具提供的输入不同,请确认可用的输入字段:
bash
undefinedPreToolUse / PostToolUse
PreToolUse / PostToolUse
{
"input": {
"file_path": "/path/to/file.ts", // Read, Write, Edit
"command": "npm test", // Bash
"old_string": "...", // Edit
"new_string": "..." // Edit
}
}
**Validate fields exist before using them:**
```bash
FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
if [[ -z "$FILE" ]]; then
echo "No file path provided" >&2
exit 1
fi{
"input": {
"file_path": "/path/to/file.ts", // Read、Write、Edit工具
"command": "npm test", // Bash工具
"old_string": "...", // Edit工具
"new_string": "..." // Edit工具
}
}
**使用前务必验证字段是否存在**:
```bash
FILE=$(echo "$INPUT" | jq -r '.input.file_path // empty')
if [[ -z "$FILE" ]]; then
echo "未提供文件路径" >&2
exit 1
fiShould This Be a Command Hook or Prompt Hook?
应使用命令式Hook还是提示式Hook?
Command hooks ():
type: "command"- Fast (milliseconds)
- Deterministic
- Good for: formatting, logging, file checks
Prompt hooks ():
type: "prompt"- Slow (2-10 seconds)
- Context-aware (uses LLM)
- Good for: complex validation, security analysis, intent detection
Rule of thumb: Use command hooks unless you need LLM reasoning.
命令式Hook ():
type: "command"- 速度快(毫秒级)
- 确定性执行
- 适用场景:格式化、日志记录、文件检查
提示式Hook ():
type: "prompt"- 速度慢(2-10秒)
- 上下文感知(使用大语言模型)
- 适用场景:复杂验证、安全分析、意图识别
经验法则:除非需要大语言模型推理,否则优先使用命令式Hook。
What Exit Code Communicates Success/Failure?
用什么退出码表示成功/失败?
- - Success (continue operation)
exit 0 - - Block operation (show error to Claude)
exit 2 - or other - Non-blocking error (log but continue)
exit 1
For PreToolUse hooks:
- Exit 2 blocks the tool from running
- Exit 0 allows it (optionally with modified input)
For PostToolUse hooks:
- Exit codes don't block (tool already ran)
- Use exit 0 for success, 1 for logging errors
- - 成功(继续执行操作)
exit 0 - - 阻止操作(向Claude显示错误)
exit 2 - 或其他 - 非阻塞错误(记录日志但继续执行)
exit 1
对于PreToolUse Hook:
- 退出码2会阻止工具运行
- 退出码0允许工具运行(可选择修改输入)
对于PostToolUse Hook:
- 退出码不会阻止操作(工具已执行)
- 使用退出码0表示成功,退出码1表示记录错误
Top 5 Pitfalls (Must Know)
五大常见陷阱(必须掌握)
Pitfall #1: Not Quoting Variables
陷阱1:未给变量加引号
Error: Hooks break on filenames with spaces or special characters
Why: Unquoted variables split on whitespace
Example:
bash
undefined问题:Hook在文件名含空格或特殊字符时失效
原因:未加引号的变量会按空格拆分
示例:
bash
undefined❌ WRONG - breaks on "my file.txt"
❌ 错误写法 - 在"my file.txt"场景下失效
cat $FILE
prettier --write $FILE
rm $FILE
cat $FILE
prettier --write $FILE
rm $FILE
✅ RIGHT - handles spaces and special chars
✅ 正确写法 - 支持空格和特殊字符
cat "$FILE"
prettier --write "$FILE"
rm "$FILE"
**Why this matters**: Files with spaces (`"my file.txt"`), Unicode (`"文件.txt"`), or special chars (`"file (1).txt"`) are common.
**For quoting best practices**: Load `references/security-requirements.md` for comprehensive input handling patterns.
---cat "$FILE"
prettier --write "$FILE"
rm "$FILE"
**重要性**:含空格(`"my file.txt"`)、Unicode(`"文件.txt"`)或特殊字符(`"file (1).txt"`)的文件很常见。
**引号最佳实践参考**:加载`references/security-requirements.md`获取全面的输入处理模式。
---Pitfall #2: Trusting Input Without Validation
陷阱2:未验证就信任输入
Error: Hook executes on malicious or malformed input
Why: Not validating JSON fields before using them
Example:
bash
undefined问题:Hook在恶意或格式错误的输入下执行
原因:使用JSON字段前未验证
示例:
bash
undefined❌ DANGEROUS - no validation
❌ 危险写法 - 无验证
FILE=$(jq -r '.input.file_path')
rm "$FILE" # Could delete ../../../etc/passwd
FILE=$(jq -r '.input.file_path')
rm "$FILE" // 可能删除../../../etc/passwd
✅ SAFE - validate first
✅ 安全写法 - 先验证
FILE=$(jq -r '.input.file_path // empty')
[[ -n "$FILE" ]] || exit 1
[[ "$FILE" == "$CLAUDE_PROJECT_DIR"* ]] || exit 2
[[ "$FILE" != ".." ]] || exit 2
rm "$FILE"
**Why this matters**: Prevents path traversal attacks, protects files outside project, prevents malformed input crashes.
**For complete security patterns**: Load `references/security-requirements.md`.
---FILE=$(jq -r '.input.file_path // empty')
[[ -n "$FILE" ]] || exit 1
[[ "$FILE" == "$CLAUDE_PROJECT_DIR"* ]] || exit 2
[[ "$FILE" != ".." ]] || exit 2
rm "$FILE"
**重要性**:防止路径遍历攻击,保护项目外的文件,避免格式错误的输入导致崩溃。
**完整安全模式参考**:加载`references/security-requirements.md`。
---Pitfall #3: Blocking Operations Too Long
陷阱3:阻塞操作时间过长
Error: Hook takes 30+ seconds, blocking Claude
Why: Running expensive operations (tests, builds) synchronously in hook
Example:
bash
undefined问题:Hook耗时30秒以上,阻塞Claude
原因:在Hook中同步执行耗时操作(测试、构建)
示例:
bash
undefined❌ BLOCKS Claude for 30 seconds
❌ 阻塞Claude达30秒
npm test
npm run build
npm test
npm run build
✅ RUN IN BACKGROUND - returns immediately
✅ 后台运行 - 立即返回
(npm test > /tmp/test-results.log 2>&1 &)
(npm run build > /tmp/build.log 2>&1 &)
exit 0
**Why this matters**: Slow hooks create bad user experience. Target < 100ms for PreToolUse, < 500ms for PostToolUse.
**For performance optimization**: Load `references/reliability-performance.md`.
---(npm test > /tmp/test-results.log 2>&1 &)
(npm run build > /tmp/build.log 2>&1 &)
exit 0
**重要性**:缓慢的Hook会带来糟糕的用户体验。PreToolUse Hook目标耗时<100ms,PostToolUse Hook目标耗时<500ms。
**性能优化参考**:加载`references/reliability-performance.md`。
---Pitfall #4: Wrong Exit Code for Blocking
陷阱4:使用错误的退出码来阻止操作
Error: PreToolUse hook doesn't actually block the operation
Why: Using exit 1 instead of exit 2
Example:
bash
undefined问题:PreToolUse Hook实际上并未阻止操作
原因:使用退出码1而非退出码2
示例:
bash
undefined❌ WRONG - logs error but doesn't block
❌ 错误写法 - 记录错误但不阻止操作
if [[ $FILE == ".env" ]]; then
echo "Don't edit .env" >&2
exit 1 # Tool still runs!
fi
if [[ $FILE == ".env" ]]; then
echo "请勿编辑.env" >&2
exit 1 // 工具仍会运行!
fi
✅ RIGHT - actually blocks
✅ 正确写法 - 真正阻止操作
if [[ $FILE == ".env" ]]; then
echo "Blocked: .env is protected" >&2
exit 2 # Tool is blocked
fi
**Why this matters**: Exit 1 only logs errors. Exit 2 is required to block in PreToolUse hooks.
**For exit code patterns**: Load `references/hook-templates.md` for complete hook response patterns.
---if [[ $FILE == ".env" ]]; then
echo "已阻止:.env受保护" >&2
exit 2 // 工具被阻止
fi
**重要性**:退出码1仅记录错误。在PreToolUse Hook中必须使用退出码2来阻止操作。
**退出码模式参考**:加载`references/hook-templates.md`获取完整的Hook响应模式。
---Pitfall #5: Assuming Tools Exist
陷阱5:假设工具已安装
Error: Hook crashes when dependency is missing
Why: Not checking if tool is installed before using
Example:
bash
undefined问题:依赖缺失时Hook崩溃
原因:使用工具前未检查是否已安装
示例:
bash
undefined❌ BREAKS if prettier not installed
❌ 写法 - prettier未安装时会崩溃
prettier --write "$FILE"
prettier --write "$FILE"
✅ SAFE - check first
✅ 安全写法 - 先检查
if command -v prettier &>/dev/null; then
prettier --write "$FILE"
else
echo "prettier not installed, skipping" >&2
exit 0 # Success exit, just skip
fi
**Why this matters**: Users may not have all tools installed. Hooks should degrade gracefully.
**For reliability patterns**: Load `references/reliability-performance.md`.
---if command -v prettier &>/dev/null; then
prettier --write "$FILE"
else
echo "prettier未安装,跳过格式化" >&2
exit 0 // 成功退出,仅跳过操作
fi
**重要性**:用户可能未安装所有工具。Hook应优雅降级。
**可靠性模式参考**:加载`references/reliability-performance.md`。
---Critical Rules
关键规则
Always Do
必须执行的操作
✅ Validate all JSON input before using ()
✅ Quote all variables containing paths or user input
✅ Use absolute paths for scripts ()
✅ Block sensitive files (, , credentials)
✅ Check if required tools exist ()
✅ Set reasonable timeouts (< 5s for PreToolUse)
✅ Run heavy operations in background
✅ Test with edge cases (spaces, Unicode, special chars)
✅ Use exit 2 to block in PreToolUse hooks
✅ Log errors to stderr or file, not stdout
jq -r '... // empty'${CLAUDE_PLUGIN_ROOT}/....env*.keycommand -v toolname✅ 使用jq验证所有标准输入
✅ 给所有包含路径或用户输入的变量加引号
✅ 脚本使用绝对路径()
✅ 阻止敏感文件(, , 凭证文件)
✅ 检查所需工具是否存在()
✅ 设置合理的超时时间(PreToolUse Hook<5秒)
✅ 后台运行耗时操作
✅ 使用边缘情况测试(空格、Unicode、特殊字符)
✅ 在PreToolUse Hook中使用退出码2来阻止操作
✅ 将错误记录到标准错误或文件,而非标准输出
${CLAUDE_PLUGIN_ROOT}/....env*.keycommand -v toolnameNever Do
禁止执行的操作
❌ Trust JSON input without validation
❌ Use unquoted variables ($FILE instead of "$FILE")
❌ Use relative paths for scripts
❌ Skip path sanitization (check for , validate in project)
❌ Assume tools are installed
❌ Block for > 1 second in PreToolUse hooks
❌ Use exit 1 when you mean to block (use exit 2)
❌ Log sensitive data to stdout or files
❌ Use unless truly necessary
..matcher: "*"❌ 未验证就信任JSON输入
❌ 使用未加引号的变量($FILE而非"$FILE")
❌ 脚本使用相对路径
❌ 跳过路径清理(检查,验证是否在项目内)
❌ 假设工具已安装
❌ PreToolUse Hook阻塞时间>1秒
❌ 想阻止操作时使用退出码1(应使用退出码2)
❌ 将敏感数据记录到标准输出或文件
❌ 除非必要,否则不要使用
..matcher: "*"When to Load References
何时加载参考文档
Load reference files when working on specific hook aspects:
处理Hook的特定方面时,请加载对应的参考文件:
Security Requirements (references/security-requirements.md
)
references/security-requirements.md安全要求(references/security-requirements.md
)
references/security-requirements.mdLoad when:
- Implementing input validation and sanitization
- Securing hooks that handle sensitive data
- Blocking sensitive files (, keys, credentials)
.env - Preventing path traversal attacks
- Understanding security vulnerabilities and best practices
- Testing security with malicious input
以下场景请加载:
- 实现输入验证和清理
- 保护处理敏感数据的Hook
- 阻止敏感文件(, 密钥、凭证)
.env - 防止路径遍历攻击
- 了解安全漏洞和最佳实践
- 使用恶意输入测试安全性
Reliability & Performance (references/reliability-performance.md
)
references/reliability-performance.md可靠性与性能(references/reliability-performance.md
)
references/reliability-performance.mdLoad when:
- Handling missing dependencies or tools
- Setting timeouts and handling slow operations
- Optimizing hook performance (< 100ms target)
- Running heavy operations in background
- Caching expensive results
- Testing with edge cases (Unicode, spaces, deep paths)
- Deduplicating expensive operations
以下场景请加载:
- 处理缺失的依赖或工具
- 设置超时和处理缓慢操作
- 优化Hook性能(目标<100ms)
- 后台运行耗时操作
- 缓存昂贵的计算结果
- 使用边缘情况测试(Unicode、空格、深层路径)
- 去重昂贵的操作
Code Templates (references/code-templates.md
)
references/code-templates.md代码模板(references/code-templates.md
)
references/code-templates.mdLoad when:
- Starting a new hook and need working examples
- Implementing format-on-save functionality
- Blocking sensitive files from modification
- Logging commands or operations
- Using prompt-based security analysis
- Customizing templates for specific use cases
以下场景请加载:
- 启动新Hook时需要可用示例
- 实现保存时格式化功能
- 阻止敏感文件被修改
- 记录命令或操作
- 使用基于提示的安全分析
- 针对特定场景自定义模板
Testing & Debugging (references/testing-debugging.md
)
references/testing-debugging.md测试与调试(references/testing-debugging.md
)
references/testing-debugging.mdLoad when:
- Writing test cases for hooks
- Debugging hook failures or unexpected behavior
- Testing with edge cases (malformed JSON, missing fields)
- Checking hook execution in transcript (Ctrl-R)
- Profiling hook performance
- Creating automated test suites
以下场景请加载:
- 为Hook编写测试用例
- 调试Hook故障或意外行为
- 使用边缘情况测试(格式错误的JSON、缺失字段)
- 在会话记录中检查Hook执行情况(Ctrl-R)
- 分析Hook性能
- 创建自动化测试套件
Publishing Guide (references/publishing-guide.md
)
references/publishing-guide.md发布指南(references/publishing-guide.md
)
references/publishing-guide.mdLoad when:
- Publishing hooks to PRPM registry
- Creating package manifest (prpm.json)
- Configuring hook.json with advanced options
- Using ,
continue,stopReason,suppressOutputsystemMessage - Writing README.md for users
- Understanding versioning and publishing commands
以下场景请加载:
- 将Hook发布到PRPM注册表
- 创建包清单(prpm.json)
- 使用高级选项配置hook.json
- 使用,
continue,stopReason,suppressOutputsystemMessage - 为用户编写README.md
- 了解版本控制和发布命令
Quick Reference (references/quick-reference.md
)
references/quick-reference.md快速参考(references/quick-reference.md
)
references/quick-reference.mdLoad when:
- Need quick syntax lookup (exit codes, jq patterns)
- Looking up environment variables
- Finding common bash patterns (file validation, background execution)
- Checking hook events and matchers
- Need performance tips summary
- Looking up JSON input structure
以下场景请加载:
- 需要快速查找语法(退出码、jq模式)
- 查找环境变量
- 查找常见bash模式(文件验证、后台执行)
- 检查Hook事件和匹配规则
- 需要性能技巧摘要
- 查找JSON输入结构
Final Checklist
最终检查表
Before publishing a hook:
- Validates all stdin input with jq
- Quotes all variables
- Uses absolute paths for scripts
- Blocks sensitive files (,
.env, etc.)*.key - Handles missing tools gracefully
- Sets reasonable timeout (< 5s for PreToolUse)
- Logs errors to stderr or file, not stdout
- Tests with edge cases (spaces, Unicode, malformed JSON)
- Tests in real Claude Code session
- Documents dependencies in README
- Uses semantic versioning
- Clear description and tags
发布Hook前,请确认:
- 使用jq验证所有标准输入
- 给所有变量加引号
- 脚本使用绝对路径
- 阻止敏感文件(,
.env等)*.key - 优雅处理缺失的工具
- 设置合理的超时时间(PreToolUse Hook<5秒)
- 将错误记录到标准错误或文件,而非标准输出
- 使用边缘情况测试(空格、Unicode、格式错误的JSON)
- 在真实Claude Code会话中测试
- 在README中记录依赖
- 使用语义化版本
- 描述清晰且带有标签
Using Bundled Resources
使用捆绑资源
This skill includes 6 reference files for on-demand loading:
Security & Reliability (2 files):
- - Input validation, path sanitization, blocking sensitive files
security-requirements.md - - Error handling, timeouts, performance optimization
reliability-performance.md
Implementation (2 files):
- - Working hook examples (format-on-save, block-sensitive, logger, etc.)
code-templates.md - - Fast syntax lookup (exit codes, jq patterns, environment vars)
quick-reference.md
Testing & Publishing (2 files):
- - Test patterns, edge cases, debugging techniques
testing-debugging.md - - PRPM packaging, advanced configuration, README template
publishing-guide.md
Load references on-demand when specific knowledge is needed. See "When to Load References" section for triggers.
本指南包含6个可按需加载的参考文件:
安全与可靠性(2个文件):
- - 输入验证、路径清理、阻止敏感文件
security-requirements.md - - 错误处理、超时、性能优化
reliability-performance.md
实现(2个文件):
- - 可用的Hook示例(保存时格式化、阻止敏感文件、日志记录器等)
code-templates.md - - 快速语法查找(退出码、jq模式、环境变量)
quick-reference.md
测试与发布(2个文件):
- - 测试模式、边缘情况、调试技巧
testing-debugging.md - - PRPM打包、高级配置、README模板
publishing-guide.md
需要特定知识时,请按需加载参考文档。请查看“何时加载参考文档”部分了解触发场景。