hook-creator
Create and configure Claude Code hooks for customizing agent behavior. Use when the user wants to (1) create a new hook, (2) configure automatic formatting, logging, or notifications, (3) add file protection or custom permissions, (4) set up pre/post tool execution actions, or (5) asks about hook events like PreToolUse, PostToolUse, Notification, etc.
When & Why to Use This Skill
The Hook Creator skill enables developers to customize and extend Claude Code's behavior by implementing shell-based hooks at key lifecycle events. It allows users to intercept tool executions (PreToolUse/PostToolUse) to automate workflows, enforce security guardrails, and manage complex multi-agent coordination, significantly enhancing the agent's integration with local development environments.
Use Cases
- Automated Code Quality: Automatically trigger linters or formatters like Prettier or Ruff immediately after the agent modifies a file to ensure code style consistency.
- Security Guardrails: Implement custom permissions to block the agent from reading or writing to sensitive files, such as .env files or production credentials, by intercepting file-path inputs.
- Sequential Agent Orchestration: Coordinate complex workflows by enforcing execution orders between different sub-agents, ensuring a 'validator' agent only starts after a 'creator' agent completes its task.
- Audit and Activity Logging: Stream tool inputs and outputs to external log files or monitoring dashboards using jq for real-time debugging and compliance auditing.
- Custom Notifications: Set up automated alerts (e.g., Slack or system notifications) that trigger when specific tools are used or when long-running agent tasks reach a certain milestone.
| name | hook-creator |
|---|---|
| description | Create and configure Claude Code hooks for customizing agent behavior. Use when the user wants to (1) create a new hook, (2) configure automatic formatting, logging, or notifications, (3) add file protection or custom permissions, (4) set up pre/post tool execution actions, or (5) asks about hook events like PreToolUse, PostToolUse, Notification, etc. |
Hook Creator
Create Claude Code hooks that execute shell commands at specific lifecycle events.
Hook Creation Workflow
- Identify the use case - Determine what the hook should accomplish
- Select the appropriate event - Choose from available hook events (see references/hook-events.md)
- Design the hook command - Write shell command that processes JSON input from stdin
- Configure the matcher - Set tool/event filter (use
*for all, or specific tool names likeBash,Edit|Write) - Choose storage location - User settings (
~/.claude/settings.json) or project (.claude/settings.json) - Test the hook - Verify behavior with a simple test case
Hook Configuration Structure
{
"hooks": {
"<EventName>": [
{
"matcher": "<ToolPattern>",
"hooks": [
{
"type": "command",
"command": "<shell-command>"
}
]
}
]
}
}
Common Patterns
Reading Input Data
Hooks receive JSON via stdin (NOT as placeholder variables). Use jq to extract fields:
# Extract tool input field
jq -r '.tool_input.file_path'
# Extract with fallback
jq -r '.tool_input.description // "No description"'
# Conditional processing
jq -r 'if .tool_input.file_path then .tool_input.file_path else empty end'
IMPORTANT: Do NOT use $TOOL_INPUT or $TOOL_OUTPUT as shell variables. The entire JSON is piped to stdin. Use pipes:
# ✅ Correct
command: "jq -r '.tool_input' | ./scripts/process.sh"
# ❌ Incorrect (legacy/deprecated)
command: "./scripts/process.sh $TOOL_INPUT"
Exit Codes for PreToolUse
0- Allow the tool to proceed2- Block the tool and provide feedback to Claude
Matcher Patterns
*- Match all toolsBash- Match only Bash toolEdit|Write- Match Edit or Write toolsRead- Match Read tool
Quick Examples
Log all bash commands:
jq -r '"\(.tool_input.command)"' >> ~/.claude/bash-log.txt
Auto-format TypeScript after edit:
jq -r '.tool_input.file_path' | { read f; [[ "$f" == *.ts ]] && npx prettier --write "$f"; }
Block edits to .env files:
python3 -c "import json,sys; p=json.load(sys.stdin).get('tool_input',{}).get('file_path',''); sys.exit(2 if '.env' in p else 0)"
Skill Hooks vs Global Hooks
Hooks can be configured in two scopes:
Global Hooks (settings.json)
Configured in ~/.claude/settings.json or .claude/settings.json:
- Scope: Active for all Claude Code sessions
- Lifecycle: Persistent until manually removed
- Use cases: User-wide preferences, project-wide enforcement
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{"type": "command", "command": "echo 'Global hook'"}]
}
]
}
}
Skill Hooks (SKILL.md frontmatter)
Configured in SKILL.md YAML frontmatter:
- Scope: Active only when Skill is executing
- Lifecycle: Automatically cleaned up when Skill finishes
- Use cases: Skill-specific validation, quality control, agent orchestration
---
name: my-skill
description: Example skill with hooks
hooks:
PreToolUse:
- matcher: "Edit"
hooks:
- type: command
command: "./scripts/validate.sh" # Simple script (no JSON processing)
---
Subagent Hooks (.claude/agents/)
Configured in subagent .md files:
- Scope: Active only when that specific subagent is executing
- Lifecycle: Automatically cleaned up when subagent finishes
- Use cases: Agent-specific validation, logging, quality control
---
name: code-reviewer
description: Reviews code quality
hooks:
PostToolUse:
- matcher: "Read"
hooks:
- type: command
command: "./scripts/track-files.sh" # Simple logging script
---
Using Hooks in Skills
To add hooks to a Skill, include them in the YAML frontmatter:
---
name: quiz-workflow
description: Create Korean learning quizzes with 3-agent validation
hooks:
PreToolUse:
- matcher: "Task"
hooks:
- type: command
command: "jq -r '.tool_input' | ./scripts/check-agent-order.sh"
once: true
PostToolUse:
- matcher: "mcp__supabase-mcp__execute_sql"
hooks:
- type: command
command: "jq -r '.tool_output' | ./scripts/validate-db-insert.sh"
Stop:
- matcher: "*"
hooks:
- type: command
command: "./scripts/generate-quality-report.sh"
---
Note: The once: true field is supported for Skills and Slash commands, but NOT for Agents.
Sequential Agent Execution Example
When running multiple agents in sequence (e.g., creator → validator → reviewer), use hooks to enforce order:
Skill structure:
quiz-workflow/
├── SKILL.md (with hooks configuration)
└── scripts/
├── check-agent-order.sh
└── mark-checkpoint.sh
Hook configuration in SKILL.md:
hooks:
PreToolUse:
- matcher: "Task"
hooks:
- type: command
command: "jq -r '.tool_input' | ./scripts/check-agent-order.sh"
PostToolUse:
- matcher: "Task"
hooks:
- type: command
command: "jq -r '.tool_output' | ./scripts/mark-checkpoint.sh"
scripts/check-agent-order.sh:
#!/bin/bash
# Parse JSON directly from stdin (already filtered by jq in hook command)
agent=$(jq -r '.subagent_type // empty')
# Check prerequisites
case "$agent" in
"quiz-validator")
[[ -f /tmp/quiz-creator.done ]] || exit 2 # Block if creator not done
;;
"quiz-reviewer")
[[ -f /tmp/quiz-validator.done ]] || exit 2 # Block if validator not done
;;
esac
exit 0
scripts/mark-checkpoint.sh:
#!/bin/bash
# Parse JSON directly from stdin (already filtered by jq in hook command)
agent=$(jq -r '.subagent_type // empty')
touch "/tmp/${agent}.done"
This pattern ensures Agent 2 cannot start before Agent 1 completes.
Resources
- Hook Events Reference: See
references/hook-events.mdfor detailed event documentation with input/output schemas - Example Configurations: See
references/examples.mdfor complete, tested hook configurations