Skip to content

エージェント状態 ​

ドキュメント作成中

一部の内容はまだ不完全な場合があります。

Claude Code のセッションの横に開いたエージェントパネル:実行中と待機中のエージェント、サブタスク、エージェントのホバーカード

長いタスクを実行している Thread は現在の状態を持ちます。おかげで、一つずつ見に行かなくても、どのセッションが自分を必要としているか一目で分かります。Thread がひと区切りの作業を終えたとき、あるいは判断を待ち始めたときには、短い音が鳴ります。

状態は working(作業中)、blocked(ユーザーの判断待ち)、idle(待機中)で、エラーで止まったと報告するプログラムには error が加わります。ThinkTerm が分類できないセッションには何も付きません。

検出は既定で有効で、設定 › サイドバーとプラグイン から無効にできます。Agents パネルと検出器は同じスイッチを共有しています。設定ファイルに agent_status_detection = false と書いても無効になり、設定ウィンドウを持たない mux サーバーはこの項目だけに従います。無効にすると、以下で説明するネイティブのエスケープシーケンスだけが読まれます。検出はペインのある側で動くため、mux サーバー側で無効にすることと、目の前のクライアントで無効にすることは別の行為です。

対応しているエージェント ​

ThinkTerm が名前で知っているエージェントは次のとおりです。状態レポートを送るエージェントは自分の状態を ThinkTerm に伝え、レポートがそのまま状態を決めます。送らないエージェントには、ThinkTerm は画面ルールを読みます。検出のためにどれかへ何かをインストールすることはなく — フックもプラグインもラッパースクリプトもなし — どれも設定は要りません。それとは別に、自分で実行した場合に限り、thinkterm skill setup が Claude Code と Codex にスキルとセッション開始時のフックを加え、ほかのペインを使えるようにします。コマンドライン を参照してください。

エージェントPATH で探すコマンド対応の仕方
Claude Codeclaudeバージョン 2.1.295 以降は状態レポート、それより古ければ画面ルール
Codexcodexバージョン 0.163.0 以降は状態レポート、それより古ければ画面ルール
Copilot CLIcopilot画面ルール
Cursor Agentcursor-agent または cursor画面ルール
Pipiバージョン 1.1.0 以降は状態レポート、それより古ければ画面ルール
OpenCodeopencode画面ルール
Kimi Codekimi画面ルール
SoulsoulTHINKTERM_AGENT で自ら状態を報告します
OMPomp一覧にはありますが、まだ検出しません。普通に動き、状態が表示されないだけです

Claude Code は起動時に、ターミナルが状態レポートを理解するかを尋ね、ThinkTerm が答えるので、設定は要りません。tmux の中、Claude Code 自身のバックグラウンドセッション、CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1 のときは送らないので、そのときは従来どおり画面ルールが対応します。Codex は 0.163.0 から、出力先がターミナルであれば尋ねずに送ります。Pi は 1.1.0 から送り、PI_PROGRAM_STATUS=1 か 0 で強制的にオン・オフできます。画面ルールが使われるときは、ペインのライブ画面の下部とターミナルタイトルを読み、作業中・入力待ち・待機中を見分けます。ほかのプログラムも、自分の状態を報告するか、ルールファイルを書いてもらえばこの一覧に加われます。

設定 › エージェント は 連携 の下に同じエージェントを並べ、それぞれのマークと、どう対応しているかを示す一行を出します。画面ルールのエージェントでは、その行がコマンドを PATH で見つけたかどうかも伝えます。ThinkTerm は自分の PATH に加えて、ログインシェルの PATH と、よくあるインストール先も探します。これはあなたへのヒントであって条件ではありません。このチェックで見つかったかどうかにかかわらず、検出は動いているプログラムを認識します。行をクリックすると短い説明が開き、ルールを上書きするファイルのパスも書かれています。

状態はどう決まるか ​

