Back in January, I wrote about falling in love with Claude Code. In June, I wrote about six months in, and how the job had quietly turned into full-time code review. The conclusion I kept coming back to in that post was that AI only amplifies what's already there. Good judgment, it multiplies. Missing judgment, it multiplies too, just faster than you can catch it.

What I didn't have back then was a way to turn that judgment into something that runs automatically, every time, without me having to be paying attention. That's what hooks are for.

What a hook actually is

A hook is a shell command that Claude Code runs automatically at a specific point in its lifecycle: before a tool call, after one, when a session starts or stops. You give it an event, an optional matcher (which tools it applies to), and a command. The hook gets JSON on stdin describing what's happening, and it can respond in a way that blocks the action entirely.

The part that matters: it's deterministic. A rule in your CLAUDE.md is a request. Claude usually follows it, but "usually" isn't a guarantee, especially deep into a long session when things drift. A hook isn't a request. It just runs, every time, whether Claude remembers or not.