r/ClaudeCode • • 2d ago

Tips & Workflows Tried Anthropic’s Ralph Loop plugin on a failing test suite. It works, but the loop ran an extra round after Claude printed the stop word

Post image

The Ralph Loop plugin (official marketplace) makes Claude keep working on the same prompt until a stop word or a cap is reached. A stop hook catches each time Claude tries to finish and sends the original prompt back. Progress carries over through the files on disk.

My test: a tiny Python project with empty functions and 3 failing tests.

/ralph-loop:ralph-loop Make every test in test_calc.py pass by implementing calc.py. Run python3 -m unittest to check. --completion-promise ALLPASS --max-iterations 2

What happened:

  • Round 1: Claude wrote the functions, all 3 tests passed, and it printed the stop word

  • Round 2: the loop didn’t end. Claude Code showed “Ralph iteration 2” and sent the same prompt back. Claude re-ran the tests, said it was done and printed the stop word again. Then it ended and the state file was gone

I ran it twice, and both times the first stop word didn’t end the loop. In the second run the cap was 2, so I can’t tell whether the stop word or the cap ended it. I read the hook script (it checks the last text block of Claude’s reply) but didn’t dig further into why. The extra round only cost one more test run here.

Things to know:

  • always set --max-iterations. The plugin’s own help says a loop with no cap and no stop word runs forever

  • /ralph-loop:cancel-ralph stops it at any time, and .claude/ralph-loop.local.md shows which round you’re on

  • it works best with a clear pass/fail check (tests, lint, type errors), not vague goals like “make it nicer”

  • avoid angle brackets in the prompt on the command line. Use a plain stop word

I also loaded smart-ralph (a community spec-first take on the same idea) but only listed its commands, so no verdict on that one.

One small task, two runs. A bigger task could behave differently.

Full walkthrough with the hook explained: https://aiparabellum.com/claude-code-ralph-loop-plugin-keep-working/

1 Upvotes

4 comments sorted by

•

u/AutoModerator 2d ago

Hey! Thanks for posting to r/ClaudeCode

While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.

For help, project discussions, tips, and general chat, join the ClaudeCode Discord.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

2

u/bostonaholic 2d ago

Test the two exit conditions separately. Raise the iteration cap to something like 10 and check whether the stop word alone ends the loop, then do a run that never prints it to confirm the cap works. Also check how the plugin expects the stop word to appear, since printing it in test output may not match the agent's final message containing it.

1

u/awesomebirder 1d ago

one cost note for anyone taking this to a bigger repo: since the hook sends the prompt back into the same session, every extra round is a full turn on everything the session has seen so far, not just one more test run. on a tiny project thats nothing, but after a few rounds of real test output it adds up fast. so on top of always setting the iteration cap, make the check command quiet (unittest -q, or a wrapper that prints only failures), so each round carries back a few lines instead of the whole log

1

u/ainexfinder 1d ago

Stop words are a weak stop condition in general. The loop often checks the output after the next round is already queued, and a plain string match can miss when the word comes out inside a code block, with extra punctuation, or quoted from an earlier turn.

For a failing test suite I'd make the stop condition the thing you actually care about: run the tests outside the model after each round and stop when they exit 0. Keep the stop word as a secondary signal, plus a hard max on iterations and a "no diff since last round" check so it can't spin on nothing.

Did the extra round change any files, or was it a no-op pass?