ai-cli-mcp 2.12.0 → 2.14.0

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.
Files changed (46) hide show
  1. package/.github/workflows/publish.yml +25 -0
  2. package/CHANGELOG.md +20 -0
  3. package/README.ja.md +20 -5
  4. package/README.md +20 -6
  5. package/dist/__tests__/app-cli.test.js +34 -2
  6. package/dist/__tests__/cli-bin-smoke.test.js +4 -0
  7. package/dist/__tests__/cli-builder.test.js +37 -0
  8. package/dist/__tests__/cli-process-service.test.js +180 -5
  9. package/dist/__tests__/cli-utils.test.js +31 -0
  10. package/dist/__tests__/mcp-contract.test.js +287 -9
  11. package/dist/__tests__/parsers.test.js +37 -1
  12. package/dist/__tests__/process-management.test.js +2 -1
  13. package/dist/app/cli.js +8 -6
  14. package/dist/app/mcp.js +16 -8
  15. package/dist/cli-builder.js +14 -0
  16. package/dist/cli-parse.js +8 -5
  17. package/dist/cli-process-service.js +13 -23
  18. package/dist/cli-utils.js +17 -0
  19. package/dist/cli.js +4 -3
  20. package/dist/model-catalog.js +4 -1
  21. package/dist/parsers.js +55 -0
  22. package/dist/process-result.js +51 -0
  23. package/dist/process-service.js +11 -22
  24. package/dist/server.js +1 -1
  25. package/package.json +2 -2
  26. package/server.json +1 -1
  27. package/src/__tests__/app-cli.test.ts +43 -1
  28. package/src/__tests__/cli-bin-smoke.test.ts +4 -0
  29. package/src/__tests__/cli-builder.test.ts +47 -0
  30. package/src/__tests__/cli-process-service.test.ts +200 -5
  31. package/src/__tests__/cli-utils.test.ts +34 -0
  32. package/src/__tests__/mcp-contract.test.ts +325 -9
  33. package/src/__tests__/parsers.test.ts +44 -1
  34. package/src/__tests__/process-management.test.ts +2 -1
  35. package/src/app/cli.ts +9 -7
  36. package/src/app/mcp.ts +17 -8
  37. package/src/cli-builder.ts +18 -3
  38. package/src/cli-parse.ts +8 -5
  39. package/src/cli-process-service.ts +12 -23
  40. package/src/cli-utils.ts +21 -1
  41. package/src/cli.ts +4 -3
  42. package/src/model-catalog.ts +5 -1
  43. package/src/parsers.ts +61 -0
  44. package/src/process-result.ts +79 -0
  45. package/src/process-service.ts +11 -24
  46. package/src/server.ts +1 -1
@@ -43,22 +43,47 @@ jobs:
43
43
  - name: Verify provenance attestations
44
44
  run: npm audit signatures
45
45
 
46
+ - name: Capture version before release
47
+ id: release_before
48
+ run: |
49
+ VERSION=$(node -p 'require("./package.json").version')
50
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
51
+
46
52
  - name: Release
47
53
  env:
48
54
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49
55
  run: npx semantic-release
50
56
 
57
+ - name: Capture version after release
58
+ id: release_after
59
+ run: |
60
+ VERSION=$(node -p 'require("./package.json").version')
61
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
62
+
63
+ - name: Detect whether a release was published
64
+ id: release_status
65
+ run: |
66
+ if [ "${{ steps.release_before.outputs.version }}" != "${{ steps.release_after.outputs.version }}" ]; then
67
+ echo "published=true" >> "$GITHUB_OUTPUT"
68
+ else
69
+ echo "published=false" >> "$GITHUB_OUTPUT"
70
+ fi
71
+
51
72
  - name: Install mcp-publisher
73
+ if: steps.release_status.outputs.published == 'true'
52
74
  run: |
53
75
  curl -L "https://github.com/modelcontextprotocol/registry/releases/latest/download/mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz" | tar xz mcp-publisher
54
76
 
55
77
  - name: Authenticate to MCP Registry
78
+ if: steps.release_status.outputs.published == 'true'
56
79
  run: ./mcp-publisher login github-oidc
57
80
 
58
81
  - name: Set version in server.json
82
+ if: steps.release_status.outputs.published == 'true'
59
83
  run: |
60
84
  VERSION=$(node -p "require('./package.json').version")
