Create hooks for Claude Code automation. USE WHEN user says 'create a hook', 'add a hook', 'automate when', 'trigger when', 'run automatically', 'after I save', 'before I commit', 'when file changes'.
Teaches Claude how to create automation hooks that trigger on specific events.
A hook is automation that runs when something happens. Hooks live in .claude/settings.json.
Key insight: Hooks make Claude proactive, not just reactive.
When creating a NEW hook, guide the user through these phases:
Ask the user:
Goal: Identify the event and matcher
Ask the user:
Goal: Determine hook type and action
| Event | When It Fires | Common Use |
|---|---|---|
PreToolUse |
Before a tool runs | Validate, confirm dangerous actions |
PostToolUse |
After a tool runs | Lint, format, organize files |
Stop |
Claude stops responding | Session summary, reminders |
SubagentStop |
An agent completes | Process agent results |
UserPromptSubmit |
User sends message | Input validation |
Claude evaluates the prompt and decides what to do:
{
"type": "prompt",
"prompt": "If a file was created in the wrong location, suggest moving it."
}
Use when: You need Claude's judgment
Runs a bash command automatically:
{
"type": "command",
"command": "npm run lint --fix"
}
Use when: You want a specific command to run
Matchers filter which tools trigger the hook:
| Matcher | What It Matches |
|---|---|
Write |
Only Write tool |
Write|Edit |
Write OR Edit tools |
Bash |
Any Bash command |
Bash(git:*) |
Only git commands |
.* |
All tools (use carefully) |
{
"permissions": {
"allow": ["Read", "Glob", "Grep"]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "prompt",
"prompt": "Your instruction here"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "Summarize what was accomplished"
}
]
}
]
}
}
{
"matcher": "Write|Edit",
"hooks": [{
"type": "prompt",
"prompt": "Check if a skill was just created or renamed in .claude/skills/. If so, update the CLAUDE.md routing table to include it."
}]
}
{
"matcher": "Write",
"hooks": [{
"type": "prompt",
"prompt": "If a file was just created in the project root, suggest moving it to the appropriate folder (content/, research/, data/, exports/)."
}]
}
{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "npm run lint --fix"
}]
}
{
"hooks": [{
"type": "prompt",
"prompt": "Summarize what was accomplished this session in 2-3 bullet points."
}]
}
(Note: Stop hooks don't use matchers)
{
"matcher": "Write|Edit",
"hooks": [{
"type": "prompt",
"prompt": "If 5+ files have been modified, remind the user to commit their changes."
}]
}
{
"matcher": "Bash",
"hooks": [{
"type": "prompt",
"prompt": "Check if this command could delete files or make irreversible changes. If so, warn the user."
}]
}
When user wants to create a hook:
Before finalizing a hook, verify:
.* unless needed).* triggers on everything, use specific matchersLocation: .claude/settings.json → hooks section
Events: PreToolUse, PostToolUse, Stop, SubagentStop, UserPromptSubmit