【Claude Code 連載 第46回】/goal — 完了条件を決めて、Claude を走り続けさせる

スポンサーリンク
【Claude Code 連載 第46回】/goal — 完了条件を決めて、Claude を走り続けさせる 用語解説
【Claude Code 連載 第46回】/goal — 完了条件を決めて、Claude を走り続けさせる
この記事は約11分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

スポンサーリンク

背景

この連載では、Claude Codeの公式ドキュメントを1ページずつ読み解いていきます。公式ドキュメントは情報が網羅されている分、「結局どの機能を、どんな場面で使えばいいのか」は自分で考える必要があり、読むのに意外と時間がかかります。そこで、私が実務で使うために読み込んだ内容を「使う場面→実例コード」の順に整理して残していくことにしました。専門家の解説というより、一次情報を読んだ記録です。推測や動作を確認していない部分には、その都度そう書きます。

1. 一言でいうと何か

/goal は、「この状態になったら終わり」という条件を先に宣言しておき、その条件が満たされるまで Claude が自分でターンを繰り返し続けるためのコマンドです。

Claude Code の通常の動きは、1ターン作業して、あなたに制御を返す、の繰り返しです。あなたは返ってきた結果を見て「続けて」「次はこれ」と打ち込む。作業が10ターン必要なら、10回の合いの手が要ります。/goal はこの合いの手を消します。

仕組みは意外にシンプルです。Claude が1ターンを終えるたびに、小さく高速なモデル(デフォルトは Haiku)が別途起動して、「条件は満たされたか?」をイエス/ノーで判定します。ノーなら Claude は制御をあなたに返さず、そのまま次のターンを始めます。イエスなら、ゴールは自動的にクリアされ、トランスクリプトに達成の記録が残ります。

ここで重要なのは、完了を判定するのが作業をしている当のモデルではないという点です。作業者本人に「終わったか?」と聞けば、途中で満足して手を止めることがあります。/goal は評価役を別に立てることで、そのバイアスを避けています。判定のたびに評価器は「なぜ満たされていないか」の短い理由を返し、それが次のターンのガイダンスとして Claude に渡されます。つまり、単に走らせ続けるだけでなく、毎ターン軌道修正のヒントが注入される構造になっています。

公式ドキュメントは、実質的な作業で検証可能な終了状態がある場合に使うものだと位置づけています。挙げられている例はこの4つです。

  • モジュールを新しい API に移行し、すべてのコールサイトがコンパイルされてテストが成功するまで
  • デザインドキュメントを実装し、すべての受け入れ基準が満たされるまで
  • 大きなファイルをフォーカスされたモジュールに分割し、各モジュールがサイズ予算以下になるまで
  • ラベル付きの問題バックログを処理し、キューが空になるまで

共通しているのは、「終わり」が客観的に判定できることです。テストが通る、コンパイルが通る、行数が閾値を下回る、キューが空になる。裏を返せば、終わりが主観的な作業には向きません(後述)。

なお /goal には Claude Code v2.1.139 以降が必要です。

2. どういう場面で役立つか

シーン1:大量だが単調な機械的作業を回し切る

API 移行やライブラリのバージョン上げのように、「やることは決まっているが、対象が多くて何十ターンもかかる」タイプの作業がもっとも相性がいい。all call sites compile and npm test exits 0 のような条件を置いておけば、あとは放っておける。あなたが「続けて」と打つためだけに席に張り付く必要がなくなります。

シーン2:受け入れ基準つきの実装

デザインドキュメントや仕様書に受け入れ基準が列挙されている場合、それをそのまま条件に写せます。評価器が毎ターン「まだこの基準が満たされていない」と指摘し続けるので、Claude が基準の一部を取りこぼして「完成しました」と言って止まる、という事故が起きにくくなります。

シーン3:数値の閾値に向かうリファクタ

「どのモジュールも300行以下にする」のように、測れる目標があるリファクタ。進捗が単調に一方向へ進むので、条件判定が安定します。

3つの「走り続ける」手段の使い分け

現在のセッションを走らせ続ける方法は3つあり、次のターンが何をきっかけに始まるかで選びます。

アプローチ次のターンが始まる契機停止する条件
/goal前のターンが終わったときモデルが条件成立を確認したとき
/loop時間間隔が経過したときあなたが止めるか、Claude が完了と判断したとき
Stop hook前のターンが終わったときあなた自身のスクリプトまたはプロンプトが判断したとき

