Ralph Loops Everywhere
January 23, 2026
Someone recently asked for tips on using ralph loops for more than just iterating through an implementation plan. For those unfamiliar, ralph loops involve having Claude Code run the same prompt repeatedly with a checklist of tasks, completing and checking off one task at a time.
The advantage is that each task starts with a fresh context window. Think of a context window like Claude's short-term memory. The more stuff in there, the more distracted it can get. Starting fresh means Claude only has what's needed for that specific task, which is where it does its best work. For a deeper dive into why, check out Dexter Horthy's ideas.
I figured I'd share some ways I've been using ralph loops, in hopes it helps others adopt this method. Fair warning: it will probably be a long read.
I decided to build a fairly complex turn-based web game and used ralph loops as much as possible throughout the process. I based the game on a board game with cards (I'm not a game developer, so this made things easier) and had a PDF of the instructions, which proved helpful.
If you don't already have a set of rules or specs like I did, you should have a thorough conversation with Claude first and work through all of the specs beforehand. This is really important. Claude Code needs all the behavior you want from your app spelled out clearly so it doesn't have to guess and make the wrong call. The more detailed your specs are, the better the output will be and the less likely Claude is to make stuff up or go in a direction you didn't want.
One way to make sure your specs are complete is to use a ralph loop for that too. You could have Claude look at your specs, find any unanswered questions or gaps, and add them to a QUESTIONS.md file. Then you answer those questions, and the loop keeps going until Claude can't think of anything else that's missing. It's a good way to make sure you've thought through all the edge cases before you start building.
I started with a regular Claude Code chat and gave it the instructions PDF. Then I talked through my idea of adapting the game for web. Some things wouldn't work well in a digital version, and the board game was really more of a multiplayer experience while I only wanted to build a single-player game. I had Claude create a SPECS.md file and update it as we discussed how the game would work, adding as much detail as I thought necessary. To finish up the specs, I started my first ralph loop using something along the lines of this prompt:
- Study the spec files in @specs/ about this game that is being designed
- Look for missing information in the functionality, mechanics, game flow, or anything else that should be addressed or clarified
- Study this document about the inspiration for this new game: @specs/game.pdf
- Update the spec files based on the original game and your own expertise
I monitored the output occasionally to see what Claude was doing. To get readable output from Claude when running it in a script, you can pass in these arguments:
cat PROMPT.md | claude -p --dangerously-skip-permissions --output-format=stream-json --verbose
Claude outputs its response as JSON (a structured data format), so I use a tool called jq to pull out just the text I care about. This next line looks scary, but all it does is filter out the noise and show you what Claude is actually saying:
| jq --unbuffered -r 'select(.type == "assistant") | .message.content[]? | select(.type == "text") | (.text // empty)'
Don't worry if that looks like gibberish. If you get stuck, just give Claude this info and it can write the whole script for you. I'm working on a Mac, so it may be a bit different on Windows or Linux. Once the output from the loop started to say there were no more changes needed, I stopped it. With my spec files complete, I moved on to the planning phase.
For the planning phase, I created another ralph loop prompt. This one had Claude study the specs and then build out a detailed implementation plan. The idea was to get a phased, multi-step plan that covered everything in the specs so nothing would get missed during development. Here's roughly what I used:
- Study the spec files in @specs/ to understand the full scope of the project
- Identify all features, mechanics, and requirements that need to be implemented
- Create or update @PLAN.md with a detailed multi-phase implementation plan
- Break each phase into specific, actionable steps
- Make sure every requirement from the specs is accounted for in the plan
- Review the plan for completeness and add any missing details
Again, I just monitored the output occasionally until it started saying the plan looked complete. Then I stopped the loop and reviewed what it came up with.
After reviewing the plan, it looked good to me, so I moved on to the implementation phase. This is where the ralph loop really shines. Each iteration picks up the next task from the plan, implements it, and checks it off. For context, this was a Ruby on Rails backend in the app/ directory with a React frontend in the frontend/ directory. Here's the prompt I used:
- 0a. Familiarize yourself with test/
- 0b. Familiarize yourself with code in app/
- 0c. Familiarize yourself with code in frontend/
- 0d. Familiarize yourself with the specifications in specs/
- 1. Read @PLAN.md and implement the single highest priority feature using up to 5 subagents
- 2. After all tests and linting pass, update @PLAN.md with your progress
- 3. Use `git add -A` and `git commit -m "..."` to commit your changes
This basically looped dozens of times before it completed the entire plan. After that, I wanted to find a way to automate testing and bug hunting. Since this is a turn-based game, I figured Claude could think through every possible game state scenario based on the specs and add them to a list. The idea was to have Claude brainstorm potential game states that should be tested. I used a prompt something like this:
- 1. Familiarize yourself with the specifications in specs/
- 2. Read @GAME_STATES.md
- 3. Update @GAME_STATES.md with one additional new game state that should be tested
- 4. Use `git add -A` and `git commit -m "..."` to commit your changes
I monitored the output until Claude started saying it couldn't think of any more game states. At that point, it was time to actually test them. The GAME_STATES.md file had grown so large that I had Claude break it up into multiple files, one for each game state, and use GAME_STATES.md as more of a progress tracking file.
This is where I had to start using Playwright MCP so Claude could actually test the game in a browser window and look for visual or behavioral bugs. MCP stands for Model Context Protocol, and it's basically a way to give Claude extra abilities it doesn't have by default. In this case, Playwright MCP lets Claude control a web browser, click around, and see what's on screen. I generally try to avoid using MCPs unless I really need them because I want the context to stay as focused as possible on the task at hand. But for this kind of testing, there was no way around it that I could think of. Similar to the test files, BUGS.md also grew large enough that I had Claude create individual bug files. Here's something like the testing prompt I came up with:
- 0a. Familiarize yourself with the specifications in specs/
- 0b. Read @GAME_STATES.md
- 1. Recreate one incomplete game state test from the list
- 2. Use Playwright MCP to verify it works correctly
- 3. Update @BUGS.md with any bugs found including all context needed to recreate them
- 4. Create a corresponding bug file in @bugs/ for each bug without fixing them
- 5. Update @GAME_STATES.md and the individual test file in @game_states/ with your progress
- 6. Fix any incorrect info in @GAME_STATES.md you encountered but don't actively look for mistakes
- 7. Use `git add -A` and `git commit -m "..."` to commit your changes
Finally, after it had tested all the game states and documented the bugs, I started a ralph loop to fix them. This one also used Playwright MCP to first confirm the bug existed and then verify it was actually fixed. Here's something like the prompt I used:
- 0a. Familiarize yourself with the specifications in specs/
- 0b. Read @BUGS.md
- 1. Select a single bug based on priority
- 2. Verify it's a bug using Playwright MCP
- 3. Research and fix the bug using up to 5 subagents
- 4. Verify the fix using Playwright MCP repeating until resolved
- 5. Add any new bugs found to @BUGS.md and @bugs/
- 6. After all tests and linting pass, update @BUGS.md and @bugs/ with your progress
- 7. Use `git add -A` and `git commit -m "..."` to commit your changes
I repeated the bug search and bug fix loops until they stopped finding anything. I did all of this before really testing the app myself beyond just making sure it basically ran. Definitely over 90% of the work on the game was done autonomously with ralph loops.
Up until this point, the main times I had to open a regular Claude Code conversation were during the initial spec creation and to fix a Tailwind loading bug that was causing the frontend styling to break. For some reason the ralph loops never caught that one. After the loops finished, I did find 2 or 3 more bugs while testing that I had Claude Code fix using a typical research, plan, implement, verify pattern with a /clear between each phase to keep the context fresh. (The /clear command wipes Claude's memory of the current conversation, giving you a fresh start.)
Stopping the Loop Automatically
One thing I wanted to mention is how to have Claude stop the loop on its own when it's done. You can add a step to your prompt like "If all tasks are complete, output <promise>COMPLETE</promise> otherwise output <promise>MORE</promise>" and then have your script check for that string.
I use two options instead of just one because with only one option, Claude would sometimes output the promise even when it wasn't done. It would say something like "I don't want to output <promise>COMPLETE</promise> because the tasks are not complete" and the script would see that string and stop anyway. Giving it two choices forces it to pick one intentionally.
To make this work, save Claude's output to a temp file by adding | tee "$output_file" to the end of your command. Then after each iteration, check for the completion signal:
if grep -q "<promise>COMPLETE</promise>" "$output_file"; then
echo "Done!"
exit 0
fi
The grep command searches for text in a file. When it finds the completion signal, the script exits cleanly. Otherwise it continues to the next iteration.
Hopefully this helps you understand ralph loops a little better. The main takeaway is that you can use them for way more than just running through a plan. I used them for refining specs, creating plans, implementing features, brainstorming test scenarios, running tests, and fixing bugs. Basically any task where you want Claude to chip away at something one piece at a time with a fresh mind each round.
I'm still learning all of this myself, and there are a lot of opinions out there about how to make these tools work best. This is just what's been working for me.
If you want to check out the game I built, you can play it at fresno-farms.chesterton.tech.