Claude Code /loopで繰り返し実行—loop.mdと発火しないスキル

Claude Code /loopで繰り返し実行—loop.mdと発火しないスキル | mohablog

/loop 5m デプロイが終わったか確認して と打つと、5分おきに同じプロンプトが流れます。間隔を省けば、Claude が1分〜1時間の幅で次回の実行時刻を自分で決める自走モードに切り替わります。Claude Code v2.1.220 時点の挙動を、公式ドキュメントと手元での実行結果で確認しました。

目次

動くのはセッションが開いている間だけ

公式ドキュメント “Run prompts on a schedule” の “Compare scheduling options” に、繰り返し実行の手段が3つ並んでいます。

Routines(クラウド)デスクトップタスク/loop
実行場所Anthropic のクラウド自分のマシン自分のマシン
マシンの起動不要必要必要
セッションを開いたままにする不要不要必要
再起動をまたぐかまたぐまたぐ期限内なら --resume で復元
ローカルファイル不可(毎回クローン)
MCPサーバータスクごとに設定設定ファイルとコネクタセッションから継承
権限プロンプト出ない(無人実行)タスクごとに設定セッションから継承
最短間隔1時間1分1分

セッション継承が効く場面

/loop の性格は、この表の「セッションから継承」の2行に出ています。今のセッションで承認済みの権限も、接続済みの MCP サーバーも、そのまま次の周回で使えます。クラウド側の Routines は毎回まっさらなクローンから始まるので、ローカルの .env や未コミットの差分は見えません。CI の失敗をローカルのビルドログと突き合わせたい用途なら /loop 側です。

クラウドの Routines は1時間刻みが下限。5分で終わるデプロイの監視には間に合いません。

–resume で戻るもの、戻らないもの

タスクはセッションスコープです。新しい会話を始めた時点で全部消えます。claude --resume--continue で復元されるのは、作成から7日以内の定期タスクと、発火時刻がまだ来ていない単発タスクだけ。バックグラウンドBash と Monitor のタスクは復元対象外です。

セッションをバックグラウンド化した場合は例外で、/loop のタスクはバックグラウンドセッションに引き継がれ、ターミナルを閉じても回り続けます。

間隔を渡すかどうかで挙動が変わる

/loop 5m check if the deployment finished and tell me what happened

間隔とプロンプトを両方渡した形。Claude が間隔を cron 式に変換してジョブを登録し、周期とジョブIDを返します。手元で同じ内容を登録したときの出力がこれです。

Scheduled recurring job ee4d4e00 (Every 5 minutes).
Session-only (not written to disk, dies when Claude exits).
Auto-expires after 7 days. Use CronDelete to cancel sooner.

ジョブIDは 8文字。1セッションで同時に保持できるスケジュールタスクは 50個までです。

渡す引数と起きること

渡すもの起きること
間隔とプロンプト/loop 5m check the deploy固定スケジュールでプロンプトが走る
プロンプトのみ/loop check the deployClaude が周回ごとに間隔を決める
間隔のみ、または何もなし/loop組み込みのメンテナンスプロンプト、または loop.md が走る

7m や 90m は丸められる

間隔の単位は s / m / h / d。先頭に 30m と裸のトークンで置いても、末尾に every 2 hours と節で書いても通ります。cron の粒度が1分なので、秒指定は分に切り上げ。7m90m のようにきれいな cron ステップへ落ちない間隔は近い値に丸められ、丸めた結果が返ってきます。

登録される cron 式は5フィールドの標準形です。*/5 * * * * が5分ごと、7 * * * * が毎時7分、0 9 * * 1-5 が平日9時。曜日は日曜が 07、土曜が 6LWMON のような拡張構文は通りません。

間隔を省くと1分〜1時間で自走する

“Let Claude choose the interval” の挙動。周回ごとに、観測した状況から次の待ち時間を1分〜1時間の範囲で選びます。ビルドが終わりかけていれば短く、PR が静かになれば長く。選んだ待ち時間と、その理由が毎回の最後に出力されます。

/loop check whether CI passed and address any review comments

実行結果は、CI が回っている間は数分間隔、マージ待ちで止まったら30分間隔、という具合に伸縮する周回になります。固定間隔と違って後述の jitter は乗りませんが、7日で終わる制限は同じです。

Amazon Bedrock、Claude Platform on AWS、Google Cloud の Agent Platform、Microsoft Foundry では自走モードが使えず、間隔なしのプロンプトは10分固定になります。

loop.md でデフォルトのプロンプトを差し替える

