TL;DR
- A Stop hook that re-triggers itself can loop an agent for hours.
- Hooks are powerful precisely because they're deterministic — Anthropic's docs say so — and that's also why a bad one loops.
- Claude Code now force-ends a turn after 8 consecutive blocks, but you still want your own
stop_hook_activeguard. Thecc-hooksskill ships it.
What happened#
You leave two Claude Code agents on a refactor over the weekend. Monday morning, one of them has been editing the same three files in a loop since 1am. Not crashed — looping. Quietly burning tokens, making a small change on every cycle, never finishing.
The culprit is almost always a Stop hook. A Stop hook fires when the agent tries to end its turn. If that hook itself does something that causes another stop event — and does not check whether it is already inside a stop cycle — you get an infinite loop. The agent stops, the hook fires, the hook causes a stop, the hook fires again.
Why hooks loop: the same property that makes them useful#
Hooks are not suggestions. That is the whole point of them, and it's why teams reach for them. Anthropic's Claude Code best-practices guide draws the line clearly:
"Unlike CLAUDE.md instructions which are advisory, hooks are deterministic and guarantee the action happens."
— Anthropic, Best practices for Claude Code
That guarantee is exactly why a misfiring Stop hook is dangerous. A CLAUDE.md rule that says "run the tests before stopping" is advice the model can weigh; a Stop hook that enforces it will run, every single time the turn tries to end — including the time its own action triggered the next stop. Determinism doesn't know when to give up. The guide recommends hooks for precisely this reason — "for actions that must happen every time with zero exceptions" — and that strength is the failure mode's source.
The happy-path docs miss it#
Most hook examples show the clean case: a Stop hook that runs a formatter and exits. It works in the demo because the demo runs once, with you watching. The loop only appears under autonomous, unattended execution — which is exactly when nobody is watching.
This is the gap cyberg7-skills was built around: every skill documents what breaks when an agent runs it at 2am, not just how it works at the desk. (For more on why unattended runs are a different discipline, see We ported a blog by changing one file.)
The two guards that stop it#
Guard one ships with Claude Code. The platform added a circuit breaker for exactly this scenario. From the same docs, on using a Stop hook as a gate:
"a Stop hook runs your check as a script and blocks the turn from ending until it passes. Claude Code overrides the hook and ends the turn after 8 consecutive blocks."
— Anthropic, Best practices for Claude Code
So a runaway can no longer go truly infinite — it caps at eight. That's a real safety net, and a recent one. But eight forced cycles of an agent re-editing your files is still eight cycles of damage and wasted tokens you didn't want.
Guard two is yours to add. A Stop hook should check the stop_hook_active flag and exit early when it is already set, instead of doing work that re-enters the cycle. That's the difference between zero bad cycles and up to eight. The cc-hooks skill ships this as a lint rule and a template, so the hook you copy already has the guard in place.
The same skill documents eleven other hook failure modes — the exit-2-with-JSON conflict, the silent-deny that leaves the agent with no recovery path, the PreToolUse hook that blocks its own retries — each with a name, a trigger condition, and a fix.
How to start#
- Install
cc-hooksfrom the full library (see pricing) or grab the starter pack to begin. - Use its Stop-hook template instead of hand-rolling one — the
stop_hook_activeguard is built in. - Read its
FAILURE-MODES.mdbefore you deploy any hook to an unattended agent. - New to skills generally? Start with Your first 20 minutes with cyberg7-skills.
The platform now caps the damage at eight cycles. The guard caps it at zero. More hard-won Claude Code lessons in the Claude Code pillar.