ClaudeCode無限ループ(ralph-loop)による完全自律開発ワークフローで開発者のウェルビーイングを取り戻す!
こんにちは。チームみらい 永田町エンジニアチームの伊藤(エディ)です。
先日投稿した記事では、Claude Code Webを8並列で回すためのハーネスエンジニアリングについて書きましたが、そこから試行錯誤を進め、人間が細かく指示しなくても、1コマンドのロングセッションで大量の機能を作り切る開発手法(いわゆる ralph loop )を自分でも研究してみました。
現時点で、15分程度でドキュメントを仕上げてAIに任せると、3~4時間のロングセッションで、数千〜1万行程度の、比較的品質の高い実装が安定して完成するような状態になったので、工夫を紹介してみようと思います。
思えばコーディングLLMの誕生以降、圧倒的な情報の洪水で脳が常に焼き切れそうな感覚を覚えていましたが、この方法を使えるようになった今、実装完了を待つ間にお散歩やお昼寝をできるようになり、圧倒的にウェルビーイングを取り戻せた感じがしています。
参考実装も↓に公開したので、興味のある方はぜひ覗いてみてください。
※ ロングセッションでもうまくいくように冗長めな検証がたくさん挟まるので、自分で本気でオーケストレーションする場合と比べ、開発速度は2/3くらいになります。純粋な開発スピードは2/3になったけど、自分の稼働時間に対する時間効率は10倍くらいになったというイメージが適切かもしれません。
とても大事な注意事項
ここに書いてあることは「僕はこうやったら結構うまくいったよ」くらいのものであり、万能な方法論ではありません。
TypeScript + Next.js という LLM が得意な技術スタックであること
1人で開発しているため、合意形成のコストが低いこと
大まかに動けば有用で、バグの存在が致命的にならないタイプのプロダクトであること
これらの前提があってこその話です。あくまで一事例としてお読みください。
前提: ralph-loop とは
ralph-loop は、Geoffrey Huntleyさんが発見・命名した、LLM コーディングエージェントを自律的にループさせるパターンで、無限ループで1タスクずつコーディングエージェントを起動させることで、コンテクスト領域を使いすぎることなく実装がいくらでも進んでいくという開発手法です。
知識の永続化は Git 履歴 + CLAUDE.md + タスクファイルで行い、LLM の記憶ではなくファイルに書くというのが発明ポイントでした。
素朴なralph-loopに感じた課題
オリジナルのRalph Loop実装や、それを参考にしたシンプルな自作実装を手元で回してみたところ、動くには動くのですが、自分のユースケースでは、以下のような課題がありました。
モックやダミーデータによるごまかしの横行:テストは通るものの、モックや決め打ちのデータでごまかしており、実際にDBを繋ぐと、思ったように動作しない
コード品質のブレ: テストの書き方やレイヤー構成について、セッションごとのばらつきが大きくなる
時間がかかる: デフォルトのralph-loopは直列であるため、一定以上のサイズのアプリケーションを作ろうと思うとかなり時間がかかる
という感じで、可能性は感じるものの、品質観点で物足りない部分も多いという感想を持ちました。
これらを改善すべく、前回紹介したハーネスエンジニアリングの工夫をもとに、並列実装による恩恵を受けながら高品質なアプリが実装できる方法について試行錯誤してみて、自分なりのループ実装にたどり着きました。
自分のループ実装の全体像
自分の実装では、オリジナル実装に追加する形で、
マイルストーン > ウェーブ > タスク構造による並列可能なタスク分解
3エージェント分業による実行品質の向上
を採用することでより品質の向上を試みています。図解するとこんな感じです。

ポイント1: マイルストーン > ウェーブ> タスク 構造による、並列可能なタスク分解
タスク管理では、開発の進行を3つの粒度で制御しています。
マイルストーン: 「1つの機能が動く」単位。
ウェーブ: マイルストーン内のタスク依存順序。同じウェーブ番号のタスクは並列実行できる
タスク: 1つの具体的な実装作業。1タスク = 1エージェントセッション

