If you have read the Claude Code Hooks documentation, the example you remember is probably one that prints to stderr and exits 0. That example is correct, and it is where most tutorials stop. The four exit codes that decide whether your hook is safe in production are the ones the docs barely mention. We run a PreToolUse hook on our own monorepo every working day, and the shape it settled into is not what we expected when we wrote the first version. What looked like a single conditional turned out to be a state machine with four branches. The hook grew into that shape because each of the four cases meant something different to a production team, and collapsing any two caused real bugs. The shape of a PreToolUse hook A PreToolUse hook is a script Claude Code runs immediately before a tool call — a Bash command, a file write, an MCP invocation. It receives the tool input as JSON on stdin and can do three things: pass the call through, modify the input, or signal deny or human confirmation.…