61
85
  jq --arg v "$VERSION" '.version = $v | .packages[0].version = $v' server.json > server.tmp && mv server.tmp server.json
62
86
 
63
87
  - name: Publish to MCP Registry
88
+ if: steps.release_status.outputs.published == 'true'
64
89
  run: ./mcp-publisher publish
package/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ # [2.14.0](https://github.com/mkXultra/ai-cli-mcp/compare/v2.13.0...v2.14.0) (2026-04-07)
2
+
3
+
4
+ ### Features
5
+
6
+ * get_result・waitにcompact/verbose出力形式を追加 ([21fdff3](https://github.com/mkXultra/ai-cli-mcp/commit/21fdff3813f28327a2da94f4b5bed94b54abcd74))
7
+
8
+ # [2.13.0](https://github.com/mkXultra/ai-cli-mcp/compare/v2.12.0...v2.13.0) (2026-04-07)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **ci:** correct release version capture shell quoting ([2986b0b](https://github.com/mkXultra/ai-cli-mcp/commit/2986b0bb0452fcf4b34491c3d832cff3b271616c))
14
+ * **ci:** skip MCP Registry publish when no release is created ([9de4c83](https://github.com/mkXultra/ai-cli-mcp/commit/9de4c836a946b4a0028a46525b4bcfa2094032cc))
15
+
16
+
17
+ ### Features
18
+
19
+ * Forge CLIを新しいAIバックエンドとして追加 ([35ae860](https://github.com/mkXultra/ai-cli-mcp/commit/35ae8604ff0a663e960fc758eee2872680aec503))
20
+
1
21
  # [2.12.0](https://github.com/mkXultra/ai-cli-mcp/compare/v2.11.0...v2.12.0) (2026-03-12)
2
22
 
3
23
 
package/README.ja.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  > **📦 パッケージ移行のお知らせ**: 本パッケージは旧名 `@mkxultra/claude-code-mcp` から `ai-cli-mcp` に名称変更されました。これは、複数のAI CLIツールのサポート拡大を反映したものです。
7
7
 
8
- AI CLIツール(Claude, Codex, Gemini)をバックグラウンドプロセスとして実行し、権限処理を自動化するMCP(Model Context Protocol)サーバーです。
8
+ AI CLIツール(Claude, Codex, Gemini, Forge)をバックグラウンドプロセスとして実行し、権限処理を自動化するMCP(Model Context Protocol)サーバーです。
9
9
 
10
10
  Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦戦していることに気づいたことはありませんか?このサーバーは、強力な統合 `run` ツールを提供し、複数のAIエージェントを活用してコーディングタスクをより効果的に処理できるようにします。
11
11
 
@@ -20,10 +20,12 @@ Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦
20
20
  - すべての権限確認をスキップしてClaude CLIを実行(`--dangerously-skip-permissions` を使用)
21
21
  - 自動承認モードでCodex CLIを実行(`--full-auto` を使用)
22
22
  - 自動承認モードでGemini CLIを実行(`-y` を使用)
23
+ - Forge CLI を非対話モードで実行(`forge -C <workFolder> -p <prompt>` を使用)
23
24
  - 複数のAIモデルのサポート:
24
25
  - Claude (sonnet, sonnet[1m], opus, opusplan, haiku)
25
26
  - Codex (gpt-5.4, gpt-5.3-codex, gpt-5.2-codex, gpt-5.1-codex-mini, gpt-5.1-codex-max, など)
26
27
  - Gemini (gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview)
28
+ - Forge (`forge`)
27
29
  - PID追跡によるバックグラウンドプロセスの管理
28
30
  - ツールからの構造化された出力の解析と返却
29
31
 
@@ -55,7 +57,7 @@ Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦
55
57
 
56
58
  - **真の非同期マルチタスク**: エージェントの実行はバックグラウンドで行われ、即座に制御が戻ります。呼び出し元のAIは実行完了を待つことなく、並行して次のタスクの実行や別のエージェントの呼び出しを行うことができます。
57
59
  - **CLI in CLI (Agent in Agent) の実現**: MCPをサポートするあらゆるIDEやCLIから、Claude CodeやCodexといった強力なCLIツールを直接呼び出せます。ホスト環境の制限を超えた、より広範で複雑なシステム操作や自動化が可能になります。
58
- - **モデル・プロバイダの制約からの解放**: 特定のエコシステムに縛られることなく、Claude、Codex (GPT)、Geminiの中から、タスクに最適な「最強のモデル」や「コスト効率の良いモデル」を自由に選択・組み合わせて利用できます。
60
+ - **モデル・プロバイダの制約からの解放**: 特定のエコシステムに縛られることなく、Claude、Codex (GPT)、Gemini、Forgeの中から、タスクに最適な「最強のモデル」や「コスト効率の良いモデル」を自由に選択・組み合わせて利用できます。
59
61
 
60
62
  ## 前提条件
61
63
 
@@ -64,6 +66,7 @@ Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦
64
66
  - **Claude Code**: `claude doctor` が通り、`--dangerously-skip-permissions` での実行が承認済み(一度手動で実行してログイン・承認済み)であること。
65
67
  - **Codex CLI**(オプション): インストール済みで、ログインなどの初期設定が完了していること。
66
68
  - **Gemini CLI**(オプション): インストール済みで、ログインなどの初期設定が完了していること。
69
+ - **Forge CLI**(オプション): インストール済みで、初期設定が完了していること。
67
70
 
68
71
  ## インストールと使い方
69
72
 
@@ -115,7 +118,9 @@ ai-cli models
115
118
  ai-cli run --cwd "$PWD" --model sonnet --prompt "summarize this repository"
116
119
  ai-cli ps
117
120
  ai-cli result 12345
121
+ ai-cli result 12345 --verbose
118
122
  ai-cli wait 12345 --timeout 300
123
+ ai-cli wait 12345 --verbose
119
124
  ai-cli kill 12345
120
125
  ai-cli cleanup
121
126
  ai-cli-mcp
@@ -182,7 +187,9 @@ ai-cli models
182
187
  ai-cli run --cwd "$PWD" --model codex-ultra --prompt "fix failing tests"
183
188
  ai-cli ps
184
189
  ai-cli wait 12345
190
+ ai-cli wait 12345 --verbose
185
191
  ai-cli result 12345
192
+ ai-cli result 12345 --verbose
186
193
  ai-cli cleanup
187
194
  ```
188
195
 
@@ -222,7 +229,7 @@ detached 実行された `ai-cli` の自然終了 exit code は、まだ永続
222
229
 
223
230
  ### `run`
224
231
 
225
- Claude CLI、Codex CLI、またはGemini CLIを使用してプロンプトを実行します。モデル名に基づいて適切なCLIが自動的に選択されます。
232
+ Claude CLI、Codex CLIGemini CLI、または Forge CLI を使用してプロンプトを実行します。モデル名に基づいて適切なCLIが自動的に選択されます。
226
233
 
227
234
  **引数:**
228
235
  - `prompt` (string, 任意): AIエージェントに送信するプロンプト。`prompt` または `prompt_file` のいずれかが必須です。
@@ -233,16 +240,20 @@ Claude CLI、Codex CLI、またはGemini CLIを使用してプロンプトを実
233
240
  - Claude: `sonnet`, `sonnet[1m]`, `opus`, `opusplan`, `haiku`
234
241
  - Codex: `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
235
242
  - Gemini: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3-flash-preview`
236
- - `reasoning_effort` (string, 任意): Claude と Codex の推論制御。Claude では `--effort` を使います(許容値: "low", "medium", "high")。Codex では `model_reasoning_effort` を使います(許容値: "low", "medium", "high", "xhigh")。
237
- - `session_id` (string, 任意): 以前のセッションを再開するためのセッションID。対応モデル: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview。
243
+ - Forge: `forge`
244
+ - `reasoning_effort` (string, 任意): Claude Codex の推論制御。Claude では `--effort` を使います(許容値: "low", "medium", "high")。Codex では `model_reasoning_effort` を使います(許容値: "low", "medium", "high", "xhigh")。Forge では `reasoning_effort` はサポートしません。
245
+ - `session_id` (string, 任意): 以前のセッションを再開するためのセッションID。対応モデル: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview, forge。
238
246
 
239
247
  ### `wait`
240
248
 
241
249
  複数のAIエージェントプロセスの完了を待機し、結果をまとめて返します。指定されたすべてのPIDが終了するか、タイムアウトになるまでブロックします。
242
250
 
251
+ デフォルトでは、返される各結果項目は `get_result(verbose: false)` と同じ compact 形を使います。`pid`、`agent`、`status`、`exitCode`、`model` などの運用上必要な項目に加え、利用可能であれば `agentOutput` やトップレベルの `session_id` を含みます。`verbose: true` を指定すると、`startTime`、`workFolder`、`prompt` などの完全なメタデータや、`agentOutput.tools` のような詳細な解析結果を含む full 形を返します。
252
+
243
253
  **引数:**
244
254
  - `pids` (array of numbers, 必須): 待機するプロセスIDのリスト(`run` ツールから返されたもの)。
245
255
  - `timeout` (number, 任意): 最大待機時間(秒)。デフォルトは180秒(3分)です。
256
+ - `verbose` (boolean, 任意): `true` の場合、各結果項目を full 形で返します。デフォルトは `false` です。
246
257
 
247
258
  ### `list_processes`
248
259
 
@@ -252,8 +263,11 @@ Claude CLI、Codex CLI、またはGemini CLIを使用してプロンプトを実
252
263
 
253
264
  PIDを指定して、AIエージェントプロセスの現在の出力とステータスを取得します。
254
265
 
266
+ デフォルトでは compact 形を返します。これには `pid`、`agent`、`status`、`exitCode`、`model` などの運用上必要な項目に加え、利用可能であれば `agentOutput` やトップレベルの `session_id` を含みます。`startTime`、`workFolder`、`prompt` は含みません。`verbose: true` を指定すると、これらのメタデータや `agentOutput.tools` のような詳細な解析結果を含む full 形を返します。解析結果が得られない場合や不完全な場合は、従来どおり `stdout` / `stderr` のフォールバックを維持します。
267
+
255
268
  **引数:**
256
269
  - `pid` (number, 必須): `run` ツールによって返されたプロセスID。
270
+ - `verbose` (boolean, 任意): `true` の場合、full 形で返します。デフォルトは `false` です。
257
271
 
258
272
  ### `kill_process`
259
273
 
@@ -296,6 +310,7 @@ npm run test:e2e
296
310
  - `CLAUDE_CLI_NAME`: Claude CLIのバイナリ名または絶対パスを上書き(デフォルト: `claude`)
297
311
  - `CODEX_CLI_NAME`: Codex CLIのバイナリ名または絶対パスを上書き(デフォルト: `codex`)
298
312
  - `GEMINI_CLI_NAME`: Gemini CLIのバイナリ名または絶対パスを上書き(デフォルト: `gemini`)
313
+ - `FORGE_CLI_NAME`: Forge CLIのバイナリ名または絶対パスを上書き(デフォルト: `forge`)
299
314
  - `MCP_CLAUDE_DEBUG`: デバッグログを有効化(`true` に設定すると詳細な出力が表示されます)
300
315
 
301
316
  **CLI名の指定方法:**
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  > **📦 Package Migration Notice**: This package was formerly `@mkxultra/claude-code-mcp` and has been renamed to `ai-cli-mcp` to reflect its expanded support for multiple AI CLI tools.
9
9
 
10
- An MCP (Model Context Protocol) server that allows running AI CLI tools (Claude, Codex, and Gemini) in background processes with automatic permission handling.
10
+ An MCP (Model Context Protocol) server that allows running AI CLI tools (Claude, Codex, Gemini, and Forge) in background processes with automatic permission handling.
11
11
 
12
12
  Did you notice that Cursor sometimes struggles with complex, multi-step edits or operations? This server, with its powerful unified `run` tool, enables multiple AI agents to handle your coding tasks more effectively.
13
13
 
@@ -22,7 +22,8 @@ This MCP server provides tools that can be used by LLMs to interact with AI CLI
22
22
  - Run Claude CLI with all permissions bypassed (using `--dangerously-skip-permissions`)
23
23
  - Execute Codex CLI with automatic approval mode (using `--full-auto`)
24
24
  - Execute Gemini CLI with automatic approval mode (using `-y`)
25
- - Support multiple AI models: Claude (sonnet, sonnet[1m], opus, opusplan, haiku), Codex (gpt-5.4, gpt-5.3-codex, gpt-5.2-codex, gpt-5.1-codex-mini, gpt-5.1-codex-max, gpt-5.2, gpt-5.1, gpt-5.1-codex, gpt-5-codex, gpt-5-codex-mini, gpt-5), and Gemini (gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview)
25
+ - Execute Forge CLI in non-interactive mode (using `forge -C <workFolder> -p <prompt>`)
26
+ - Support multiple AI models: Claude (sonnet, sonnet[1m], opus, opusplan, haiku), Codex (gpt-5.4, gpt-5.3-codex, gpt-5.2-codex, gpt-5.1-codex-mini, gpt-5.1-codex-max, gpt-5.2, gpt-5.1, gpt-5.1-codex, gpt-5-codex, gpt-5-codex-mini, gpt-5), Gemini (gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview), and Forge (`forge`)
26
27
  - Manage background processes with PID tracking
27
28
  - Parse and return structured outputs from both tools
28
29
 
@@ -54,7 +55,7 @@ You can reuse heavy context (like large codebases) using session IDs to save cos
54
55
 
55
56
  - **True Async Multitasking**: Agent execution happens in the background, returning control immediately. The calling AI can proceed with the next task or invoke another agent without waiting for completion.
56
57
  - **CLI in CLI (Agent in Agent)**: Directly invoke powerful CLI tools like Claude Code or Codex from any MCP-supported IDE or CLI. This enables broader, more complex system operations and automation beyond host environment limitations.
57
- - **Freedom from Model/Provider Constraints**: Freely select and combine the "strongest" or "most cost-effective" models from Claude, Codex (GPT), and Gemini without being tied to a specific ecosystem.
58
+ - **Freedom from Model/Provider Constraints**: Freely select and combine the "strongest" or "most cost-effective" models from Claude, Codex (GPT), Gemini, and Forge without being tied to a specific ecosystem.
58
59
 
59
60
  ## Prerequisites
60
61
 
@@ -63,6 +64,7 @@ The only prerequisite is that the AI CLI tools you want to use are locally insta
63
64
  - **Claude Code**: `claude doctor` passes, and execution with `--dangerously-skip-permissions` is approved (you must run it manually once to login and accept terms).
64
65
  - **Codex CLI** (Optional): Installed and initial setup (login etc.) completed.
65
66
  - **Gemini CLI** (Optional): Installed and initial setup (login etc.) completed.
67
+ - **Forge CLI** (Optional): Installed and initial setup completed.
66
68
 
67
69
  ## Installation & Usage
68
70
 
@@ -114,7 +116,9 @@ ai-cli models
114
116
  ai-cli run --cwd "$PWD" --model sonnet --prompt "summarize this repository"
115
117
  ai-cli ps
116
118
  ai-cli result 12345
119
+ ai-cli result 12345 --verbose
117
120
  ai-cli wait 12345 --timeout 300
121
+ ai-cli wait 12345 --verbose
118
122
  ai-cli kill 12345
119
123
  ai-cli cleanup
120
124
  ai-cli-mcp
@@ -181,7 +185,9 @@ ai-cli models
181
185
  ai-cli run --cwd "$PWD" --model codex-ultra --prompt "fix failing tests"
182
186
  ai-cli ps
183
187
  ai-cli wait 12345
188
+ ai-cli wait 12345 --verbose
184
189
  ai-cli result 12345
190
+ ai-cli result 12345 --verbose
185
191
  ai-cli cleanup
186
192
  ```
187
193
 
@@ -221,7 +227,7 @@ This server exposes the following tools:
221
227
 
222
228
  ### `run`
223
229
 
224
- Executes a prompt using Claude CLI, Codex CLI, or Gemini CLI. The appropriate CLI is automatically selected based on the model name.
230
+ Executes a prompt using Claude CLI, Codex CLI, Gemini CLI, or Forge CLI. The appropriate CLI is automatically selected based on the model name.
225
231
 
226
232
  **Arguments:**
227
233
  - `prompt` (string, optional): The prompt to send to the AI agent. Either `prompt` or `prompt_file` is required.
@@ -232,16 +238,20 @@ Executes a prompt using Claude CLI, Codex CLI, or Gemini CLI. The appropriate CL
232
238
  - Claude: `sonnet`, `sonnet[1m]`, `opus`, `opusplan`, `haiku`
233
239
  - Codex: `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
234
240
  - Gemini: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3.1-pro-preview`, `gemini-3-pro-preview`, `gemini-3-flash-preview`
235
- - `reasoning_effort` (string, optional): Reasoning control for Claude and Codex. Claude uses `--effort` (allowed: "low", "medium", "high"). Codex uses `model_reasoning_effort` (allowed: "low", "medium", "high", "xhigh").
236
- - `session_id` (string, optional): Optional session ID to resume a previous session. Supported for: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview.
241
+ - Forge: `forge`
242
+ - `reasoning_effort` (string, optional): Reasoning control for Claude and Codex. Claude uses `--effort` (allowed: "low", "medium", "high"). Codex uses `model_reasoning_effort` (allowed: "low", "medium", "high", "xhigh"). Forge does not support `reasoning_effort`.
243
+ - `session_id` (string, optional): Optional session ID to resume a previous session. Supported for: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3.1-pro-preview, gemini-3-pro-preview, gemini-3-flash-preview, forge.
237
244
 
238
245
  ### `wait`
239
246
 
240
247
  Waits for multiple AI agent processes to complete and returns their combined results. Blocks until all specified PIDs finish or a timeout occurs.
241
248
 
249
+ By default, each returned result item uses the compact shape shared with `get_result(verbose: false)`: operational fields such as `pid`, `agent`, `status`, `exitCode`, `model`, parsed output such as `agentOutput`, and top-level `session_id` when available. Set `verbose: true` to include full metadata like `startTime`, `workFolder`, `prompt`, and detailed parsed output such as `agentOutput.tools`.
250
+
242
251
  **Arguments:**
243
252
  - `pids` (array of numbers, required): List of process IDs to wait for (returned by the `run` tool).
244
253
  - `timeout` (number, optional): Maximum wait time in seconds. Defaults to 180 (3 minutes).
254
+ - `verbose` (boolean, optional): If `true`, each result item uses the full result shape. Defaults to `false`.
245
255
 
246
256
  ### `list_processes`
247
257
 
@@ -251,8 +261,11 @@ Lists all running and completed AI agent processes with their status, PID, and b
251
261
 
252
262
  Gets the current output and status of an AI agent process by PID.
253
263
 
264
+ By default, this returns the compact result shape: operational fields such as `pid`, `agent`, `status`, `exitCode`, `model`, parsed output such as `agentOutput`, and top-level `session_id` when available. It omits metadata fields like `startTime`, `workFolder`, and `prompt`. Set `verbose: true` to return the full result shape including those metadata fields and detailed parsed output such as `agentOutput.tools`. If parsed output is unavailable or incomplete, the raw `stdout`/`stderr` fallback is preserved.
265
+
254
266
  **Arguments:**
255
267
  - `pid` (number, required): The process ID returned by the `run` tool.
268
+ - `verbose` (boolean, optional): If `true`, returns the full result shape. Defaults to `false`.
256
269
 
257
270
  ### `kill_process`
258
271
 
@@ -281,6 +294,7 @@ Normally not required, but useful for customizing CLI paths or debugging.
281
294
  - `CLAUDE_CLI_NAME`: Override the Claude CLI binary name or provide an absolute path (default: `claude`)
282
295
  - `CODEX_CLI_NAME`: Override the Codex CLI binary name or provide an absolute path (default: `codex`)
283
296
  - `GEMINI_CLI_NAME`: Override the Gemini CLI binary name or provide an absolute path (default: `gemini`)
297
+ - `FORGE_CLI_NAME`: Override the Forge CLI binary name or provide an absolute path (default: `forge`)
284
298
  - `MCP_CLAUDE_DEBUG`: Enable debug logging (set to `true` for verbose output)
285
299
 
286
300
  **CLI Name Specification:**
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { CLI_HELP_TEXT, DOCTOR_HELP_TEXT, MODELS_HELP_TEXT, RUN_HELP_TEXT, WAIT_HELP_TEXT, runCli, } from '../app/cli.js';
2
+ import { CLI_HELP_TEXT, DOCTOR_HELP_TEXT, MODELS_HELP_TEXT, RESULT_HELP_TEXT, RUN_HELP_TEXT, WAIT_HELP_TEXT, runCli, } from '../app/cli.js';
3
3
  describe('ai-cli app', () => {
4
4
  it('prints help and exits successfully when no subcommand is provided', async () => {
5
5
  const stdout = vi.fn();
@@ -108,9 +108,21 @@ describe('ai-cli app', () => {
108
108
  waitForProcesses,
109
109
  });
110
110
  expect(exitCode).toBe(0);
111
- expect(waitForProcesses).toHaveBeenCalledWith([123, 456], 5);
111
+ expect(waitForProcesses).toHaveBeenCalledWith([123, 456], 5, false);
112
112
  expect(stdout).toHaveBeenCalledWith(expect.stringContaining('"status": "completed"'));
113
113
  });
114
+ it('passes verbose through to wait', async () => {
115
+ const stdout = vi.fn();
116
+ const stderr = vi.fn();
117
+ const waitForProcesses = vi.fn().mockResolvedValue([{ pid: 123, status: 'completed' }]);
118
+ const exitCode = await runCli(['wait', '123', '--verbose'], {
119
+ stdout,
120
+ stderr,
121
+ waitForProcesses,
122
+ });
123
+ expect(exitCode).toBe(0);
124
+ expect(waitForProcesses).toHaveBeenCalledWith([123], undefined, true);
125
+ });
114
126
  it('rejects invalid wait timeout values', async () => {
115
127
  const stdout = vi.fn();
116
128
  const stderr = vi.fn();
@@ -172,6 +184,7 @@ describe('ai-cli app', () => {
172
184
  expect(stdout).toHaveBeenCalledWith(expect.stringContaining('"aliases"'));
173
185
  expect(stdout).toHaveBeenCalledWith(expect.stringContaining('"claude-ultra"'));
174
186
  expect(stdout).toHaveBeenCalledWith(expect.stringContaining('"gpt-5.4"'));
187
+ expect(stdout).toHaveBeenCalledWith(expect.stringContaining('"forge"'));
175
188
  expect(stderr).not.toHaveBeenCalled();
176
189
  });
177
190
  it('prints doctor status as structured json', async () => {
@@ -196,6 +209,12 @@ describe('ai-cli app', () => {
196
209
  available: true,
197
210
  lookup: 'path',
198
211
  },
212
+ forge: {
213
+ configuredCommand: 'forge',
214
+ resolvedPath: '/tmp/bin/forge',
215
+ available: true,
216
+ lookup: 'path',
217
+ },
199
218
  });
200
219
  const exitCode = await runCli(['doctor'], { stdout, stderr, getDoctorStatus });
201
220
  expect(exitCode).toBe(0);
@@ -221,6 +240,17 @@ describe('ai-cli app', () => {
221
240
  expect(stdout).toHaveBeenCalledWith(expect.stringContaining('claude-ultra'));
222
241
  expect(stdout).toHaveBeenCalledWith(expect.stringContaining('gpt-5.2-codex'));
223
242
  expect(stdout).toHaveBeenCalledWith(expect.stringContaining('gemini-2.5-pro'));
243
+ expect(stdout).toHaveBeenCalledWith(expect.stringContaining('forge'));
244
+ expect(stderr).not.toHaveBeenCalled();
245
+ });
246
+ it('prints detailed help for result --help', async () => {
247
+ const stdout = vi.fn();
248
+ const stderr = vi.fn();
249
+ const exitCode = await runCli(['result', '--help'], { stdout, stderr });
250
+ expect(exitCode).toBe(0);
251
+ expect(stdout).toHaveBeenCalledWith(RESULT_HELP_TEXT);
252
+ expect(stdout).toHaveBeenCalledWith(expect.stringContaining('compact result shape'));
253
+ expect(stdout).toHaveBeenCalledWith(expect.stringContaining('--verbose'));
224
254
  expect(stderr).not.toHaveBeenCalled();
225
255
  });
226
256
  it('prints detailed help for wait --help', async () => {
@@ -229,6 +259,8 @@ describe('ai-cli app', () => {
229
259
  const exitCode = await runCli(['wait', '--help'], { stdout, stderr });
230
260
  expect(exitCode).toBe(0);
231
261
  expect(stdout).toHaveBeenCalledWith(WAIT_HELP_TEXT);
262
+ expect(stdout).toHaveBeenCalledWith(expect.stringContaining('compact shape'));
263
+ expect(stdout).toHaveBeenCalledWith(expect.stringContaining('--verbose'));
232
264
  expect(stderr).not.toHaveBeenCalled();
233
265
  });
234
266
  it('prints detailed help for models --help', async () => {
@@ -25,6 +25,7 @@ describe('ai-cli entrypoint smoke', () => {
25
25
  writeExecutable(fakeBinDir, 'claude');
26
26
  writeExecutable(fakeBinDir, 'codex');
27
27
  writeExecutable(fakeBinDir, 'gemini');
28
+ writeExecutable(fakeBinDir, 'forge');
28
29
  const output = execFileSync('node', ['--import', 'tsx', 'src/bin/ai-cli.ts', 'doctor'], {
29
30
  cwd: process.cwd(),
30
31
  encoding: 'utf8',
@@ -34,11 +35,13 @@ describe('ai-cli entrypoint smoke', () => {
34
35
  CLAUDE_CLI_NAME: 'claude',
35
36
  CODEX_CLI_NAME: 'codex',
36
37
  GEMINI_CLI_NAME: 'gemini',
38
+ FORGE_CLI_NAME: 'forge',
37
39
  },
38
40
  });
39
41
  expect(output).toContain('"claude"');
40
42
  expect(output).toContain('"codex"');
41
43
  expect(output).toContain('"gemini"');
44
+ expect(output).toContain('"forge"');
42
45
  expect(output).toContain('"available": true');
43
46
  });
44
47
  it('prints run help for the ai-cli entrypoint', () => {
@@ -50,5 +53,6 @@ describe('ai-cli entrypoint smoke', () => {
50
53
  expect(output).toContain('Usage: ai-cli run --cwd <path> [options]');
51
54
  expect(output).toContain('--model <model>');
52
55
  expect(output).toContain('claude-ultra');
56
+ expect(output).toContain('forge');
53
57
  });
54
58
  });
@@ -14,6 +14,7 @@ const DEFAULT_CLI_PATHS = {
14
14
  claude: '/usr/bin/claude',
15
15
  codex: '/usr/bin/codex',
16
16
  gemini: '/usr/bin/gemini',
17
+ forge: '/usr/bin/forge',
17
18
  };
18
19
  describe('cli-builder', () => {
19
20
  beforeEach(() => {
@@ -70,6 +71,9 @@ describe('cli-builder', () => {
70
71
  it('should throw for unsupported model families', () => {
71
72
  expect(() => getReasoningEffort('gemini-2.5-pro', 'high')).toThrow('reasoning_effort is only supported for Claude and Codex models.');
72
73
  });
74
+ it('should reject reasoning_effort for forge explicitly', () => {
75
+ expect(() => getReasoningEffort('forge', 'high')).toThrow('reasoning_effort is not supported for forge.');
76
+ });
73
77
  });
74
78
  describe('buildCliCommand', () => {
75
79
  describe('validation', () => {
@@ -322,5 +326,38 @@ describe('cli-builder', () => {
322
326
  expect(cmd.resolvedModel).toBe('gemini-3.1-pro-preview');
323
327
  });
324
328
  });
329
+ describe('forge agent', () => {
330
+ it('should build forge command without model flags', () => {
331
+ const cmd = buildCliCommand({
332
+ prompt: 'test',
333
+ workFolder: '/tmp',
334
+ model: 'forge',
335
+ cliPaths: DEFAULT_CLI_PATHS,
336
+ });
337
+ expect(cmd.agent).toBe('forge');
338
+ expect(cmd.cliPath).toBe('/usr/bin/forge');
339
+ expect(cmd.resolvedModel).toBe('forge');
340
+ expect(cmd.args).toEqual(['-C', '/tmp', '-p', 'test']);
341
+ });
342
+ it('should map session_id to --conversation-id for forge', () => {
343
+ const cmd = buildCliCommand({
344
+ prompt: 'test',
345
+ workFolder: '/tmp',
346
+ model: 'forge',
347
+ session_id: 'forge-conv-123',
348
+ cliPaths: DEFAULT_CLI_PATHS,
349
+ });
350
+ expect(cmd.args).toEqual(['-C', '/tmp', '--conversation-id', 'forge-conv-123', '-p', 'test']);
351
+ });
352
+ it('should reject reasoning_effort for forge in command building', () => {
353
+ expect(() => buildCliCommand({
354
+ prompt: 'test',
355
+ workFolder: '/tmp',
356
+ model: 'forge',
357
+ reasoning_effort: 'high',
358
+ cliPaths: DEFAULT_CLI_PATHS,
359
+ })).toThrow('reasoning_effort is not supported for forge.');
360
+ });
361
+ });
325
362
  });
326
363
  });