hook-development by anthropics/claude-plugins-official
npx skills add https://github.com/anthropics/claude-plugins-official --skill hook-development钩子是基于事件驱动的自动化脚本,用于响应 Claude Code 事件执行。使用钩子来验证操作、执行策略、添加上下文,并将外部工具集成到工作流程中。
核心功能:
使用 LLM 驱动的决策进行上下文感知验证:
{
"type": "prompt",
"prompt": "Evaluate if this tool use is appropriate: $TOOL_INPUT",
"timeout": 30
}
支持的事件: Stop, SubagentStop, UserPromptSubmit, PreToolUse
优势:
执行 bash 命令进行确定性检查:
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
"timeout": 60
}
适用于:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
对于插件钩子,在 hooks/hooks.json 中使用包装器格式:
{
"description": "钩子的简要说明(可选)",
"hooks": {
"PreToolUse": [...],
"Stop": [...],
"SessionStart": [...]
}
}
关键点:
description 字段是可选的hooks 字段是包含实际钩子事件的必需包装器示例:
{
"description": "代码质量验证钩子",
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate.sh"
}
]
}
]
}
}
对于用户设置,在 .claude/settings.json 中使用直接格式:
{
"PreToolUse": [...],
"Stop": [...],
"SessionStart": [...]
}
关键点:
重要提示: 下面的示例展示了钩子事件结构,这些结构可以放入任一格式中。对于插件 hooks.json,请将这些包装在 {"hooks": {...}} 中。
在任何工具运行前执行。用于批准、拒绝或修改工具调用。
示例(基于提示):
{
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "验证文件写入安全性。检查:系统路径、凭据、路径遍历、敏感内容。返回 'approve' 或 'deny'。"
}
]
}
]
}
PreToolUse 的输出:
{
"hookSpecificOutput": {
"permissionDecision": "allow|deny|ask",
"updatedInput": {"field": "modified_value"}
},
"systemMessage": "给 Claude 的解释"
}
在工具完成后执行。用于对结果做出反应、提供反馈或记录日志。
示例:
{
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "prompt",
"prompt": "分析编辑结果的潜在问题:语法错误、安全漏洞、破坏性更改。提供反馈。"
}
]
}
]
}
输出行为:
当主代理考虑停止时执行。用于验证完成度。
示例:
{
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "prompt",
"prompt": "验证任务完成情况:测试已运行、构建成功、问题已回答。返回 'approve' 以停止,或返回 'block' 并附上继续的原因。"
}
]
}
]
}
决策输出:
{
"decision": "approve|block",
"reason": "解释",
"systemMessage": "附加上下文"
}
当子代理考虑停止时执行。用于确保子代理已完成其任务。
类似于 Stop 钩子,但用于子代理。
当用户提交提示时执行。用于添加上下文、验证或阻止提示。
示例:
{
"UserPromptSubmit": [
{
"matcher": "*",
"hooks": [
{
"type": "prompt",
"prompt": "检查提示是否需要安全指导。如果讨论身份验证、权限或 API 安全,返回相关警告。"
}
]
}
]
}
当 Claude Code 会话开始时执行。用于加载上下文和设置环境。
示例:
{
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
}
]
}
]
}
特殊功能: 使用 $CLAUDE_ENV_FILE 持久化环境变量:
echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"
查看 examples/load-context.sh 获取完整示例。
当会话结束时执行。用于清理、日志记录和状态保存。
在上下文压缩前执行。用于添加要保留的关键信息。
当 Claude 发送通知时执行。用于对用户通知做出反应。
{
"continue": true,
"suppressOutput": false,
"systemMessage": "给 Claude 的消息"
}
continue:如果为 false,则停止处理(默认为 true)suppressOutput:从记录中隐藏输出(默认为 false)systemMessage:显示给 Claude 的消息0 - 成功(stdout 显示在记录中)2 - 阻塞错误(stderr 反馈给 Claude)所有钩子都通过 stdin 接收 JSON,包含公共字段:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/current/working/dir",
"permission_mode": "ask|allow",
"hook_event_name": "PreToolUse"
}
事件特定字段:
tool_name, tool_input, tool_resultuser_promptreason在提示中使用 $TOOL_INPUT、$TOOL_RESULT、$USER_PROMPT 等访问字段。
在所有命令钩子中可用:
$CLAUDE_PROJECT_DIR - 项目根路径$CLAUDE_PLUGIN_ROOT - 插件目录(用于可移植路径)$CLAUDE_ENV_FILE - 仅 SessionStart:在此处持久化环境变量$CLAUDE_CODE_REMOTE - 如果在远程上下文中运行则设置始终在钩子命令中使用 ${CLAUDE_PLUGIN_ROOT} 以确保可移植性:
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}
在插件中,在 hooks/hooks.json 中定义钩子:
{
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "验证文件写入安全性"
}
]
}
],
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "prompt",
"prompt": "验证任务完成情况"
}
]
}
],
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh",
"timeout": 10
}
]
}
]
}
插件钩子与用户的钩子合并并并行运行。
精确匹配:
"matcher": "Write"
多个工具:
"matcher": "Read|Write|Edit"
通配符(所有工具):
"matcher": "*"
正则表达式模式:
"matcher": "mcp__.*__delete.*" // 所有 MCP 删除工具
注意: 匹配器区分大小写。
// 所有 MCP 工具
"matcher": "mcp__.*"
// 特定插件的 MCP 工具
"matcher": "mcp__plugin_asana_.*"
// 所有文件操作
"matcher": "Read|Write|Edit"
// 仅 Bash 命令
"matcher": "Bash"
始终在命令钩子中验证输入:
#!/bin/bash
set -euo pipefail
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')
# 验证工具名称格式
if [[ ! "$tool_name" =~ ^[a-zA-Z0-9_]+$ ]]; then
echo '{"decision": "deny", "reason": "Invalid tool name"}' >&2
exit 2
fi
检查路径遍历和敏感文件:
file_path=$(echo "$input" | jq -r '.tool_input.file_path')
# 拒绝路径遍历
if [[ "$file_path" == *".."* ]]; then
echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2
exit 2
fi
# 拒绝敏感文件
if [[ "$file_path" == *".env"* ]]; then
echo '{"decision": "deny", "reason": "Sensitive file"}' >&2
exit 2
fi
查看 examples/validate-write.sh 和 examples/validate-bash.sh 获取完整示例。
# 好:已引用
echo "$file_path"
cd "$CLAUDE_PROJECT_DIR"
# 不好:未引用(注入风险)
echo $file_path
cd $CLAUDE_PROJECT_DIR
{
"type": "command",
"command": "bash script.sh",
"timeout": 10
}
默认值: 命令钩子(60秒),提示钩子(30秒)
所有匹配的钩子并行运行:
{
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{"type": "command", "command": "check1.sh"}, // 并行
{"type": "command", "command": "check2.sh"}, // 并行
{"type": "prompt", "prompt": "Validate..."} // 并行
]
}
]
}
设计影响:
通过检查标志文件或配置来创建有条件激活的钩子:
模式:标志文件激活
#!/bin/bash
# 仅当标志文件存在时激活
FLAG_FILE="$CLAUDE_PROJECT_DIR/.enable-strict-validation"
if [ ! -f "$FLAG_FILE" ]; then
# 标志不存在,跳过验证
exit 0
fi
# 标志存在,运行验证
input=$(cat)
# ... 验证逻辑 ...
模式:基于配置的激活
#!/bin/bash
# 检查配置以激活
CONFIG_FILE="$CLAUDE_PROJECT_DIR/.claude/plugin-config.json"
if [ -f "$CONFIG_FILE" ]; then
enabled=$(jq -r '.strictMode // false' "$CONFIG_FILE")
if [ "$enabled" != "true" ]; then
exit 0 # 未启用,跳过
fi
fi
# 已启用,运行钩子逻辑
input=$(cat)
# ... 钩子逻辑 ...
使用场景:
最佳实践: 在插件 README 中记录激活机制,以便用户知道如何启用/禁用临时钩子。
重要提示: 钩子在 Claude Code 会话开始时加载。更改钩子配置需要重新启动 Claude Code。
无法热交换钩子:
hooks/hooks.json 不会影响当前会话claude测试钩子更改:
claude 或 ccclaude --debug 测试钩子钩子在 Claude Code 启动时验证:
使用 /hooks 命令查看当前会话中加载的钩子。
claude --debug
查找钩子注册、执行日志、输入/输出 JSON 和计时信息。
直接测试命令钩子:
echo '{"tool_name": "Write", "tool_input": {"file_path": "/test"}}' | \
bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh
echo "Exit code: $?"
确保钩子输出有效的 JSON:
output=$(./your-hook.sh < test-input.json)
echo "$output" | jq .
| 事件 | 时机 | 用途 |
|---|---|---|
| PreToolUse | 工具使用前 | 验证、修改 |
| PostToolUse | 工具使用后 | 反馈、日志记录 |
| UserPromptSubmit | 用户输入时 | 上下文、验证 |
| Stop | 代理停止时 | 完成度检查 |
| SubagentStop | 子代理完成时 | 任务验证 |
| SessionStart | 会话开始时 | 上下文加载 |
| SessionEnd | 会话结束时 | 清理、日志记录 |
| PreCompact | 压缩前 | 保留上下文 |
| Notification | 用户通知时 | 日志记录、反应 |
应该:
不应该:
有关详细模式和高级技术,请查阅:
references/patterns.md - 常见钩子模式(8+ 种经过验证的模式)references/migration.md - 从基本钩子迁移到高级钩子references/advanced.md - 高级用例和技术examples/ 中的工作示例:
validate-write.sh - 文件写入验证示例validate-bash.sh - Bash 命令验证示例load-context.sh - SessionStart 上下文加载示例scripts/ 中的开发工具:
validate-hook-schema.sh - 验证 hooks.json 结构和语法test-hook.sh - 在部署前使用示例输入测试钩子hook-linter.sh - 检查钩子脚本的常见问题和最佳实践claude --debug 获取详细日志jq 验证钩子 JSON 输出在插件中实现钩子:
hooks/hooks.json 中编写钩子配置scripts/validate-hook-schema.sh hooks/hooks.json 验证配置scripts/test-hook.sh 测试钩子claude --debug 在 Claude Code 中测试对于大多数用例,专注于基于提示的钩子。保留命令钩子用于性能关键或确定性检查。
每周安装次数
317
仓库
GitHub 星标
9.6K
首次出现
2026年2月5日
安全审计
安装在
opencode271
codex270
gemini-cli267
github-copilot260
amp250
claude-code250
Hooks are event-driven automation scripts that execute in response to Claude Code events. Use hooks to validate operations, enforce policies, add context, and integrate external tools into workflows.
Key capabilities:
Use LLM-driven decision making for context-aware validation:
{
"type": "prompt",
"prompt": "Evaluate if this tool use is appropriate: $TOOL_INPUT",
"timeout": 30
}
Supported events: Stop, SubagentStop, UserPromptSubmit, PreToolUse
Benefits:
Execute bash commands for deterministic checks:
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
"timeout": 60
}
Use for:
For plugin hooks in hooks/hooks.json, use wrapper format:
{
"description": "Brief explanation of hooks (optional)",
"hooks": {
"PreToolUse": [...],
"Stop": [...],
"SessionStart": [...]
}
}
Key points:
description field is optionalhooks field is required wrapper containing actual hook eventsExample:
{
"description": "Validation hooks for code quality",
"hooks": {
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/validate.sh"
}
]
}
]
}
}
For user settings in .claude/settings.json, use direct format:
{
"PreToolUse": [...],
"Stop": [...],
"SessionStart": [...]
}
Key points:
Important: The examples below show the hook event structure that goes inside either format. For plugin hooks.json, wrap these in {"hooks": {...}}.
Execute before any tool runs. Use to approve, deny, or modify tool calls.
Example (prompt-based):
{
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "Validate file write safety. Check: system paths, credentials, path traversal, sensitive content. Return 'approve' or 'deny'."
}
]
}
]
}
Output for PreToolUse:
{
"hookSpecificOutput": {
"permissionDecision": "allow|deny|ask",
"updatedInput": {"field": "modified_value"}
},
"systemMessage": "Explanation for Claude"
}
Execute after tool completes. Use to react to results, provide feedback, or log.
Example:
{
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "prompt",
"prompt": "Analyze edit result for potential issues: syntax errors, security vulnerabilities, breaking changes. Provide feedback."
}
]
}
]
}
Output behavior:
Execute when main agent considers stopping. Use to validate completeness.
Example:
{
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "prompt",
"prompt": "Verify task completion: tests run, build succeeded, questions answered. Return 'approve' to stop or 'block' with reason to continue."
}
]
}
]
}
Decision output:
{
"decision": "approve|block",
"reason": "Explanation",
"systemMessage": "Additional context"
}
Execute when subagent considers stopping. Use to ensure subagent completed its task.
Similar to Stop hook, but for subagents.
Execute when user submits a prompt. Use to add context, validate, or block prompts.
Example:
{
"UserPromptSubmit": [
{
"matcher": "*",
"hooks": [
{
"type": "prompt",
"prompt": "Check if prompt requires security guidance. If discussing auth, permissions, or API security, return relevant warnings."
}
]
}
]
}
Execute when Claude Code session begins. Use to load context and set environment.
Example:
{
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh"
}
]
}
]
}
Special capability: Persist environment variables using $CLAUDE_ENV_FILE:
echo "export PROJECT_TYPE=nodejs" >> "$CLAUDE_ENV_FILE"
See examples/load-context.sh for complete example.
Execute when session ends. Use for cleanup, logging, and state preservation.
Execute before context compaction. Use to add critical information to preserve.
Execute when Claude sends notifications. Use to react to user notifications.
{
"continue": true,
"suppressOutput": false,
"systemMessage": "Message for Claude"
}
continue: If false, halt processing (default true)suppressOutput: Hide output from transcript (default false)systemMessage: Message shown to Claude0 - Success (stdout shown in transcript)2 - Blocking error (stderr fed back to Claude)All hooks receive JSON via stdin with common fields:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/current/working/dir",
"permission_mode": "ask|allow",
"hook_event_name": "PreToolUse"
}
Event-specific fields:
tool_name, tool_input, tool_resultuser_promptreasonAccess fields in prompts using $TOOL_INPUT, $TOOL_RESULT, $USER_PROMPT, etc.
Available in all command hooks:
$CLAUDE_PROJECT_DIR - Project root path$CLAUDE_PLUGIN_ROOT - Plugin directory (use for portable paths)$CLAUDE_ENV_FILE - SessionStart only: persist env vars here$CLAUDE_CODE_REMOTE - Set if running in remote contextAlways use ${CLAUDE_PLUGIN_ROOT} in hook commands for portability:
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh"
}
In plugins, define hooks in hooks/hooks.json:
{
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "Validate file write safety"
}
]
}
],
"Stop": [
{
"matcher": "*",
"hooks": [
{
"type": "prompt",
"prompt": "Verify task completion"
}
]
}
],
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/load-context.sh",
"timeout": 10
}
]
}
]
}
Plugin hooks merge with user's hooks and run in parallel.
Exact match:
"matcher": "Write"
Multiple tools:
"matcher": "Read|Write|Edit"
Wildcard (all tools):
"matcher": "*"
Regex patterns:
"matcher": "mcp__.*__delete.*" // All MCP delete tools
Note: Matchers are case-sensitive.
// All MCP tools
"matcher": "mcp__.*"
// Specific plugin's MCP tools
"matcher": "mcp__plugin_asana_.*"
// All file operations
"matcher": "Read|Write|Edit"
// Bash commands only
"matcher": "Bash"
Always validate inputs in command hooks:
#!/bin/bash
set -euo pipefail
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name')
# Validate tool name format
if [[ ! "$tool_name" =~ ^[a-zA-Z0-9_]+$ ]]; then
echo '{"decision": "deny", "reason": "Invalid tool name"}' >&2
exit 2
fi
Check for path traversal and sensitive files:
file_path=$(echo "$input" | jq -r '.tool_input.file_path')
# Deny path traversal
if [[ "$file_path" == *".."* ]]; then
echo '{"decision": "deny", "reason": "Path traversal detected"}' >&2
exit 2
fi
# Deny sensitive files
if [[ "$file_path" == *".env"* ]]; then
echo '{"decision": "deny", "reason": "Sensitive file"}' >&2
exit 2
fi
See examples/validate-write.sh and examples/validate-bash.sh for complete examples.
# GOOD: Quoted
echo "$file_path"
cd "$CLAUDE_PROJECT_DIR"
# BAD: Unquoted (injection risk)
echo $file_path
cd $CLAUDE_PROJECT_DIR
{
"type": "command",
"command": "bash script.sh",
"timeout": 10
}
Defaults: Command hooks (60s), Prompt hooks (30s)
All matching hooks run in parallel :
{
"PreToolUse": [
{
"matcher": "Write",
"hooks": [
{"type": "command", "command": "check1.sh"}, // Parallel
{"type": "command", "command": "check2.sh"}, // Parallel
{"type": "prompt", "prompt": "Validate..."} // Parallel
]
}
]
}
Design implications:
Create hooks that activate conditionally by checking for a flag file or configuration:
Pattern: Flag file activation
#!/bin/bash
# Only active when flag file exists
FLAG_FILE="$CLAUDE_PROJECT_DIR/.enable-strict-validation"
if [ ! -f "$FLAG_FILE" ]; then
# Flag not present, skip validation
exit 0
fi
# Flag present, run validation
input=$(cat)
# ... validation logic ...
Pattern: Configuration-based activation
#!/bin/bash
# Check configuration for activation
CONFIG_FILE="$CLAUDE_PROJECT_DIR/.claude/plugin-config.json"
if [ -f "$CONFIG_FILE" ]; then
enabled=$(jq -r '.strictMode // false' "$CONFIG_FILE")
if [ "$enabled" != "true" ]; then
exit 0 # Not enabled, skip
fi
fi
# Enabled, run hook logic
input=$(cat)
# ... hook logic ...
Use cases:
Best practice: Document activation mechanism in plugin README so users know how to enable/disable temporary hooks.
Important: Hooks are loaded when Claude Code session starts. Changes to hook configuration require restarting Claude Code.
Cannot hot-swap hooks:
hooks/hooks.json won't affect current sessionclaude againTo test hook changes:
claude or ccclaude --debugHooks are validated when Claude Code starts:
Use /hooks command to review loaded hooks in current session.
claude --debug
Look for hook registration, execution logs, input/output JSON, and timing information.
Test command hooks directly:
echo '{"tool_name": "Write", "tool_input": {"file_path": "/test"}}' | \
bash ${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh
echo "Exit code: $?"
Ensure hooks output valid JSON:
output=$(./your-hook.sh < test-input.json)
echo "$output" | jq .
| Event | When | Use For |
|---|---|---|
| PreToolUse | Before tool | Validation, modification |
| PostToolUse | After tool | Feedback, logging |
| UserPromptSubmit | User input | Context, validation |
| Stop | Agent stopping | Completeness check |
| SubagentStop | Subagent done | Task validation |
| SessionStart | Session begins | Context loading |
| SessionEnd | Session ends | Cleanup, logging |
| PreCompact | Before compact | Preserve context |
| Notification | User notified | Logging, reactions |
DO:
DON'T:
For detailed patterns and advanced techniques, consult:
references/patterns.md - Common hook patterns (8+ proven patterns)references/migration.md - Migrating from basic to advanced hooksreferences/advanced.md - Advanced use cases and techniquesWorking examples in examples/:
validate-write.sh - File write validation examplevalidate-bash.sh - Bash command validation exampleload-context.sh - SessionStart context loading exampleDevelopment tools in scripts/:
validate-hook-schema.sh - Validate hooks.json structure and syntaxtest-hook.sh - Test hooks with sample input before deploymenthook-linter.sh - Check hook scripts for common issues and best practicesclaude --debug for detailed logsjq to validate hook JSON outputTo implement hooks in a plugin:
hooks/hooks.jsonscripts/validate-hook-schema.sh hooks/hooks.jsonscripts/test-hook.sh before deploymentclaude --debugFocus on prompt-based hooks for most use cases. Reserve command hooks for performance-critical or deterministic checks.
Weekly Installs
317
Repository
GitHub Stars
9.6K
First Seen
Feb 5, 2026
Security Audits
Gen Agent Trust HubFailSocketWarnSnykPass
Installed on
opencode271
codex270
gemini-cli267
github-copilot260
amp250
claude-code250
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
136,300 周安装