Awesome-omni-skill claude-code-hook-development
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.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/claude-code-hook-development" ~/.claude/skills/diegosouzapw-awesome-omni-skill-claude-code-hook-development && rm -rf "$T"
skills/development/claude-code-hook-development/SKILL.mdClaude Code Hook Development
Create hooks that run shell commands on specific events to add guardrails, automations, and policy enforcement.
Quick Reference
You MUST read the reference files for detailed schemas and examples:
- Hook Events Reference - All events with input/output schemas
- Examples: Firewall - Block dangerous commands
- Examples: Quality Checks - Lint/format after edits
- Examples: Pre-Push Tests - Run tests before git push
Core Concepts
Hook Types
- Command hooks - Run bash scripts
- Prompt hooks - Query LLM for context-aware decisions
Exit Codes
| 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 |
File Locations
- Settings:
.claude/settings.json - Scripts:
(mark executable).claude/hooks/
Settings Structure
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": ".claude/hooks/my-script.sh", "timeout": 60 } ] } ] } }
Hook Events Summary
| 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 |
Common Matchers
For PreToolUse/PostToolUse/PermissionRequest:
- Shell commandsBash
,Edit
,Write
- File operationsRead
,Glob
- Search operationsGrep
- Subagent tasksTask
- MCP toolsmcp__<server>__<tool>- Regex patterns supported
Wildcard Permissions
Use wildcards for flexible matching patterns:
- Match any npm commandBash(npm *)
- Match commands containingBash(*-h*)-h
- Match any git subcommandBash(git:*)
This reduces configuration overhead and avoids mismatched permissions blocking legitimate workflows.
Script Template
#!/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
Critical: Activating Hook Changes
Hooks are snapshotted at startup. After creating or modifying hooks:
⚠️ Changes won't take effect until you either:
- Restart Claude Code (exit and re-run
), ORclaude- Run
to review and apply the updated configuration/hooksThis is a security feature - it prevents malicious hook modifications from affecting your current session.
Verifying Hooks Are Loaded
After restart, run
/hooks to confirm your hook appears in the list. If it doesn't show up:
- Check JSON syntax in settings file
- Verify file is in correct location (
).claude/settings.json - Look for
in any settings filedisableAllHooks: true
Troubleshooting
Hook Not Triggering
- Did you restart? Hooks are snapshotted at startup - run
or restart Claude Code/hooks - Check
output - Your hook should be listed with correct matcher/hooks - Validate JSON - Run
to check syntaxcat .claude/settings.json | jq . - Check matcher - Tool names are case-sensitive (
notBash
)bash
Testing Hooks Safely
When creating hooks that block operations (like preventing push to main):
- Test on a safe branch first - Modify the hook to block a test branch
- Verify the block works - Attempt the blocked operation
- Update to production config - Change to block the actual target (e.g., main)
- Restart and verify - Run
to confirm the updated hook is loaded/hooks
Debugging
Use
claude --debug to see hook execution details, or add logging to your hook:
echo "[DEBUG] Hook triggered: $cmd" >> /tmp/hook-debug.log
Attribution
Examples adapted from Steve Kinney's Claude Code Hook Examples.