Cutting Code AFK. How Ralph Wiggum can do the work for you

So it finally happened, I was pulled into a meeting and told to replace myself with AI.

Well, it was not quite that dramatic. What actually happened is that I was put on a client engagement, and since I am a consultant, client work is the main job. The catch was that the resource management system I had been building could not just stop moving while I was away. So the brief, more or less, was to see whether the Ralph Wiggum loop could keep the system going while I was full time on the client, and free me up to go and work with humans again.

I had been tinkering with Claude Code for about two months at that point, using agents to do chunks of the work and managing them a bit like a team of colleagues I could only ever text. A Ralph Wiggum loop sounded too good to be true, so obviously I had to try it.

What a Ralph Wiggum loop actually is

If you have not come across it, the Ralph Wiggum loop comes from Geoffrey Huntley, who wrote it up in July 2025 in a post called “Ralph Wiggum as a software engineer”. The name is a nod to the Simpsons character, who keeps cheerfully going no matter how many times things go wrong for him. Huntley’s own description is that Ralph is a bash loop, and that really is all it is. You feed the same prompt to a coding agent over and over until the work is done, and progress lives in your files and git history rather than in the model’s context window.

Anthropic later packaged the idea as an official Claude Code plugin, which is the version I use. You kick it off once with /ralph-loop:ralph-loop, hand it a prompt and set two guard rails with --max-iterations and --completion-promise. A stop hook intercepts the agent every time it tries to finish and checks, with an exact string match, whether your completion promise has actually been output. If it has not, the same prompt goes back in for another go. The string match is fussy, so in practice the iteration cap is your safety net.

The whole shape of it fits in two lines.

while not done:
    run the plan again

You point the pipeline at a plan and let it cycle through implementing, running the quality gates, reviewing and opening a PR, and if the work is not finished when it gets to the end, round it goes again.

Which all makes it sound like the loop is the clever part, and it turned out not to be. What settled the result, before a single line of code was written, was the state of the codebase the loop started from and how much ambiguity was left in the plan. The rest of this post is really about those two things.

Fix the codebase first, because the codebase is the context

Most people think context for Claude means CLAUDE.md and whatever agents you have dropped into /agents. Those matter, but in reality the biggest piece of context you have is the code itself. The agent reads your codebase the way a new starter would and copies what it finds there, so clear and enforced conventions get followed, and patchy ones get guessed at, confidently.

I had built the application with clean architecture principles and test driven development, but I had let the test coverage slip in the way you do. “I’ll do it later.” “The full functionality isn’t there yet, I’ll add Playwright when this page is done done.” So task one was getting the coverage back up and putting real Playwright end to end tests in place. I was lucky that my CI/CD pipeline was already running linting, formatting, type checking and tests on every push, so the gates existed, I just had not been feeding them enough.

Task two was checking that I was actually practising what I preach. I asked Claude, in plan mode, to audit the repo for clean architecture violations and hand me a plan to fix them. It found only a few, and the re-architecting it suggested did not feel scary, because the freshly written tests meant I could accept the plan knowing that if anything broke I would hear about it straight away.

The plan

With the codebase tidied up it was time to plan the first Ralph run. For this one I picked a nice contained vertical slice across the app, consisting of a new model, an API to go with it and a front end form to populate it.

I used the same plan template as my manual agent workflow, with acceptance criteria at the top and the tasks broken down by code area, backend first and then frontend. Nothing exotic, just a plan the agents could read top to bottom and know what done meant.

The set up

A Wiggum loop needs a predefined step list, and you also want some way of seeing what is happening without being glued to your terminal. I chose to track progress with GitHub issues. Before the first step, I had Claude open a batch of issues and then start the loop, adding an “in progress” label to whichever one it was working on and a “Wiggum done” label once all the checks passed, before moving on to the next.

The steps themselves were deliberately simple.

  • Implement backend

  • Implement frontend

  • Check code quality

  • Review

  • Repeat

Run 1. The first pancake

