• システム開発に関わる内容をざっくりと書いていく

Cursorで始めるループエンジニアリング

Cursor で Agent を使うと、「あと少しで終わるはず」が1時間経っても終わらない、という経験をした人は多いはず。会話が長くなるほど指示が薄れる・以前の制約を忘れる・同じ修正を繰り返す、といった症状が出てくる。

ループエンジニアリング(Ralph Loop とも呼ばれる)は、これを避けるためのやり方。1回の Agent 実行を短く区切り、状態はファイルと Git に残し、終了条件は LLM の「完了しました」ではなくテストや grep で判定する

この記事では、Cursor ユーザー向けにループエンジニアリングの考え方と、今日から試せる最小構成をざっくり整理する。C# / ASP.NET Core プロジェクトを例に触れる。

関連: Agent 設定フォルダ構成 / Skills ベストプラクティス / AGENTS.md ベストプラクティス


先に結論

  • ループエンジニアリング = 短い Agent 実行を繰り返す。各回は新しいコンテキストで始め、進捗はリポジトリ上のファイルに残す
  • 終了条件は「Agent が言ったから」ではなく、dotnet test / grep / 型チェックなど外部ツールで決める
  • Cursor なら ① エディタ + Subagent / プラグイン② CLI(cursor-agent -p)+ Bash ループ、のどちらかから始められる
  • 最初は「大きな機能」ではなく、機械的に分割できる作業(リネーム、テスト追加、警告ゼロ化)が向く
  • Plan Mode でタスク分解 → ループ用プロンプトと検証コマンドを固定、が定石

ループエンジニアリングとは

もともと Geoffrey Huntley 氏の Ralph Wiggum テクニック(Simpsons の Ralph から。間違えても諦めない、という意味合い)として知られるパターン。Cursor コミュニティでも Ralph Loop として再実装・プラグイン化されている。

1回のループはだいたい次の流れ。

  1. ディスク上のタスク一覧・進捗メモを読む
  2. 1タスクだけ実装する(新しい Agent セッション)
  3. テスト・lint・grep で外部検証
  4. 成功なら Git commit、進捗ファイルを更新
  5. 終了条件を満たすまで 1 に戻る(上限回数あり)

ポイントはチャット履歴を引き継がないこと。前の会話の要約に頼らず、progress.mdprd.json、Git log から「今どこまで終わったか」を毎回読み直す。

1本の長いチャットとの違い

従来の長い Agent セッション          ループエンジニアリング
────────────────────────────────────────────────────────────
コンテキストが膨らむ                  各イテレーションは新規コンテキスト
「さっき言った制約」を忘れる          制約は AGENTS.md / タスク JSON に固定
「完了しました」で終わる              dotnet test / grep で終了判定
人間がずっと見張る                    夜間・バックグラウンド実行もしやすい

Cursor で始める3つの入り口

全部いきなり入れなくてよい。自分の環境に合う1つからで十分。

① エディタ + Subagent(.cursor/agents/)

Subagent は Markdown で定義する専門 Agent。呼び出すたびに独立したコンテキストになるので、ループの「1イテレーション = 1 Agent」に向く。

  • .cursor/agents/ralph-loop.md … 次の未完了ストーリーを1件だけ実装する Executor
  • .ralph/prd.json … ユーザーストーリー一覧(passes: true/false、優先度)
  • .ralph/progress.md … 失敗パターン・学びを次のイテレーションへ引き継ぐ

チャットで /ralph-loop のように明示呼び出しする運用が多い。1回呼ぶ = 1ストーリー完了まで、を人間またはスクリプトが繰り返す。

② Cursor 公式 Ralph Loop プラグイン

Cursor の Marketplace 向けプラグインとして Ralph Loop が公開されている(Claude Code 版の移植)。Hooks で Agent の終了をフックし、同じプロンプトを再注入してループする。

  • 状態ファイル: .cursor/ralph/scratchpad.md
  • Skills: ralph-loop(開始)、cancel-ralph(中断)、ralph-loop-help
  • 完了は Agent の宣言だけでなく、Hook 側の完了シグナル検出も絡む

「自分で Bash を書きたくない」なら、まずプラグインから試すのが楽。

③ CLI(cursor-agent -p)+ Bash ループ

ヘッドレスの cursor-agent を print モード(-p)で起動すると、プロンプトを読んでファイル編集・シェル実行のあとプロセスが終了する。この「終了」をフックに Bash で回すのが CLI 版 Ralph Loop。

#!/usr/bin/env bash
MAX=20
for i in $(seq 1 $MAX); do
  remaining=$(grep -rl "TODO(migrate)" src/ | wc -l)
  if [ "$remaining" -eq 0 ] && dotnet test --no-build -q; then
    echo "Done."
    exit 0
  fi
  cursor-agent -p --model auto "Read AGENTS.md and progress.md. Fix ONE file. Run dotnet test."
done
echo "Max iterations reached."
exit 1

長時間バッチ(大規模リネーム、警告ゼロ化、テスト追加)向き。各イテレーションで –resume は使わないのが原則。継続性は Git と progress ファイルが担う。


今日から試す最小構成(5ステップ)

架空の受注 API OrderNestAGENTS.md 記事と同じ例)で、警告ゼロ化をループに載せる想定。

Step 1: Plan Mode でタスクを「機械的」に割る

「リファクタして」ではなく、1イテレーション = 1ファイル or 1警告種別まで分解。Plan Mode で次を出させる。

  • 対象ファイル一覧(または grep パターン)
  • 各タスクの完了条件(例: CS8618 がそのファイルから消える)
  • 検証コマンド: dotnet build -warnaserror / dotnet test

Step 2: 状態ファイルをリポジトリに置く

.ralph/
  prd.json       # ストーリー一覧(id, title, passes, priority)
  progress.md    # 失敗理由・次に気をつけること

AGENTS.md        # ビルドコマンド・触ってはいけない領域

prd.json の例(抜粋):

[
  {
    "id": "warn-01",
    "title": "OrderController.cs の nullable 警告を解消",
    "passes": false,
    "priority": 1
  },
  {
    "id": "warn-02",
    "title": "OrderService.cs の nullable 警告を解消",
    "passes": false,
    "priority": 2
  }
]

Step 3: Executor 用プロンプト(または Subagent)を固定

毎回同じ指示を渡す。変えるのはディスク上の状態だけ

1. .ralph/prd.json を読み、passes:false のうち priority が最小の1件を選ぶ
2. なければ ALL STORIES ARE COMPLETE と出力して終了
3. その1件だけ実装。スコープ外は触らない
4. dotnet build -warnaserror && dotnet test を実行
5. 成功したら passes を true に更新し progress.md に1行追記
6. git commit(メッセージに story id を含める)

Step 4: ループを回す

  • 手動: チャットで /ralph-loop を完了まで繰り返し(小規模向け)
  • 半自動: Ralph Loop プラグインの Skill を起動
  • 自動: ralph.sh や自前 Bash で cursor-agent -p を最大 N 回

Step 5: 朝、diff とテスト結果を見る

ループエンジニアリングは無人で merge までがゴールではない。git log と CI 相当のコマンドで確認し、変な方向に行っていたら progress.md にガードレールを足して再実行、が現実的な運用。


止め方・安全装置

ループは必ず上限を付ける。無限ループは Agent でも人間でも起きる。

  • 最大イテレーション数(例: 20〜50)。超えたら停止して人間が progress.md を読む
  • 同一ファイルの連続失敗で停止(gutter detection)。同じエラーを3回繰り返したらスキップ or タスク分割
  • 触ってはいけないパスを AGENTS.md に明記(Migrations/、本番設定など)
  • コスト: CLI ループは安いモデル(–model 指定)で実行フェーズを回し、Plan だけ高能力モデル、が定番
  • プラグイン利用時は cancel-ralph Skill で .cursor/ralph/ をクリーンアップ

向いている作業・向いていない作業

向いている

  • 警告・lint のゼロ化、命名統一、ボイラープレート生成
  • テストの追加(既存パターンの横展開)
  • API クライアント生成後の呼び出し側置き換え(1エンドポイントずつ)
  • ドキュメントとコードの同期(grep で未更新箇所を数える)

向いていない(最初は手で)

  • 要件が曖昧な新機能の設計
  • セキュリティ・認可の根幹変更
  • 「完了」の定義がテストで書けない探索的リファクタ

ループに載せる前に Plan Mode で検証可能な粒度まで落とせるかが判断基準。


うまくいかないとき

  • 同じ修正を繰り返す → タスクが大きい。prd.json を分割。progress.md に「前回失敗理由」を必ず書かせる
  • テストが通らないまま commit する → プロンプトに「テスト失敗時は commit 禁止」を明記。Hook や CI で二重チェック
  • スコープが広がる → AGENTS.md に「今回触っていいディレクトリ」を1行追加。Rules で glob 制限
  • コンテキストがまた膨らむ → Subagent / 新規セッションを使っているか確認。–resume 付き長セッションはループ向きではない
  • コストが読めない → イテレーションごとにトークン概算を log に残す Skill を足す

AGENTS.md / Skills / Rules との組み合わせ

役割              ループでの使い方
────────────────────────────────────────────
AGENTS.md         毎イテレーション必読。ビルド・禁止事項
Skills            ralph-loop 開始手順、cancel、障害時の調査
Rules             触ってよいパスの glob 制限
Subagents         1ストーリー executor / 任意で verifier
Git               真の進捗ログ。progress.md は補助

詳細は フォルダ構成記事 を参照。ループエンジニアリングはこれらの上に載る運用パターンと考えると整理しやすい。


まとめ

  • ループエンジニアリング = 短い Agent × 外部状態 × 外部検証の繰り返し
  • Cursor なら Subagent / Ralph Loop プラグイン / CLI の3経路
  • 最初の一歩は Plan でタスク分解 → prd.json + 検証コマンド → 5回だけ手動ループ
  • うまくいったら Bash 化や夜間実行へ。上限と cancel は必須

長い1本のチャットに頼るより、「1タスク終わったら Agent を一度降ろす」方が、C# の大規模ソリューションでも安定しやすい。まずは手元の警告1種類を prd.json に載せて試してみるのがおすすめ。


関連記事