プロンプトを省いた /loop は、組み込みのメンテナンスプロンプトを回します。中身は公式ドキュメントに明記されていて、周回ごとに次の順で処理が進みます。

  • 会話の中でやりかけになっている作業を継続する
  • 現在のブランチの PR を世話する(レビューコメント、失敗した CI、マージコンフリクト)
  • 他に何も残っていなければ、バグ探しや簡素化のクリーンアップを回す

この範囲の外で新しいことを始めることはありません。push や削除のような取り消しにくい操作も、会話ですでに承認された作業の続きに当たるときだけ実行されます。

.claude/loop.md と ~/.claude/loop.md

組み込みプロンプトを自分の指示に置き換えるのが loop.md です。”Customize the default prompt with loop.md” セクションの通り、Claude が探す場所は2つで、先に見つかった方が使われます。

  • .claude/loop.md – プロジェクト単位。両方あるときはこちらが優先される
  • ~/.claude/loop.md – ユーザー単位。自前の定義を持たないプロジェクトに適用される

中身は素の Markdown で、決まった構造はありません。/loop のプロンプトをそのまま打つつもりで書きます。公式ドキュメントが載せているのは、リリースブランチを健全に保つ例。

Check the `release/next` PR. If CI is red, pull the failing job log,
diagnose, and push a minimal fix. If new review comments have arrived,
address each one and resolve the thread. If everything is green and
quiet, say so in one line.

これを .claude/loop.md に置いて /loop と打つと、CI が赤ければ失敗ジョブのログを引いて最小の修正を push、レビューコメントが来ていれば個別に対応してスレッドを解決、全部緑なら1行だけ報告、という周回になります。日本語でも同じように書けます。

main への未マージ PR を確認する。CI が失敗していたら失敗ジョブのログを取得し、
原因を特定して最小の修正を push する。新しいレビューコメントがあれば1件ずつ対応し、
スレッドを解決する。すべて緑で静かなら「変化なし」とだけ報告する。

- 1周目のざっくりした指示から始めて、ログを引く範囲や修正の粒度は
  周回の出力を見ながらこのファイルに書き足していく運用に落ち着いた
- テストの新規追加はしない。既存テストが落ちた場合のみ手を入れる

実行結果としては、PR が静かな間は「変化なし」の1行だけが返り、CI が落ちた周回だけログの引用と修正差分が出ます。

走らせたまま書き換えられる

loop.md への編集は次の周回から効きます。ループを止めて、書き直して、立ち上げ直す、という手順は要りません。1周目の出力を見てから指示を絞り込めるので、最初から完璧なプロンプトを書く必要がなくなります。

/loop のプロンプトをコマンドラインで渡した場合、loop.md は無視されます。あくまで引数なしの /loop に対するデフォルト定義であって、スケジュールタスクのリストではありません。別のプロンプトを並行して回したいなら /loop <prompt> を追加で打ちます。

25,000バイトを超えた分は切られる

loop.md の上限は 25,000バイト。超えた分は切り捨てられます。手順書を丸ごと貼るような使い方は想定されていません。長い手順を回したいなら Skill へ切り出し、/loop 20m /my-skill の形で呼ぶ方がコンテキストの消費も抑えられます。ただしスキルを渡す場合は、次の制約に引っかかります。

スキルを渡しても発火時に実行されないものがある

/loop 20m /code-review を仕掛けて席を立ち、20分後に戻ってきたらレビュー結果ではなく「/code-review を実行してほしいという依頼文」として解釈された返答が並んでいた。原因は v2.1.196 で入った制約です。

スケジュール発火で通るもの、通らないもの

スケジュールされた発火が実行できるのは、Claude が自分の判断で呼べるスキルだけ。次のものはプレーンテキストとして届き、コマンドとしては動きません。

  • /permissions/model/clear のような組み込みコマンド
  • disable-model-invocation: true が付いたスキル。組み込みの /verify/code-review がこれに該当する
  • skillOverrides 設定や Skill の deny ルールで Claude から隠されているスキル
  • /mcp__github__list_prs のような MCP プロンプト

回すなら自作スキル側に寄せる

動かない書き方:

/loop 20m /code-review

実行結果: 20分ごとにテキストが届くだけで、レビューは走りません。

動く書き方:

/loop 20m /review-pr 1234

実行結果: .claude/skills/review-pr/SKILL.md が周回ごとに実行され、PR 1234 の差分に対する指摘が返ります。

自作スキルの frontmatter に disable-model-invocation: true を書いていると同じ扱いになります。/loop から回す前提のスキルには、この行を入れないでおきます。

止め方と、放置したときの終わり方