/goal と Stop hook はどちらも毎ターン後に走ります。違いはスコープと自由度です。/goalセッションスコープのショートカットで、条件を打ち込んだセッションでだけ有効。Stop hook は設定ファイルに書くもので、そのスコープの全セッションに効き、決定論的なチェックのためにスクリプトを走らせることも、モデル評価のためにプロンプトを走らせることもできます。「今回のこの作業だけ」なら /goal、「常にこのルールで止まってほしい」なら Stop hook、という切り分けになります。

自動モードとの関係——競合ではなく補完

混同しやすいので明示しておきます。**自動モードは1ターンの中でツール呼び出しを承認する仕組みで、新しいターンは始めません。**Claude が「作業は完了した」と判断すれば、そこで止まります。/goal はその外側で、毎ターン後に別の評価器を走らせる。

  • 自動モード = ツールごとのプロンプトを消す
  • /goal = ターンごとのプロンプトを消す

つまり両方を組み合わせて初めて、本当に無人で長時間走る状態になります。片方だけだと、どこかで必ず止まります。

不要・向かないケース

  • 終了状態が主観的な作業。「コードを読みやすくする」「良い設計にする」のような条件は、評価器が判定できません。測れる形に翻訳できないなら使うべきではない。
  • 探索・調査フェーズ。あなたが途中結果を見て方針を変えたい作業では、制御が返ってこないこと自体がデメリットです。
  • 1〜2ターンで終わる作業。オーバーヘッドのほうが大きい。
  • 時間間隔で回したいとき。それは /loop の役割です。条件成立ではなく「N分ごと」で動かしたいなら /goal ではありません。
  • カスタムな評価ロジックが必要なとき。スクリプトで決定論的に判定したい、複数セッションに常時適用したい、という要件なら自前の Stop hook を書くべきです。
  • 開いているセッションと無関係に走らせたいとき。夜間テストや朝のトリアージのような作業は、クラウドルーチンやデスクトップのスケジュール済みタスクの領分です。/goal はあくまで「今開いているセッション」を走らせ続けるもの。
  • hooks が無効化された環境。後述のとおり /goal は使えません。

3. 前提条件と、コマンドの実例

前提条件

コマンドを打つ前に確認すべきことが3つあります。

  1. Claude Code v2.1.139 以降であること。
  2. 信頼ダイアログを受け入れたワークスペースであること。/goal の評価器はフックシステムの一部なので、信頼していないワークスペースでは動きません。
  3. hooks が無効化されていないこと。具体的には、いずれかの設定レベルで disableAllHooks が設定されている場合、または管理設定で allowManagedHooksOnly が設定されている場合、/goal は利用できません。

3番目について親切な点として、こういうときコマンドは黙って何もしないのではなく、理由を伝えてくれます。「打ったのに反応がない」と悩む必要はありません。

もうひとつ、前提というより誤解の予防として重要な点:**ゴールは権限を変更しません。**デフォルトの権限モードのままなら、Claude は設定で許可されていないツール呼び出しの前に、これまでどおり確認を求めます。テスト実行コマンドがその一例です。つまり /goal だけ設定して席を立つと、権限確認で止まっている可能性がある。無人で走らせたいなら自動モードとの併用が必須です。

ゴールを設定する

セッションごとにアクティブなゴールは1つだけです。同じ /goal コマンドが、引数によって「設定」「確認」「クリア」を切り替えます。

設定は、コマンドの後に条件を書くだけです。

/goal all tests in test/auth pass and the lint step is clean

設定した瞬間に、条件そのものがディレクティブとなってターンが即座に始まります。別途プロンプトを送る必要はありません。ゴールがアクティブな間は ◎ /goal active インジケーターが表示され、経過時間がわかります。すでにゴールがアクティブな状態で新しく設定すると、新しいゴールが古いゴールを置き換えます。

効果的な条件の書き方

ここが /goal を使いこなせるかどうかの分かれ目です。

**評価器は、Claude が会話上に表示した内容に対してのみ判定します。**評価器は独立してコマンドを実行したり、ファイルを読んだりしません。だから条件は、Claude 自身の出力で実証できる形に書く必要があります。

test/auth のすべてのテストが成功する」がうまく機能するのは、Claude がテストを実行すれば結果がトランスクリプトに現れ、評価器がそれを読めるからです。逆に、Claude が何も出力しない類の条件は、いつまでも成立しません。

