Claude Code ralph loop — Stop hookで同じ指示を繰り返す公式プラグイン
ralph-loopは、Stop hookで終了を止めて同じプロンプトを何度も実行させる公式プラグインです。/ralph-loopの引数、終了条件、8回の上限との関係、向く課題をまとめます。
ralph-loopは、Claudeが応答を終えようとするたびにStop hookで止め、最初と同じプロンプトを送り直すプラグインです。/ralph-loop を1回実行すれば、完了の合図が出るか回数の上限に達するまで、同じセッションの中で作業が繰り返されます。Anthropicの公式マーケットプレイス(claude-plugins-official)に入っています。
テストが全部通るまで直し続けさせたい、といった課題に向いています。一方で、終了条件の書き方を誤ると回り続けます。仕組みと引数、止まる条件を押さえておくと、放置して回しても安全になります。
ralph-loopは何をするプラグインか
名前の由来は、Geoffrey Huntleyが紹介した「Ralph is a Bash loop」という手法です。while true でAIエージェントに同じプロンプトを渡し続け、成果物が仕上がるまで反復させます。ralph-loopはこれを外部のシェルループなしで、Claude Codeのセッション内に再現します。
ループを成立させているのは3つの事実です。
- プロンプトは毎回同じで、変わりません。
- 前の周回の成果はファイルとgitの履歴に残ります。
- Claudeは次の周回でそのファイルを読み、自分の前の仕事を踏まえて直します。
つまり「会話を引き継ぐ」のではなく「ファイルシステムを引き継ぐ」設計です。テストの出力やlintの結果が毎周ファイルに反映される課題ほど、手応えが出ます。
インストールと最初の1回
公式マーケットプレイスは、対話セッションを初めて開いたときに自動で登録されます。そのため、インストールはプラグイン名とマーケットプレイス名を指定するだけです。
/plugin install ralph-loop@claude-plugins-officialセッション内では、このコマンドはすぐには入れず、プラグインの詳細画面を開いてスコープを選ばせます。シェルから入れる場合は claude plugin install ralph-loop@claude-plugins-official です。プラグインの入れ方全般はClaude Codeのプラグインとマーケットプレイスにあります。
入れたら、次の形で1回だけ実行します。
/ralph-loop "ToDo APIを実装する。CRUD、入力検証、テストが必要。
完了したら <promise>COMPLETE</promise> と出力する。" \
--completion-promise "COMPLETE" --max-iterations 20READMEのクイックスタートに沿った形です(READMEは回数を50にしています。ここでは安全側に20としました)。実行後の動きは、Claudeが作業し、終わろうとしてStop hookに止められ、同じプロンプトで再開する、の繰り返しです。
引数は2つだけ
/ralph-loop が受け取るのはプロンプトと次の2つのオプションです。
| オプション | 役割 | 省略したとき |
|---|---|---|
--max-iterations <n> | 役割n回で自動停止する | 省略したとき無制限(0 も無制限) |
--completion-promise "<text>" | 役割完了を示す文字列 | 省略したとき完了判定なし(止まらない) |
両方を省くと、止める手段が /cancel-ralph だけになります。セットアップ時の警告も、回数か完了の合図のどちらかを必ず設定するよう促しています。READMEが勧めるのは、完了の合図より --max-iterations を主たる安全網にする運用です。
プロンプトは引用符で囲まなくても受け付けますが、--completion-promise に複数語を渡すときは引用符が必要です。
1周ごとに何が起きているか
ソースを読むと、仕組みは「状態ファイル」と「Stop hook」の2点に絞れます。
ralph-loopの1周
- 1
状態ファイルを作る
/ralph-loopの実行時に、.claude/ralph-loop.local.mdが作られます。YAMLの先頭部にiteration: 1、max_iterations、completion_promise、session_idなどを持ち、その下にプロンプト本文が入ります。 - 2
Claudeが作業して終わろうとする
通常ならここでセッションが終わります。プラグインの
hooks.jsonがStopイベントにシェルスクリプトを登録しているので、スクリプトが先に呼ばれます。 - 3
スクリプトが終了条件を調べる
状態ファイルがなければ何もせず終了を許します。あれば、回数の上限と完了の合図を順に確かめます。
- 4
条件を満たさなければブロックする
iterationを1増やし、decision: "block"と、reasonに入れたプロンプト本文を返します。Claudeはそのreasonを次の指示として受け取り、再び作業します。
状態ファイルの先頭部は、例えば次のような形になります。
---
active: true
iteration: 1
session_id: <セッションID>
max_iterations: 20
completion_promise: "COMPLETE"
started_at: "2026-10-10T06:00:00Z"
---
ToDo APIを実装する。…状態ファイルは作業ディレクトリの .claude/ に置かれるため、プロジェクト単位です。それでも他のセッションを巻き込まないよう、スクリプトは session_id を比べます。状態ファイルに記録されたIDと違うセッションでは、Stop hookは何もせず終了を許します。同じプロジェクトを別のターミナルで開いていても、ループは起動したセッションの中でだけ続きます。
Gitに入れたくなければ、.claude/ralph-loop.local.md を .gitignore に追加しておくと安心です。
止まる条件は3つ
ループが終わる経路は、ソース上では次の3つです。
- 完了の合図が一致した。Claudeの最後のテキスト出力に
<promise>…</promise>があり、中身が--completion-promiseの文字列と一致する。 - 回数の上限に達した。
iterationがmax_iterations以上になる(max_iterationsが0より大きいときだけ)。 /cancel-ralphを実行した。状態ファイルを消して終了する。
どの経路でも、終了時には状態ファイルが削除されます。状態ファイルの数値欄が壊れていたり、トランスクリプトが読めなかったりしたときも、スクリプトはファイルを消してループを終えます。手で状態ファイルを消せば、ループは止まります。
完了の合図は完全一致で、1種類しか扱えない
完了判定には癖が3つあります。
- 見るのは、直近のアシスタント出力に含まれる最後のテキストブロックだけです。途中の周回で書いた文は対象になりません。
- 最初の
<promise>タグの中身を取り出し、前後の空白を削り、連続する空白を1つにまとめてから比べます。大文字小文字や表記ゆれは吸収されません。 - 条件は1つしか指定できません。READMEも「成功」と「ブロックされた」のように複数の完了条件を持たせることはできないと注意しています。
そのため、うまくいかなかった場合の出口は --max-iterations に任せ、プロンプト側には「N周しても終わらなければ、詰まっている点と試したことを書き出して終了する」と書いておきます。READMEもこの組み合わせを勧めています。
また、/ralph-loop のコマンド文面は、完了の合図を偽って出すことを禁じています。条件が本当に満たされたときだけ出すよう、Claudeに念を押す指示です。
Stop hookの8回上限とはぶつからないのか
Claude Code側には、Stop hookが続けてブロックできる回数の上限があります。既定は8回です。ralph-loopもStop hookで継続させるので、気になる点です。
hooksのリファレンスによれば、連続継続の数は、Claudeがツールを呼ぶたびにリセットされます。ファイルを編集し、テストを実行する周回では毎回ツールが呼ばれるため、通常の作業はこの上限に当たりにくい構成です。逆に、ツールを呼ばないターンが8回続くと、Claude Codeは次のブロックを上書きしてターンを終わらせます。
ralph-loopのREADMEにこの上限の記載はありません。長いループで「ツールを使わない周回」が続きそうな課題では、環境変数で上限を上げる選択肢があります。
# 上限を20回に引き上げる(0なら無効化。ralph-loopの外でも全Stop hookに効く)
CLAUDE_CODE_STOP_HOOK_BLOCK_CAP=20 claudeただし、上限は暴走を止める最後の安全網でもあります。上げる前に、プロンプトの完了条件が実際に満たせるかを見直すほうが先です。数え方や適用範囲はCLAUDE_CODE_STOP_HOOK_BLOCK_CAPの解説にまとめています。
反復に向くプロンプトの書き方
READMEの要点は、「完了を機械的に確かめられる形」で書くことです。曖昧な目的(「良いものを作って」)では、Claudeは終わりどころを自分で決められず、ループが空回りします。
次のようなプロンプトなら、毎周の結果をテストが判定してくれます。公式の例に沿って組んだものです。
認証機能(JWT)を実装する。進め方は次の通り。
1. 失敗するテストを先に書く
2. 実装する
3. `npm test` を実行し、失敗があれば原因を直す
4. すべて通ったらリファクタリングする
完了条件: テストがすべて通り、README に API の説明がある。
その時だけ <promise>COMPLETE</promise> と出力する。
15周しても終わらない場合は、詰まっている点、試したこと、
別のアプローチ案を書き出して終了する。大きな課題は、段階に分けて書きます。READMEは「ユーザー認証 → 商品カタログ → カート」のようにフェーズ分けし、全フェーズが終わったときだけ完了の合図を出す構成を示しています。
テスト駆動で書く流れはClaude CodeでTDDを回す手順でも扱っています。ralph-loopはその繰り返し部分を自動化する位置づけです。
向く課題と向かない課題
READMEの整理を表にすると、次のとおりです。
| 向く | 向かない |
|---|---|
| 成功条件が明確な課題 | 向かない人の判断や設計の決定が要る課題 |
| 反復して詰めていく課題(テストを通すなど) | 向かない1回で済む操作 |
| 放置できる新規開発 | 向かない成功条件が曖昧な課題 |
| テストやlintで自動検証できる課題 | 向かない本番環境の障害調査 |
自動検証の手段がないと、Claudeは「終わったつもり」で完了の合図を出せてしまいます。ralph-loopは完了を判定する側を持たないため、判定は課題側のテストに任せる設計です。
/goalや/loopとの使い分け
セッション内で作業を続けさせる仕組みは、ほかにもあります。
| 仕組み | 次の周回が始まるきっかけ | 終わらせるのは誰か |
|---|---|---|
| ralph-loop | 次の周回が始まるきっかけターンの終了 | 終わらせるのは誰か完了の合図の文字列一致、または回数上限 |
/goal | 次の周回が始まるきっかけターンの終了 | 終わらせるのは誰か別のモデルが条件の成否を判定 |
/loop | 次の周回が始まるきっかけ時間の経過 | 終わらせるのは誰か間隔の指定や自己ペース |
/goal は、組み込みのセッション単位のStop hookです。条件を自然文で渡すと、毎ターン後に別のモデルが達成を判定します。「完了」を文字列の一致ではなく中身で見てほしいなら、こちらが向きます。詳しくは/goalコマンドの解説にあります。
/loop は時間で回すもので、仕組みの軸が違います。使いどころは/loopコマンドの解説で比べられます。ralph-loopは「同じプロンプトを、ファイルの変化を頼りに何度でも」という点で、この2つとは別の道具です。
つまずきやすい点
- Windowsでフックが失敗する。Stop hookはbashスクリプトで、Git for Windowsが必要です。
bashがWSLのものに解決されると、wsl: Unknown keyやexecvpe(/bin/bash) failedが出ます。READMEは、キャッシュされたhooks/hooks.jsonのコマンドをGit Bashの絶対パスに書き換える回避策を示しています。 - jqが前提。スクリプトはJSONの処理に
jqを、完了の合図の抽出にperlを使います。入っていない環境では動きません。 - 停止の案内が食い違う。セットアップ時のヘルプ表示には「手動では止められない」とありますが、READMEとコマンド定義には
/cancel-ralphが用意されています。止めたいときは/cancel-ralphか状態ファイルの削除が確実です。 - 無制限は費用が膨らむ。回数も完了の合図も付けない実行は、止める手段が手動に限られます。最初は小さな上限(5〜10周)で試して、周回あたりの消費を見てから広げる流れが無難です。
まとめ
ralph-loopの核心は、Stop hookで終了を止めて同じプロンプトを送り直すという、ごく単純な仕組みです。品質を決めるのはプラグインではなく、プロンプトの完了条件と、それを機械的に確かめるテストの有無です。
試すなら、--max-iterations を必ず付け、テストで成否が決まる小さな課題から始めます。条件の中身をモデルに判定させたい場合は /goal、Stop hookの動作そのものを書き換えたい場合はHooksの完全ガイドが出発点です。