Hooks System
Customize Claude Code behavior with Hooks β auto-formatting, security interception, notifications, and more
Hooks System¶
Hooks allow you to insert custom logic at key lifecycle points in Claude Code, such as automatically formatting code, intercepting dangerous commands, sending notifications, and more.
Core Concepts¶
Each Hook consists of three parts:
-
Event: When it triggers (e.g.,
PreToolUseβ before a tool executes) -
Matcher: Optional tool name filter (e.g., match only
BashorWrite) -
Handler: Shell command, prompt, or sub-agent
Common Events¶
| Event | When It Triggers | Can Block? | Typical Use Cases |
|---|---|---|---|
PreToolUse |
Before tool execution | Yes (exit code 2) | Security interception, file protection |
PostToolUse |
After tool execution | No | Auto lint/formatting |
Notification |
When Claude sends a notification | No | Slack/webhook alerts |
UserPromptSubmit |
When user submits a prompt | Yes | Context augmentation |
Stop |
When Claude finishes responding | No | Quality checks, summaries |
SessionStart |
When a session starts | No | Environment initialization |
Configuration¶
Add hooks to .claude/settings.json (project-level) or ~/.claude/settings.json (user-level):
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "prettier --write $FILEPATH"
}
]
}
]
}
}
Practical Examples¶
1. Auto-format After File Save¶
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $FILEPATH"
}
]
}
]
}
}
2. Block Dangerous Shell Commands¶
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo $TOOL_INPUT | grep -qE 'rm -rf|sudo|git push --force' && exit 2 || exit 0"
}
]
}
]
}
}
exit 2blocks tool execution;exit 0allows it to proceed.
3. Protect Sensitive Files from Being Read¶
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "echo $TOOL_INPUT | grep -qE '\\.env|credentials|secret' && exit 2 || exit 0"
}
]
}
]
}
}
4. Send Notification on Task Completion¶
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"$NOTIFICATION_MESSAGE\" with title \"Claude Code\"'"
}
]
}
]
}
}
Input/Output Mechanism¶
-
Hook scripts receive JSON data via stdin (containing
session_id,tool_name,tool_input) -
Environment variables:
$FILEPATH,$TOOL_INPUT,$NOTIFICATION_MESSAGE, etc. -
PreToolUse exit codes:
0= allow,2= block
Debugging Tips¶
-
Press
Ctrl+Oto enable verbose mode and view hook stdout/stderr output -
Before deploying a hook script, test it manually in the terminal to verify the logic
Important Notes¶
-
Hook scripts should not take too long to execute, as they will block Claude Code's interaction
-
Project-level hooks take priority over user-level hooks
-
Enterprise plans can enforce organization-wide security hooks via
managed-settings.json
Next Steps¶
-
See Skills for more advanced extensibility
-
See MCP Servers for external tool integration
-
See CLI Tips for command-line usage tips