Automating with Hooks
Hooks let you run scripts in response to Claude Code events, enabling powerful automation workflows.
Hook Events
| Event | Trigger | Use Case |
|-------|---------|----------|
| PreToolUse | Before a tool runs | Validation, logging |
| PostToolUse | After a tool completes | Formatting, notifications |
| Notification | Claude sends a notification | Alerts, logging |
| Stop | Session ends | Cleanup, reports |
Configuration Location
# Project-specific hooks
.claude/settings.json
# Global hooks
~/.claude/settings.jsonCreating Your First Hook
1. Create settings file
mkdir -p .claude
touch .claude/settings.json2. Add hook configuration
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
]
}
]
}
}Hook Examples
Auto-format on Edit
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
]
}
]
}
}Lint on File Changes
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx eslint --fix $CLAUDE_FILE_PATH"
}
]
}
]
}
}Desktop Notification on Complete
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code session ended\" with title \"Claude Code\"'"
}
]
}
]
}
}Log All Tool Usage
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "echo \"$(date): $CLAUDE_TOOL_NAME\" >> ~/.claude/tool-log.txt"
}
]
}
]
}
}Environment Variables
Hooks have access to these variables:
| Variable | Description | Available In |
|----------|-------------|--------------|
| $CLAUDE_TOOL_NAME | Name of the tool | All events |
| $CLAUDE_FILE_PATH | File being modified | Edit, Write |
| $CLAUDE_TOOL_INPUT | Tool input (JSON) | All events |
| $CLAUDE_TOOL_OUTPUT | Tool output | PostToolUse |
Matchers
Use regex patterns to filter which tools trigger hooks:
{
"matcher": "Edit|Write", // Multiple tools
"matcher": "Bash", // Single tool
"matcher": ".*", // All tools
"matcher": "Read|Glob|Grep" // Read operations
}Combining Multiple Hooks
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
},
{
"type": "command",
"command": "npx eslint --fix $CLAUDE_FILE_PATH"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "say 'Claude Code finished'"
}
]
}
]
}
}Best Practices
- Keep hooks fast: Slow hooks delay Claude's workflow
- Handle errors gracefully: Don't break on hook failures
- Use matchers: Only run hooks when needed
- Test thoroughly: Hooks run automatically, so test in isolation first
- Log for debugging: Add logging while developing hooks