Chapter 13 · Hooks Automation
Chapter goals: Understand Claude Code's Hooks mechanism — automatically executing custom commands at key tool call lifecycle nodes to实现 code formatting, security audits, notification pushing, and other automations.
13.1 What Are Hooks
Hooks are shell commands that Claude Code自动 executes at specific lifecycle nodes. You don't手动 trigger them — they run automatically on every tool call.
User input → Claude thinks → Calls a tool
↑
PreToolUse hook (intercept before execution)
↓
Tool actually executes
↓
PostToolUse hook (post-processing)Core value: turn engineering conventions from "verbal agreements" into "forced execution." For example, if you tell Claude "run lint after every code write," it might forget; but configure a PostToolUse hook, and lint runs自动 after every file write — impossible to bypass.
13.2 Hook Types
Claude Code supports the following hook events:
| Event | Trigger Timing | Typical Use |
|---|---|---|
PreToolUse | Before tool call | Intercept dangerous commands; block writing to sensitive files |
PostToolUse | After tool call | Auto-format, run tests, update indexes |
Notification | When Claude sends a notification | Push to Slack/DingTalk/desktop notification |
Stop | When Claude completes a response | Send completion notification; trigger CI |
SubagentStop | When a sub-agent completes | Collect子代理 results |
13.3 Configuring Hooks
Configure hooks in .claude/settings.json (project-level) or ~/.claude/settings.json (global):
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "npx prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo \"$TOOL_INPUT\" | grep -q 'rm -rf /' && echo 'BLOCK: Dangerous command' && exit 1 || exit 0"
}
]
}
],
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "osascript -e 'display notification \"Claude Code needs your attention\" with title \"Claude Code\"'"
}
]
}
]
}
}Key concepts:
matcher: regex matching tool names (Write|Editmatches write-file tools);command: the shell command to execute;- Exit code:
exit 0to continue,exit 1to block (only effective for PreToolUse).
13.4 Practical Scenarios
Scenario 1: Auto-format After Writing Files
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{ "type": "command", "command": "npx prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true" },
{ "type": "command", "command": "npx eslint --fix \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true" }
]
}
]
}
}Every time Claude writes code, prettier and eslint run自动 — code style never drifts.
Scenario 2: Block Modifications to Sensitive Files
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "echo \"$CLAUDE_FILE_PATHS\" | grep -qE '(\\.env|credentials|secrets)' && echo 'BLOCK: Sensitive files cannot be modified' && exit 1 || exit 0"
}
]
}
]
}
}Any attempt to modify .env, credentials, or other sensitive files is自动 intercepted.
Scenario 3: Slack Notification
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "curl -s -X POST $SLACK_WEBHOOK -H 'Content-Type: application/json' -d '{\"text\":\"Claude Code: needs human confirmation\"}'"
}
]
}
]
}
}13.5 Debugging Hooks
Troubleshooting steps when hooks don't take effect:
# 1. Confirm settings.json syntax is correct
cat .claude/settings.json | python3 -m json.tool
# 2. Test the hook command manually
echo '{"file_path": "/tmp/test.ts"}' | npx prettier --stdin-filepath test.ts
# 3. Check Claude Code's hook logs
claude --debugSecurity Reminder
Hooks execute arbitrary shell commands with your user权限. Do not blindly accept hooks configurations in untrusted projects — a malicious hook can do anything. Claude Code will ask you to confirm the first time it encounters new hooks.
Chapter Summary
- Hooks自动 execute at tool call lifecycle nodes; turn conventions from "agreements" into "enforcement";
- Five events: PreToolUse (intercept), PostToolUse (post-process), Notification, Stop, SubagentStop;
- Configured in settings.json;
matchermatches tool names;exit 1blocks execution; - Typical scenarios: auto-formatting, sensitive file protection, notification pushing.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. To auto-run prettier after Claude writes a file each time, which hook event should be used?
2. What happens when a PreToolUse hook's command returns exit 1?
3. What is the purpose of the matcher field in hooks configuration?
4. Regarding hook security, what is the correct approach?
🛠️ Hands-on Practice
- Configure a PostToolUse hook: auto-run
ruff check --fixafter Claude writes a Python file each time. - Configure a PreToolUse hook: block any Bash命令 containing
DROP TABLEorDELETE FROM(without a WHERE clause). - Configure a Notification hook: send a system desktop notification when Claude completes a long task.
After completing, proceed to Chapter 14: IDE Integration.