This skill should be used when the user asks to "create a hook", "add a hook", "write a hook", or mentions Claude Code hooks. Also suggest this skill when the user asks to "automatically do X" or "run X before/after Y" as these are good candidates for hooks.
/plugin marketplace add dwmkerr/claude-toolkit/plugin install toolkit@claude-toolkitThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/examples/firewall.mdreferences/examples/pre-push-tests.mdreferences/examples/quality-checks.mdreferences/hook-events.mdCreate hooks that run shell commands on specific events to add guardrails, automations, and policy enforcement.
You MUST read the reference files for detailed schemas and examples:
| Code | Meaning | Behavior |
|---|---|---|
| 0 | Success | Action proceeds; stdout shown in verbose mode |
| 2 | Block | Action blocked; stderr fed to Claude |
| Other | Error | Non-blocking; stderr shown to user |
.claude/settings.json.claude/hooks/ (mark executable){
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/my-script.sh",
"timeout": 60
}
]
}
]
}
}
| Event | When | Can Block? |
|---|---|---|
| PreToolUse | Before tool executes | Yes (exit 2) |
| PostToolUse | After tool completes | Feedback only |
| PermissionRequest | User sees permission dialog | Yes |
| UserPromptSubmit | User submits prompt | Yes |
| Stop | Main agent finishes | Yes (continue) |
| SubagentStop | Subagent finishes | Yes (continue) |
| SessionStart | Session begins | Add context |
| SessionEnd | Session ends | Cleanup only |
| Notification | Notifications sent | No |
| PreCompact | Before compact | No |
For PreToolUse/PostToolUse/PermissionRequest:
Bash - Shell commandsEdit, Write, Read - File operationsGlob, Grep - Search operationsTask - Subagent tasksmcp__<server>__<tool> - MCP toolsUse wildcards for flexible matching patterns:
Bash(npm *) - Match any npm commandBash(*-h*) - Match commands containing -hBash(git:*) - Match any git subcommandThis reduces configuration overhead and avoids mismatched permissions blocking legitimate workflows.
#!/usr/bin/env bash
set -euo pipefail
# Read JSON input
input=$(cat)
tool_name=$(echo "$input" | jq -r '.tool_name // ""')
command=$(echo "$input" | jq -r '.tool_input.command // ""')
# Your validation logic here
if [[ "$command" =~ dangerous_pattern ]]; then
echo "Blocked: reason here" >&2
exit 2
fi
exit 0
Examples adapted from Steve Kinney's Claude Code Hook Examples.