自分の状態レポートを送るプログラムは、そのペインについて答えを決めます。報告が状態を決め、報告が有効なあいだそのペインでは画面ルールを読みません。報告の app がエージェントの名前になるので、ThinkTerm が知らないプログラムでも、その名前でエージェントパネルに出ます。報告は送ったプログラムと、そのプログラムがターミナルを渡した相手(ページャーやエディタなど)について語ります。シェルがターミナルを取り戻すと、進行中の作業の報告は終わります。done と error の結果は、誰かがそのペインを見るまで残ります。

そうした報告を送らないプログラムについては、3 つの根拠を、契約として強い順に参照します。

1. THINKTERM_AGENT 変数。 プログラム自身が身元・セッション・状態を報告します。以下で説明する ThinkTerm 独自の変数で、画面ルールと違い、プログラムの画面がどう作り直されても生き残ります。

2. 画面ルール。 ペインの可視出力とターミナルタイトルに対して照合される TOML マニフェストです。同梱のルールは herdr プロジェクト由来です。

3. ネイティブのエスケープシーケンス。 OSC 9;4 の進捗報告と、タイトル先頭のスピナー表示です。機能を無効にしているときに使われるのもこれだけです。

重要な調停規則が 2 つあり、意図的に逆を向いています。

  • 生きているプロセスが「身元」で勝ちます。 マニフェストに一致する前景プロセスは「いま何が動いているか」の事実そのものです。報告された変数は過去からのメッセージであり、これを覆すことはありません。終了したプログラムが残した変数が、そのペインで次に動くものに誤ったラベルを付けることはない、ということです。
  • 画面が「状態」で勝ちます。 プログラムは「ユーザーが Esc を押した」「プロンプトが取り消された」という遷移をしばしば取りこぼし、そのどちらも画面上は明らかに待機状態で終わります。したがって一致した画面ルールは、報告された状態より優先されます。

画面から推定された遷移 — blocked からの離脱、および working から idle への変化 — にはおよそ 450 ミリ秒のデバウンスがかかります。描画途中のフレームが通知を再生してしまってはならないからです。プロトコルで報告された状態はデバウンスを通りません。明示的な報告は推測ではないからです。

サイドバーでの表示 ​

サイドバーの Thread の行には、ペインがいくつあっても Thread 全体で 1 つの印が付きます。印は Thread 内のすべてのペインから決まり、エージェントの状態があるペインはそれを、ほかのペインはネイティブのエスケープシーケンスを使います。

Threadいつ
要確認いずれかのペインが blocked、または OSC 9;4 か状態レポートでエラーを報告している。ほかのすべてに優先します。プログラムがエラーで止まった Thread には、待ちを示す琥珀色ではなく赤いバツ印が付きます
実行中いずれかのペインが working、または進捗報告やタイトルのスピナーを出している
完了Thread が動いていて止まり、それ以来まだ見ていない
待機中どれにも当たらない。行に印は付きません

サイドバーの 完了 は、報告された状態ではなく ThinkTerm 自身の記録です。注意がほかに向いている間に Thread が作業中から待機中に移ったことを示します。その Thread を開くか、その中で入力したりクリックしたりするまで続き、再起動しても残ります。要確認と完了の Thread は、すべての Space をまたいでサイドバーの「通知」ボタンの下にもまとめられます — Space、Project、Thread を参照してください。

Thread の行にポインタを重ねると、その横にカードが開きます。カードには Thread の名前とエージェントの数が出て、状態のあるエージェントが 1 つずつ並びます。それぞれ、マークとタイトルと状態アイコン、その下に、言葉にした状態、プログラムが伝えていれば、どこまで進んだか、何を待っているか、何をしているかが出ます。ウィンドウの高さに収まるだけのエージェントを出し、入りきらないときは ほか 3 件 のような行で終わります。タブバーでは、作業中のエージェントはタブのアイコンを回し、あなたを待っているもの、エラーで止まったもの、まだ誰も見ていない結果を持つものは、アイコンの角に点を付けます。結果は、フォーカスのあるウィンドウでそのペインが前面に出た時点で見たものとみなされます。