Run one took about 24 minutes, completed in a single iteration, and skipped my code quality and review steps entirely. The code that came out was very readable but it had subtle bugs. The worst was in the migration it generated, which meant I could not even run the feature locally without fixing it myself first. The end to end tests were missed, a few hygiene issues crept in, and the new endpoints were not fully wired up.

There were positives, though. Once I fixed the migration the app booted, existing functionality was intact, and overall test coverage crept up by around one percent across the board.

I had been sceptical about the whole thing and was pleasantly surprised, so I fixed up the PR Ralph had raised and went again with a tighter set up. The diagnosis was not complicated, because the loop only does what you force it to do, and I had named the steps without making any of them mandatory. The issue log went straight to “complete” with no QA and no review anywhere in sight, so this time I enforced both.

/ralph-loop:ralph-loop "Execute plans/TA-2-consultant+basic-assignment.md following the Ralph Wiggum loop in CLAUDE.md. For each issue: first write failing tests (QA role), then implement backend and frontend (engineer roles), then run all 6 quality gates and self-review against the acceptance criteria and SOLID/DRY standards (tech lead role). Work issues in dependency order. Output ISSUE_1_COMPLETE through ISSUE_5_COMPLETE after each issue. When all 5 are done and the PR is open, output ALL_ISSUES_COMPLETE." --max-iterations 20 --completion-promise "ALL_ISSUES_COMPLETE"

Run 2. Electric Boogaloo

Run two took longer at 48 minutes and cost $9.24. This time it was actually reviewing its own work, which felt like progress, except that the tech lead agent would find issues and then sign off anyway rather than rejecting the changes and sending them back to be fixed. It completed cleanly in one pass again and introduced no obvious errors, but it did make one wonderfully silly decision, showing user.id instead of user.full_name in the table on the front end.

After fixing that PR the penny dropped. The plan was the problem rather than the loop, and if I wanted better behaviour I needed to restrict Ralph, be very specific about what I wanted and give the review gate some teeth.

The turning point. Twenty clarifications later

So I stopped writing the plan on my own and instead fired up Claude in plan mode, pointed it at the plan for my next feature and told it to interrogate me.

let's look over plan plans/TA-6-view-weekly-timesheet.md I want to ensure that there is absolutely no ambiguity, ask me questions about every single decision wiggum loop will make so the plan is very descriptive also I want to enforce tighter rules so that any issues or minor nit picks raised by the lead engineer are addressed by the loop going back to step 1
do not make any assumptions

Twenty clarification questions later I had an answer for every decision the loop would otherwise have made for me, and those answers went into a Confirmed Decisions table baked into the plan as the single source of truth. The other change was zero tolerance review. Any finding from a reviewer, down to naming, formatting or import ordering, now sent the issue all the way back to step one, and sign off meant zero findings with no “approved with suggestions” path left open.

I also ran this one with --dangerously-skip-permissions, because Ralph kept inventing new ways to git add or run tests that were not in my approved command list. I had a decent set of allowed commands in my settings.json, which had made my semi manual agent workflow tolerable, but Ralph outran it constantly and I got tired of approving things. That flag deserves some respect, since it switches off the permission prompts entirely, so it belongs in a contained environment and nowhere near production or your credentials.

/ralph-loop:ralph-loop 'Execute plans/TA-6-view-weekly-timesheet.md using the Ralph Wiggum loop defined in .claude/CLAUDE.md.

