Guide for implementing Claude Code hooks. Use when creating event-driven automation, auto-linting, validation, or context injection. Covers all hook events, matchers, exit codes, and environment variables.
Creates event-driven automation for Claude Code using hooks that execute at specific workflow points.
/plugin marketplace add hgeldenhuys/claude-code-sdk/plugin install hgeldenhuys-session-naming@hgeldenhuys/claude-code-sdkThis skill is limited to using the following tools:
EVENTS.mdEXAMPLES.mdFRONTMATTER-HOOKS.mdTROUBLESHOOTING.mdBuild event-driven automation for Claude Code using hooks - scripts that execute at specific workflow points.
| Hook Event | When It Fires | Uses Matcher | Common Use Cases |
|---|---|---|---|
PreToolUse | Before tool executes | Yes | Validation, auto-approval, input modification |
PostToolUse | After tool completes | Yes | Auto-formatting, linting, logging |
PermissionRequest | User shown permission dialog | Yes | Auto-allow/deny, policy enforcement |
Notification | Claude sends notification | Yes | Custom alerts, logging |
UserPromptSubmit | User submits prompt | No | Prompt validation, context injection |
Stop | Main agent finishes | No | Task completion checks, force continue |
SubagentStop | Subagent (Task) finishes | No | Subagent task validation |
PreCompact | Before context compaction | Yes | Custom compaction handling |
SessionStart | Session begins/resumes | Yes | Context loading, env setup |
SessionEnd | Session ends | No | Cleanup, logging |
Hooks are configured in settings files (in order of precedence):
| Location | Scope | Committed |
|---|---|---|
~/.claude/settings.json | User (all projects) | No |
.claude/settings.json | Project | Yes |
.claude/settings.local.json | Local project | No |
| Enterprise managed policy | Organization | Yes |
{
"hooks": {
"EventName": [
{
"matcher": "ToolPattern",
"hooks": [
{
"type": "command",
"command": "your-command-here",
"timeout": 30
}
]
}
]
}
}
| Pattern | Matches | Example |
|---|---|---|
Write | Exact tool name | Only Write tool |
Edit|Write | Regex OR | Edit or Write |
Notebook.* | Regex wildcard | NotebookEdit, NotebookRead |
mcp__memory__.* | MCP server tools | All memory server tools |
* or "" | All tools | Any tool |
Note: Matchers are case-sensitive and only apply to PreToolUse, PostToolUse, and PermissionRequest.
| Type | Description | Key Field |
|---|---|---|
command | Execute bash script | command: bash command to run |
prompt | LLM-based evaluation | prompt: prompt text for Haiku |
| Option | Type | Description |
|---|---|---|
timeout | number | Timeout in seconds (default: 60, max: 600 as of 2.1.3) |
once | boolean | Run only once per session (frontmatter hooks only) |
Note: As of 2.1.3, the maximum hook timeout was increased from 60 seconds to 10 minutes (600s).
| Exit Code | Meaning | Behavior |
|---|---|---|
0 | Success | Continue normally. stdout parsed for JSON control |
2 | Blocking error | Block action. stderr shown to Claude |
| Other | Non-blocking error | Log warning. Continue normally |
| Event | Exit Code 2 Effect |
|---|---|
PreToolUse | Blocks tool call, stderr to Claude |
PermissionRequest | Denies permission, stderr to Claude |
PostToolUse | stderr to Claude (tool already ran) |
UserPromptSubmit | Blocks prompt, erases it, stderr to user |
Stop / SubagentStop | Blocks stoppage, stderr to Claude |
Notification / SessionStart / SessionEnd / PreCompact | stderr to user only |
| Variable | Description | Available In |
|---|---|---|
CLAUDE_PROJECT_DIR | Absolute path to project root | All hooks |
CLAUDE_PLUGIN_ROOT | Absolute path to plugin directory | Plugin hooks only |
CLAUDE_ENV_FILE | File path for persisting env vars | SessionStart only |
CLAUDE_CODE_REMOTE | "true" if running in web environment | All hooks |
All hooks receive JSON via stdin with common fields:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.jsonl",
"cwd": "/current/directory",
"permission_mode": "default",
"hook_event_name": "EventName"
}
Permission modes: default, plan, acceptEdits, dontAsk, bypassPermissions
Use PreToolUse to:
Use PostToolUse to:
Use PermissionRequest to:
Use UserPromptSubmit to:
Use SessionStart to:
Use SessionEnd to:
Use Stop / SubagentStop to:
Use PreCompact to:
Use Notification to:
Create hook script
Configure in settings
Test
claude --debug to see hook execution/hooks menu for registrationchmod +x)Common patterns for hooks targeting specific tools.
Validate commands before execution, log sensitive operations, or block dangerous commands.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate-bash.sh"
}
]
}
]
}
}
Common validations:
rm -rf / patternssudo commandsValidate file paths, enforce naming conventions, or auto-format after write.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/after-write.sh"
}
]
}
]
}
}
Common patterns:
Validate edits, prevent changes to critical files, or run linting after edits.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate-edit.sh"
}
]
}
]
}
}
Common patterns:
Log file access, validate read permissions, or inject context based on files read.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate-read.sh"
}
]
}
]
}
}
Common patterns:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/format.sh"
}
]
}
]
}
}
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "echo \"Git branch: $(git branch --show-current)\""
}
]
}
]
}
}
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/approve-docs.py"
}
]
}
]
}
}
| Issue | Solution |
|---|---|
| Hook not running | Check /hooks menu, verify JSON syntax |
| Wrong matcher | Tool names are case-sensitive |
| Command not found | Use absolute paths or $CLAUDE_PROJECT_DIR |
| Script not executing | Check permissions (chmod +x) |
| Exit code ignored | Only 0, 2, and other are recognized |
Run with debug mode:
claude --debug
"$VAR" not $VAR)..).env, keys)Hooks can also be defined directly in YAML frontmatter of Skills, Agents, and Slash Commands. These hooks are:
Supported events: PreToolUse, PostToolUse, Stop
---
name: my-skill
description: A skill with lifecycle hooks
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./validate.sh"
once: true
---
| Aspect | Settings Hooks | Frontmatter Hooks |
|---|---|---|
| Location | settings.json | Skill/Agent/Command YAML |
| Scope | Global or project | Component lifecycle |
| Events | All 10 events | PreToolUse, PostToolUse, Stop |
| Cleanup | Manual | Automatic |
once option | No | Yes |
See FRONTMATTER-HOOKS.md for complete documentation.
| File | Contents |
|---|---|
| EVENTS.md | Detailed event documentation with input/output schemas |
| EXAMPLES.md | Complete working examples |
| FRONTMATTER-HOOKS.md | Frontmatter hooks in skills, agents, commands |
| TROUBLESHOOTING.md | Common issues and solutions |
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.