Hooks & Automation
Use Claude Code hooks to run shell commands automatically before and after Claude edits files — enabling auto-format, auto-test, and team notifications.
Use Claude Code hooks to run shell commands automatically before and after Claude edits files — enabling auto-format, auto-test, and team notifications.
Hooks are shell commands that Claude Code runs at defined points in its lifecycle. They let you plug in your own tooling — linters, formatters, test runners, Slack bots — without modifying Claude's core behaviour.
Think of hooks like Git hooks (pre-commit, post-merge), but for Claude Code's tool-use lifecycle.
| Hook | When it runs | Common use |
|---|---|---|
| PreToolUse | Before Claude writes, reads, or executes anything | Run a linter, validate the change target |
| PostToolUse | After Claude completes a tool call | Format the file, run affected tests |
| Notification | When Claude sends a chat message | Log to Slack, trigger alerts |
| Stop | When Claude finishes a task | Commit changes, send a summary |
Hooks live in .claude/hooks.json in your project root:
{
"hooks": [
{
"event": "PostToolUse",
"match": { "tool": "write_file" },
"command": "npx eslint --fix {{file}}",
"description": "Auto-fix ESLint issues after Claude writes a file"
}
]
}The {{file}} placeholder is replaced at runtime with the path of the file Claude just wrote.
Run Prettier on every file Claude touches:
{
"hooks": [
{
"event": "PostToolUse",
"match": { "tool": "write_file" },
"command": "npx prettier --write {{file}}",
"description": "Format file with Prettier after Claude edits it"
}
]
}Now when you run /fix and Claude writes a fix to disk, Prettier runs automatically. Your code is always formatted without a separate step.
Prevent Claude from committing broken code:
{
"hooks": [
{
"event": "PreToolUse",
"match": { "tool": "bash", "command_contains": "git commit" },
"command": "yarn test --run",
"description": "Run test suite before any git commit"
}
]
}If yarn test exits with a non-zero code, Claude Code aborts the commit and reports the failure.
Send a message when Claude finishes a long-running task:
{
"hooks": [
{
"event": "Stop",
"command": "curl -s -X POST $SLACK_WEBHOOK_URL -d '{\"text\": \"Claude Code finished the task in {{cwd}}\"}'",
"description": "Notify Slack when Claude finishes"
}
]
}Useful for background tasks you kick off and walk away from.
| Placeholder | Value |
|---|---|
| {{file}} | Absolute path of the file being written or read |
| {{cwd}} | Current working directory |
| {{tool}} | Name of the tool Claude invoked |
| {{event}} | Hook event type (PreToolUse, PostToolUse, etc.) |
You can define as many hooks as you need. They run in order:
{
"hooks": [
{
"event": "PostToolUse",
"match": { "tool": "write_file" },
"command": "npx prettier --write {{file}}",
"description": "Format"
},
{
"event": "PostToolUse",
"match": { "tool": "write_file" },
"command": "npx eslint --fix {{file}}",
"description": "Lint"
},
{
"event": "Stop",
"command": "yarn test --run",
"description": "Test suite after all changes"
}
]
}Hooks run arbitrary shell commands. Review every hook before committing .claude/hooks.json to a shared repository. A malicious hook could exfiltrate files or modify system state. Treat hooks with the same caution as CI pipeline scripts.
To see hook activity as it happens, start Claude Code with verbose output:
claude --debugHook execution is logged with the command, exit code, and stdout/stderr. If a hook silently fails, --debug will show you why.
Commit .claude/hooks.json to version control. Everyone who clones the project gets the same hooks automatically — no per-developer configuration needed.
Hooks turn Claude Code from an interactive assistant into an automated pipeline. The recommended starting set is: format on write (PostToolUse + Prettier) and test before commit (PreToolUse + your test runner). The next and final module covers MCP — the protocol that lets you extend Claude Code with external tools like databases, browsers, and APIs.