Hooks
Event-driven automation for Claude Code's entire lifecycle
What are Hooks?
Hooks are scripts or prompts that execute in response to specific events in Claude Code. They support four types: command (shell scripts), HTTP (webhook calls), prompt (LLM-powered decisions), and agent (subagent verification). Use them to enforce policies, automate workflows, and integrate external tools.
Event-Driven
Respond to 20+ lifecycle events automatically
Four Hook Types
Command, HTTP, Prompt, and Agent hooks for different needs
Policy Enforcement
Enforce team standards, security policies, and code quality rules
External Integrations
Call webhooks, run scripts, and connect to external services
Available Hook Events (20+)
PreToolUse
Fired before Claude uses any tool. Validate, modify, or block tool usage.
PostToolUse
Fired after a tool completes successfully. Process results, trigger notifications.
UserPromptSubmit
Fired when user submits a prompt. Modify, augment, or intercept prompts.
Notification
Fired when Claude sends a notification. Customize notification behavior.
SessionStart
Fired when a Claude session starts. Initialize resources, check environment, load context.
SessionEnd
Fired when a session ends. Clean up resources, save state, generate reports.
Setup
Triggered via --init, --init-only, or --maintenance flags. For repository setup and maintenance.
SubagentStop
Fired when a subagent completes. Process results, chain tasks, notify.
SubagentStart
Fired when a subagent is about to start. Monitor, inject context, or block.
PermissionRequest
Fired when a permission is requested. Auto-approve, deny, or log requests.
PreCompact
Fired before context compaction. Save important information before context is compressed.
Prompt-Based Hooks
Use LLM-powered decision making in hooks. Describe what you want in natural language instead of writing code. The LLM evaluates the condition and returns a structured decision.
{
"hooks": {
"PreToolUse": [
{
"type": "prompt",
"matcher": { "tool": "Write" },
"prompt": "Review this file write operation. Check if it follows
our coding standards. Respond with 'allow' or 'deny'
and explain why."
}
]
}
}When to Use
- +Complex decision logic that's hard to write in code
- +Code review and quality checks
- +Context-aware validation
Response Format
{
"decision": "allow" | "deny" | "skip",
"reason": "Optional explanation",
"modifiedInput": { /* optional */ }
}Practical Examples
Auto-Format Code After Edits
Automatically run Prettier on files after Claude edits them
// Auto-format files after Edit tool
export async function postToolUse({ tool, result }) {
if (tool.name === 'Edit' && result.success) {
const { execSync } = require('child_process');
try {
execSync(`prettier --write "${tool.params.file_path}"`);
console.log('β Formatted', tool.params.file_path);
} catch (error) {
console.error('Format failed:', error.message);
}
}
}Protect Sensitive Files
Prevent Claude from editing critical configuration files
// Protect sensitive files
export async function preToolUse({ tool }) {
const protectedFiles = [
'.env',
'credentials.json',
'package-lock.json'
];
if (['Edit', 'Write'].includes(tool.name)) {
const filePath = tool.params.file_path;
if (protectedFiles.some(f => filePath.includes(f))) {
return {
allow: false,
reason: `Cannot modify protected file: ${filePath}`
};
}
}
return { allow: true };
}Send Slack Notifications via HTTP Hook
Call a webhook when deployment happens
// Notify team on deployment
export async function postToolUse({ tool, result }) {
if (tool.name === 'Bash' &&
tool.params.command.includes('deploy')) {
const webhook = process.env.SLACK_WEBHOOK;
await fetch(webhook, {
method: 'POST',
body: JSON.stringify({
text: `π Deployment completed!
Success: ${result.success}
Command: ${tool.params.command}`
})
});
}
}Security Considerations
Hooks execute code on your system. Follow these security best practices:
Never store secrets in hook files β use environment variables
Validate all inputs before executing external commands
Review hooks from external sources before using them
Use try-catch blocks to handle errors gracefully
Best Practices
Keep Hooks Simple
Each hook should do one thing well. Complex logic can slow down Claude.
Handle Errors Gracefully
Always use try-catch blocks and provide meaningful error messages.
Use Async Hooks
Hooks support async execution for external API calls and long-running operations.
Test Your Hooks
Use /hooks command to browse and test hooks interactively.
Ready to Automate Your Workflow?
Start creating hooks to enforce standards, automate tasks, and integrate external tools.