Esc は待機中のループに効く

“Stop a loop” セクションの内容。次の周回を待っている /loopEsc で止まります。待機中のウェイクアップが消えるので、以降は発火しません。

ただし Claude に自然文で頼んで登録したタスクは Esc の対象外。こちらは明示的に消します。一覧も削除も自然文で通ります。

> what scheduled tasks do I have?

ee4d4e00 — Every 5 minutes (recurring) [session-only]: check if the deployment finished and tell me what happened

> cancel the deploy check job

Cancelled job ee4d4e00.

全部消えた状態で一覧を叩くと No scheduled jobs. が返ります。裏で動いているのは CronCreate / CronList / CronDelete の3ツールで、削除に必要なのは前述の8文字IDだけです。

自走モードは Claude 側から降りる

間隔を省いた自走モードでは、作業が完了したと判断した時点で Claude が ScheduleWakeupstop: true で呼び、待機中のウェイクアップを取り消します。stop フィールドは v2.1.202 以降。それより前は「次を予約しない」ことだけが自発的な終了手段でした。

周回の終わりに再予約も停止もしなかった場合、約20分後にフォールバックのウェイクアップが1回入ります。その周回でも再予約されなければ、そこでループは終わります。

放置しても7日で消える

“Seven-day expiry” の通り、定期タスクは作成から7日で自動的に期限切れになります。最後に1回だけ発火してから自分を削除する動きなので、消し忘れたループが延々と走り続けることはありません。7日を超えて回したいなら、期限前に作り直すか、Routines かデスクトップタスクへ移します。

スケジューラごと殺すなら環境変数です。CLAUDE_CODE_DISABLE_CRON=1 を設定すると cron 系ツールと /loop が使えなくなり、登録済みのタスクも発火しなくなります。

発火時刻はきっかり揃わない

“Jitter” セクションに、意図的なずれの仕様が書かれています。世界中のセッションが同じ壁時計時刻に API を叩かないよう、発火時刻へ決定的なオフセットが乗ります。定期タスクは指定時刻から最大30分後まで(1時間より短い周期なら間隔の半分まで)、単発タスクが :00:30 に置かれている場合は最大90秒前。

オフセットはタスクIDから導出されるため、同じタスクは毎回同じだけずれます。時刻を厳密に扱いたいなら 0 9 * * * ではなく 3 9 * * * と書きます。これで単発タスクの jitter は乗りません。

ポーリングより Monitor が向く場面

自走モードの /loop を頼むと、Claude が代わりに Monitor ツールを使うことがあります。Monitor はバックグラウンドでスクリプトを走らせ、出力行が届くたびにそれをイベントとして受け取る仕組み。ポーリング自体が要らなくなるので、同じ監視をトークン効率よく、かつ速く回せます。

出力行が届いたときだけ動く

ログの tail、PR や CI ジョブのステータス変化、ディレクトリの変更検知、長時間スクリプトの出力追跡。いずれも /loop の定間隔ポーリングより Monitor 側が速く拾えます。イベントを push してくるサーバーが相手なら、Monitor は WebSocket を開いて受信メッセージをそのままイベントとして扱えます。

権限ルールは Bash と共通

Monitor がコマンドを実行するとき、権限判定は Bash と同じルールを使います。Bash 向けに書いた allow / deny パターンがそのまま効くので、監視用に別途権限を切る必要はありません。WebSocket ソースだけは独自の承認プロンプトが出ます。

ループを止めるのは、Claude にキャンセルを頼むか、セッションを終わらせるかのどちらか。条件が満たされるまで会話をまたいで作業を続けさせたいなら、間隔ベースの /loop ではなく /goal の方が形として合います。

まとめ

  • /loop はセッションが開いている間だけ動く。最短間隔1分、ローカルファイルと MCP はセッションから継承
  • 間隔を渡せば固定 cron、省けば Claude が1分〜1時間で自走。7m90m は近い値に丸められる
  • 引数なしの /loop は組み込みのメンテナンスプロンプトを回す。.claude/loop.md~/.claude/loop.md で差し替え可能、上限25,000バイト
  • loop.md の編集は次の周回から反映される。走らせたまま指示を絞り込める
  • v2.1.196 以降、disable-model-invocation: true のスキルと組み込みコマンドはスケジュール発火で実行されない
  • 止め方は Esc、自走モードの stop: true、7日の自動期限切れ。全停止は CLAUDE_CODE_DISABLE_CRON=1
  • 発火時刻にはタスクIDから決まるオフセットが乗る。厳密さが要るなら :00:30 を外す
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次