エージェントパネル ​

右サイドバーのエージェントパネルは、認識したエージェントが動いているペインを、すべての Space とウィンドウにわたって、接続しているサーバー上のペインも含めて一覧にします。ウィンドウの右サイドバーはこのパネルで開きます。パネルをオフにしているときは、まだ提供されている最初のパネルで開きます。

エージェントごとに 1 枚のカードです。1 行目には、エージェントのマーク、ペインのタイトル(fix the build)、そして右端に状態のアイコンが出ます。作業中はスピナー、あなたを待っているときは琥珀色の警告、エラーなら赤いバツ、まだ誰も見ていない結果なら緑のチェック、待機中なら灰色のチェックです。Soul やルールファイルで加えたエージェントのように固有のマークがないものは汎用のマークになり、タイトルの前に名前が付きます(Soul · fix the build)。2 行目はペインの場所で、my-project · Thread 2 のように出ます。状態はアイコンが示すので、この行が状態を言葉でも添えるのは、アイコンでは足りないときだけです。結果とは色しか違わないチェックの アイドル、そしてアイコンのない 不明 です。アイドル · my-project · Thread 2。

状態レポートを送るプログラムのカードには、そのプログラムが伝えた内容も出ます。場所の上の 1 行に、何をしているか、何を終えたか、なぜ止まったか。何を待っているか — 許可待ち、質問、サインイン — はその前に小さなタグとして付きます。そして進捗バー、サブタスクで、これは数を示す 1 行に畳まれ、クリックすると一覧が開きます。開いた一覧では、サブタスクごとに状態の色の点が付き、最初の 5 件を出して、ほか 3 件 のような行で終わります。設定 › エージェント › 状態の表示 に 4 つそれぞれのスイッチがあり、既定ではすべてオンです。下の表示メニューも同じスイッチを切り替えます。Thread のホバーカードと通知に何が出るかも、これで決まります。作業中の説明はきらめくように光り、エラーの説明は赤です。カードに収まらない行は折り返さず、末尾がフェードします。説明の中のパスは、それで収まるなら、最後のフォルダーまで短くされます。

このコンピューター上のリンクされた git worktree にペインがあるエージェントには、場所の下にもう 1 行、ブランチのアイコンとともに出ます。worktree のフォルダーとそこでチェックアウトされているブランチ(feature-login · feat/login)で、ブランチがなければコミットの先頭です。Thread はタスクにちなんだ名前なので、同じ名前でもチェックアウト先が違うことがあります。リポジトリ本体のチェックアウトには何も出ません。Thread がすでに Project を示しているからです。ほかのマシンのペインや ssh セッションの中のペインにも出ません。

このウィンドウのアクティブなペインにいるエージェントのカードは、パネルより一段明るく浮き上がり、いまどこにいるかが一覧から分かります。

グループ化と表示メニュー ​

カードは件数付きの見出しの下にまとまります。既定のグループは状態で、あなたを必要とする順に 要確認、実行中、完了、待機中、そして状態を判別できなかったエージェントの 不明 です。グループの中では Project と Thread、次にエージェントの順に並ぶので、Space を切り替えてもエージェントの状態が変わっても並びは入れ替わりません。

右上のボタンが表示メニューを開きます。タグは 表示オプション です。左隣の行は、言うことがあるときだけ表示されます。再読み込みの数秒間は 検出ルールを再読み込みしました。 か拒否されたファイルの数、一覧が空のときは エージェントは検出されていません です。

