Run Commands Every Time with Lifecycle Hooks

Hooks in Claude Code execute deterministically at five key events—user prompt submit (before processing), pre-tool use (before tool calls), post-tool use (after), notification (on sends), and stop (on finish)—unlike prompt instructions that sometimes fail. Define them in .claude/settings.json with an event, optional matcher (e.g., "edit" or "multi-edit" for file changes), and command. This guarantees actions like logging every command for compliance or notifying on task completion, eliminating reliance on Claude's inconsistent prompt adherence.

Auto-Format Files After Edits

Set a post-tool-use hook with matcher "edit" or "multi-edit" to trigger formatters on every file modification. The command reads stdin for details, checks file extension, and runs project-specific tools: Prettier for TypeScript/JS, gofmt for Go, Ruff for Python. Use $CLAUDE_PROJECT_DIR environment variable to reference scripts reliably, regardless of working directory. Result: Clean, consistent code without manual intervention or prompt nagging.

Block Dangerous Operations Pre-Tool-Use

Pre-tool-use hooks receive tool name and input as JSON on stdin. Exit code 0 allows the action; exit code 2 blocks it, feeding stderr message back to Claude for adjustment. Enforce rules like: reject writes to production config dirs, block bash with "rm -rf", or prevent commits in restricted domains. This creates hard safeguards, overriding Claude's judgment for compliance-critical environments.

Share Hooks Repo-Wide for Teams

Store settings.json in .claude/ and commit to repo—hooks apply project-level automatically for all teammates. No per-user setup needed. Combine with reference scripts in the project for portable, deterministic workflows across machines.