Currently Available: Need a skilled Software Developer for your next project?
Categories
Coding Agents

How to Keep Claude Code Working Until a Task Is Done With a Stop Hook Loop

Claude Code can end its response before its code change meets your requirements. A Stop hook is an automated action that runs when Claude Code is about to end its turn. The hook can check whether the task is complete and, if it is not, send Claude a reason to continue.

A Stop-hook loop repeats the cycle of Claude doing work and the hook checking it. Define “done” with checks Claude can verify, such as passing tests or a successful build. Set a limit too: the hook can ask Claude to keep working, but it cannot prove the result is correct or guarantee that Claude will finish.

How a Stop hook keeps Claude working

After Claude Code’s agent finishes a response, Claude Code runs a Stop hook before returning control to you. If the hook returns a blocking decision, Claude continues instead of ending the turn. The hook’s reason tells Claude what remains to do.

A command-based hook returns its decision as JSON on standard output, the stream where a command prints its results. A response can look like this:

{
  "decision": "block",
  "reason": "The required checks have not passed. Run the failing tests, fix the issues, and verify again."
}

The reason field is required when the hook blocks a stop. The hook can also provide guidance through hookSpecificOutput.additionalContext. Both approaches give Claude feedback to act on; neither one verifies that Claude’s next attempt will succeed. The Claude Code Hooks reference documents the Stop event and its response format.

A useful loop has three parts: a specific goal, a check that produces observable evidence, and a stopping rule. For a code change, that check might be a project test command or a build. The hook should allow Claude to stop when the required checks pass. If they keep failing, a limit should end the loop and leave Claude to report what remains unfinished.

Choose /goal, a plugin, or a custom hook

Use /goal when you want Claude Code’s built-in way to keep working toward a goal for the current session. Anthropic describes it as a prompt-based Stop hook. Its loop guidance recommends goals with verifiable exit criteria, such as naming the tests that must pass, rather than asking Claude to decide whether the work simply feels complete. The loop engineering guidance recommends starting with the simplest approach that fits the task.

Anthropic’s ralph-loop plugin runs a Stop-hook loop for work that repeats within one session, with a set limit on the number of iterations. Its documented example is:

/ralph-loop "Build a REST API for todos. Requirements: CRUD operations, input validation, tests. Output COMPLETE when done." --completion-promise "COMPLETE" --max-iterations 50

The plugin uses the completion phrase to signal that Claude believes it has met the stated condition. Its --max-iterations option sets a limit, and /cancel-ralph cancels an active loop. These are plugin commands, not general Claude Code Stop-hook syntax. The plugin README advises stating concrete requirements, asking Claude to respond to test results, and telling it what to report if it reaches the limit.

A completion phrase is still a signal from Claude, not independent evidence. For stronger verification, make the hook or a separate check inspect the test or build result before allowing the task to end.

Write a custom command hook when your completion rule needs project-specific checks, such as requiring both passing tests and a build artifact. The exact implementation depends on how the repository runs those checks and handles failures. Claude Code also supports prompt- and agent-based hooks; the official documentation describes agent hooks as an option when verification requires inspecting files or test output. Test the hook’s success and failure paths before relying on it.

Set limits and handle failure

Claude Code documents a cap of eight consecutive Stop-hook continuations. The count resets when Claude calls a tool. This cap limits consecutive hook blocks; it does not mean Claude will finish in eight iterations. The documentation says you can raise the cap with CLAUDE_CODE_STOP_HOOK_BLOCK_CAP, but a higher cap does not make the task more likely to succeed. A plugin’s --max-iterations setting is a separate limit.

If you interrupt Claude, the loop stops running hooks. Stop hooks do not run after a user interrupt, and API errors use the separate StopFailure event. Treat those as reasons to inspect the current state, rather than assuming the loop recovered or completed.

Keep the task limited in scope; when Claude reaches that limit, have it summarize the failed check and remaining work if the checks are still broken or it cannot proceed. The plugin keeps work in the current session, so previous changes remain available for later iterations. If you run parallel sessions, check how the installed plugin scopes its loop state: a repository issue reports state affecting concurrent sessions. That report is a warning to verify the current setup, not evidence that every installation has the same problem.

What I'm building

Delegate tasks. Get software.

Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.

Take a look at vroni.com

Email updates

Usually a new article and a few links I found interesting.

No spam. Unsubscribe with one click.

Leave a Reply

Your email address will not be published. Required fields are marked *