Deterministic automation scripts that run at specific lifecycle events
Config: ~/.claude/settings.json | Scripts: ~/.claude/hooks/
ai-servicers.com
Hooks are shell scripts or Python programs that run automatically at specific points in Claude Code's lifecycle. Unlike skills (prompts) or agents (LLM-driven), hooks provide deterministic behavior — they always run and always produce the same output given the same input.
Runs once when a Claude Code session begins. Use for context detection, environment setup, and session audit logging.
Fires when the user submits a prompt. Use for prompt logging and usage tracking. Rarely blocks (exit 0).
Runs before each tool call (Bash, Write, etc.). The most powerful event — can block with exit code 1, or inject warnings. Use for security and validation.
Runs after each tool completes. Use for audit logging, tracking what was done, and cleanup tasks.
Fires when the agent session ends. Use for session summaries and cleanup of temporary files.
7 hooks across 5 event types — all registered in ~/.claude/settings.json
new-project-checklist.py — Detects mkdir ~/projects/NEW and injects a "don't forget" checklist: GitLab repo, CLAUDE.md, deploy.sh, Traefik/Keycloak setup.
naming-validation.py — Enforces naming conventions. Blocks mkdir ~/projects/My-Project (uppercase), docker run --name MyContainer, and CREATE DATABASE MyDB.
pre-tool-use.sh — Blocks force pushes to main, deletion of secrets/, and recursive deletion of home. Agent-aware via CLAUDE_AGENT_TYPE.
post-tool-use.sh — Logs every tool call to ~/.claude/audit/YYYY-MM-DD.log. Captures agent type, tool name, and command text (truncated). Auto-rotates after 30 days.
session-start.sh — Checks for CLAUDE.md, project agents, and skills in the current directory. Logs session start and reports available context.
stop.sh — Logs session end. For PM agent sessions, writes a summary file to ~/.claude/sessions/. Auto-cleans summaries older than 7 days.
user-prompt-submit.sh — Records prompt timestamps (not content) to ~/.claude/prompt-log.txt for usage tracking. Always exits 0.
Hooks are registered in ~/.claude/settings.json under the hooks key
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 ~/.claude/hooks/new-project-checklist.py",
"timeout": 10
},
{
"type": "command",
"command": "python3 ~/.claude/hooks/naming-validation.py",
"timeout": 10
},
{
"type": "command",
"command": "bash ~/.claude/hooks/pre-tool-use.sh",
"timeout": 10
}
]
}
],
"PostToolUse": [
{
"hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/post-tool-use.sh" }]
}
],
"SessionStart": [
{
"hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/session-start.sh" }]
}
],
"Stop": [
{
"hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/stop.sh" }]
}
]
}
}
Exit code 0 = proceed | Exit code 1 = block operation | Exit code 2 = block + show error to user
Hooks are the enforcement layer of Claude Code. While skills provide guidance and agents perform complex tasks, hooks ensure that certain rules are always followed — regardless of what the LLM decides to do. Security guards, naming validators, and audit loggers all belong here.
Rule of thumb: If it must always happen, use a hook. If it should guide behavior, use a skill. If it needs autonomous execution, use an agent.
ai-servicers.com