マイルストーンの作成はclaudeのカスタムスキル経由で行えるようにしています。
マイルストーン内のタスク・ウェーブ詳細については、ループ開始後、そのタスクに着手する段階ではじめて設計するようにしています。
ポイント2: 3つのエージェントの分業による実行品質の向上
LLMは、複数の目的を持たせると、達成のために本質をねじ曲げて完了扱いにしてしまうことがよくあります。
これを防ぐため、シンプルさをキープできる最小単位として、プランナー, ビルダー, ベリファイヤーのミッションの異なる3エージェントを協調させる構成にしています。
Planner…マイルストーンのゴールをウェーブ構造のタスク群に分解し、詳細仕様書を書く
Builder…タスクの実装者。個別ワークツリーで実装とユニットテストの通過までに責任をもつ
Verifier…Builderのブランチを順にマージし、E2Eやブラウザ上での品質検証を行う。失敗時には修正も担う。
ここまでの内容を読むと、かなり複雑なことをしているように感じるかもしれませんが、実はこのループは、170行のシェルスクリプト1つと、日本語で書かれた文章9つの、計10ファイルで構成されています。
.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 # 品質規約後述しますが、LLMの判断力を信じて、shellのロジックを最小限にしていることで、シンプルで問題が起きにくい構成にできています。
無限ループを機能させるための工夫ポイント
ここからは、さらに具体的な工夫ポイントについて紹介していきます。
工夫①: アーキテクチャ設計とハーネスエンジニアリングでミスを検知できるようにする
大前提、安定したAI駆動開発の土台は、アーキテクチャ設計とハーネスエンジニアリングと考えています。先日こちらの記事に書いたような
レイヤードアーキテクチャ+戦術的DDDによる「触るファイルの自明化」
ユニットテスト, E2Eテスト, lint, typecheck, dependency-cruiser などのハーネス
を、architecture.md, quality.md というファイルにまとめ、セッションごとに遵守させることで、独立したセッションのLLMが大量に動作しても、大きく品質がブレないようになっています。
工夫②:スクリプトにロジックを書きすぎず、LLM の判断力を信じる
メインループとなる run.sh でやっているのは、突き詰めていえば、worktree 作成と、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 フラグ更新マージコンフリクトの解消、テスト失敗の原因分析、修正と再検証の判断、マイルストーンファイルの更新など、分岐や判断を伴う処理もなるべく LLM に任せる方針にしています。
初期では並列で実装されたブランチのマージ処理などはシェルスクリプトに書いていたのですが、失敗時のハンドリングなどが複雑になりすぎたため、LLMに自然言語で指示するようにしたところ、一気に問題が起きにくくなりました。
またエージェント間の情報伝達も Git コミットメッセージの「申し送り」で行っています。人間向けの仕組みをうまくLLMに活用させることで、仕組みを複雑にしすぎないようにしています。
工夫③:一気に全体を設計させない
タスク一覧となる milestones.json には、初期時点ではプロジェクト全体で4~8個程度の大まかなマイルストーンだけを作らせており、それ以上の詳細はあえて作らない設計にしています。
そして、マイルストーンに着手するタイミングで、プランナーエージェント が「今のコードベース」を調査してから詳細設計し、マイルストーン単位の設計ドキュメントを書くようなSDD(Spec Driven Development)開発フローを定義しています。
これは
LLMに大量の情報を処理させると、コンテクストを消費することで設計の品質が徐々に下がっていく
前の成果物が次のマイルストーンの設計前提になるので、着手する瞬間に設計したほうが矛盾が発生しにくく、前フェーズでハマった落とし穴に再度ハマりにくい
という点を考慮しての工夫となります。
工夫④:ウォーターフォールではなく、ちょっとずつ動くものを作る
マイルストーンの切り方については、「レイヤーごとの横割り」ではなく「機能ごとの縦割り」をするようにプロンプトに書いています
❌ マイルストーン1: ドメインモデル全部 → マイルストーン2: Repository 全部 → マイルストーン3: UI 全部(ウォーターフォール)
✅ マイルストーン1: 基盤 → マイルストーン2: 機能Aを DB〜UI まで縦に通す → マイルストーン3: 機能Bを縦に通す
横割りだと「コードはあるけど何も動かない」状態が長く続き、統合時に問題が噴出しがちです。1機能を縦に通すことで「全レイヤーの実装パターン」が早期に確立されることで、以降の手戻りが最小限になりました。
マイルストーンを作成する gen-milestones のプロンプトにはゴールについて下記のような例を明記して、なるべく具体的でごまかしようのないゴールを作らせるようにしています。
❌️「DDD レイヤー構造で構成され、Gateway interface が定義される」
✅「rules ページで表現ルールの一覧表示・登録・編集・削除ができ、本物のDB に永続化される」
工夫⑤:「実際にブラウザで動くこと/動いているところの動画を撮ること」を完了条件として強制する
マイルストーンのゴールは「ブラウザで動作確認できる状態」でなければならず、「コードが存在する・テストが通っているだけ」は不合格という設計思想にしています。
現在のLLMの悪いクセとして、試行錯誤してうまくいかないと、モックやスタブをうまく利用して完了扱いにすることがあります。これをさせないため、各ウェーブの完了時点でE2Eテストを実行し、各マイルストーンの完了時点で、ブラウザ操作を動画で保存させることにしています。
ウェーブ完了後に動画ができるのはあとで実装を確認するときにも嬉しく、まずは動画を見てどういう機能ができたのか確認したのちに自分で動作確認することで、最終チェックの効率化にも役立っています。
試してみたい方向けの使い方説明
この章では、試してみたくなった方向けに、使い方を解説しておきます。
使い方3ステップ
Step 1: /plan スラッシュコマンドで設計ドキュメントを作る
/plan 以下のアプリケーションの設計を行って。...(要件を記述)まずはタスクの全体像をマークダウンに記載します。コマンド内に、参照すべき設計ドキュメントへのリンクがあるので、適切なタスク設計がなされます。
(どんなことを書くといいかは、このファイルを参考にしてみてください。)
Step 2: /gen-milestones コマンドで milestones.json を生成
/gen-milestones docs/tasks/設計ドキュメント.mdStep1で作ったタスクをエージェントが読み込み、タスク全体のマイルストーンを定め、進捗を書き込むためのjson 形式のファイルが生成されます。(すでに存在する場合は適切な場所にアーカイブし、新しく作ってくれます)
Step 3: bash looper/run.sh で実行
bash looper/run.sh全マイルストーンが完了になるまで、Plan -> Build -> Verifyの無限ループが続きます!お散歩やお昼寝をしよう!
watch -n3 bash looper/monitor.sh -v状況を眺めたい場合はmonitorコマンドで状況を見ることができます。
カスタマイズしたい場合
ループエンジン自体(looper/run.sh)やプロンプトは、それほど言語やフレームワークに依存していません。自分のプロジェクトに合わせて書き換える場合は、以下を変更すればOKです。
docs/ — 設計や技術スタックについての規約。エージェントが毎セッション読みに行くので、お好みで調整してください。
looper/prompts/ — Plan, Build, Verifyエージェントのプロンプト。検証コマンドなどがtypescript用なので、別言語使う場合は調整の必要があります。
ちょっと手直しすればどのような言語でも動作すると思います。
実装した感想
あらためて考えれば、今回導入した工夫はどれも、ふだんPdM・エンジニアとして働くときに気をつけていることでもあるなと思います。
先の詳細まで一気に設計せず、大まかなマイルストーンから徐々に細かくしていく
ちょっとずつ動くことを確かめながら、徐々に機能を増やしていく
タスクの完了条件は、プログラムではなく外部からの振る舞いで定義する
LLMも、人間の言語を学習してつくられたものですし、gitなど人間向けに作られたツールを利用するので、適切な開発プロセスが似通ってくるのも自然なことなのかもしれません。
今回作ったループシステムは、今後自分が新規サービスを作ったり、既存アプリの大きめの機能改修をするときには、概ね必ず使うのではないかと思います。
コーディングAIの出現以降、時間あたりに受けとる情報が増え続け、日常的にこれまでにない疲れを感じていたのですが、初めて自分のメンタルも含めて楽になる仕組みを作れたことがシンプルに嬉しいなと思っています。
このような開発は、今は実験的な手法ですが、いずれ決定版となるようなツールが出て、エンジニアが直接コードを書いたり読んだりすることは減っていくのではないかと思います。
自分としては、このような開発スタイルの変化はポジティブに捉えており、コードに向き合うべき時間が減ったぶん、顧客やチームメイトとの会話に参加し、より本質的な課題の解決を考えられる時間が増えていくのではないかと思います!Forward Deployed Engineer(FDE)ですね!
今後、より本質的な課題に向き合う開発者のウェルビーイングのために、この記事が参考になれば幸いです!
