Claude Media
Claude Codeの/goal Stop hookが止まらない — 無限再発火の症状と回避策

Claude Codeの/goal Stop hookが止まらない — 無限再発火の症状と回避策

/goalのStop hookが同じ理由で何十回も再発火する不具合の報告をまとめます。再発火する状況の型、止め方、条件文の書き換え例を扱います。

/goalを設定したセッションで、作業はもう終わっている(または止めたい)のに、Stop hookが「条件は未達」と返し続けることがあります。anthropics/claude-codeのissue #94041に、同じ症状が6件のコメント付きで集まっています。再発火は9回から約50回まで、ほぼ毎回「待っているだけ」の1行返信を生みます。

先に止め方を書きます。ユーザー側から/goal clearを打てば確実に終わります。モデルには解除する手段がありません。以降は、報告された状況の型、再発火を減らす条件文の書き方、似て見える正常動作との見分け方を順に扱います。

どんなときに再発火するのか

issueの本文とコメントを状況別に並べると、再発火の起点は大きく5つに分かれます。

状況再発火の回数起きていること
圧縮(コンパクト)待ちの意図的な保留再発火の回数9回以上起きていること保留中でも同じ文面で未達を返す
完了済みの項目を含む複数条件再発火の回数21回以上起きていること会話内で2度訂正しても、古い文面のまま
ユーザーの一時停止・取り消し・断念の指示再発火の回数7回、24ターン、約50回起きていること評価側が指示を認識したうえで、なお未達とする
最後の項目がユーザー操作・日付・バックグラウンド作業の完了待ち再発火の回数9回(同一セッションで2度)、11回、7回起きていること「正しく待っている」状態を表す判定がない
13項目のうち4項目が「ユーザー待ちなら質問を記録」再発火の回数12回連続起きていること毎回違う理由で未達とされる

環境はLinuxとmacOS、CLIとデスクトップアプリの両方です。バージョンは本文が2.1.258以降、コメントでは2.1.296や2.1.306も挙がっています。サブスクリプションとAPIキーのどちらでも起きており、モデルにも依存しないと報告されています。

再発火の1回は、1ターン分の課金になる

Stop hookが「未達」を返すと、Claudeは次のターンを始めます。ターンの中身が「まだ待っています」の1文でも、モデル呼び出しは1回走ります。

一時停止を頼んだ報告では、この点が最も皮肉な形で出ました。使用上限のリセットを待つための停止指示だったのに、再発火のたびに上限が減っていきます。別の報告では、同じ要約が再発火のたびに印刷され、ユーザーの手元に十数通の同じレポートが残りました。

原因はどこにあるのか

仕組みの側から見ると、/goalはセッション限定のプロンプト型Stop hookです。ターンが終わるたびに、条件と会話を小型の高速モデルへ渡し、判定を受け取ります。判定は3種類しかありません。

判定

評価モデルが返せる3つの判定

  • 未達(Not yet met)

    Claudeが続行します。理由は次のターンの手がかりになります。

  • 達成(Met)

    ゴールが解除されます。

  • 不可能(Impossible)

    条件が満たせないと判断されたときに解除されます。

「条件は正しく、ただ待つしかない」を表す判定がありません。ユーザーの操作待ち、明日の時刻まで終わらない観測、動作中のバックグラウンドエージェントはどれも、未達にも不可能にも当てはまらない状態です。評価モデルは理由欄に「日付に縛られているだけで不可能ではない」と書きながら、未達を返し続けます。

原因の見立ては、報告者の間で分かれています。

  • issue本文は、評価側が会話の最新の状態を読み直していない可能性を挙げます
  • コメントの1つは、評価は会話を正しく読めており理由も正確で、足りないのは判定の種類だと述べます

後者の見立てでは、「完了済み」の訂正が効かない説明は付きません。両方の型が混在している、と考えるのが妥当です。いずれもissue上の仮説で、原因は確定していません。

最新のコメントは2026-10-21付けで、修正バージョンへの言及はありません。issueの状態はopenです。報告者の間では、第4の判定(ユーザー待ち・待機中の判定)を足す案が共通して出ています。

上限が働くと何が変わるか

再発火が無制限に続くわけではありません。Stop hookは、Claudeのツール呼び出しを挟まずに8回連続でブロックすると、Claude Code側が判断を上書きしてターンを終わらせます。/goalのページも、ツールを使わないターンが続くとループを止め、ゴールを設定したまま制御を返すと書いています。仕組みの詳細はCLAUDE_CODE_STOP_HOOK_BLOCK_CAPの解説にまとめています。

ただし、これは再発火の「終わり」であって「解決」ではありません。ゴールは残ったままなので、次のプロンプトで評価が再開し、同じ循環が始まります。issueも「上限が止めた後、別のターンで同じパターンが戻る」と報告しています。

デスクトップアプリで試した報告では、ゴールがアプリの終了・再起動を越えて残りました。再開したセッションの最初の返信で、Stop hookがもう一度発火しています。設定ファイルやhookファイルにゴールは書かれていないため、シェルから消す方法もありません。

今すぐできる止め方

ユーザーが/goal clearを打つ

