Claude Code hooks: why "just tell it not to" doesn't hold up A developer argues that Claude Code's system prompts are advisory and can be deprioritized in long sessions, making them unreliable for enforcing critical rules. The solution is to use Claude Code hooks, which execute as deterministic shell commands at lifecycle points, guaranteeing behavior regardless of model attention. The developer packages a set of hooks, slash commands, subagents, and a statusline as the Claude Code Power Pack. If you've spent time customizing Claude Code, you've probably written a line like this in your CLAUDE.md : "always run the formatter after editing a file" or "never touch .env or any .pem / .key file." It works — until a long session, a big diff, or a context window full of other instructions makes that one line easy to deprioritize. The model isn't being careless; a system prompt is advisory. Every instruction in it competes with everything else in context for attention, and instructions written early tend to fade as the conversation grows. That's a structural limit, not a prompting mistake. And it means anything you actually need to happen every single time — not "usually," not "when the model remembers to" — doesn't belong in a prompt at all. Claude Code hooks are shell commands wired to specific points in the tool's lifecycle: after a file edit, before a tool runs, when Claude finishes responding, when it needs your permission, at the start of a session. They execute as code, deterministically, regardless of what's in the conversation or what the model "decided" to prioritize that turn. The model doesn't get a vote — the hook just runs. That distinction matters more than it sounds. A CLAUDE.md rule is a request you're hoping gets honored. A hook is a guarantee, because it's not the model doing the enforcing. Not everything belongs in a hook. The useful split is: Getting this backwards is the common failure mode: people write increasingly elaborate CLAUDE.md instructions trying to force deterministic behavior out of a probabilistic system, when a five-line shell hook would have made the question moot. A statusline doesn't enforce anything — it's just a line under your prompt showing which model, which directory, which git branch you're currently in. It matters for a much smaller reason: once you're running more than one Claude Code session in parallel a common outcome of subagents and worktrees , "which one is this again" becomes a real source of mistakes. Cheap to add, easy to forget you need until you're context-switching between four terminals. Before adding another paragraph to your CLAUDE.md, ask whether what you actually want is a rule the model should weigh, or a guarantee that shouldn't depend on it weighing anything at all. If it's the latter, write a hook instead. Written with AI assistance. A working set of these — auto-format on edit, a secret-file guard that blocks writes to .env / .pem / .key before they happen, run-tests-on-stop, desktop notifications, and session logging — plus 12 slash commands, 6 subagents, and a git-aware statusline, is packaged as the Claude Code Power Pack copy-paste into .claude/ , €29 : https://vincentdu2a.gumroad.com/l/bqndfi https://vincentdu2a.gumroad.com/l/bqndfi . It's an independent, unofficial project — not affiliated with, endorsed by, or sponsored by Anthropic. "Claude" and "Claude Code" are trademarks of Anthropic.