Hook automation
Hook lifecycle events, matchers, command/http/mcp_tool/prompt/agent handlers, and common automation templates.
Hooks are Claude Code's automation layer. They run scripts, HTTP requests, MCP tools, or model checks at session startup, prompt submission, tool execution, configuration changes, compaction, and other lifecycle points.
Use hooks to turn team conventions into mechanisms: formatting, auditing, blocking commands, recording tool calls, and notifying when long tasks finish.
#Lifecycle
| Frequency | Example events | Purpose |
|---|---|---|
| Session | SessionStart, SessionEnd, Setup | Initialize environment, show instructions, record sessions |
| Conversation turn | UserPromptSubmit, Stop, StopFailure | Check prompts, notify completion, diagnose errors |
| Tool call | PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure | Block, audit, format, validate |
| Batches/subagents | PostToolBatch, SubagentStart, SubagentStop, TaskCreated, TaskCompleted | Track parallel work |
| Configuration/context | InstructionsLoaded, ConfigChange, CwdChanged, FileChanged, PreCompact, PostCompact | Observe settings and memory loading |
| MCP interaction | Elicitation, ElicitationResult | Handle MCP requests for user input |
Common events:
PreToolUse: before execution; can prevent an operation.PostToolUse: after success; format or run a lightweight check.UserPromptSubmit: before the prompt reaches the model; validate or add context.Stop: after a response; notify or record completion.ConfigChange: settings, hooks, or rules change.FileChanged: watch selected files such as.envrcor lockfiles.
#Basic configuration
Put hooks in a settings file:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npm run lint -- --quiet"
}
]
}
]
}
}There are three levels:
- Event, such as PreToolUse.
- Matcher group, such as Bash only.
- Handler: command, http, mcp_tool, prompt, or agent.
#Matcher rules
| Pattern | Meaning | Example | |
|---|---|---|---|
Omitted, empty, or * | Match all | Every tool call | |
Bash | Exact tool name | Bash only | |
| `Edit | Write` | Multiple tool names | After file edits |
mcp__memory__.* | Regular expression | All tools from the memory server |
For tool events, an if field can narrow the match:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm *)",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
}
]
}
]
}
}if uses permission-rule syntax. Compound Bash commands are checked by subcommand, not only against the complete line.
#Handler types
| Type | Behavior | Use |
|---|---|---|
| command | Local command receiving JSON on stdin | Formatting, auditing, blocking |
| http | POST JSON to a URL | Central audits and notifications |
| mcp_tool | Call a connected MCP tool | Server-hosted checks |
| prompt | Single-turn model judgment | Lightweight semantic checks |
| agent | Start a verifying subagent | File reads and complex checks |
Command stdin is event JSON. Output can be empty or a JSON decision.
#Block destructive commands
#!/usr/bin/env bash
set -euo pipefail
COMMAND=$(jq -r '.tool_input.command // ""')
if echo "$COMMAND" | grep -Eq 'rm -rf (~/|/|\\$HOME)'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Refuse to remove home or root paths"
}
}'
fiCorresponding configuration:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm *)",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh"
}
]
}
]
}
}A silent hook does not approve the action. Empty output or exit 0 continues the normal permission flow. This pattern is an example, not comprehensive shell isolation.
#Automatic formatting
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npm run lint -- --fix"
}
]
}
]
}
}Do not run a full build after every edit in a large project. Keep hooks short, stable, and predictable; run comprehensive validation deliberately at task completion.
#Configuration locations
| Location | Scope |
|---|---|
~/.claude/settings.json | Personal global hooks |
.claude/settings.json | Shared project hooks |
.claude/settings.local.json | Personal project hooks |
| Managed settings | Enforced organization hooks |
| Plugin hooks | Loaded when the plugin is enabled |
| Skill/agent frontmatter | Loaded when the skill or agent activates |
#Troubleshooting
| Symptom | Check |
|---|---|
| Hook did not fire | Inspect loaded hooks and matchers in /hooks |
| Settings edit did not apply | Check ConfigChange and valid JSON |
| Command not found | Use an absolute path or ${CLAUDE_PROJECT_DIR} |
| Too slow | Narrow with if and avoid unnecessary process starts |
| MCP tool not matched | Use mcp__server__tool |
| Suspected custom configuration interference | Try claude --safe-mode temporarily |
#Official references
Support
Need help?
For setup, billing, or model issues, email us. Check the status page for uptime.
WeChat / QQ support is available at the bottom right.

