Run your setup commands that modify the environment
[Skip to main content](https://code.claude.com/docs/en/hooks#content-area)
Overview
English
Search...
⌘KAsk AI
Search...
Navigation
Reference
Hooks reference
Getting started Build with Claude Code Deployment Administration Configuration Reference Resources
On this page
- Hook lifecycle
- Configuration
- Structure
- Project-Specific Hook Scripts
- Plugin hooks
- Hooks in skills and agents
- Prompt-Based Hooks
- How prompt-based hooks work
- Configuration
- Response schema
- Supported hook events
- Example: Intelligent Stop hook
- Example: SubagentStop with custom logic
- Comparison with bash command hooks
- Best practices
- Hook Events
- PreToolUse
- PermissionRequest
- PostToolUse
- Notification
- UserPromptSubmit
- Stop
- SubagentStop
- PreCompact
- Setup
- SessionStart
- Persisting environment variables
- SessionEnd
- Hook Input
- PreToolUse Input
- Bash tool
- Write tool
- Edit tool
- Read tool
- PostToolUse Input
- Notification Input
- UserPromptSubmit Input
- Stop Input
- SubagentStop Input
- PreCompact Input
- Setup Input
- SessionStart Input
- SubagentStart Input
- SessionEnd Input
- Hook Output
- Simple: Exit Code
- Exit Code 2 Behavior
- Advanced: JSON Output
- Common JSON Fields
- PreToolUse Decision Control
- PermissionRequest Decision Control
- PostToolUse Decision Control
- UserPromptSubmit Decision Control
- Stop/SubagentStop Decision Control
- Setup Decision Control
- SessionStart Decision Control
- SessionEnd Decision Control
- Exit Code Example: Bash Command Validation
- JSON Output Example: UserPromptSubmit to Add Context and Validation
- JSON Output Example: PreToolUse with Approval
- Working with MCP Tools
- MCP Tool Naming
- Configuring Hooks for MCP Tools
- Examples
- Security Considerations
- Disclaimer
- Security Best Practices
- Configuration Safety
- Hook Execution Details
- Debugging
- Basic Troubleshooting
- Advanced Debugging
- Debug Output Example
For a quickstart guide with examples, see Get started with Claude Code hooks.
Hook lifecycle
Hooks fire at specific points during a Claude Code session.

| Hook | When it fires |
|---|---|
SessionStart | Session begins or resumes |
UserPromptSubmit | User submits a prompt |
PreToolUse | Before tool execution |
PermissionRequest | When permission dialog appears |
PostToolUse | After tool succeeds |
PostToolUseFailure | After tool fails |
SubagentStart | When spawning a subagent |
SubagentStop | When subagent finishes |
Stop | Claude finishes responding |
PreCompact | Before context compaction |
SessionEnd | Session terminates |
Notification | Claude Code sends notifications |
Configuration
Claude Code hooks are configured in your settings files:
~/.claude/settings.json\- User settings.claude/settings.json\- Project settings.claude/settings.local.json\- Local project settings (not committed)- Managed policy settings
Enterprise administrators can use allowManagedHooksOnly to block user, project, and plugin hooks. See Hook configuration.
Structure
Hooks are organized by matchers, where each matcher can have multiple hooks:
Copy
Ask AI
{
"hooks": {
"EventName": [\\
{\\
"matcher": "ToolPattern",\\
"hooks": [\\
{\\
"type": "command",\\
"command": "your-command-here"\\
}\\
]\\
}\\
]
}
}
- matcher: Pattern to match tool names, case-sensitive (only applicable for
PreToolUse,PermissionRequest, andPostToolUse)- Simple strings match exactly:
Writematches only the Write tool - Supports regex:
Edit|WriteorNotebook.* - Use
*to match all tools. You can also use empty string ("") or leavematcherblank.
- Simple strings match exactly:
- hooks: Array of hooks to execute when the pattern matches
type: Hook execution type -"command"for bash commands or"prompt"for LLM-based evaluationcommand: (Fortype: "command") The bash command to execute (can use$CLAUDE_PROJECT_DIRenvironment variable)prompt: (Fortype: "prompt") The prompt to send to the LLM for evaluationtimeout: (Optional) How long a hook should run, in seconds, before canceling that specific hook
For events like UserPromptSubmit, Stop, SubagentStop, and Setup
that don’t use matchers, you can omit the matcher field:
Copy
Ask AI
{
"hooks": {
"UserPromptSubmit": [\\
{\\
"hooks": [\\
{\\
"type": "command",\\
"command": "/path/to/prompt-validator.py"\\
}\\
]\\
}\\
]
}
}
Project-Specific Hook Scripts
You can use the environment variable CLAUDE_PROJECT_DIR (only available when
Claude Code spawns the hook command) to reference scripts stored in your project,
ensuring they work regardless of Claude’s current directory:
Copy
Ask AI
{
"hooks": {
"PostToolUse": [\\
{\\
"matcher": "Write|Edit",\\
"hooks": [\\
{\\
"type": "command",\\
"command": "\\"$CLAUDE_PROJECT_DIR\\"/.claude/hooks/check-style.sh"\\
}\\
]\\
}\\
]
}
}
Plugin hooks
Plugins can provide hooks that integrate seamlessly with your user and project hooks. Plugin hooks are automatically merged with your configuration when plugins are enabled.How plugin hooks work:
- Plugin hooks are defined in the plugin’s
hooks/hooks.jsonfile or in a file given by a custom path to thehooksfield. - When a plugin is enabled, its hooks are merged with user and project hooks
- Multiple hooks from different sources can respond to the same event
- Plugin hooks use the
${CLAUDE_PLUGIN_ROOT}environment variable to reference plugin files
Example plugin hook configuration:
Copy
Ask AI
{
"description": "Automatic code formatting",
"hooks": {
"PostToolUse": [\\
{\\
"matcher": "Write|Edit",\\
"hooks": [\\
{\\
"type": "command",\\
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",\\
"timeout": 30\\
}\\
]\\
}\\
]
}
}
Plugin hooks use the same format as regular hooks with an optional description field to explain the hook’s purpose.
Plugin hooks run alongside your custom hooks. If multiple hooks match an event, they all execute in parallel.
Environment variables for plugins:
${CLAUDE_PLUGIN_ROOT}: Absolute path to the plugin directory${CLAUDE_PROJECT_DIR}: Project root directory (same as for project hooks)- All standard environment variables are available
See the plugin components reference for details on creating plugin hooks.
Hooks in skills and agents
In addition to settings files and plugins, hooks can be defined directly in skills and subagents using frontmatter. These hooks are scoped to the component’s lifecycle and only run when that component is active.Supported events: PreToolUse, PostToolUse, and StopExample in a Skill:
Copy
Ask AI
---
name: secure-operations
description: Perform operations with security checks
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/security-check.sh"
---
Example in an agent:
Copy
Ask AI
---
name: code-reviewer
description: Review code changes
hooks:
PostToolUse:
- matcher: "Edit|Write"
hooks:
- type: command
command: "./scripts/run-linter.sh"
---
Component-scoped hooks follow the same configuration format as settings-based hooks but are automatically cleaned up when the component finishes executing.Additional option for skills:
once: Set totrueto run the hook only once per session. After the first successful execution, the hook is removed. Note: This option is currently only supported for skills, not for agents.
Prompt-Based Hooks
In addition to bash command hooks (type: "command"), Claude Code supports prompt-based hooks (type: "prompt") that use an LLM to evaluate whether to allow or block an action. Prompt-based hooks are currently only supported for Stop and SubagentStop hooks, where they enable intelligent, context-aware decisions.
How prompt-based hooks work
Instead of executing a bash command, prompt-based hooks:
- Send the hook input and your prompt to a fast LLM (Haiku)
- The LLM responds with structured JSON containing a decision
- Claude Code processes the decision automatically
Configuration
Copy
Ask AI
{
"hooks": {
"Stop": [\\