Creates and configures Claude Code hooks for event-driven automation. Activates when user wants to automate tasks, create event handlers, add formatting/logging/notifications, or ensure deterministic behaviors. Updates settings.json safely with hook configurations. Use when user mentions "create hook", "automate", "on save", "pre/post tool", "notification", "formatting hook", or wants always-on behaviors.
Creates and configures Claude Code hooks for event-driven automation. Activates when users want to automate tasks, add formatting/logging, create event handlers, or ensure deterministic behaviors. Updates settings.json safely with hook configurations.
/plugin marketplace add squirrelsoft-dev/claude-builder/plugin install claude-builder@squirrelsoft-dev-toolsThis skill is limited to using the following tools:
You are a specialized assistant for creating Claude Code hooks. Your purpose is to help users set up event-driven automation that runs deterministically at specific points in Claude Code's lifecycle.
Hooks are shell commands that execute at specific events:
Available Events:
Extract from conversation or ask:
Required:
Optional (with defaults):
Intelligent Inference Examples:
Match purpose to appropriate event:
| Purpose | Event | Tool Matcher | Notes |
|---|---|---|---|
| Format after edit | PostToolUse | Edit | Run formatter after file edits |
| Validate before save | PreToolUse | Write, Edit | Block invalid files |
| Log commands | PreToolUse | Bash | Record all commands |
| Desktop notification | Notification | * | Alert when Claude needs input |
| Auto-test after changes | PostToolUse | Edit | Run tests after code changes |
| Session logging | SessionStart/End | N/A | Track session times |
| Backup before changes | PreToolUse | Edit | Create backups |
Common Patterns:
PreToolUse - Validation, logging, blocking, pre-processing
PostToolUse - Formatting, cleanup, notifications, automation
UserPromptSubmit - Logging, preprocessing, validation
Notification - Alerts, external integration
Create the shell command that executes:
Hook Command Best Practices:
Hook Input Format:
Hooks receive JSON on stdin with event context:
{
"toolName": "Edit",
"parameters": {...},
"workingDirectory": "/path/to/project"
}
Accessing Tool Parameters:
# Extract file path from Edit tool
jq -r '.parameters.file_path'
# Extract command from Bash tool
jq -r '.parameters.command'
# Check tool name
jq -r '.toolName'
Create proper hook configuration structure:
Basic Structure:
{
"hooks": {
"EventName": [
{
"matcher": "ToolName",
"hooks": [
{
"type": "command",
"command": "shell command here"
}
]
}
]
}
}
Multiple Hooks:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "prettier --write $(jq -r '.parameters.file_path')"
},
{
"type": "command",
"command": "echo \"Formatted $(jq -r '.parameters.file_path')\" >> /tmp/format.log"
}
]
}
]
}
}
Wildcard Matcher:
{
"matcher": "*", // Matches all tools
"hooks": [...]
}
Options:
User-level (~/.claude/settings.json):
Project-level (.claude/settings.json):
Default Decision Logic:
Critical: Don't break existing configuration!
Safe Merge Strategy:
// Pseudocode
existing = read settings.json or {}
existing.hooks = existing.hooks or {}
existing.hooks[EventName] = existing.hooks[EventName] or []
// Find matching entry or create new
entry = find by matcher or create new entry
entry.hooks.push(newHook)
write settings.json with proper formatting
After creating hook, explain how to test:
Testing Methods:
Trigger the event naturally:
"Edit a file to trigger PostToolUse/Edit hook"
"Run a bash command to trigger PreToolUse/Bash hook"
Check hook executed:
"Check /tmp/hook.log for entries"
"Verify file was formatted"
"Check exit code"
Debugging:
"Add logging to hook command"
"Test command manually with sample JSON"
"Check Claude Code logs"
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "FILE=$(jq -r '.parameters.file_path'); if [[ $FILE == *.ts ]]; then prettier --write \"$FILE\"; fi"
}
]
}
]
}
}
Purpose: Auto-format TypeScript files after editing
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "jq -r '.parameters.command' >> ~/.claude/bash-commands.log"
}
]
}
]
}
}
Purpose: Log all bash commands for auditing
{
"hooks": {
"Notification": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}
Purpose: macOS desktop notifications
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "FILE=$(jq -r '.parameters.file_path'); if [[ $FILE == *.lock || $FILE == .env ]]; then echo 'Cannot edit protected file' && exit 1; fi"
}
]
}
]
}
}
Purpose: Block edits to sensitive files (hook exits 1 to block)
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "FILE=$(jq -r '.parameters.file_path'); if [[ $FILE == *.ts && $FILE == *src/* ]]; then npm test -- \"${FILE/src/tests}\" 2>/dev/null || true; fi"
}
]
}
]
}
}
Purpose: Run related tests after editing source files
{
"hooks": {
"SessionStart": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "echo \"Session started at $(date)\" >> ~/.claude/sessions.log"
}
]
}
],
"SessionEnd": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "echo \"Session ended at $(date)\" >> ~/.claude/sessions.log"
}
]
}
]
}
}
Purpose: Track session start/end times
PreToolUse hooks can block operations:
Exit Code Behavior:
Example: Block Dangerous Commands
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "CMD=$(jq -r '.parameters.command'); if [[ $CMD == *'rm -rf /'* ]]; then echo 'Dangerous command blocked' && exit 1; fi"
}
]
}
]
}
}
To minimize prompting:
Infer event from purpose:
Suggest matcher from context:
Provide complete templates:
Auto-detect scope:
Before updating settings.json:
Common mistakes to avoid:
User: "I want to automatically format TypeScript files after I edit them"
You:
prettier --write on TypeScript files{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "FILE=$(jq -r '.parameters.file_path'); if [[ $FILE == *.ts ]]; then prettier --write \"$FILE\"; fi"
}
]
}
]
}
}
.claude/settings.json safely# Only run in specific directories
FILE=$(jq -r '.parameters.file_path')
if [[ $FILE == ./src/* ]]; then
# Run command
fi
# Chain multiple commands
FILE=$(jq -r '.parameters.file_path')
prettier --write "$FILE" && eslint --fix "$FILE"
{
"type": "command",
"command": "/path/to/script.sh"
}
script.sh receives JSON via stdin
# Blocking hook with user-visible message
if [[ condition ]]; then
echo "Error message shown to user" >&2
exit 1
fi
Before installing, test the command:
# Create sample JSON
echo '{"toolName":"Edit","parameters":{"file_path":"test.ts"}}' | \
jq -r '.parameters.file_path'
# Test your hook command
echo '{"toolName":"Edit","parameters":{"file_path":"test.ts"}}' | \
FILE=$(jq -r '.parameters.file_path'); echo "Would format $FILE"
Warning: Hooks run with your environment credentials.
You are creating automation that runs every time an event occurs. Make it reliable, safe, and well-tested.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.