Files
stef-openclaw-skills/tools/ai-cli-dispatch/SKILL.md
T

203 lines
6.8 KiB
Markdown

---
name: ai-cli-dispatch
description: Dispatch AI CLI coding tasks to available clients (Codex, Claude Code, OpenCode) with automatic discovery, version checking, and execution.
metadata: {"clawdbot":{"emoji":"robot","requires":{"bins":["node"]}}}
---
# AI CLI Dispatch
Use this skill when the user wants to run a coding task through an AI CLI client such as Codex, Claude Code, or OpenCode.
The skill discovers installed clients, resolves versions, selects the best available tool, and forwards the task with arguments intact.
Use the local helper from the installed skill directory:
```bash
cd ~/.openclaw/workspace/skills/ai-cli-dispatch
scripts/ai-cli-dispatch --help
```
## Setup
```bash
cd ~/.openclaw/workspace/skills/ai-cli-dispatch
npm install
```
## Commands
### `list`
Discover and report all supported clients.
```bash
scripts/ai-cli-dispatch list --json
scripts/ai-cli-dispatch list --text
```
### `start` — start a background job
Starts a detached background job and returns immediately with a job ID.
```bash
scripts/ai-cli-dispatch start --client codex --prompt "refactor this function"
scripts/ai-cli-dispatch start --client claude --prompt "add tests for auth middleware"
```
### `run` — run a task (async by default)
Runs a prompt through a named client. By default this is **async**: it starts a background job and returns the job ID immediately. Use `--sync` to block until the client finishes and return the full result.
```bash
# Async (default) — returns job ID immediately
scripts/ai-cli-dispatch run --client codex --prompt "refactor this function"
scripts/ai-cli-dispatch run --client claude --prompt "add tests for auth middleware"
scripts/ai-cli-dispatch run --client opencode --prompt "migrate to ESM"
# Sync — blocks until completion and returns stdout/stderr/exitCode
scripts/ai-cli-dispatch run --client codex --prompt "fix lint errors" --sync
```
### `dispatch` — auto-resolve client and run (async by default)
Auto-resolves the client from prompt keywords, then executes. By default this is **async**. Use `--sync` to block until completion.
```bash
# Async (default)
scripts/ai-cli-dispatch dispatch "use codex to write tests"
scripts/ai-cli-dispatch dispatch "claude: add unit tests for utils.ts"
scripts/ai-cli-dispatch dispatch "opencode migrate to ESM"
# Sync
scripts/ai-cli-dispatch dispatch "review this PR" --client claude --sync
```
### Job lifecycle commands
After starting an async job, manage it with these subcommands:
```bash
# Check job status
scripts/ai-cli-dispatch status <job-id>
# Get results (only when status is completed)
scripts/ai-cli-dispatch results <job-id>
# Cancel a running job
scripts/ai-cli-dispatch cancel <job-id>
# List all jobs, newest first
scripts/ai-cli-dispatch list-jobs --json
scripts/ai-cli-dispatch list-jobs --status running --json
# Clean up old job files
scripts/ai-cli-dispatch cleanup-jobs --max-age 24h
```
## Async vs Sync Mode
The dispatcher is **async-first**: `run` and `dispatch` start a detached background job unless you pass `--sync`.
| Mode | Behavior | When to use |
|---|---|---|
| **Async** (default) | Starts a detached process, returns a `jobId` immediately, and stores output on disk. | Fire-and-forget tasks, long-running jobs, parallel dispatches, or when you need to poll/check results later. |
| **Sync** (`--sync`) | Blocks until the client subprocess exits, then returns `stdout`, `stderr`, and `exitCode` directly. | Short, interactive tasks where you need the result in the same turn. |
Use `--timeout <ms>` to control how long a job may run before it is terminated (default: 10 minutes for async, 5 minutes for sync). Use `--debug` to emit diagnostic metadata to stderr.
## Flags
| Flag | Description |
|---|---|
| `--sync` | Run synchronously and block until the client returns. Default is async (starts a background job). |
| `--timeout <ms>` | Timeout in milliseconds. Overrides the default and any config value. |
| `--debug` | Emit diagnostic JSON to stderr (command, args, PID, duration, exit signal). |
| `--json` | Output JSON (default). |
| `--text` | Output plain text instead of JSON. |
| `--client <name>` | Explicitly set the client (`codex`, `claude`, `opencode`). |
| `--prompt <text>` | The prompt to send to the client. |
| `--status <status>` | Filter `list-jobs` by status (`running`, `completed`, `failed`). |
| `--max-age <number>[h\|m\|s\|d]` | Maximum age for `cleanup-jobs` (default unit: hours). |
## Client Discovery
The skill searches for the following clients in order:
- `codex` — OpenAI Codex CLI
- `claude` — Anthropic Claude Code
- `opencode` — OpenCode CLI
Run `list` to see which clients are installed and their resolved versions.
## Job Lifecycle & Storage
Async jobs run as detached child processes. Each job writes a record to disk at:
```text
~/.openclaw/ai-cli-dispatch/jobs/<jobId>.json
```
A job moves through the following statuses:
| Status | Meaning |
|---|---|
| `running` | The client subprocess is active. |
| `completed` | The subprocess exited with code 0. |
| `failed` | The subprocess exited with a non-zero code. |
| `timed_out` | The job exceeded `--timeout` and was terminated. |
| `cancelled` | The job was cancelled via `cancel <job-id>`. |
Example async workflow:
```bash
# 1. Start a job
scripts/ai-cli-dispatch run --client codex --prompt "refactor auth module"
# → { "jobId": "a1b2c3d4...", "client": "codex", "status": "running" }
# 2. Poll status
scripts/ai-cli-dispatch status a1b2c3d4...
# → { "id": "a1b2c3d4...", "status": "running", ... }
# 3. Get results when done
scripts/ai-cli-dispatch results a1b2c3d4...
# → { "stdout": "...", "stderr": "...", "exitCode": 0, "client": "codex", "durationMs": 42000 }
```
## Background Jobs (Programmatic API)
For long-running or fire-and-forget tasks, use the programmatic job API:
```typescript
import { startJob, getJob, getJobResult, cancelJob, listJobs, cleanupJobs } from "./src/jobs.js";
// Start a detached job
const job = await startJob("codex", "refactor auth module", { timeoutMs: 300_000 });
console.log(job.id); // e.g. "a1b2c3d4..."
console.log(job.status); // "running"
// Poll for completion
const latest = getJob(job.id);
console.log(latest.status); // "running" | "completed" | "failed" | "timed_out" | "cancelled"
// Get result (throws if not completed)
const result = getJobResult(job.id);
console.log(result.stdout, result.exitCode);
// Cancel a running job
cancelJob(job.id);
// List all jobs (newest first)
const jobs = listJobs(); // Job[]
const running = listJobs({ filter: "running" });
// Clean up job files older than 24 hours (default)
cleanupJobs({ maxAgeMs: 24 * 60 * 60 * 1000 });
```
Job files include stdout, stderr, exit code, timing, and error state.
## Output Rules
- Normal JSON output redacts local file paths and credential metadata.
- Use `--debug` only when deeper troubleshooting requires internal paths and resolved config metadata.