--- summary: "CLI backends: text-only fallback via local AI CLIs" read_when: - You want a reliable fallback when API providers fail - You are running Claude Code CLI or other local AI CLIs and want to reuse them - You need a text-only, tool-free path that still supports sessions and images --- # CLI backends (fallback runtime) Clawdbot can run **local AI CLIs** as a **text-only fallback** when API providers are down, rate-limited, or temporarily misbehaving. This is intentionally conservative: - **Tools are disabled** (no tool calls). - **Text in → text out** (reliable). - **Sessions are supported** (so follow-up turns stay coherent). - **Images can be passed through** if the CLI accepts image paths. This is designed as a **safety net** rather than a primary path. Use it when you want “always works” text responses without relying on external APIs. ## Beginner-friendly quick start You can use Claude Code CLI **without any config** (Clawdbot ships a built-in default): ```bash clawdbot agent --message "hi" --model claude-cli/opus-4.5 ``` Codex CLI also works out of the box: ```bash clawdbot agent --message "hi" --model codex-cli/gpt-5.2-codex ``` If your gateway runs under launchd/systemd and PATH is minimal, add just the command path: ```json5 { agents: { defaults: { cliBackends: { "claude-cli": { command: "/opt/homebrew/bin/claude" } } } } } ``` That’s it. No keys, no extra auth config needed beyond the CLI itself. ## Using it as a fallback Add a CLI backend to your fallback list so it only runs when primary models fail: ```json5 { agents: { defaults: { model: { primary: "anthropic/claude-opus-4-5", fallbacks: [ "claude-cli/opus-4.5" ] }, models: { "anthropic/claude-opus-4-5": { alias: "Opus" }, "claude-cli/opus-4.5": {} } } } } ``` Notes: - If you use `agents.defaults.models` (allowlist), you must include `claude-cli/...`. - If the primary provider fails (auth, rate limits, timeouts), Clawdbot will try the CLI backend next. ## Configuration overview All CLI backends live under: ``` agents.defaults.cliBackends ``` Each entry is keyed by a **provider id** (e.g. `claude-cli`, `my-cli`). The provider id becomes the left side of your model ref: ``` / ``` ### Example configuration ```json5 { agents: { defaults: { cliBackends: { "claude-cli": { command: "/opt/homebrew/bin/claude" }, "my-cli": { command: "my-cli", args: ["--json"], output: "json", input: "arg", modelArg: "--model", modelAliases: { "claude-opus-4-5": "opus", "claude-sonnet-4-5": "sonnet" }, sessionArg: "--session", sessionMode: "existing", sessionIdFields: ["session_id", "conversation_id"], systemPromptArg: "--system", systemPromptWhen: "first", imageArg: "--image", imageMode: "repeat", serialize: true } } } } } ``` ## How it works 1) **Selects a backend** based on the provider prefix (`claude-cli/...`). 2) **Builds a system prompt** using the same Clawdbot prompt + workspace context. 3) **Executes the CLI** with a session id (if supported) so history stays consistent. 4) **Parses output** (JSON or plain text) and returns the final text. 5) **Persists session ids** per backend, so follow-ups reuse the same CLI session. ## Sessions - If the CLI supports sessions, set `sessionArg` (e.g. `--session-id`) or `sessionArgs` (placeholder `{sessionId}`) when the ID needs to be inserted into multiple flags. - If the CLI uses a **resume subcommand** with different flags, set `resumeArgs` (replaces `args` when resuming) and optionally `resumeOutput` (for non-JSON resumes). - `sessionMode`: - `always`: always send a session id (new UUID if none stored). - `existing`: only send a session id if one was stored before. - `none`: never send a session id. ## Images (pass-through) If your CLI accepts image paths, set `imageArg`: ```json5 imageArg: "--image", imageMode: "repeat" ``` Clawdbot will write base64 images to temp files. If `imageArg` is set, those paths are passed as CLI args. If `imageArg` is missing, Clawdbot appends the file paths to the prompt (path injection), which is enough for CLIs that auto- load local files from plain paths (Claude Code CLI behavior). ## Inputs / outputs - `output: "json"` (default) tries to parse JSON and extract text + session id. - `output: "jsonl"` parses JSONL streams (Codex CLI `--json`) and extracts the last agent message plus `thread_id` when present. - `output: "text"` treats stdout as the final response. Input modes: - `input: "arg"` (default) passes the prompt as the last CLI arg. - `input: "stdin"` sends the prompt via stdin. - If the prompt is very long and `maxPromptArgChars` is set, stdin is used. ## Defaults (built-in) Clawdbot ships a default for `claude-cli`: - `command: "claude"` - `args: ["-p", "--output-format", "json", "--dangerously-skip-permissions"]` - `modelArg: "--model"` - `systemPromptArg: "--append-system-prompt"` - `sessionArg: "--session-id"` - `systemPromptWhen: "first"` - `sessionMode: "always"` Clawdbot also ships a default for `codex-cli`: - `command: "codex"` - `args: ["exec","--json","--color","never","--sandbox","read-only","--skip-git-repo-check"]` - `resumeArgs: ["exec","resume","{sessionId}","--color","never","--sandbox","read-only","--skip-git-repo-check"]` - `output: "jsonl"` - `resumeOutput: "text"` - `modelArg: "--model"` - `imageArg: "--image"` - `sessionMode: "existing"` Override only if needed (common: absolute `command` path). ## Limitations - **No Clawdbot tools** (the CLI backend never receives tool calls). Some CLIs may still run their own agent tooling. - **No streaming** (CLI output is collected then returned). - **Structured outputs** depend on the CLI’s JSON format. - **Codex CLI sessions** resume via text output (no JSONL), which is less structured than the initial `--json` run. Clawdbot sessions still work normally. ## Troubleshooting - **CLI not found**: set `command` to a full path. - **Wrong model name**: use `modelAliases` to map `provider/model` → CLI model. - **No session continuity**: ensure `sessionArg` is set and `sessionMode` is not `none` (Codex CLI currently cannot resume with JSON output). - **Images ignored**: set `imageArg` (and verify CLI supports file paths).