diff --git a/docs/ai-cli-dispatch.md b/docs/ai-cli-dispatch.md new file mode 100644 index 0000000..66928ef --- /dev/null +++ b/docs/ai-cli-dispatch.md @@ -0,0 +1,258 @@ +# ai-cli-dispatch + +Dispatch AI CLI coding tasks to available clients (Codex, Claude Code, OpenCode) with automatic discovery, version checking, and execution. + +## Scope + +- discover installed AI CLI clients on the host +- report client versions and availability +- dispatch a prompt to a specific client by name +- auto-resolve the best client from prompt keywords +- forward arguments natively to each client + +The tool is a lightweight sync-only dispatcher. It does not implement streaming, chat sessions, or ACP orchestration. For ACP-based harnesses, see `docs/openclaw-acp-orchestration.md`. + +## Setup + +From the repo or installed skill directory: + +```bash +cd tools/ai-cli-dispatch +npm install +``` + +The dispatcher itself requires only Node.js 20+ and `npm`. The actual AI CLI clients (`codex`, `claude`, `opencode`) are discovered from the host `PATH`; they are not bundled. + +## Commands + +```bash +ai-cli-dispatch list [--json|--text] +ai-cli-dispatch run --client --prompt [--json|--text] +ai-cli-dispatch dispatch [--client ] [--json|--text] +ai-cli-dispatch --help +``` + +### `list` + +Discover and report all supported clients. + +```bash +ai-cli-dispatch list --json +``` + +Example JSON output: + +```json +[ + { + "name": "codex", + "path": "/usr/local/bin/codex", + "version": "1.2.3", + "found": true + }, + { + "name": "claude", + "found": false + }, + { + "name": "opencode", + "path": "/opt/homebrew/bin/opencode", + "version": "0.5.1", + "found": true + } +] +``` + +Use `--text` for human-readable checkmarks: + +```bash +ai-cli-dispatch list --text +``` + +### `run` + +Execute a prompt directly through a named client. + +```bash +ai-cli-dispatch run --client codex --prompt "refactor this function" +ai-cli-dispatch run --client claude --prompt "add tests for auth middleware" +ai-cli-dispatch run --client opencode --prompt "migrate to ESM" +``` + +The prompt is forwarded with each client’s native argument shape: + +| Client | Arguments passed | +|---|---| +| `codex` | `exec ""` | +| `claude` | `-p ""` | +| `opencode` | `""` | + +### `dispatch` + +Auto-resolve the client from prompt keywords, then execute. + +```bash +ai-cli-dispatch dispatch "use claude to write tests" +ai-cli-dispatch dispatch "codex refactor auth module" +ai-cli-dispatch dispatch "opencode migrate to ESM" +``` + +Keyword matching is case-insensitive and ordered: + +1. `--client` flag (highest precedence) +2. `"open code"` (spaced variant) → `opencode` +3. `"claude"` → `claude` +4. `"codex"` → `codex` +5. `"opencode"` → `opencode` +6. `defaultClient` from config (lowest precedence) + +Override auto-resolution explicitly: + +```bash +ai-cli-dispatch dispatch "fix the bug" --client claude +``` + +## Client Discovery + +Discovery searches `PATH` in this order for each client name: + +1. `codex` — OpenAI Codex CLI +2. `claude` — Anthropic Claude Code +3. `opencode` — OpenCode CLI + +The search uses `which` (or `where` on Windows) first, then falls back to a manual `PATH` directory scan. If a binary is found, `--version` is invoked to extract a semver string. + +## Configuration + +Optional config file: + +```text +~/.openclaw/ai-cli-dispatch.json +``` + +Example: + +```json +{ + "paths": { + "codex": "/usr/local/bin/codex", + "claude": "/opt/homebrew/bin/claude" + }, + "defaultClient": "claude" +} +``` + +Resolution priority for paths and default client (highest to lowest): + +1. CLI flag (`--client`, `--codex-path`, etc.) +2. Environment variable (`AI_CLI_CODEX_PATH`, `AI_CLI_DEFAULT_CLIENT`, etc.) +3. Config file (`paths`, `defaultClient`) +4. `which` / `where` discovery + +Supported env vars: + +| Variable | Purpose | +|---|---| +| `AI_CLI_CODEX_PATH` | Override `codex` binary path | +| `AI_CLI_CLAUDE_PATH` | Override `claude` binary path | +| `AI_CLI_OPENCODE_PATH` | Override `opencode` binary path | +| `AI_CLI_DEFAULT_CLIENT` | Override default client (`codex`, `claude`, or `opencode`) | + +## Output Model + +Default output is JSON. Use `--text` to stream raw `stdout`/`stderr` directly. + +JSON success shape (`run` and `dispatch`): + +```json +{ + "stdout": "...", + "stderr": "...", + "exitCode": 0 +} +``` + +JSON error shape: + +```json +{ + "error": "..." +} +``` + +Exit codes: + +| Code | Meaning | +|---|---| +| `0` | Success | +| `1` | Missing/unknown command, missing argument, unknown client, resolution failure, or execution error | + +## Error Handling Guidance + +### `Client "" not found or not installed` + +Meaning: the requested client binary is not on `PATH` and not overridden by config. + +Actions: + +1. Confirm the client is installed (`codex --version`, `claude --version`, etc.) +2. Check that its directory is on `PATH` +3. Or override the path in `~/.openclaw/ai-cli-dispatch.json` + +### `Prompt cannot be empty` + +Meaning: the prompt string was empty or whitespace-only. + +Action: supply a non-empty `--prompt` or positional prompt argument. + +### `Execution timed out after 300000ms` + +Meaning: the client subprocess did not finish within the default 5-minute timeout. + +Action: the client may be waiting for interactive input or the task is too large. Break the prompt into smaller pieces, or run the client directly to diagnose. + +### `Could not resolve client from prompt` + +Meaning: `dispatch` found no matching keyword and no `defaultClient` is configured. + +Action: include a client name in the prompt (e.g., `"use claude to ..."`) or set `defaultClient` in config. + +## Common Flows + +### Check what is installed + +```bash +ai-cli-dispatch list --json +``` + +### Run a quick task through a specific client + +```bash +ai-cli-dispatch run --client codex --prompt "fix lint errors in src/app.ts" +``` + +### Let the tool pick the client from the prompt + +```bash +ai-cli-dispatch dispatch "claude: add unit tests for utils.ts" +``` + +### Force a client when the prompt is ambiguous + +```bash +ai-cli-dispatch dispatch "review this PR" --client claude +``` + +## Coexistence with ACP + +`ai-cli-dispatch` is a direct subprocess dispatcher. It runs the client binary synchronously and returns its output. It is not an ACP agent and does not participate in ACP orchestration. + +- Use `ai-cli-dispatch` when you need a quick, local, one-shot CLI execution. +- Use ACP (`docs/openclaw-acp-orchestration.md`) when you need session-bound coding harnesses with thread context, multi-turn review, or orchestrator-managed verification gates. + +## Implementation Notes + +- The dispatcher is TypeScript/Node.js with a single external dependency (`minimist`). +- Client arguments are hardcoded per tool to match each client’s stable CLI contract. +- The default timeout is 5 minutes (`300_000` ms). +- On Windows, discovery uses `where` instead of `which` and `.exe` extensions are assumed.