Regaining Developer Well-being with a Fully Autonomous Development Workflow Using ClaudeCode Infinite Loop (ralph-loop)!
Hello. I am Ito (Eddie) from the Team Mirai Nagatacho Engineer Team.
In a post I shared recently, I wrote about harness engineering for running Claude Code Web in 8 parallel streams. Since then, I have continued to experiment and research a development method (the so-called ralph loop) that allows me to complete a large amount of functionality in a single-command long session without needing detailed human instructions.
At this point, I have reached a state where if I spend about 15 minutes finishing the documentation and leave it to the AI, it reliably completes several thousand to 10,000 lines of relatively high-quality implementation in a 3-4 hour long session, so I would like to introduce the techniques I used.
Thinking back, ever since the birth of coding LLMs, I felt like my brain was constantly burning out from an overwhelming flood of information. Now that I can use this method, I can go for walks or take naps while waiting for the implementation to finish, and I feel like I have overwhelmingly regained my well-being.
I have also published a reference implementation below, so please take a look if you are interested.
※ Because many redundant validations are inserted to ensure success even in long sessions, the development speed is about 2/3 compared to when you orchestrate it seriously yourself. It might be appropriate to say that while pure development speed became 2/3, the time efficiency relative to my own working hours increased by about 10 times.
Very important notes
What is written here is just "this is how it worked quite well for me", and it is not a universal methodology.
The technology stack is TypeScript + Next.js, which LLMs are good at
The cost of consensus building is low because I am developing alone
It is a type of product where it is useful if it works roughly, and the existence of bugs is not fatal
This story is based on these premises. Please read it as just one case study.
Premise: What is ralph-loop
ralph-loop is a pattern discovered and named by Geoffrey Huntley for autonomously looping LLM coding agents. It is a development method where the coding agent is launched one task at a time in an infinite loop, allowing implementation to proceed indefinitely without using up the context window.
The invention point was that knowledge persistence is done via Git history + CLAUDE.md + task files, writing to files instead of relying on the LLM's memory.
Challenges I felt with the naive ralph-loop
When I ran the original Ralph Loop implementation and a simple self-made implementation based on it locally, it worked, but in my use case, there were the following challenges.
Rampant use of mocks and dummy data: Although tests pass, it cheats with mocks or hardcoded data, and it does not work as expected when actually connecting to a DB
Inconsistency in code quality: There is significant variation between sessions regarding how tests are written and the layer structure
It takes time: Since the default ralph-loop is serial, it takes quite a long time if you try to build an application of a certain size or larger
With that said, while I feel the potential, I also have the impression that there are many areas lacking in terms of quality.
To improve these, based on the harness engineering techniques I introduced last time, I went through trial and error to find a way to implement high-quality apps while benefiting from parallel implementation, and I arrived at my own loop implementation.
Overview of my loop implementation
In my implementation, I add to the original implementation by adopting:
Task decomposition that allows for parallelism using a Milestone > Wave > Task structure
Improvement of execution quality through division of labor among 3 agents
I am attempting to improve quality by adopting these. It looks like this when illustrated.

Point 1: Task decomposition that allows for parallelism using a Milestone > Wave > Task structure
In task management, I control the progress of development at three levels of granularity.
Milestone: A unit where "one feature works."
Wave: Task dependency order within a milestone. Tasks with the same wave number can be executed in parallel.
Task: One concrete implementation task. 1 task = 1 agent session.