多くのターンにわたって機能する条件には、だいたい次の3つが含まれます。

  • 1つの測定可能な終了状態:テスト結果、ビルドの終了コード、ファイル数、空のキュー
  • 述べられたチェック:Claude がそれをどう証明すべきか。例えば「npm test が 0 で終了する」「git status がクリーンである」
  • 重要な制約:その過程で変えてはならないもの。例えば「他のテストファイルは変更されない」

3番目の「制約」は見落とされがちですが重要です。条件を満たすことだけが目的化すると、テストを書き換えて通す、といった抜け道が生まれます。触ってはいけないものを明示しておくと安全です。

条件の長さは最大4,000文字。実運用では十分な余裕があります。

暴走が心配なら、条件の中に打ち切り句を入れられますor stop after 20 turns のようなターン句や時間句を書いておくと、Claude は毎ターンその句に対する進捗を報告し、評価器が会話からそれを判断します。無人運転させる場合は入れておくのが無難です。

ステータスを確認する

引数なしで実行すると、現在の状態が見られます。

/goal

アクティブなら、条件・実行時間・評価されたターン数・現在のトークン支出・評価器の最新の理由が表示されます。この「最新の理由」が実質的な進捗ログになるので、Claude が今どこに向かっているかを知りたいときはここを見ます。ただしターン数と理由は、最初の評価が走ったあとでないと表示されません。

すでに達成済みの場合は、達成された条件と、その所要時間・ターン数・トークン支出が表示されます。

ゴールをクリアする

条件が満たされる前に手動で止めたいときはこれです。

/goal clear

stopoffresetnonecancelclear のエイリアスとして受け付けられます。また、/clear で新しい会話を始めると、アクティブなゴールも一緒に消えます。

セッションを再開したときの挙動

セッション終了時にまだアクティブだったゴールは、--resume または --continue でそのセッションを再開すると復元されます。ただし復元されるのは条件だけで、ターン数・タイマー・トークン支出のベースラインはすべてリセットされます。すでに達成済みのゴールやクリア済みのゴールは復元されません。

打ち切り句を or stop after 20 turns のように書いていた場合、再開でターン数が0に戻る点は意識しておいたほうがいいでしょう。

非対話的に実行する

/goal は非対話的モード、デスクトップアプリ、リモートコントロールでも機能します。-p でゴールを設定すると、ループが単一の呼び出しで完了まで走ります

claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"

ここで実用上の落とし穴があります。**デフォルトのテキスト出力では、条件が満たされるまで何も出力されません。**多くのターンを回すゴールは、外から見ると「フリーズしている」ように見えます。中で何が起きているかを見たいなら、--output-format stream-json --verbose を付けて各メッセージを流してください。

途中で止めたい場合は Ctrl+C でプロセスを中断します。

4. まとめ + 次回予告

/goal の要点を整理します。

  • 完了条件を宣言し、満たされるまで自動でターンを回し続けるコマンド。v2.1.139 以降。
  • 判定するのは作業者とは別の、小さく高速なモデル(デフォルト Haiku、プロバイダー設定に従う)。毎ターン後にイエス/ノーと短い理由を返し、ノーの理由が次ターンのガイダンスになる。
  • 実体はセッションスコープのプロンプトベース Stop hook のラッパー。だから信頼済みワークスペースが必要で、disableAllHooks / allowManagedHooksOnly があると使えない。
  • 評価器はツールを呼ばない。Claude が会話に出した内容だけで判定するので、条件は「Claude の出力で証明できる形」に書く。測定可能な終了状態+証明方法+守るべき制約、の3点セットが定石。
  • 権限は変わらない。無人運転には自動モードとの併用が事実上必須。「自動モード=ツールごとの承認を消す」「/goal=ターンごとの承認を消す」で役割が分かれている。
  • 条件は最大4,000文字。or stop after 20 turns のような打ち切り句を入れておくと安全。
  • 評価トークンは小型モデルで課金され、メインのターン支出に比べれば通常は無視できる

使い分けの一行整理:条件成立で止めたいなら /goal、時間間隔で回したいなら /loop、常時・全セッションに効かせたいなら自前の Stop hook、開いているセッションと無関係に走らせたいならスケジュール機能。

次回予告(暫定)/goal と対で使うことになる**自動モード(auto-mode-config)**を取り上げ、ツール呼び出しの自動承認をどこまで許すか、その設定と安全な使い方を扱う予定です。


よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました