Claude Code Hooks: Complete Documentation and Reference
Learn everything about Claude Code hooks — pre-action and post-action hooks, configuration, practical examples, and best practices for automating your development workflow.
Claude Code hooks let you run custom shell commands before or after Claude performs actions like file edits, command execution, or tool calls. Configure hooks in your `.claude/settings.json` file to automate workflows like running linters, formatting code, or triggering deployments.
What are Claude Code Hooks?
Hooks are shell commands that execute automatically in response to events in Claude Code. They allow you to integrate custom automation into your AI-assisted development workflow. Hooks run before (pre) or after (post) specific actions, giving you fine-grained control over how Claude Code interacts with your project.
Hook Types
Pre-Action Hooks
Pre-action hooks run before Claude Code performs an action. They can be used to:
- Validate changes before they happen
- Set up environment requirements
- Prevent unwanted actions by returning a non-zero exit code
- Prepare context or state
Post-Action Hooks
Post-action hooks run after Claude Code completes an action. They are useful for:
- Running linters and formatters on changed files
- Triggering builds or tests
- Sending notifications
- Updating documentation
- Committing changes to version control
Configuration
Hooks are configured in your project's .claude/settings.json file:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "echo 'About to modify a file'"
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "npx prettier --write $CLAUDE_FILE_PATH"
}
],
"Notification": [
{
"command": "osascript -e 'display notification \"Claude Code finished\" with title \"BeClaude\"'"
}
],
"Stop": [
{
"command": "echo 'Claude Code session ended'"
}
]
}
}
Hook Events
| Event | When it fires | Use case |
|---|---|---|
PreToolUse | Before a tool is used | Validate inputs, block certain actions |
PostToolUse | After a tool is used | Format code, run linters |
Notification | When Claude sends a notification | Custom alerts, logging |
Stop | When Claude stops generating | Cleanup, final checks |
Matcher Patterns
Matchers use regex patterns to filter which tools trigger the hook:
Edit|Write— Match file modification toolsBash— Match shell command execution.*— Match all toolsRead— Match file reads
Environment Variables
Hooks receive these environment variables:
CLAUDE_TOOL_NAME— The name of the tool being usedCLAUDE_FILE_PATH— The file path (for file-related tools)CLAUDE_SESSION_ID— The current session identifier
Practical Examples
1. Auto-format on File Changes
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\" 2>/dev/null || true"
}
]
}
}
2. Lint Check Before Edits
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "npx eslint --no-warn-ignored \"$CLAUDE_FILE_PATH\" || exit 1"
}
]
}
}
3. Auto-run Tests After Changes
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "npm test -- --related \"$CLAUDE_FILE_PATH\" --passWithNoTests"
}
]
}
}
4. Desktop Notifications
{
"hooks": {
"Notification": [
{
"command": "osascript -e 'display notification \"$CLAUDE_TOOL_NAME completed\" with title \"Claude Code\"'"
}
]
}
}
5. Block Sensitive File Modifications
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "echo \"$CLAUDE_FILE_PATH\" | grep -qE '\\.(env|secret|key)$' && exit 1 || exit 0"
}
]
}
}
Best Practices
- Keep hooks fast — Hooks run synchronously and block Claude Code while executing. Keep them under a few seconds.
- Use graceful error handling — Append
|| trueto commands that shouldn't block Claude's workflow. - Test hooks incrementally — Start with simple hooks and add complexity gradually.
- Use matchers wisely — Be specific with matchers to avoid running hooks unnecessarily.
- Document your hooks — Add comments in your settings file explaining what each hook does.
- Consider project-level vs user-level — Put project-specific hooks in
.claude/settings.jsonand personal preferences in~/.claude/settings.json. - Handle edge cases — Account for missing files, network issues, and other failure modes.
Troubleshooting
Hooks not running:- Verify the JSON syntax in your settings file is valid
- Check that the command is executable (try running it manually)
- Ensure the matcher pattern matches the tool name
- Pre-hooks returning non-zero exit codes will block the action
- Use
|| trueto prevent accidental blocking - Check hook command output for errors
- Profile your hooks with
timeto identify slow commands - Consider using incremental tools (e.g.,
--relatedflags for test runners) - Avoid hooks that trigger full project scans