Milestone creation is set up to be done via Claude's custom skills.
Regarding the details of tasks and waves within a milestone, I design them only when I reach the stage of starting that task after the loop begins.
Point 2: Improvement of execution quality through division of labor among 3 agents
When LLMs are given multiple objectives, they often distort the essence to treat them as completed in order to achieve them.
To prevent this, as the smallest unit that can maintain simplicity, I have a configuration where 3 agents with different missions—Planner, Builder, and Verifier—collaborate.
Planner...Decomposes the milestone goal into a wave structure of tasks and writes detailed specifications.
Builder...The task implementer. Responsible for implementation and passing unit tests in an individual work tree.
Verifier...Merges Builder branches in order and performs quality verification via E2E or on a browser. Also handles fixes when failures occur.
Reading this far, you might feel like this is doing something quite complex, but in reality, this loop consists of just one 170-line shell script and nine documents written in Japanese, for a total of 10 files.
.claude/commands/ # Claude Code スラッシュコマンド
├── plan.md # /plan — 設計ドキュメント作成
└── gen-milestones.md # /gen-milestones — milestones.json 生成
looper/ # 開発ループエンジン
├── run.sh # オーケストレーション(170行)
└── prompts/ # エージェントプロンプト
├── planner.md
├── builder.md
└── verifier.md
docs/ # 設計規約
├── architecture.md # DDD 4層・依存ルール・命名規約
├── frontend.md # フロントエンド規約
├── infrastructure.md # インフラ規約
└── quality.md # 品質規約As I will explain later, by trusting the LLM's judgment and keeping the shell logic to a minimum, I have been able to create a simple and robust configuration that is less prone to issues.
Key points for making the infinite loop work
From here on, I will introduce more specific points of ingenuity.
Ingenuity 1: Enabling error detection through architectural design and harness engineering
The fundamental premise is that the foundation of stable AI-driven development lies in architectural design and harness engineering. As I wrote in this article the other day,
"Clarifying which files to touch" through layered architecture + tactical DDD
Harnesses such as unit tests, E2E tests, lint, typecheck, and dependency-cruiser
are summarized in files named architecture.md and quality.md, and by having them adhered to in every session, the quality does not fluctuate significantly even when a large number of independent LLM sessions are running.
Ingenuity 2: Do not write too much logic in scripts; trust the LLM's judgment
What the main loop, run.sh, does, in essence, is just creating a worktree and starting/waiting for the LLM.
# ループの流れ(本質を取り出した疑似コード)
milestones = load("milestones.json")
for milestone in milestones.where(done == false):
# ① Planner: LLM が設計ドキュメントとタスク分割を生成
if milestone.tasks is empty:
claude(prompt_planner(milestone.goal))
# → milestones.json にタスク一覧と plan_doc パスが書き込まれる
# ② ③ Wave ループ(wave = 依存のないタスク群)
while has_undone_tasks(milestone):
wave = next_wave(milestone) # 同一 wave 番号のタスクは並行実行可能
# ② Builder: タスクごとに worktree を切って並列実行
for task in wave (parallel, max=8):
worktree = git_worktree_create(task.id)
claude(prompt_builder(task, plan_doc),
cwd=worktree) # worktree 内でコード生成&コミット
wait_all()
# ③ Verifier: コミットのあるブランチをまとめて検証・マージ
branches = [t.branch for t in wave if has_new_commits(t)]
claude(prompt_verifier(branches, milestone))
# → develop へマージ, milestones.json の done フラグ更新For processes involving branching and decision-making, such as resolving merge conflicts, analyzing the causes of test failures, deciding on fixes and re-verification, and updating milestone files, the policy is to leave them to the LLM as much as possible.
Initially, I wrote things like merge processing for branches implemented in parallel in shell scripts, but since handling failures became too complex, I switched to giving instructions to the LLM in natural language, which immediately made the system much less prone to problems.
Also, information transfer between agents is done via "handover notes" in Git commit messages. By effectively utilizing mechanisms designed for humans within the LLM, I am keeping the system from becoming overly complex.
Ingenuity 3: Do not design everything at once
In milestones.json, which serves as the task list, I only have the LLM create about 4 to 8 rough milestones for the entire project at the initial stage, and I intentionally design it not to create any more detail than that.
Then, at the timing of starting a milestone, the planner agent investigates the "current codebase," performs detailed design, and writes a design document for each milestone, defining an SDD (Spec Driven Development) development flow.
This is because
when an LLM is made to process a large amount of information, the quality of the design gradually decreases due to context consumption
and since the previous deliverables become the design premises for the next milestone, designing at the moment of starting makes it less likely for contradictions to occur and less likely to fall into the same pitfalls encountered in the previous phase
This is an improvement made with that point in mind.
Improvement 4: Build things that work little by little, not waterfall
Regarding how to set milestones, I have written in the prompt to use "vertical slicing by feature" rather than "horizontal slicing by layer".
❌ Milestone 1: All domain models → Milestone 2: All Repositories → Milestone 3: All UI (Waterfall)
✅ Milestone 1: Infrastructure → Milestone 2: Pass Feature A vertically from DB to UI → Milestone 3: Pass Feature B vertically
With horizontal slicing, a state where "the code exists but nothing works" tends to persist for a long time, and problems often erupt during integration. By passing one feature vertically, the "implementation pattern for all layers" is established early, which minimizes rework later on.
In the prompt for gen-milestones, which creates the milestones, I specify examples of goals like the ones below to ensure the agent creates goals that are as concrete and unambiguous as possible.
❌ "Composed of a DDD layer structure, with Gateway interfaces defined"
✅ "The rules page allows listing, registering, editing, and deleting expression rules, and they are persisted to a real DB"
Improvement 5: Enforce "actually working in a browser/recording a video of it working" as a completion condition
The design philosophy is that a milestone goal must be in a "state where operation can be verified in a browser," and "code exists or tests pass" is considered a failure.
A bad habit of current LLMs is that when they try and fail, they use mocks or stubs to treat the task as complete. To prevent this, I have decided to run E2E tests at the end of each wave and save a video of browser operations at the end of each milestone.
Having a video after a wave is completed is also helpful when checking the implementation later; it helps streamline the final check by allowing me to watch the video to see what features were built before verifying the operation myself.
Instructions for those who want to try it out
In this chapter, I will explain how to use it for those who have become interested in trying it out.
3 Steps to Use
Step 1: Create a design document with the /plan slash command
/plan 以下のアプリケーションの設計を行って。...(要件を記述)First, describe the overall picture of the task in Markdown. Since the command contains a link to the design document that should be referenced, appropriate task design is performed.
(For what to write, please refer to this file.)
Step 2: Generate milestones.json with the /gen-milestones command
/gen-milestones docs/tasks/設計ドキュメント.mdThe agent reads the task created in Step 1, determines the milestones for the entire task, and generates a JSON file to record progress. (If it already exists, it will archive it in an appropriate place and create a new one.)
Step 3: Execute with bash looper/run.sh
bash looper/run.shThe infinite loop of Plan -> Build -> Verify will continue until all milestones are complete!Go for a walk or take a nap!
watch -n3 bash looper/monitor.sh -vIf you want to check the status, you can use the monitor command.
If you want to customize it
The loop engine itself (looper/run.sh) and the prompts are not heavily dependent on specific languages or frameworks. If you want to rewrite them for your own project, you just need to change the following:
docs/ — Conventions for design and tech stack. The agent reads these every session, so feel free to adjust them as you like.
looper/prompts/ — Prompts for the Plan, Build, and Verify agents. Since the verification commands are for TypeScript, you will need to adjust them if you use a different language.
I think it will work with any language with just a little tweaking.
Reflections on implementation
Thinking about it again, all the ingenuity I introduced this time is something I am usually careful about when working as a PdM or engineer.
Do not design all the details at once; start from rough milestones and gradually refine them
Gradually increase functionality while verifying that it works little by little
Define task completion criteria by external behavior rather than by program
Since LLMs are also created by learning human language and use tools made for humans like git, it may be natural that the appropriate development processes are similar.
I think I will almost certainly use the loop system I created this time whenever I build a new service or perform major feature modifications to an existing app in the future.
Since the advent of coding AI, the amount of information I receive per hour has continued to increase, and I have been feeling an unprecedented level of daily fatigue, so I am simply happy that I was able to create a mechanism that makes me feel more at ease, including my mental state as well.
This type of development is currently an experimental method, but I think that eventually, a definitive tool will emerge, and the amount of time engineers spend directly writing or reading code will decrease.
For my part, I view this change in development style positively, and I think that as the time I need to spend facing code decreases, the time I can spend participating in conversations with customers and teammates and thinking about solving more essential problems will increase! It's a Forward Deployed Engineer (FDE) approach!
I hope this article will be helpful for the well-being of developers who will face more essential problems in the future!