項目何をするか
表示一覧に出す状態にチェックを付けます。実行中、要確認、完了、待機中。最後の 1 つは非表示にできません
マシン一覧に出すマシンにチェックを付けます。このコンピュータ と各サーバー。エージェントが複数のマシンにいるとき、またはマシンを 1 つ隠しているときだけ出ます
グループ化状態(既定)、セッション(Project と Thread を見出しにし、Thread のないエージェントは その他 にまとめます)、なし
並べ替え固定順(既定。グループの中で Thread、エージェント、ペインの順)、または 最近のアクティビティ(状態が最後に変わったエージェントを先頭に)
説明、待っている理由、進捗、サブタスク設定 › エージェント › 状態の表示 の 4 つのスイッチ
検出ルールを再読み込み画面ルールを再読み込みします。上書きファイルを追加・変更したときに使います。そのあとボタンの隣の行に結果が出ます。拒否されたファイルの理由はログにあります

選択は保存され、すべてのウィンドウに適用されます。選択によって存在するエージェントがすべて隠れたときは、パネルに 表示オプションですべてのエージェントが非表示です と出ます。どちらの場所で検出を無効にしても、このパネルはサイドバーから外れます。

カードをクリックするとそのペインへ移ります。このウィンドウのペインなら、そのタブとペインが選ばれます。そうでなければ ThinkTerm はペインの Thread を開いてペインを選びます。Thread がこのウィンドウの Space のものならここで、その Space を開いているウィンドウがあればそのウィンドウで(前面に出して)、どのウィンドウもその Space を開いていなければこのウィンドウがその Space に切り替わって開きます。

カードにポインタを重ねると、パネルの横にもう 1 枚カードが開き、カードに収まらなかった内容が出ます。タイトルと説明の全文(折り返し)、エージェントとその状態、進捗と待っている内容、そして セッション、マシン、経過(この状態になってからの時間)、サブタスク です。ホバーカードは、ボタンのタグと同じく、少し間を置いて現れ、直前に別のものが出ていたときは即座に現れ、クリック、キー入力、ポインタがウィンドウを離れたときに消えます。

音と通知 ​

同梱の 2 つの音が、知らせる価値のある 2 つの瞬間を示します。Thread が終わったときの音と、あなたを待ち始めたときの音です。設定 › ワークスペース › 通知音 で止められます。既定ではオンです。

  • 完了 は Thread が作業中から待機中に移ったときに鳴ります。ただし作業が 5 秒以上続いた場合だけなので、すぐ終わるコマンドでは鳴りません。
  • 待機 はペインが判断を待ち始めたときに、待ち始めるたびに 1 回鳴ります。同じ Thread の別のペインが待ち始めるとまた鳴りますが、質問に答えを入力しても鳴りません。

音はサイドバーと同じ状態に従うため、エージェントに限らず、進捗を報告するどのプログラムでも鳴ります。見ている Thread でも鳴ります。目の前で長いタスクが終われば、やはり音がします。

ThinkTerm を起動する前に環境変数 THINKTERM_DISABLE_SOUND を設定すると、設定にかかわらずすべての音が止まります。プレゼンに使うマシンで便利です。Linux では paplay か pw-play で再生し、どちらもないシステムでは鳴りません。ThinkTerm に接続したブラウザーとターミナル UI では音は鳴りません。

設定 › ワークスペース › システム通知 は既定でオンで、Thread が終わったとき、あなたを待ち始めたとき、エラーで止まったときに、システムにも知らせます。ただし ThinkTerm がバックグラウンドにあるときだけで、同じ Thread については 30 秒に 1 回までです。通知には Thread の名前と状態、そしていちばん差し迫ったプログラムが伝えた内容があれば、それが載ります。それが画面に出ることの意味は プライバシーとセキュリティ を参照してください。THINKTERM_DISABLE_SOUND はこれも止めます。

これらの通知をクリックすると Thread が前面に出ます。すでにその Thread を表示しているウィンドウで、なければ最後に使ったウィンドウで開き、そのウィンドウは Thread の Space に切り替わります。macOS、Windows、および freedesktop の通知規格に従う Linux デスクトップで動作します。ビルドが終わったことを知らせるなど、プログラムが自分で出すデスクトップ通知も、同じようにそのペインを前面に出します。

自分のプログラムから状態を報告する ​

