Claude Code hooks let you run scripts at specific points in the session lifecycle: before a tool runs, after it runs, at session start, at session end. They're powerful and underused.
The four hook points
PreToolUse — runs before Claude executes a tool (bash command, file edit, etc.). Good for: logging, validation, cost tracking.
PostToolUse — runs after a tool completes. Good for: auto-formatting, running tests after file edits, updating a task log.
SessionStart — runs when a session opens. Good for: loading state, reading the task file, printing a status summary.
SessionEnd — runs when a session closes. Be careful: this doesn't always fire if the container is killed unexpectedly. Don't rely on it for critical state saves.
What I actually use
SessionStart: read the task file. My session start hook reads tasks/current-task.md and prepends it to the context. When I start a new session, Claude immediately knows where I was. No re-explaining.
PostToolUse (file edits): run linter. After every file edit, my hook runs the project's linter. Claude sees the output immediately and can fix lint errors inline rather than discovering them later.
PreToolUse (bash): log commands. I log every bash command Claude runs to a session log file. Useful for reviewing what happened in a long session, especially for debugging.
What I tried and dropped
SessionEnd state saves. The hook doesn't fire on container kills. Switched to explicit checkpoint writes after each task step instead.
Auto-commit hooks. Too aggressive. Some file edits are intermediate — you don't want to commit after every single change. Better to run commit-check manually.
Setting up hooks
Hooks live in your Claude Code settings file (.claude/settings.json). Each hook specifies the event type and a shell command to run. The shell command gets context about what Claude was doing via environment variables.
The documentation is at docs.anthropic.com/claude-code — search for "hooks". It's sparse but the basics work well.
Top comments (0)