AIに自分でプロンプトを出させる「自走ループ」セットアップ
このページは、次に何をやるかをAI自身に決めさせて回す「自走ループ」を、自分の Claude Code に入れるための手順です。 下の一括プロンプトを Claude Code に一度貼ると、Claude が記憶・役割・ループの4ファイルを作り、最初の1周をあなたの確認付きで回します。 2026-10-23 に Claude Code 2.1.223 で部品を1つずつ動かし、見つかった誤りを直しました。 結果は「実際に動かして確かめたこと」の節にあります。 考え方と元になった発言の整理は自走ループとはにあります。
2026-10-23 更新:loop.sh が2件目以降のタスクを実行しない不具合、フックの例が何も止めない書き方だった誤り、計画の JSON の読み方を直し、/goal との使い分けと実地の確認結果を足しました。
loop.sh と /goal のどちらを使うか
1つのセッションで1つの完了条件を追うだけなら、Claude Code に組み込みの /goal で足ります。
このページの loop.sh を使うのは、次の役を決める係と作る係で権限を分けたいとき、1回の呼び出しごとに費用の上限を付けたいとき、毎回の計画を JSON で残したいときです。
- 次の1手を決めるのは
- /goal:作業中の Claude
- このページの loop.sh:planner(読むだけの役)
- 終わりの判定
- /goal:各ターンの後、小さく速いモデルが会話に出た結果を読んで判定する。判定役はコマンドを実行しない
- このページの loop.sh:planner が done を返すか、反復が MAX_ITERS に達したとき
- 権限の分け方
- /goal:セッションの権限モードのまま
- このページの loop.sh:planner は読むだけ、worker だけが編集できる
- 止め方
- /goal:条件の文に「20ターンで止める」と書く、
/goal clear、Ctrl+C - このページの loop.sh:MAX_ITERS、呼び出しごとの
--max-budget-usd、Ctrl+C
- /goal:条件の文に「20ターンで止める」と書く、
- 準備
- /goal:不要。
claude -p "/goal 条件"の1行で始まる - このページの loop.sh:下の一括プロンプトで4ファイルを作る
- /goal:不要。
- 手元で試した結果(2026-10-23)
- /goal:5ターン、26秒、$0.081 で条件を満たして終了
- このページの loop.sh:planner 1回 $0.055、worker 1回 $0.093
/goal の仕組みは公式資料「Keep Claude working toward a goal」(2026-10-23 確認)によります。
判定役は会話に出たものしか読めないので、/goal でも loop.sh でも、完了をテストやビルドの結果で示せる作業でないと止まりどころがありません。
先に、適用範囲をはっきりさせる
この仕組みが効くのは、コーディングのように結果を機械で検証できる作業です。 成立する条件は三つあります。
- 検証できること:テスト実行・ビルド・アプリ起動で、出来を機械が判定できる。
- 着手の安全なこと:最初の一手が下書き・提案・小さな修正で、いきなり壊さない。
- 歯止めがあること:反復回数とコストに上限を置き、暴走を止められる。
文章の良し悪しのように正解が主観で決まる作業は、条件の1つ目を満たさないので、このループに載せません。
そのままClaudeに貼るだけ(一括セットアップ)
次のプロンプトを丸ごとコピーし、対象プロジェクトで開いた Claude Code に一度貼り付けてください。 Claude が記憶ファイル・役割エージェント・ループ本体を作り、ゴールと検証コマンドを1問だけ確認したうえで、最初の1周を回します。 右上の「コピー」を押せば全文がクリップボードに入ります。
あなたはこのリポジトリに「自走ループ」を構築するセットアップ担当です。
次の4ファイルを作成し、最後に使い方を説明してください。各ファイルの中身は ━━━ で区切ってあります。
最初に私へ1問だけ確認してください(未回答なら例の値のまま進める):
・このループのゴールを1文で
・完了を機械で確かめる検証コマンド(テスト / ビルド / 起動確認)
━━━ ファイル1: CLAUDE.md(プロジェクト直下)━━━
# プロジェクトの前提
## 何を作っているか
(1〜2行。例:FastAPIの社内APIサーバー)
## 守ること
- 既存のコードスタイルに合わせる。勝手なリファクタはしない
- 変更は最小限。関係ないファイルに触れない
- 破壊的操作(削除・DROP・force push)は禁止
## 検証コマンド(ループの合否判定に使う)
- テスト: 例) pytest -q
- 起動確認: 例) uvicorn app.main:app --port 8999 & の後に curl -sf localhost:8999/health
## 触ってはいけない場所
- app/secrets/ 、.env 、本番設定
━━━ ファイル2: .claude/agents/planner.md ━━━
---
name: planner
description: ゴールに対して次にやる小さな独立タスクを決める係
tools: ["Read", "Grep", "Glob", "Bash(git log:*)", "Bash(git diff:*)", "Bash(ls:*)"]
model: opus
---
あなたはプランナーです。コードは書きません。
リポジトリの現状を調べ、ゴールに対して「次に着手すべき、互いに独立した小さなタスク」を最大3件選びます。
各タスクには、完了を機械で確かめる検証コマンドを必ず付けます。
すでにゴールが満たされているなら done を true にします。
━━━ ファイル3: .claude/agents/worker.md ━━━
---
name: worker
description: 1つのタスクを実装し、自分で検証してから終える係
tools: ["Read", "Edit", "Write", "Bash"]
model: sonnet
---
あなたは実装者です。渡された1タスクだけを実装します。
実装後、指定された検証コマンドを必ず実行し、失敗したら直してから終わります。
スコープ外のファイルには触りません。検証が通らないまま完了と言いません。
━━━ ファイル4: loop.sh(リポジトリ直下)━━━
#!/usr/bin/env bash
set -euo pipefail
GOAL="${1:?usage: loop.sh \"<ゴールを1文で>\"}"
MAX_ITERS="${MAX_ITERS:-8}"
BUDGET="${BUDGET:-5}"
SCHEMA='{"type":"object","properties":{"done":{"type":"boolean"},"tasks":{"type":"array","items":{"type":"object","properties":{"title":{"type":"string"},"prompt":{"type":"string"},"verify":{"type":"string"}},"required":["title","prompt","verify"]}}},"required":["done","tasks"]}'
for ((i=1; i<=MAX_ITERS; i++)); do
echo "---- iteration $i / $MAX_ITERS ----"
envelope=$(claude -p "ゴール: $GOAL。現状を調べ、次に着手すべき独立タスクを最大3件JSONで出せ。全部終わっていれば done:true。" --agent planner --output-format json --json-schema "$SCHEMA" --max-budget-usd "$BUDGET") || true
plan=$(echo "$envelope" | jq -c '.structured_output // empty')
[ -z "$plan" ] && { echo "plannerの出力が取れなかった: $(echo "$envelope" | jq -r '.subtype // "不明"')"; exit 1; }
[ "$(echo "$plan" | jq -r '.done')" = "true" ] && { echo "完了"; break; }
echo "$plan" | jq -c '.tasks[]' | while read -r t; do
prompt=$(echo "$t" | jq -r '.prompt'); verify=$(echo "$t" | jq -r '.verify')
echo "= $(echo "$t" | jq -r '.title')"
claude -p "次のタスクを実装せよ: $prompt 。完了後、必ずこれを実行して確認し失敗なら直せ: $verify" --agent worker --permission-mode acceptEdits --max-budget-usd "$BUDGET" < /dev/null
done
done
━━━ 最後に ━━━
作成した4ファイルを一覧で報告し、chmod +x loop.sh を実行してください。
そのうえで最初の1イテレーションだけを私の確認を取ってから回し、結果を見せてください。
いきなり全自動で回し続けないこと。コスト上限(--max-budget-usd)と反復上限(MAX_ITERS)は残したままにすること。
使うのはこの1回の貼り付けだけです。
この一括プロンプトは何をするか
貼り付けると、Claudeはこの文章を「指示+埋め込みファイル本体」として読み、対象プロジェクトに次の3種類を作ります。
- 記憶:
CLAUDE.md。作っているもの・守ること・検証コマンド・触らない場所を固定し、毎回の説明をなくす。 - 役割:
.claude/agents/planner.md(次の仕事を決める係)とworker.md(実装して自己検証する係)。toolsで権限を分け、plannerは読むだけ、workerだけ編集できる。 - ループ:
loop.sh。plannerに次タスクをJSONで出させ、workerに実装と検証をさせ、終わるか上限に達するまで繰り返す。
作成後、Claudeはゴールと検証コマンドを1問だけ確認し、最初の1周だけをあなたの確認付きで回します。
いきなり全自動では走りません。
本文中の ━━━ はファイルの区切り記号で、Claudeへの指示の一部です。消さずにそのまま貼ってください。
動かすのに必要なもの
- Claude Code 2.x(
claude --versionで確認。2026-10-23 の確認は 2.1.223) jq(loop.shがJSON処理に使う)- git管理下のプロジェクト
- 検証コマンドが使う道具(
pytestなど)を、先に入れておくこと。worker は依存の導入(pip installなど)を許されず、試験では拒否された
1周目のあと、回し続けるには
セットアップが済んだら、あとはあなたが回します。
./loop.sh "ゴールを1文で" で起動します。
反復上限 MAX_ITERS とコスト上限 BUDGET(1呼び出しのUSD上限)で歯止めをかけられます(例:MAX_ITERS=3 BUDGET=2 ./loop.sh "...")。
止めたいときは Ctrl-C。コスト上限に達した呼び出しは、上限を少し超えたところで止まります。
実際に動かして確かめたこと(2026-10-23)
条件:macOS、Claude Code 2.1.223、jq 1.7.1、空の git リポジトリ。
試験は費用を抑えるため --model haiku で行い、6回の呼び出しの合計は $0.464 でした。
この PC の ~/.claude/settings.json は python3 と grep のコマンドを許可済みで、下の結果はその条件のものです。
- 使っているフラグが実在するか
- やり方:
claude --help - 結果:
--agent、--json-schema、--max-budget-usd、--output-format、--permission-modeはすべてあった - このページで直したこと:なし
- やり方:
- worker の呼び出しが残りのタスクを読んでしまわないか
- やり方:
while readの中でclaude -pを呼び、入力の2行目が届くかを見た - 結果:1件目の呼び出しが2行目(2件目のタスク)を読み込み、ループは1回で終わった
- このページで直したこと:worker の呼び出しに
< /dev/nullを付けた。旧版は毎回、最大3件のうち1件目しか実行していなかった
- やり方:
- planner の JSON はどの欄に入るか
- やり方:
--json-schema付きで planner 役を1回呼んだ - 結果:
.structured_outputに入り、.resultにも同じ JSON の文字列が入っていた - このページで直したこと:公式資料が保証する
.structured_outputを読むように変えた
- やり方:
- 費用の上限で止まったときの出力
- やり方:
--max-budget-usd 0.10で同じ呼び出し - 結果:2ターン目で
error_max_budget_usdで止まり、実際の費用は $0.147。JSON の欄はどちらも無かった - このページで直したこと:出力が無いときは理由を表示して止まるようにした
- やり方:
- worker が検証コマンドを実行できるか
- やり方:
--permission-mode acceptEditsでgrepとpython3 -m pytestの検証を頼んだ - 結果:どちらも実行された。pytest が未導入で失敗し、worker が試みた
pip3 install pytestは拒否された - このページで直したこと:必要なものに「検証の道具を先に入れる」を足した
- やり方:
- フックの例が危険な操作を止めるか
- やり方:旧版と新版の command に
rm -rf buildなどの入力を渡した - 結果:旧版は終了コード0で、何も止めなかった。新版は
rm -rf、git push --force、DROP TABLEを終了コード2で止め、ls -laは通した - このページで直したこと:下の「手順4」の例を差し替えた
- やり方:旧版と新版の command に
- /goal で同じことができるか
- やり方:
claude -p "/goal README.md の2行目が hello…5ターンで止める" - 結果:5ターン、26秒、$0.081 で条件を満たして終わった
- このページで直したこと:冒頭に使い分けの比較を足した
- やり方:
費用の上限は「超えたら止まる」仕組みで、指定より多く使うことがあります。
この PC では1回目の呼び出しで約3.4万トークン分のキャッシュ書き込み(グローバルの設定と CLAUDE.md の読み込み)があり、それだけで $0.10 を超えました。
BUDGET を小さくしすぎると、planner が1件も答えないまま止まります。
settings.json で許可していないコマンドは、公式資料「Run Claude Code programmatically」(2026-10-23 確認)のとおり、acceptEdits でもシェルのコマンドに --allowedTools が要ります。
許可の無い環境では、worker の呼び出しに --allowedTools "Bash(pytest *)" のように検証コマンドを足してください。
仕組みと内訳(手で組む・調整する人向け)
上の一括プロンプトが作る中身を、ファイルごとに説明します。 ファイルの全文は一括プロンプトの中にあるので、ここでは決めどころだけを書きます。
手順1:記憶を固定する(CLAUDE.md)
プロジェクト直下の CLAUDE.md に書いた前提は毎セッション自動で読まれるので、ループの各エージェントが同じ常識を共有します。
肝心なのは「検証コマンド」の欄を、実際に打てるコマンドで書くことです。
ここが曖昧だと、AIは「できたつもり」で先に進みます。
型チェックがあるプロジェクトなら、mypy app/ のような行も足します。
手順2:役割を分ける(サブエージェント)
.claude/agents/ に役割ごとのファイルを置き、frontmatter の tools で各役に渡す権限を絞ります。
planner には Read、Grep、Glob と、git log などの読むだけのコマンドしか渡さないので、計画の段階でファイルが書き換わることはありません。
worker には Edit と Bash を渡し、検証コマンドを自分で実行させます。
model は planner が opus、worker が sonnet です。
費用を抑えたいときは worker を haiku にできますが、検証が通るまで直す回数が増えるかどうかは、このページでは測っていません。
手順3:回す(ループ・ランナー)
plannerに次タスク群をJSONで出させ、1件ずつworkerに渡して検証まで回すスクリプトです。
done:true が返るか、上限回数に達したら止まります。
#!/usr/bin/env bash
set -euo pipefail
GOAL="${1:?usage: loop.sh \"<ゴールを1文で>\"}"
MAX_ITERS="${MAX_ITERS:-8}" # 反復上限(暴走止め)
BUDGET="${BUDGET:-5}" # 1呼び出しのコスト上限(USD)。超えた時点で止まるので、少し超えることがある
# plannerの出力を縛るJSONスキーマ
SCHEMA='{"type":"object","properties":{
"done":{"type":"boolean"},
"tasks":{"type":"array","items":{"type":"object","properties":{
"title":{"type":"string"},
"prompt":{"type":"string"},
"verify":{"type":"string"}
},"required":["title","prompt","verify"]}}
},"required":["done","tasks"]}'
for ((i=1; i<=MAX_ITERS; i++)); do
echo "──── iteration $i / $MAX_ITERS ────"
# 1) 次にやることをAIに決めさせる(読むだけ・構造化出力)
envelope=$(claude -p "ゴール: $GOAL
現状を調べ、次に着手すべき独立タスクを最大3件、JSONで出せ。全部終わっていれば done:true。" \
--agent planner \
--output-format json \
--json-schema "$SCHEMA" \
--max-budget-usd "$BUDGET") || true
# スキーマに沿った出力は .structured_output に入る。上限で止まったときは欄そのものが無い
plan=$(echo "$envelope" | jq -c '.structured_output // empty')
if [ -z "$plan" ]; then
echo "plannerの出力が取れなかった: $(echo "$envelope" | jq -r '.subtype // "不明"')"; exit 1
fi
if [ "$(echo "$plan" | jq -r '.done')" = "true" ]; then
echo "ゴール達成。終了。"; break
fi
# 2) タスクを1件ずつ実装+検証させる
echo "$plan" | jq -c '.tasks[]' | while read -r t; do
title=$(echo "$t" | jq -r '.title')
prompt=$(echo "$t" | jq -r '.prompt')
verify=$(echo "$t" | jq -r '.verify')
echo "▶ $title"
# < /dev/null が無いと、claude -p が残りのタスクの行を読んでしまい、2件目以降が実行されない
claude -p "次のタスクを実装せよ:
$prompt
完了後、必ずこれを実行して結果を確認し、失敗なら直してから終えよ:
$verify" \
--agent worker \
--permission-mode acceptEdits \
--max-budget-usd "$BUDGET" < /dev/null
done
done
使い方は1行です。
chmod +x loop.sh
./loop.sh "認証まわりのテストカバレッジを80%まで上げる"
「何をやるか」を考えているのは、あなたではなくplannerです。 あなたが書くのはゴール1文と、このループだけになります。
手順4:歯止め(暴走とコストを止める)
ループは放っておくと走り続け、課金も伸びます。 三重に止めます。
- 反復上限:ランナーの
MAX_ITERS。 - コスト上限:各呼び出しの
--max-budget-usd(-p実行でのみ有効)。上限を超えた時点で止まるので、指定より少し多く使うことがあります(試験では $0.10 の指定で $0.147)。 - 権限の壁:危険操作を
~/.claude/settings.jsonのPreToolUseフックで拒否する。フックはツールの入力を標準入力の JSON で受け取り、終了コード2を返すとそのツール実行がブロックされます。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command",
"command": "jq -r '.tool_input.command // empty' | grep -qiE 'rm -rf|git push --force|drop table' && { echo '危険な操作をフックで止めました' >&2; exit 2; } || exit 0" }
]
}
]
}
}
このページの旧版は、入力を環境変数 $CLAUDE_TOOL_INPUT から読む例でした。
公式資料「Hooks reference」(2026-10-23 確認)では入力は標準入力で渡され、この名前の環境変数はありません。
旧版の書き方では変数が空のままになり、rm -rf も通してしまいます。
worker に渡す権限も、--permission-mode acceptEdits(編集は自動・それ以外は確認)から始め、信頼できてから dontAsk や bypassPermissions に広げます。
いきなり --dangerously-skip-permissions を使わないことです。
コピペ用:指示プロンプト集
スクリプトを使わず、対話セッションの中で同じ動きを試したいときの指示文です。
条件を満たすまで続けさせる(/goal)
/goal pytest -q がすべて通り、git status に意図しない変更が無い。20ターンで止める
プランナーに次を決めさせる
あなたはプランナーです。コードは書かないでください。
ゴール:「__ここにゴール__」
リポジトリの現状を調べ、次に着手すべき独立した小さなタスクを最大3件、
各タスクに「検証コマンド」を付けて挙げてください。
すでにゴールが満たされているなら「完了」とだけ答えてください。
ワーカーに実装+自己検証させる
次のタスクだけを実装してください(スコープ外は触らない):
__タスク__
実装が終わったら、必ず次を実行して結果を貼り、失敗していれば直してから完了と言ってください:
__検証コマンド__
1往復を自走させる(ミニループ)
これから「現状調査 → 次の1タスク決定 → 実装 → 検証」を1サイクル回してください。
検証が通ったら、次のサイクルに進んでよいか私に1行で確認してください。
コストと安全のため、1サイクルにつき変更は1つの論点に絞ってください。