方法は 2 つあります。状態レポートを使ってください。ほかのターミナルも読むオープンなプロトコルで、エラー状態、理由、進捗、サブタスクを運び、どの画面ルールよりも優先されます。THINKTERM_AGENT 変数は ThinkTerm 独自のもので、運ぶのは基本の 3 状態だけ、画面ルールに覆されることもあります。

状態レポート(OSC 7501) ​

状態レポートは OSC 7501(Program Status Protocol)に従います。Claude Code は 2.1.295、Codex は 0.163.0、Pi は 1.1.0 から送ります。何かが変わるたびに、シーケンスを 1 つ書き出します。終端は ESC \ でも BEL でもかまいません。

ESC ] 7501 ; state=<state>[:id=<path>][:kind=<kind>][:progress=<0-100>][:app=<name>][:title=<base64>][:msg=<base64>] ESC \

シェルからは次のとおりです。

sh
msg=$(printf %s 'Running the test suite' | base64 | tr -d '\n')
printf '\033]7501;state=working:app=my-agent:progress=40:msg=%s\033\\' "$msg"
キー意味
state必須。working、blocked、idle、done(終わって、まだ誰も見ていない結果がある)、error(失敗して止まった)、または clear。clear はその記録と、その下のものすべてを消します
id報告がどの記録についてのものか。省くとプログラム自身の記録です。build/test のような / 区切りのパスは、その下にサブタスクを置きます。8 段まで、128 バイトまで
kindblocked のときだけ。permission、question、auth
progressworking か blocked のときだけ。0 から 100。省くと進捗は不定です
appプログラムの短い名前。claude-code など
title見出し。UTF-8 を base64 にしたもの
msgプログラムが何をしているか、何をしたかを述べる 1 行。UTF-8 を base64 にしたもの

id と app の名前に使えるのは英数字と _ . + - で、それぞれ 32 文字まで。title はデコード後 192 バイト、msg は 2048 バイトまでで、どちらも制御文字を含められません。シーケンス全体は 4096 バイトまでです。どれかに反した報告は丸ごと捨てられます。報告はそれぞれ記録を丸ごと置き換えるので、省いたキーは前の値が残るのではなく消えます。知らないキーは無視され、プロトコルはそうして拡張されます。ターミナルはペインごとに 256 件まで記録を持ち、あふれたら最も長く更新されていないものを捨てます。

