In this categoryClaude Code · 45
- How to Install Claude Code on macOSStart
- How to Install Claude Code on Windows Natively (No WSL)
- How to Install Claude Code on Windows with WSL
- How to Start Your First Project with Claude Code
- How to Create a CLAUDE.md File for Your Project
- How to Configure Claude Code with settings.json
- How to Layer Global, Project, and Local CLAUDE.md Files
- How to Set Up a Permissions Allowlist in Claude Code
- How to Use Claude Code Inside VS Code
- How to Add a Custom Slash Command in Claude Code
- How to Create a Custom Slash Command in Claude Code
- How to Pass Arguments to a Claude Code Slash Command
- How to Use Claude Code Slash Commands (Full List + Examples)
- How to Add Custom Slash Commands to Claude Code (Arguments + Frontmatter)
- How to Fix command not found After Installing Claude Code
- How to Add Any MCP Server to Claude Code
- How to Connect an MCP Server to Claude Code
- Best MCP Servers for Coding in 2026
- How to Add a Filesystem MCP Server to Claude Code
- How to Connect the GitHub MCP Server to Claude Code
- How to Create Your First Subagent in Claude Code
- Context7 Alternatives: MCP Servers for Up-to-Date Docs
- How to Manage MCP Server Scopes in Claude Code
- How to Restrict the Tools a Subagent Can Use
- How to Debug a Failing MCP Server in Claude Code
- How to Generate Unit Tests for a Function with Claude Code
- How to Refactor a Long Function Safely with Claude Code
- How to Debug a Failing Test with Claude Code
- How to Review Your Own Diff Before Committing with Claude Code
- How to Rename a Symbol Across the Codebase with Claude Code
- How to Review a Teammate's Pull Request with Claude Code
- How to Raise Test Coverage on a Specific File with Claude Code
- How to Debug a Runtime Error from a Stack Trace with Claude Code
- How to Add an Integration Test for an API Route with Claude Code
- How to Teach Claude Code Your Test Conventions with CLAUDE.md
- How to Find Which Commit Broke a Test with Claude Code
- How to Set Up Hooks for Automation in Claude Code
- Claude Code Hooks Explained: Events, Config, and Blocking
- How to Block Risky Commands with a Claude Code Hook
- How to Auto-Format Files After Edits with a PostToolUse Hook
- How to Get a Notification When Claude Code Finishes a Task
- How to Give a Coding Agent a Clear Stop Condition
- How to Make an Agent Plan Before It Edits
- How to Keep an Agent Session Focused by Clearing Context
- How to Pin a Specific Model for One Project
How to Set Up Hooks for Automation in Claude Code
Run shell commands automatically at key points in Claude Code's lifecycle: auto-format code, block dangerous commands, send notifications, and enforce project rules without manual intervention.
Hooks are shell commands that run automatically at specific points in Claude Code's lifecycle, like after file edits or before command execution. They provide deterministic control over Claude Code's behavior, ensuring certain tasks always happen rather than relying on the model to choose to do them. Use hooks to auto-format code, block dangerous operations, send notifications, and enforce project conventions.
- Claude Code CLI installed and a working project
- Basic shell scripting knowledge (bash or sh)
- A text editor to write hook configuration JSON
- Optionally: Prettier, a code formatter (npm install -g prettier)
Understanding hook events and lifecycle
Hooks fire at specific moments in Claude Code's execution: when a session starts, before or after tools run, when files change, or when the model finishes working. You configure them in a settings file with a matcher to filter which hooks run on which events, and a command or HTTP endpoint to trigger.
- SessionStart — fires when you start a Claude Code session; useful for injecting context or loading environment variables
- PreToolUse — runs before any tool executes; use to block dangerous commands or validate input
- PostToolUse — runs after a tool finishes; ideal for auto-formatting or validation
- Notification — fires when Claude needs your input; useful for desktop alerts so you don't watch the terminal
- FileChanged — runs when any file changes; good for reloading config like .env or .envrc
Example 1: Auto-format code with Prettier
The most common hook runs a code formatter after every edit. This example uses Prettier to format JavaScript, TypeScript, and other files automatically. Add this configuration to .claude/settings.json in your project root so it applies only to this repo.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}Example 2: Block dangerous commands
Prevent Claude from running destructive commands like rm -rf by checking the command before execution. This bash script checks the input and exits with code 2 to block the operation if it matches a dangerous pattern.
#!/bin/bash
# protect-commands.sh - block dangerous commands
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if echo "$COMMAND" | grep -qE "rm -rf|rm -r/|: /|(\|\s*sudo)"; then
echo "Blocked: potentially destructive command" >&2
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked for safety"
}
}'
exit 2
fi
exit 0{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": ""$CLAUDE_PROJECT_DIR"/.claude/hooks/protect-commands.sh"
}
]
}
]
}
}Viewing and debugging your hooks
Claude Code provides a built-in hooks browser to inspect all registered hooks, see which event they fire on, and confirm they are loaded correctly. Type the /hooks slash command during a session to open it.
Related guides
Watch related tutorials
5:42
1:42:18
28:14
41:09
9:47
8:23New guides in your inbox
Fresh step-by-step how-to guides as we publish them. One email a week, no more.