Practical Hook Examples
Module: Hooks | Lesson: 4 of 4 | Time: ~10 minutes
What You Will Learn
- How to auto-format code after edits
- How to send notifications when tasks complete
- How to add pre-commit validation hooks
- How to log Claude's actions for review
Prerequisites
- Completed Configuring Hooks
Real-World Hook Recipes
This lesson provides complete, ready-to-use hook configurations for the most common automation tasks. Each example includes the full JSON configuration and an explanation of how it works.
1. Auto-Format Code After Edits
Automatically run Prettier (or any formatter) every time Claude edits a file. This ensures your code always matches your team's style, even when Claude generates it.
Configuration:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "npx prettier --write $CLAUDE_FILE_PATH 2>/dev/null || true"
}
]
}
}
How it works: After every Edit tool call, the hook runs Prettier on the edited file. The 2>/dev/null || true part suppresses errors and ensures the hook does not fail if Prettier is not installed or the file type is not supported.
On Windows without WSL, use this command instead:
{
"command": "npx.cmd prettier --write %CLAUDE_FILE_PATH% 2>nul || exit /b 0"
}
2. Desktop Notifications When Tasks Complete
Get a notification when Claude finishes a long task so you do not have to watch the terminal.
Windows (PowerShell toast notification):
{
"hooks": {
"Notification": [
{
"command": "powershell -Command \"[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); [System.Windows.Forms.MessageBox]::Show('Claude Code has a notification for you', 'Claude Code')\""
}
]
}
}
WSL / Linux:
{
"hooks": {
"Notification": [
{
"command": "notify-send 'Claude Code' 'Task notification' 2>/dev/null || true"
}
]
}
}
How it works: When Claude sends a notification event, the hook triggers a system notification. You can minimize the terminal and still know when Claude needs your attention.
3. Block Edits to Protected Files
Prevent Claude from modifying files that should not be changed — like production configs, lock files, or environment files.
Configuration:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit",
"command": "echo $CLAUDE_FILE_PATH | grep -qE '(\\.env|package-lock\\.json|production\\.config)' && echo 'BLOCKED: This file is protected' && exit 1 || exit 0"
}
]
}
}
How it works: Before Claude edits any file, the hook checks the file path against a list of protected patterns. If the file matches, the hook exits with code 1 (which blocks the edit) and prints a message explaining why.
This uses grep, which requires WSL, Git Bash, or a Unix-like shell on Windows. For native Windows Command Prompt, you would need a batch script or PowerShell command instead.
4. Reload Environment Variables on Session Start
Automatically load your project's .env file when a Claude session begins, so Claude has access to the environment variables your project needs.
Configuration:
{
"hooks": {
"SessionStart": [
{
"command": "if [ -f .env ]; then export $(grep -v '^#' .env | xargs); echo 'Environment loaded'; fi"
}
]
}
}
How it works: When the session starts, the hook checks if a .env file exists. If it does, it loads all the variables (skipping comment lines) into the environment.
5. Audit Logging
Record every tool Claude uses to a log file. This creates an audit trail of all actions Claude takes during a session.
Configuration:
{
"hooks": {
"PreToolUse": [
{
"command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | Tool: $CLAUDE_TOOL_NAME | Session: $CLAUDE_SESSION_ID\" >> .claude/audit.log"
}
],
"SessionStart": [
{
"command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | Session started: $CLAUDE_SESSION_ID\" >> .claude/audit.log"
}
],
"SessionEnd": [
{
"command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | Session ended: $CLAUDE_SESSION_ID\" >> .claude/audit.log"
}
]
}
}
How it works: Three hooks work together. SessionStart logs when the session begins, PreToolUse logs every tool call with its name, and SessionEnd logs when the session ends. All entries go to .claude/audit.log with timestamps.
Sample log output:
2025-06-15 10:30:00 | Session started: abc123
2025-06-15 10:30:05 | Tool: Read | Session: abc123
2025-06-15 10:30:08 | Tool: Edit | Session: abc123
2025-06-15 10:30:10 | Tool: Bash | Session: abc123
2025-06-15 10:31:00 | Session ended: abc123
If you use audit logging, add .claude/audit.log to your .gitignore file so the logs do not get committed:
echo ".claude/audit.log" >> .gitignore
Combining Multiple Hooks
You can combine all of the above into a single settings file:
{
"hooks": {
"SessionStart": [
{
"command": "if [ -f .env ]; then export $(grep -v '^#' .env | xargs); fi"
},
{
"command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | Session started\" >> .claude/audit.log"
}
],
"PreToolUse": [
{
"matcher": "Edit",
"command": "echo $CLAUDE_FILE_PATH | grep -qE '\\.env$' && exit 1 || exit 0"
},
{
"command": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | Tool: $CLAUDE_TOOL_NAME\" >> .claude/audit.log"
}
],
"PostToolUse": [
{
"matcher": "Edit",
"command": "npx prettier --write $CLAUDE_FILE_PATH 2>/dev/null || true"
}
],
"Notification": [
{
"command": "notify-send 'Claude Code' 'Task complete' 2>/dev/null || true"
}
]
}
}
This configuration:
- Loads
.envand starts logging when a session begins - Blocks edits to
.envfiles and logs every tool call - Auto-formats edited files with Prettier
- Sends a desktop notification when Claude has a notification
Try It Yourself
Set up the auto-format and audit logging hooks in a test project:
- Create a project with a settings file:
mkdir hook-practice
cd hook-practice
mkdir -p .claude
- Create
.claude/settings.jsonwith the auto-format and audit hooks:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"command": "echo Formatted: $CLAUDE_FILE_PATH >> .claude/audit.log"
}
],
"PreToolUse": [
{
"command": "echo \"$(date) | $CLAUDE_TOOL_NAME\" >> .claude/audit.log"
}
]
}
}
- Create a simple file for Claude to edit:
echo "function hello() { return 'world' }" > app.js
- Start Claude Code and ask it to add a new function to
app.js - Check the audit log:
cat .claude/audit.log
You should see entries for the Read and Edit tool calls.
What You Learned
- Auto-format hooks keep code styled consistently after every edit
- Notification hooks alert you when Claude needs attention, even if you are not watching
- PreToolUse hooks can block dangerous actions by exiting with code 1
- Session hooks handle environment setup and cleanup
- Audit logging creates a record of everything Claude does
- Multiple hooks can be combined into a comprehensive automation pipeline
How was this lesson? Take 2 minutes to share your feedback — it helps us make the tutorials better for everyone.