aiterm-mcp 0.27.9 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -1,4 +1,4 @@
1
- > **任意のMCPクライアントから、Claude・Codex・Grok・Composerをクロスベンダーでも同一ベンダーでも永続対話TUIへ起動する。Codexのスラッシュコマンドや[`$imagegen`](https://learn.chatgpt.com/docs/image-generation#generate-or-edit-an-image)のような固有機能もそのまま使える。**
1
+ > **任意のMCPクライアントから、Claude Code・Codex CLI・Grok CLI・Cursor Agent CLIを単一のharness APIで永続対話TUIへ起動する。**
2
2
 
3
3
  <p align="center">
4
4
  <img src=".github/og.png" alt="Aiterm — 異なる知性が一つの持続する実行現場を共有する森の観測拠点" width="100%">
@@ -16,7 +16,7 @@
16
16
 
17
17
  > *(English: [README.md](README.md))*
18
18
 
19
- > **あなたの AI に、ほかの AI を操らせる。** 任意の MCP クライアントから 1 回の呼び出しで、コーディングエージェント(Claude・Codex・Grok・Composer)を永続端末の中に起動し、操作用のセッションを手渡す。何をしているかをトークン削減して読み、次の指示を送る。呼び出し元と起動先のベンダーは独立しており、ClaudeからClaude/Codexを、CodexからClaude/Codexを起動できる。
19
+ > **あなたの AI に、ほかの AI を操らせる。** `agent_launch`の1回の呼び出しで、実行基盤harnessとmodelを別々に選び、永続sessionを受け取る。CursorでGPT/Claude/Grokを選んでも、session・hook・transcriptはCursorが所有する。
20
20
  >
21
21
  > **これは何か:** AI が握る 1 本の永続 MCP 端末——その中に他のコーディングエージェントも起動できる。`ssh`・`docker exec`・REPL・別エージェントの TUI は、すべてその 1 本の端末の中へ「送るだけのテキスト」として入れ子になる。仕組みはあえて素朴——MCP クライアントが相手エージェントの端末を 1 ターンずつ操作するだけ。隠れたプロトコルも・aiterm独自の共有メモリ層も・自律的な交渉も無い。起動したagentは、直接CLIと同じproject/vendorの通常memory・設定を読む。
22
22
  >
@@ -94,7 +94,9 @@ host統合は、kitepon.devの製品開発を支える内部基盤
94
94
 
95
95
  **言葉でなく実測で:** 記録済み203テストのベンチマークでは、`pty_read` はコンテキストに載るトークンを生ログの **約 7.1 分の 1** に減らす。しかも pass/fail の判定は畳んでも残る。→ [組み込みシェルツールとの使い分け](#組み込みシェルツールとの使い分け)
96
96
 
97
- 14 ツール: 6 つの **PTY ツール**(`pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list`)で 1 本の永続端末を開き・操作し・読む。加えて 4 つの **エージェント起動ツール**(`claude_agent` / `codex_agent` / `grok_agent` / `composer_agent`)が別のコーディングエージェントの TUI を新しい端末の中に起動し、`agent_configure`が起動中のClaude/Codex/Grok/Composerのmodel・effortを再起動なしで変更し、`claude_turn`がdurable caller向けの構造化issue/recoveryを、`claude_approval`が相関済みClaude承認UI中継を、`diagnostics`が安全なfactory readinessを返す。バックエンドは **tmux** なので、MCP サーバや AI クライアントが再起動してもセッションは生き残る。
97
+ 15ツール: 6つのPTYツール、正規のagent起動入口`agent_launch`、移行用の旧4alias、`agent_configure`、`claude_turn`、`claude_approval`、`diagnostics`。バックエンドはtmuxなので、MCPサーバやAIクライアントが再起動してもsessionは生き残る。
98
+
99
+ **v0.28.0では実行基盤harnessとmodelを分離した。** harnessはagent loop・認証・hook・session・transcriptを所有し、modelはその上で選ぶ。Cursor Agent CLIでGPT/Claude/Grokを選んでも完了契約はCursor方式のまま。Composerは別harnessではなく、`harness:"grok-cli", model:"grok-composer-2.5-fast"`で表す。旧4起動ツールは同じ実装へ流れる互換alias。
98
100
 
99
101
  **v0.25.2ではGrok 4.6を含む同一sessionの連続設定変更を安定化。** Grok Build 1.0.3で
100
102
  `/model`の成功通知が再描画により消えても、変更前には無かった要求model/effortが常駐footerへ現れた
@@ -151,7 +153,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
151
153
  場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
152
154
  Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
153
155
 
154
- **状態:** 開発継続中 · この分野では新参で、別の形に賭けている([既存手段との比較](#既存手段との比較)参照)· 動作対象は Linux · WSL2 · macOS · Windows ネイティブ(4 launcher と相関付き完了を含む)· MIT · [変更履歴](CHANGELOG.md)。
156
+ **状態:** 開発継続中 · この分野では新参で、別の形に賭けている([既存手段との比較](#既存手段との比較)参照)· 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
155
157
 
156
158
  ## なぜ今
157
159
 
@@ -174,14 +176,14 @@ pty_read(id, { wait: true }) → 削減済みの出力を読む(完了
174
176
 
175
177
  ### 2. その端末の中に他のコーディングエージェントを起動する — オーケストレーションの旗艦
176
178
 
177
- 同じ primitive が別エージェントの TUI を宿す。4 つの起動ツールが、Claude/Codex/Grok/Composer の対話 TUI を新しい永続端末の中に起動し、`session_id` を返す。起動processは直接CLIと同じproject/user環境を使い、通常config、MCP、plugin、skill、permission、trust、memory、historyをcopy・filter・置換しない。aitermが加えるのは完了相関と、`role=subagent`、親session、delegation depth、lineage、`delegation_allowed=true`を持つ非user instructionだけ。孫以降の委譲も許可され、固定depth capはない。
179
+ 同じprimitiveが別エージェントのTUIを宿す。`agent_launch`の`harness`はagent loop・認証・hook・session・transcriptを所有する実行基盤、`model`は独立した選択。起動processは直接CLIと同じproject/user環境を使い、通常config、MCP、plugin、skill、permission、trust、memory、historyをcopy・filter・置換しない。
178
180
 
179
- 既存の人間向けtextに加えて`aiterm.agent-launch-result.v1` structured receiptも返すため、durable callerは表示文字列を解析せずsession handleを取得できる。Codexは通常rollout transcriptの`task_complete`、Grok/Composerは通常session event、Claudeは通常settingsへ加算したlaunch固有Stop hookを完了正本に使う。agent sessionへの`pty_send`は非ブロックの **dispatch** になり`event_cursor`入りreceiptを即返す。完了通知は`aiterm-wait --session <id> --cursor <event_cursor>`を親のターンを塞がない別processで受ける。durable machine callerは`claude_turn`を使い、recoveryは再送せず、検証済み完了だけがexact `raw_output`を持つ。
181
+ `aiterm.agent-launch-result.v1`は正規`harness`を返し、旧`provider`は互換fieldとして残す。同じ`harness`はagent dispatch、`aiterm-wait`、`agent_configure`、`pty_list`のagent行にも載り、旧vendor/provider/agent fieldは互換用に残る。Codexは通常rollout、Grok CLIは通常session event、Claudeはlaunch固有Stop hook、Cursorは通常agent transcript末尾の`turn_ended`を完了正本に使う。`pty_send`は非ブロックdispatchで、vendor別完了境界を表すopaqueな整数`event_cursor`を返し、完了通知は`aiterm-wait`を親のターンを塞がない別processで受ける。
180
182
 
181
- `codex_agent`・`grok_agent`・`composer_agent`は任意の`write_scope`(`"read-only"`または書込み許可パスの説明)も受ける。指定値はlaunch receipt・session metadata・`pty_list`へ保存する。3 launcherすべてで`write_scope:"read-only"`は実効能力壁となり、aitermがCLIの`--sandbox read-only`を付ける。パス説明をallowlistへ変換する同等CLI引数はないため、そちらだけは`write_scope_enforcement:"declaration_only_unsupported"`を返す。`write_scope`を省略した起動は従来どおりである。
183
+ `agent_launch`は任意の`write_scope`も受ける。Codex/Grokのread-onlyは`--sandbox read-only`、Cursorは公式`--mode ask`で実効化する。path説明は同等CLI引数がないためdeclaration-only。
182
184
 
183
185
  ```text
184
- codex_agent({ session_name: "codex1", cwd: "/repo",
186
+ agent_launch({ harness: "codex-cli", session_name: "codex1", cwd: "/repo",
185
187
  prompt: "port test/legacy.py to vitest",
186
188
  model: "gpt-5.6-sol", reasoning_effort: "high",
187
189
  write_scope: "test/ only; no commit" })
@@ -192,14 +194,16 @@ $ aiterm-wait --session codex1 --cursor <event_cursor> # exit 0=done / 3=timeo
192
194
  → 操舵し、Codex の次の入力境界で返る
193
195
  ```
194
196
 
195
- モデルごとに 1 ツール=ツール名を見ればどのモデルか分かる:
197
+ 正規のharness選択肢:
196
198
 
197
- | ツール | 起動するもの | 主な引数 |
199
+ | `harness` | 起動するもの | modelの扱い |
198
200
  | --- | --- | --- |
199
- | `claude_agent` | Claude Code CLI(Anthropic) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(`low`/`medium`/`high`/`xhigh`/`max`), `env_vars?`, `cwd?`, `session_name?` |
200
- | `codex_agent` | Codex CLI(OpenAI・端末設定/CLI既定、`model?`で上書き) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(`low`/`medium`/`high`/`xhigh`/`max`/`ultra`), `env_vars?`, `cwd?`, `session_name?`, `write_scope?` |
201
- | `grok_agent` | Grok Build(xAI、既定`grok-4.5`、`model?`で上書き) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(vendor対応値), `env_vars?`, `cwd?`, `session_name?`, `write_scope?` |
202
- | `composer_agent` | Grok Build(xAI、既定`grok-composer-2.5-fast`、`model?`で上書き。全modelをlive catalog照合) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(vendor対応値), `env_vars?`, `cwd?`, `session_name?`, `write_scope?` |
201
+ | `claude-code` | Claude Code CLI | Claude model/effort |
202
+ | `codex-cli` | Codex CLI | OpenAI model/effort |
203
+ | `grok-cli` | Grok Build CLI | Grok/Composer model、live catalog照合 |
204
+ | `cursor-cli` | Cursor Agent CLI | Cursor catalog上のGPT/Claude/Grok等 |
205
+
206
+ Cursorの`model`は`gpt-5.6-luna`のようなbase model、`reasoning_effort`は`high`のように別指定する。adapterは現行`model-effort` IDを`cursor-agent models`へ照合し、起動中変更はCursor標準model pickerのparameter editorを使う。不在時は別modelへfallbackしない。
203
207
 
204
208
  `env_vars`は環境変数の**名前**だけを並べるallowlistであり、name/value mapではない。aitermは
205
209
  launcher起動時に現在のMCP processから各名前を読み、存在する値をshell quoteして、その1回のvendor
@@ -208,7 +212,7 @@ launcher起動時に現在のMCP processから各名前を読み、存在する
208
212
  PTYの起動コマンドとして送られ、sessionの`.lastcmd`にも保持されるため、起動先vendorと同じOS userへ
209
213
  到達する。秘密転送路ではなく、席identityやworkflow用の非secret変数だけに使う。
210
214
 
211
- 各ベンダーのCLIが導入・認証済みであること。CLI不在・不正なmodel/effort・実在しない`cwd`はsession作成前に失敗し、残骸を残さない。ClaudeはさらにPTY作成前に同じCLIの`auth status --json`が`loggedIn:true`を返すことを要求する。4 launcherは通常のvendor credential/config storeをその場で使い、fake `HOME`、private `CODEX_HOME`/`GROK_HOME`、project/user config snapshotを作らない。Claudeだけは完了相関用Stop hook settingsを通常の`user,project,local` settingsへ加算する。Grok/Composerは画面入力欄だけでなく通常sessionの`mcp_init_completed` eventも確認してから送信し、共有MCP初期化中の早送信を防ぐ。相関付きClaudeのactive turn中はC-c以外の`pty_key`と素送信を拒否し、承認UIは`claude_approval`で単発Yes/Noだけを相関付きで中継する。
215
+ 選んだharnessのCLIを公式経路で導入・認証しておく。Cursorは`curl https://cursor.com/install -fsS | bash`、`agent login`、更新は`agent update`が公式経路で、Aitermは曖昧な`agent`でなく`cursor-agent`を起動する。CLI不在・未認証・不正引数はsession作成前に明示失敗し、別経路へfallbackしない。
212
216
 
213
217
  portable forkは任意である。`throughline_source_session`を使う場合、`prompt`は必須の新ミッションとなり、
214
218
  `launch_operation_id`とは併用できない。aitermは`THROUGHLINE_BIN`、次に`PATH`からThroughlineを解決し、
@@ -216,7 +220,7 @@ portable forkは任意である。`throughline_source_session`を使う場合、
216
220
  この経路だけ`throughline >= 0.9.0`が必要で、元sessionのDB所属は変わらない。引数省略時には
217
221
  Throughline自体が不要である。
218
222
 
219
- エージェント間の隠れたプロトコルは無い。起動したClaude/Codex/Grok/Composerは利用者がattachできるもう1本の永続sessionであり、MCPクライアントが通常のPTY操作で駆動する。
223
+ エージェント間の隠れたプロトコルは無い。起動したharnessは利用者がattachできるもう1本の永続sessionであり、MCPクライアントが通常のPTY操作で駆動する。
220
224
 
221
225
  ## デモ
222
226
 
@@ -271,7 +275,7 @@ Throughline自体が不要である。
271
275
  Claude Code を再起動して、接続を確認:
272
276
 
273
277
  ```bash
274
- /mcp # aiterm が connected・14 ツール公開、と出る
278
+ /mcp # aiterm が connected・15 ツール公開、と出る
275
279
  ```
276
280
 
277
281
  最初のセッション——4 回の呼び出しで、1 個の永続端末:
@@ -286,7 +290,7 @@ pty_close("t1") → 端末を解放
286
290
  `pty_close` は冪等で、`closed` / `already_closed` のstructured receiptを返す。
287
291
  MCP応答を失ったdurable callerも同じ`session_id`への再試行だけでclose結果を確定できる。
288
292
 
289
- これだけ。`t1` の端末は本物で永続——`ssh`・`docker exec`・REPL・起動したエージェントの TUI は、そこに住む「もの」に過ぎない。代わりにワーカーのエージェントを起動するのも 1 コール: `codex_agent()` が返す `session_id` を、同じ `pty_read` / `pty_send` で操作する。
293
+ これだけ。`t1` の端末は本物で永続——`ssh`・`docker exec`・REPL・起動したエージェントのTUIは、そこに住む「もの」に過ぎない。ワーカー起動も1コールで、`agent_launch({ harness: "codex-cli" })`が返す`session_id`を同じ`pty_read`/`pty_send`で操作する。
290
294
 
291
295
  **グローバル導入や別クライアントが良い場合は:**
292
296
 
@@ -300,9 +304,9 @@ claude mcp add --scope user --transport stdio aiterm -- aiterm-mcp
300
304
 
301
305
  ## ヘッドレス: 端末に人が居ない
302
306
 
303
- MCP クライアントが aiterm を stdio 越しにプログラムから駆動するので、上のすべては **tmux に誰も座らないまま**動く。Claude/Codexのどちらからでも、自分自身を含む任意のlauncherを呼び、`pty_read`で結果を読んで次へ進める——無人で。これは、人が操作する端末が向かない場所にこそ aiterm が合うということ:
307
+ MCP クライアントが aiterm を stdio 越しにプログラムから駆動するので、上のすべては **端末に誰も座らないまま**動く。任意のMCP対応統括役が、自分と同じharnessを含む`agent_launch`を呼び、`pty_read`で結果を読んで次へ進める——無人で。これは、人が操作する端末が向かない場所にこそ aiterm が合うということ:
304
308
 
305
- - **複数エージェントのオーケストレーション** — 統括役がサブタスクを Claude / Codex / Grok / Composer に渡し、各々を専用の永続セッションに置き、全部を読み戻す。
309
+ - **複数エージェントのオーケストレーション** — 統括役がサブタスクを Claude Code / Codex / Grok / Cursor harnessへ渡し、各々を専用の永続セッションに置き、全部を読み戻す。ComposerはGrok CLIのmodel presetとして扱う。
306
310
  - **CI** — ジョブのステップがエージェントを起こし、操作し、片付けられる。
307
311
  - **cron** — スケジュール実行がエージェントを起動して出力を回収できる。
308
312
 
@@ -312,11 +316,11 @@ MCP クライアントが aiterm を stdio 越しにプログラムから駆動
312
316
 
313
317
  ```mermaid
314
318
  flowchart LR
315
- AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · agent_configure · claude_agent · claude_turn · claude_approval · codex_agent<br/>grok_agent · composer_agent · diagnostics"| S["aiterm-mcp<br/>stdio MCP · 14 tools"]
319
+ AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · agent_launch · agent_configure · claude_turn · claude_approval<br/>旧launcher alias · diagnostics"| S["aiterm-mcp<br/>stdio MCP · 15 tools"]
316
320
  S -->|"pty_read<br/>token-reduced"| AI
317
- S -->|"tmux send-keys<br/>capture-pane"| P["persistent PTYs<br/>tmux · survive restarts"]
321
+ S -->|"tmux / psmux<br/>send · capture"| P["persistent PTYs<br/>再起動を跨ぐ"]
318
322
  P -->|"ssh · docker · repl"| R["nested<br/>remote · container · REPL"]
319
- P -->|"launches a fresh PTY per agent"| A["another coding-agent TUI<br/>Claude · Codex · Grok · Composer"]
323
+ P -->|"launches a fresh PTY per agent"| A["another coding-agent TUI<br/>Claude · Codex · Grok · Cursor"]
320
324
  ```
321
325
 
322
326
  primitive は「PTY を 1 個握る」ことだけ。それ以外——SSH・コンテナ・REPL・起動したエージェント TUI——は、永続端末の中で動く「対話的な何か」に過ぎず、同じ `pty_send` / `pty_read` で操作する。各起動ツールは自分専用の新しい PTY を開く。PTY は tmux 上にあるので、MCP サーバや AI クライアントが再起動してもセッションは生き残る。
@@ -348,10 +352,10 @@ aiterm はセッションの状態も持ち越せる。組み込みツールは
348
352
 
349
353
  ```text
350
354
  組み込みシェル → var= # 空。env は消え、cwd はプロジェクト直下に戻る
351
- aiterm → cwd=/tmp var=hello123 # 1 本の tmux セッションが両方を保つ
355
+ aiterm → cwd=/tmp var=hello123 # 1 本の永続PTYが両方を保つ
352
356
  ```
353
357
 
354
- cd でディレクトリを移り、環境変数を立て、ビルドを走らせる。ssh で一度ログインして、その接続のまま 10 個コマンドを打つ。REPL や起動したエージェントの TUI を 1 ターンずつ操作する。こういう流れは、1 本の tmux セッションが状態を握っていて初めて成り立つ。端末に何かを覚えておいてほしいときは、aiterm を使う。
358
+ cd でディレクトリを移り、環境変数を立て、ビルドを走らせる。ssh で一度ログインして、その接続のまま 10 個コマンドを打つ。REPL や起動したエージェントの TUI を 1 ターンずつ操作する。こういう流れは、1 本の永続PTYが状態を握っていて初めて成り立つ。端末に何かを覚えておいてほしいときは、aiterm を使う。
355
359
 
356
360
  <sub>¹ いまのハーネスは ~192 KB の出力をいったんファイルに逃がして、先頭 ~2 KB だけを見せる。そのためトークン数はほぼ並ぶ。aiterm は行数を正確に返すうえ、あとから `line_range="A:B"` で好きな範囲(先頭でも末尾でも)を取り出せる。² `rtk` の grep 縮約は長い行(~80 字)を切り詰めて、あふれを `[+N more]` にまとめる。ざっと眺めるには向くが、全行をそのまま読みたいときは組み込みツールを使う。</sub>
357
361
 
@@ -361,15 +365,15 @@ aiterm は 2 つの系譜の交点にいる——端末を操作する MCP サ
361
365
 
362
366
  | | **aiterm-mcp** | 1 コマンド毎の往復<br/>(例: `mcp-server-commands`) | terminal / SSH / tmux MCP<br/>(例: `iterm-mcp`, `ssh-mcp`, `tmux-mcp`) | 共有 tmux でエージェント同士<br/>(例: `smux`) |
363
367
  | --- | --- | --- | --- | --- |
364
- | 永続セッション | ✅ tmux・再起動を跨ぐ | ❌ 毎回新シェル | ⚠️ まちまち | ✅ tmux |
368
+ | 永続セッション | ✅ tmux / psmux・再起動を跨ぐ | ❌ 毎回新シェル | ⚠️ まちまち | ✅ tmux |
365
369
  | SSH / コンテナ / REPL | `pty_send` 1 回でネスト | 毎コマンド接続し直し | ⚠️ ツールが分かれがち | ✅ tmux(人が操作) |
366
- | 1 コールで別エージェント起動 | ✅ `codex_agent` / `grok_agent` / `composer_agent` | ❌ | ❌ | ⚠️ 人が動かす tmux に CLI + skills で参加 |
370
+ | 1 コールで別エージェント起動 | ✅ `agent_launch(harness=…)` | ❌ | ❌ | ⚠️ 人が動かす tmux に CLI + skills で参加 |
367
371
  | ヘッドレス(人が tmux に居ない) | ✅ MCP 駆動・プログラム的 | ✅ | ⚠️ まちまち | ❌ 人が tmux に居る前提 |
368
372
  | MCP ネイティブ(任意の MCP クライアント) | ✅ `claude mcp add` 1 行 | ✅ | ✅(MCP なので) | ❌ tmux 設定 + CLI + Agent Skills |
369
373
  | トークン削減読取 | ✅ コマンド別 reducer | ❌ 生出力 | ⚠️ ほぼ無し | ❌ 生 tmux |
370
374
  | 完了検出 | 5 層: 終了 / `mark` / `until` / 静止 / timeout | 無し(毎回ブロック) | ⚠️ プロンプト一致・脆い | ❌ エージェントがペインを読む |
371
375
  | 破壊コマンド遮断 | ✅ tripwire(`force` で越える) | ❌ | ⚠️ まちまち | ❌ |
372
- | 人が同時操作 | ✅ 共有 tmux ソケット(`attach`) | ❌ | ⚠️ まちまち | ✅(設計の芯) |
376
+ | 人が同時操作 | ✅ 共有socket/namespace(`attach`) | ❌ | ⚠️ まちまち | ✅(設計の芯) |
373
377
 
374
378
  ## aiterm の立ち位置
375
379
 
@@ -392,8 +396,10 @@ aiterm は同じ核心の洞察——端末を出会いの場にする——を
392
396
  | `pty_read` | 出力を削減して読む(既定は増分) | `session_id`, `wait`, `until`, `until_regex`, `timeout`, `screen`, `full`, `lines`, `line_range`, `raw`, `rtk`, `agent_transcript`, `operation_id` |
393
397
  | `pty_key` | 制御キーを送る | `session_id`, `key`(`C-c`/`Enter`/`Up`…) |
394
398
  | `pty_close` | 冪等に閉じ、`closed` / `already_closed`を返す | `session_id` |
395
- | `pty_list` | セッション一覧 | (なし) |
396
- | `agent_configure` | 起動中のClaude/Codex/Grok/Composerを再起動せずmodel/effort変更 | `session_id`, `model?`, `reasoning_effort?` |
399
+ | `pty_list` | セッション一覧(agent行は正規`harness=<id>`と互換`agent=<kind>`を含む) | (なし) |
400
+ | `agent_launch` | harnessとmodelを別軸で選ぶ正規agent起動入口 | `harness`, `prompt?`, `model?`, `reasoning_effort?`, `cwd?`, `write_scope?` |
401
+ | `claude_agent` / `codex_agent` / `grok_agent` / `composer_agent` | deprecated互換alias | 旧launcher引数 |
402
+ | `agent_configure` | 起動中のClaude/Codex/Grok/Composer/Cursorを再起動せずmodel/effort変更 | `session_id`, `model?`, `reasoning_effort?` |
397
403
  | `claude_turn` | 相関済みClaude operationをdispatch(issue)または回収(recover) | `action`, `session_id`, `operation_id`, `text?` |
398
404
  | `claude_approval` | 現在表示中の相関済みClaude承認UIを検査または応答 | `action`, `session_id`, `operation_id?`, `approval_choice?`, `observed_prompt_digest?` |
399
405
  | `diagnostics` | 機械可読 JSON による read-only factory readiness | (なし) |
@@ -406,31 +412,31 @@ aiterm は同じ核心の洞察——端末を出会いの場にする——を
406
412
 
407
413
  consumer は `aiterm-runtime-errors snapshot` を読み、durable ingestion 後に `aiterm-runtime-errors ack --cursor N` を呼ぶ。運用上の明示操作は `resolve|reopen --fingerprint SHA256`。MCP からの収集・diagnostic read は timeout 付き child process に隔離し、FIFOや停止 filesystem が端末本体を止めない。store mutation は期限付き bakery ticket queue で直列化する。各waiterは PID+process start identity+owner token を持つ再利用されない固有ticketを所有するため、死んだownerだけを固有名で除去でき、固定path回収のABAを作らない。queueの期限は正常な前任者を含む総待ち時間ではなく、同じ先頭ownerが進まない時間を測る。通常pollはprocessの生存確認だけを行い、process start identityはblockerがstallした時に照合する。POSIX state は `$XDG_STATE_HOME/aiterm-mcp/`(既定 `~/.local/state/aiterm-mcp/`)へ atomic replacement で置き、every read で owner/mode を再検証する。Windows native は `%LOCALAPPDATA%\aiterm-mcp\` で current SID の非継承 FullControl ACE 1件だけへ DACL を再構築し readback する。今回 Windows は path/DACL/timeout の純粋テストだけであり、新しい実機統合成功は主張しない。
408
414
 
409
- ### 対話エージェント起動ツール
415
+ ### 対話エージェントharness
410
416
 
411
- 各ツールは特定ベンダーの対話型コーディングエージェント TUI を新しい永続 PTY の中に起動し、`session_id` を返す。以後は他のセッションと同様に `pty_read` / `pty_send` で操作する。モデルごとに 1 ツール=ツール名を見ればどのモデルか分かる。TUI は全画面アプリなので、`pty_read({ screen: true })` で描画済みの画面を読む。
417
+ `agent_launch`は選んだharnessの対話TUIを新しい永続PTYに起動し、`session_id`を返す。harnessはagent loop・認証・hook・session・transcriptを所有し、modelは独立。以後は他sessionと同じ`pty_read`/`pty_send`で操作する。
412
418
 
413
- `agent_configure({ session_id, model?, reasoning_effort? })`はvendor標準操作で起動中のClaude/Codex/Grok/Composerを変更し、PTYと会話contextを維持する。Grok/Composerは同じlive model catalog照合後に`/model <model> [effort]`または`/effort <effort>`を使う。Claude Code標準の`/model`・`/effort`は、新しいClaude sessionの既定値も同時に保存する。
419
+ `agent_configure({ session_id, model?, reasoning_effort? })`はharness標準操作で起動中のClaude/Codex/Grok/Composer/Cursorを変更し、PTYと会話contextを維持する。
414
420
 
415
- | ツール | 起動するもの | 主な引数 |
421
+ | `harness` | 起動するもの | modelの扱い |
416
422
  | --- | --- | --- |
417
- | `claude_agent` | Claude Code CLI(Anthropic) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(`low`/`medium`/`high`/`xhigh`/`max`), `env_vars?`, `cwd?`, `session_name?` |
418
- | `codex_agent` | Codex CLI(OpenAI・端末設定/CLI既定、`model?`で上書き) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(`low`/`medium`/`high`/`xhigh`/`max`/`ultra`), `env_vars?`, `cwd?`, `session_name?`, `write_scope?` |
419
- | `grok_agent` | Grok Build(xAI、既定`grok-4.5`、`model?`で上書き) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(vendor対応値), `env_vars?`, `cwd?`, `session_name?`, `write_scope?` |
420
- | `composer_agent` | Grok Build(xAI、既定`grok-composer-2.5-fast`、`model?`で上書き。全modelをlive catalog照合) | `prompt?`, `throughline_source_session?`, `model?`, `reasoning_effort?`(vendor対応値), `env_vars?`, `cwd?`, `session_name?`, `write_scope?` |
423
+ | `claude-code` | Claude Code CLI | Claude model/effort |
424
+ | `codex-cli` | Codex CLI | OpenAI model/effort |
425
+ | `grok-cli` | Grok Build CLI | Grok/Composer model、live catalog照合 |
426
+ | `cursor-cli` | Cursor Agent CLI | Cursor catalog上のGPT/Claude/Grok等 |
421
427
 
422
- 対応するCLI(`claude` / `codex` / `grok`)の導入・認証が必要。前提違反はsession作成前に明示失敗する。4 launcherすべてが通常project/user環境と同じ非ブロックdispatch契約を使う。Claude/Codex/Grok/Composerのdepth 1 live smokeと、Claude親→Claude孫のdepth 2 nested delegation smokeはgreenであり、fixtureによる検証とは区別して記録する。
428
+ 対応するCLI(`claude`/`codex`/`grok`/`cursor-agent`)の公式導入・認証が必要。前提違反はsession作成前に明示失敗する。全harnessが通常project/user環境と同じ非ブロックdispatch契約を使う。
423
429
 
424
430
  `throughline_source_session`と空でない新ミッション`prompt`を指定すると、Throughlineの読み取り専用
425
431
  handoff contextを前置きできる。この任意経路は`throughline >= 0.9.0`を必要とし、
426
432
  `launch_operation_id`とは併用不可で、元sessionのDB所属を変更しない。Throughlineは
427
433
  `THROUGHLINE_BIN`、次に`PATH`から解決し、不在・不正・空のexportはPTY作成前に明示失敗する。
428
434
 
429
- エージェントの回答が画面 tailより長ければ、対話callerは`pty_read({ agent_transcript:true })`で再promptなしに全文回収する。Claudeはlaunch相関付きStop hookのowner-only resultを検証し、private transcriptを読まない。Codexは通常rollout transcript、Grok/Composerは通常session historyから同じturnを回収する。不在・非agent・抽出不能は明示エラー。
435
+ エージェントの回答が画面tailより長ければ、`pty_read({ agent_transcript:true })`で再promptなしに全文回収する。Claudeはlaunch相関Stop hook、Codexは通常rollout、Grokは通常session history、Cursorはlaunch IDでbindした通常agent transcriptから同じturnを回収する。
430
436
 
431
437
  ### 完了検出(5 層)
432
438
 
433
- `pty_read({ wait: true })`は通常PTYを、process終了/`mark:true` sentinel/`until`一致/shell復帰を伴う出力静止/timeoutの5層で判定する。`mark`はPOSIX shellでは終了コード、PowerShellでは成功`0`/失敗`1`を出力する。fish/csh/tcshはどちらの状態取得構文にも従わないため送信前に拒否する。agent sessionは第6の正確な層を使う。Codexは通常rolloutの`task_complete`、Grok/Composerは通常sessionの`turn_ended`、Claudeは通常settingsへ加算したlaunch相関Stop eventを`aiterm-wait --cursor`が観測する。親はブロックもポーリングもしない。Grok/Composerは`mcp_init_completed`確認前に入力欄が見えても送信しない。
439
+ `pty_read({ wait: true })`は通常PTYを、process終了/`mark:true` sentinel/`until`一致/shell復帰を伴う出力静止/timeoutの5層で判定する。agent sessionは第6の正確な層を使い、Codexは通常rollout、Grokは通常session event、Claudeはlaunch相関Stop event、Cursorは通常agent transcriptの`turn_ended`を`aiterm-wait --cursor`が観測する。親はブロックもポーリングもしない。
434
440
 
435
441
  ### トークン削減
436
442
 
@@ -442,11 +448,11 @@ handoff contextを前置きできる。この任意経路は`throughline >= 0.9.
442
448
 
443
449
  `pty_send` は送信前に破壊的コマンド(`rm -rf /`, `mkfs`, `dd of=/dev/…`, `DROP TABLE` 等)を遮断し(`force: true` で越える)、ESC・ブラケットペースト終端などをサニタイズする。`pty_read` は既定で制御文字を無害化して返す(`raw: true` はバイトをそのまま返す)。これは**サンドボックスではなく tripwire**([既知の制約](#既知の制約バグではなく仕様)参照)。
444
450
 
445
- 1回の `pty_send` が受理する本文はUTF-8で最大64KiB。同一sessionへの送信はaiterm processをまたいで直列化し、chunk同士の混線を防ぐ。全OSで長いPTY入力の欠落を避けるためUTF-8境界を壊さない256-byte単位でpasteし、chunk間に10msのdrain間隔を置く。POSIX shellが前面にいる時のsanitize済み複数行は、改行を含まない単一の`eval`入力へ符号化する。shellがscript全体を所有してから先頭行を実行するため、途中で起動したpager/REPLが後続行を対話キーとして奪わない。単一行、`raw:true`、非shell前面は従来どおり直接PTYへpasteする。agent dispatch の paste はさらに tmux bracketed paste(`paste-buffer -p`)を使う: bracketed paste mode を要求している pane(vendor TUI)へは各 chunk を `ESC[200~/201~` で包んで届け、チャンク投入中のキー解釈による語中文字化け・submit 取り落としを抑える。途中chunkが失敗した場合は部分送信済みであることを明示し、自動でEnterを押さない。送信processの異常終了でlockが残った場合は送信前にfail-closedする。そのsessionを `pty_close` して作り直すか、全sessionを破棄できる場合だけ `pty_kill_all` で安全に掃除する。
451
+ 1回の `pty_send` が受理する本文はUTF-8で最大64KiB。同一sessionへの送信はaiterm processをまたいで直列化し、chunk同士の混線を防ぐ。全OSで長いPTY入力の欠落を避けるためplatformのmultiplexerへUTF-8境界を壊さない256-byte単位でpasteし、chunk間に10msのdrain間隔を置く。POSIX shellが前面にいる時のsanitize済み複数行は、改行を含まない単一の`eval`入力へ符号化する。shellがscript全体を所有してから先頭行を実行するため、途中で起動したpager/REPLが後続行を対話キーとして奪わない。単一行、`raw:true`、非shell前面は従来どおり直接PTYへpasteする。agent dispatchはtmux互換のbracketed paste操作(`paste-buffer -p`)を使う: bracketed paste modeを要求しているpaneへは各chunkを`ESC[200~/201~`で包んで届け、chunk投入中のキー解釈による語中文字化け・submit取り落としを抑える。途中chunkが失敗した場合は部分送信済みであることを明示し、自動でEnterを押さない。送信processの異常終了でlockが残った場合は送信前にfail-closedする。そのsessionを `pty_close` して作り直すか、全sessionを破棄できる場合だけ `pty_kill_all` で安全に掃除する。
446
452
 
447
453
  ## 人が覗く
448
454
 
449
- セッションは共有 tmux socket(Windows nativeはpsmux namespace)上にある。`pty_open`(および各エージェント起動ツール)の戻り値に表示される `tmux -S … attach -t <id>`、Windowsでは`psmux -L … attach -t <id>`で人間が同じ端末に入って介入できる(抜けるのは `Ctrl-b d`)——起動した Claude/Codex/Grok/Composer のセッションを見たり、途中でキーボードを引き取ったりもできる。
455
+ セッションは共有tmux socket(Windows nativeはpsmux namespace)上にある。`pty_open`/`agent_launch`の戻り値に表示されるattachコマンドで、人間がClaude/Codex/Grok/Cursor harnessの同じ端末へ入り、途中でキーボードを引き取れる。
450
456
 
451
457
  ## 要件
452
458
 
@@ -454,7 +460,7 @@ handoff contextを前置きできる。この任意経路は`throughline >= 0.9.
454
460
  - **tmux または psmux**(実行時の前提)
455
461
  - **macOS / Linux / WSL2** は tmux を直接使う。macOS は同梱されないので `brew install tmux` で導入する。MCP クライアントがターミナルでなく **GUI から起動**された場合、Homebrew の bin(Apple Silicon: `/opt/homebrew/bin`、Intel: `/usr/local/bin`)が `PATH` に入らないことがある。その場合 aiterm が自動で探索するか、**`AITERM_TMUX=/path/to/tmux`** で明示指定する。
456
462
  - **Windows ネイティブ**は WSL を使わず、tmux CLI互換の [psmux](https://github.com/psmux/psmux) **3.3.8以上**を直接使う(`winget install marlocarlo.psmux`)。pane shell用に Git for Windows も必要。解決先は **`AITERM_PSMUX`**/**`AITERM_BASH`** で上書きできる。Windows toolはSSHと同じく入れ子で握れ、`pty_send "powershell.exe"`でPowerShellへ入れる。
457
- - **エージェント起動ツール**を使う場合: 対応するベンダー CLI が導入・認証済みであること——`claude_agent` は `claude`、`codex_agent` は `codex`、`grok_agent` / `composer_agent` は `grok`。portable forkだけは追加で`throughline >= 0.9.0`が必要だが、通常のclean launchには不要。(PTY ツールだけ使うなら不要。)
463
+ - **agent harness**を使う場合: 対応CLIを製品所有者の公式経路で導入・認証する。CursorはmacOS/Linux/WSLで`curl https://cursor.com/install -fsS | bash`、Windows nativeで`irm 'https://cursor.com/install?win32=true' | iex`を使い、`agent login`で認証、`agent update`で更新する。Aitermは`cursor-agent`を起動する。portable forkだけは追加で`throughline >= 0.9.0`が必要。
458
464
  - 任意: [`rtk`](https://github.com/rtk-ai/rtk) バイナリ(`pty_send` の `rtk: true` 委譲で使う。無くても動く)
459
465
 
460
466
  ## 既知の制約(バグではなく仕様)
@@ -462,18 +468,18 @@ handoff contextを前置きできる。この任意経路は`throughline >= 0.9.
462
468
  - **ネスト中(ssh / docker / REPL / 起動したエージェント TUI)は quiescence が原理的に効かない。** 前面コマンドがシェル集合(bash/sh/zsh/fish/dash)の外になるため。ネスト中で `until` も `mark` も無いときは、待っても完了を確定できる信号が無いので、`pty_read({ wait: true })` はフル `timeout` を空費せず出力静止時点で `is_complete=False via nested` と早期に返し、`until`(既定リテラル部分一致・`until_regex: true` で正規表現)か `mark: true`(終了コード付き sentinel・自動検出)の指定を促す。全画面のエージェント TUI なら、出力が落ち着いた時点で `{ screen: true }` を読む。
463
469
  - **`is_complete=False` は失敗ではない。** 「timeout 内に完了を観測できなかった」という意味。長時間コマンドでは `timeout` を伸ばすか `until`/`mark` を使う。
464
470
  - **破壊ゲートはサンドボックスではなく tripwire。** よくある破壊形だけを弾く。相対パスの `rm`、`$VAR` 展開後に危険化するもの、ssh 先で実行されるコマンドは捕捉しない——起動したコーディングエージェントが自分のセッション内で何をするかも取り締まらない。
465
- - **エージェント起動ツールはベンダー TUI を起動するだけで、包んだり代理したりしない。** aiterm は前提を検証して CLI を永続 PTY で起動する——モデル・認証・挙動はベンダー CLI のもの。エージェント間の隠れたプロトコルはなく、「会話」とはMCPクライアントがClaude/Codex/Grok/Composer TUIへ入力を送り出力を読むことだ。
471
+ - **agent harnessは実物TUIを起動し、model APIを代理しない。** model・認証・挙動は選んだharnessのもの。隠れたagent間protocolはなく、MCPクライアントがClaude/Codex/Grok/Cursor TUIへ入力を送り出力を読む。
466
472
  - **`pty_send({ rtk: true })` は単行コマンドのみ+外部 `rtk` バイナリが必要**(無ければ素通し)。一方 `pty_read({ rtk: true })` の reducer は自前実装で rtk 非依存。
467
473
  - **`pytest` reducer は件数・罫線・`FAILURES` ブロック整形が rtk 0.42.0 と byte 一致**(回帰テストで固定)。ただし `-ra`/`-rf` 時の `FAILED` 要約行の理由は**全文を保持する**(rtk 0.42.0 は最初の `" - "` 区切りで切るが、本実装は可読性優先で情報を残すため、この行は意図的に rtk と完全一致させない)。rtk が大出力時に付ける `[full output: …]`(tee ポインタ)行は read 側では再現しない。
468
474
  - **tmux は `-f /dev/null` 起動**なので `~/.tmux.conf` を読まない(環境差を排除するため)。
469
- - **全セッションが単一 socket(POSIX では `claude.sock`)上にある。** `tmux … kill-server` は全セッションを消す。
475
+ - **全セッションが単一multiplexer endpoint(POSIXは`claude.sock`、Windows nativeは1つのpsmux namespace)を共有する。** platformの`kill-server` commandは全セッションを消す。
470
476
 
471
477
  ## 開発
472
478
 
473
479
  ```bash
474
480
  npm install
475
481
  npm run build # tsc → dist/
476
- npm test # build してから node:test 回帰スイート(tmux 必須)
482
+ npm test # build してから node:test 回帰スイート(tmux または psmux 必須)
477
483
  npm link # ローカルで `aiterm-mcp` を PATH に
478
484
  ```
479
485
 
@@ -482,7 +488,7 @@ self-hostedのmacOS native・Linux native・Windows native・WSL2で同じ`npm t
482
488
  OS別の縮小suiteで代用しません。tag起点のnpm公開は4環境greenとtagged commitの`origin/main`
483
489
  祖先確認を通過した後だけ実行します。
484
490
 
485
- ロジックは `src/core.ts`(tmux 制御・削減・完了検出・安全・エージェント起動)と `src/rtk.ts`(コマンド別 reducer)、公開は `src/index.ts`。設計の出発点と reducer の移植元(pytest reducer は本家 rtk 0.42.0 と一致するよう移植・ただし上記の `FAILED` 行の差異は意図的・回帰テストで固定)は `prototype/python/` を参照。
491
+ 共通進行は`src/core.ts`、harness固有は`src/vendors/`、OS差は`src/tmux-runtime.ts`/`src/agent-resolver.ts`、reducerは`src/rtk.ts`、公開面は`src/index.ts`が所有する。設計の出発点と reducer の移植元(pytest reducer は本家 rtk 0.42.0 と一致するよう移植・ただし上記の `FAILED` 行の差異は意図的・回帰テストで固定)は `prototype/python/` を参照。
486
492
 
487
493
  ## 試す
488
494