RULES (non-negotiable):
1. The plan file is the SINGLE SOURCE OF TRUTH for all implementation details — read it FIRST on every iteration.
2. The "Confirmed Decisions" table in the plan is BINDING — agents must not deviate from any decision.
3. Follow .claude/CLAUDE.md "Per-issue loop" EXACTLY: step 1 invoke backend-engineer/frontend-engineer, step 2 run ALL 6 quality gates, step 3 invoke qa-engineer, step 4 invoke tech-lead. You MUST use the Agent tool to invoke each named agent (backend-engineer, frontend-engineer, qa-engineer, tech-lead, devops-engineer) at the steps specified in CLAUDE.md. Never perform an agents work directly — always spawn the agent.
4. STRICT REVIEW (ZERO TOLERANCE): ANY finding from qa-engineer or tech-lead — including minor nits like naming, formatting, comments, import ordering, or style — sends the issue BACK TO STEP 1 (IMPLEMENT). Sign-off means ZERO findings. There is no fix in place or approved with suggestions path.
5. Pass EVERY agent: the plan file path (plans/TA-6-view-weekly-timesheet.md), the GitHub issue number, and the branch name (6-view-weekly-timesheet).
6. Each agent MUST commit its changes before handing off to the next agent.
7. Auto-ratchet: QA engineer MUST bump coverage thresholds if actual coverage exceeds current minimums (backend pytest.ini, frontend jest.config.js).

PROCEDURE:
- Phase 0: Read the plan file. Create labels (idempotent), branch (6-view-weekly-timesheet from main), and all 4 GitHub issues per Phase 0 steps. Copy the FULL issue section from the plan verbatim into each issue body.
- Per issue (dependency order: 1 then 2 then 3 then 4): Follow the per-issue loop in CLAUDE.md steps 1-6 exactly. Output ISSUE_N_COMPLETE (N=1-4) after BOTH qa-engineer AND tech-lead sign off with zero findings.
- Post-loop: After all 4 issues complete, commit, push, open PR. Then invoke devops-engineer per CLAUDE.md Post-loop section. If devops-engineer requests fixes, fix and re-submit.
- Final: Output ALL_ISSUES_COMPLETE only when ALL of: (a) every issue has qa-engineer + tech-lead sign-off, (b) devops-engineer has signed off, (c) PR is open, (d) all 6 quality gates pass clean.' --max-iterations 20 --completion-promise 'ALL_ISSUES_COMPLETE'

Run 3. Is that autonomy?

Run three took 2 hours and 28 minutes and cost $31.54, and this time some steps took up to four iterations to get through, which is exactly what I wanted to see. Ralph was going back and fixing its own mistakes. My reviewer agents were on it, catching dead code and sending the work back to the start of the step rather than waving it through, and the issue comments gave me a readable log of what was happening the whole way along.

The code itself was good, and it worked. When I reviewed the PR I had no notes, because every convention that already existed in the codebase had been followed, so what came out looked like something I would have written myself.

The price of getting it right

Better code cost more time and more money, and that is the trade rather than a bug.

Run Time Iterations per step Cost Outcome
Run 1 24 min 1 ~$4.60 * Subtle bugs, not runnable
Run 2 48 min 1 $9.24 Reviewed, not fixed
Run 3 2h 28m up to 4 $31.54 Shippable

*Run 1 was not metered, so its cost is estimated in proportion to Run 2.

That is roughly six times the wall clock time and about seven times the spend to go from broken to shippable. Autonomy is not free, and most of the bill is review. Once I accepted that, the numbers stopped bothering me.

What actually moved the needle

Looking back, four things made the difference, and none of them was the loop. Fixing the codebase first mattered most, because tests, CI and clean architecture are the real context window. Then came killing the ambiguity, with confirmed decisions written down and binding so the agents had no gaps to guess into. The gates had to be mandatory as well, since the loop will quietly skip any step you only named politely. And it had to be allowed to iterate, because the good run is the slow and expensive one, which is annoying but true.

So, can AI replace me?

The part of me that writes code? Probably, eventually. What I did not expect is how freeing that turned out to be, because the quality of the outcome was almost entirely decided before the first line of code was written, by the state of the codebase and the clarity of the plan, and both of those are human work.

So the human is not going anywhere just yet, we just move up the stack. Someone still has to turn human pain points into requirements and shape the plan until there is nothing left to guess, and someone has to babysit Ralph when it decides user.id is a perfectly good thing to show a person. As for me, I got what I wanted out of this. I am back working with humans on the client engagement, and the resource management system keeps moving in the background while I do.

Next
Next

The AI-Native SDLC eBook