確実に終わらせるには、ユーザーが/goal clearを実行します。stop / off / reset / none / cancelも同じ意味のエイリアスです。成功するとGoal cleared:に条件が続きます。

/goal clear

注意点が2つあります。

  • 引数なしの/goalは状況表示だけで、解除はしません。デスクトップアプリの報告では、この表示にclearの案内が出ませんでした。モデルが「/goalを実行してください」と案内し、ユーザーが2度実行しても何も変わらなかった例があります
  • 「ゴールを取り消していい」「中断して」と会話で伝えても、評価モデルはそれを理由欄に書くだけで、ゴールは解除されません

リモートのセッションから止める手段がなかった報告

約50回再発火した報告では、断念を会話で伝えた後も、引数なしの/goalが状況表示しか出さず、リモートのセッションからは、ゴールを一時停止する明確な手段が無かったと報告されています。席を離れて回すゴールでは、手元から/goal clearを打てるかどうかが止める手段の分かれ目になります。

再発火を減らす条件文の書き方

起点の型が条件の最後の項目にあるなら、条件文の側で出口を作れます。

最後の項目を「待ち」で終わらせない

ユーザーの操作・日付・バックグラウンド作業の完了のどれかを最後の条件にすると、評価は未達しか返せません。ある報告者は、ユーザー待ちで終わる条件の書き方を避ける方法を挙げ、ただしそれを人が毎回守る前提は続かないとも述べています。

番兵(sentinel)文字列を出口にする

別の報告者は、条件文に「特定の接頭辞で始まる最終メッセージも達成とみなす」と書く回避策を共有しています。2.1.306で、評価が1ターンで達成を返したそうです。公式が定めた手段ではなく、同じ挙動が他のバージョンでも続く保証はありません。

前と後

ユーザー待ちを出口付きの条件にする

BEFORE

出口がない書き方

/goal 13項目のチェックが全て終わり、ユーザーに必要な質問を全て記録している

評価は「質問を記録した」を確かめきれず、毎回違う理由で未達を返しました。

AFTER

出口を明示した書き方

/goal 13項目のチェックが全て終わる。ただし、残りの作業がユーザーの操作待ちなら、
GOAL-BLOCKED: で始まる質問1通を最終メッセージに出せば達成とみなす

例えばこの形にしておくと、待ちの状態が「達成」として扱われるため、ターンを終えられます。GOAL-BLOCKEDの部分は報告者が使った文字列で、任意の名前に置き換えられます。

打ち切りも条件に含める

「or 20ターン経過したら停止」のようにターン数の出口を足す方法は、/goalコマンドの解説でも扱っています。ただし、数えるのは会話を読む評価モデルです。厳密な回数制限ではなく、再発火を完全には防げません。

自作のStop hookならstop_hook_activeで抜ける

条件の評価を自分で書くなら、hookスクリプトの入力にあるstop_hook_activeがtrueのときに早期終了する書き方が公式の手引きにあります。prompt型の判定を自作する場合の考え方は、prompt hookでStopを判断させる記事に整理しています。同じ構造のループを意図的に回す例はralph loopプラグインです。

正常な待機と見分ける

バックグラウンド作業の待ちは、仕様として別の扱いがあります。再発火に見えても、次のような動作なら不具合ではありません。

見えるもの仕様上の動作
サブエージェントやバックグラウンドのシェルが動いている間、評価が来ない仕様上の動作動作中のターンでは評価をスキップし、作業のないターンの終わりで評価する
30分後に確認の通知が来る仕様上の動作初回のチェックインで、以降は1時間、2時間と間隔が延びる
アイドル中に勝手にターンが始まる仕様上の動作1回のプロンプトの間に最大3回まで。3回目で停止を告げる

不具合の側は、バックグラウンド作業が無い(または終わった)のに、同じ理由の未達が連続する点で区別できます。バックグラウンドの待ちで再発火する報告では、評価が動作中の作業を認識しているのに未達を返しています。チェックインの間隔を変えるCLAUDE_CODE_GOAL_CHECKIN_MINUTESは、0で自動再試行も止まります。再発火の抑止を目的にした設定ではありません。

関連する未解決の報告

issue本文は、関連する報告を6件挙げています。

  • 圧縮の境界で設定した/goalが、ターンを始めない
  • バックグラウンドタスクが動いている間にStop hookがスキップされ、終了後に再評価されない
  • 受け入れた「ブロックされた結果」の後も再発火する
  • 評価側が/goalに渡された指示を見られず、自分で不可能と宣言するまでループする

過去に閉じられた2件(stop_hook_active: trueでも再発火する報告、明示的な撤回を無視する報告)も含まれます。症状が近い場合は、issueの番号で検索すると報告をたどれます。

まとめ

再発火の根は、評価モデルに「正しく待っている」を表す判定がない点にあります。今できる対処は、ユーザーが/goal clearで解除すること、そして最後の項目を待ちで終わらせない条件文にすることです。修正バージョンの記載がないため、長時間の自走を任せるときは、解除の手段を手元に置いておく運用になります。

この記事を共有:XはてブLinkedIn