ターミナルが状態レポートを理解するか尋ねるには、ESC ] 7501 ; ? ESC \ に続けて ESC [ c を送ります。理解するターミナルは最初のものに同じシーケンスで答えます。ESC [ c への答えが先に届いたら理解しないターミナルなので、レポートを送っても意味はありません。

レポートは生かしておくために送り直す必要はありません。進行中の作業のレポート(working と blocked)は、プログラムが終了するか、シェルの次のプロンプトが始まると終わります。done と error は誰かが見るまで残ります。ですから、ユーザーが中断や取り消しをしたら idle を、終了する直前には done か error を報告してください。

サブタスクだけが残ったときは、その中でいちばん差し迫ったものがプログラムの代わりになります。エラー、待ち、作業、結果の順です。

THINKTERM_AGENT で報告する ​

状態が変わるたび、ターミナルへエスケープシーケンスを 1 つ書き出します。

ESC ] 1337 ; SetUserVar=THINKTERM_AGENT=<base64(value)> BEL

シェルからなら:

sh
v="v1;agent=my-agent;state=working;session=$SESSION_ID;ts=$(date +%s)"
printf '\033]1337;SetUserVar=THINKTERM_AGENT=%s\007' \
  "$(printf %s "$v" | base64 | tr -d '\n')"

このシーケンスは何も描画せずカーソルも動かさないため、全画面出力の合間に挟んでも安全です。SSH 越しでも ThinkTerm のマルチプレクサドメイン上でも機能します。その pty を持つターミナルが解釈し、値は mux 接続をまたいで自動的に複製されます。

値の文法、バージョン 1 ​

v1;agent=<id>;state=<working|idle|blocked>[;session=<id>][;pid=<n>][;ts=<unix-seconds>][;ended=1]
フィールド意味
v1文法バージョン。v1.1 のようなマイナーバージョンはバージョン 1 として読まれ、それ以外のバージョンは完全に無視されます
agent必須。短く安定した識別子
state必須。working、idle、blocked のいずれか。それ以外は不明として扱われ、何も駆動しません
session自分のセッション ID。セッション復元のための予約。空でも構いません
pid前方互換のために受理されますが、現在は無視されます
ts送信時刻(unix 秒)。下記参照
ended=1セッションが終了した

未知のキーは無視されるため、古い読み手を壊さずに文法を拡張できます。後のマイナーバージョンがこの版の知らないキーを加えても、ThinkTerm は知っているフィールドを読み続けます。

値には長さの上限があります。デコード後で最大 4096 バイト、そのうち agent は最大 128 バイト、session は最大 512 バイトです。どれかを超えた報告は、前の値を残すのではなく、そのペインが持っていた値を消します。

ts について。 6 時間より古い非 idle の報告は権威を失います — サーバー上のペインは、それに書き込んだセッションより長く生き残りうるからです。現在より 5 分以上先のタイムスタンプも同様に扱われ、進んだ時計によって報告が永久に新鮮なままになることを防ぎます。プロセスを観測しえないペイン(SSH、tmux、シリアル)では、この同じ 6 時間の窓が報告された身元も失効させます。プログラムが別れを告げずに落ちた可能性を示す、唯一残された信号だからです。承認プロンプトを一晩放置するなど、正当に長く非 idle でいられるセッションなら、現在の状態を定期的に再送してください。再送はこの窓をリセットします。idle の報告、および ts のない報告は無期限に信頼されます。

ended=1 について。 自分のプロセスがそのペインの前景リーダーである間、このフラグは無視されます。生きているプロセスは自らの別れの挨拶より優先されるからです。プロセスが終了すると、そのペインは分類の対象から外れます。

いつ何を送るか。 ターンの開始時に working、入力を受け付けられる状態になったら idle、答えを要するプロンプトを表示したその瞬間に blocked、そのプロンプトが解決したら再び適切な状態を — ユーザーが取り消したり中断したりした場合も含めて。これらの遷移をすべて自分で観測できるプログラムであれば、画面ルールは一切不要です。

画面ルールを上書きする ​

同梱のマニフェストは、自分の .toml ファイルを次のディレクトリへ置くことで置き換えられます。

~/.config/thinkterm/agent-detection/

どの同梱マニフェストを置き換えるかを決めるのはファイル内部の id であり、ファイル名は無視されます。ただし 設定 › エージェント が示すように id にちなんだ名前にしておくと、フォルダーが分かりやすくなります。独自の id を持つファイルは、何かを置き換えるのではなく新しいエージェントを加えます。読めない、または検証を通らないファイルは丸ごと拒否され、置き換えるはずだった同梱マニフェストがそのまま働きます。配置後、エージェントパネルの表示メニューからルールを再読み込みしてください。

このフォルダーは検出を行うマシンで読まれます。そのため ThinkTerm Connect サーバー上のペインは、あなたのではなくそのサーバーのホームフォルダーにあるファイルに従い、パネルの 検出ルールを再読み込み もこのコンピューターのルールだけを読み直します。

ルールを書くうえで知っておくべきことが一つあります。タイトルと進捗の領域は、プログラムが実際に送出したものしか見えません。タイトルや進捗の報告が届くまで両者は空であり、ペインのプログラムが変わると消去されます。表示上のフォールバック — プロセス名から導かれたタブタイトル、進捗が無いという想定 — がルールに届くことはありません。そのため、タイトルに対する regex = ['\S'] のようなルールは、プログラムが一度も発言していないペインには一致しません。

関連 ​