CLI backends (fallback runtime)
OpenClaw 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, with Claude CLI partial text streaming when enabled).
- Sessions are supported (so follow-up turns stay coherent).
- Images can be passed through if the CLI accepts image paths.
Beginner-friendly quick start
You can use Claude CLI without any config (the bundled Anthropic plugin registers a default backend):agents.defaults.cliBackends.
Using it as a fallback
Add a CLI backend to your fallback list so it only runs when primary models fail:- If you use
agents.defaults.models(allowlist), you must includeclaude-cli/.... - If the primary provider fails (auth, rate limits, timeouts), OpenClaw will try the CLI backend next.
- The bundled Claude CLI backend still accepts shorter aliases like
claude-cli/opus,claude-cli/opus-4.6, orclaude-cli/sonnet, but docs and config examples use the canonicalclaude-cli/claude-*refs.
Configuration overview
All CLI backends live under:claude-cli, my-cli).
The provider id becomes the left side of your model ref:
Example configuration
How it works
- Selects a backend based on the provider prefix (
claude-cli/...). - Builds a system prompt using the same OpenClaw prompt + workspace context.
- Executes the CLI with a session id (if supported) so history stays consistent.
- Parses output (JSON or plain text) and returns the final text.
- 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) orsessionArgs(placeholder{sessionId}) when the ID needs to be inserted into multiple flags. - If the CLI uses a resume subcommand with different flags, set
resumeArgs(replacesargswhen resuming) and optionallyresumeOutput(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.
serialize: truekeeps same-lane runs ordered.- Most CLIs serialize on one provider lane.
claude-cliis narrower: resumed runs serialize per Claude session id, and fresh runs serialize per workspace path. Independent workspaces can run in parallel.
Images (pass-through)
If your CLI accepts image paths, setimageArg:
imageArg is set, those
paths are passed as CLI args. If imageArg is missing, OpenClaw appends the
file paths to the prompt (path injection), which is enough for CLIs that auto-
load local files from plain paths (Claude CLI behavior).
Inputs / outputs
output: "json"(default) tries to parse JSON and extract text + session id.- For Gemini CLI JSON output, OpenClaw reads reply text from
responseand usage fromstatswhenusageis missing or empty. output: "jsonl"parses JSONL streams (for example Claude CLIstream-jsonand Codex CLI--json) and extracts the final agent message plus session identifiers when present.output: "text"treats stdout as the final response.
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
maxPromptArgCharsis set, stdin is used.
Defaults (plugin-owned)
The bundled Anthropic plugin registers a default forclaude-cli:
command: "claude"args: ["-p", "--output-format", "stream-json", "--include-partial-messages", "--verbose", "--permission-mode", "bypassPermissions"]resumeArgs: ["-p", "--output-format", "stream-json", "--include-partial-messages", "--verbose", "--permission-mode", "bypassPermissions", "--resume", "{sessionId}"]output: "jsonl"input: "stdin"modelArg: "--model"systemPromptArg: "--append-system-prompt"sessionArg: "--session-id"systemPromptWhen: "first"sessionMode: "always"
codex-cli:
command: "codex"args: ["exec","--json","--color","never","--sandbox","workspace-write","--skip-git-repo-check"]resumeArgs: ["exec","resume","{sessionId}","--color","never","--sandbox","workspace-write","--skip-git-repo-check"]output: "jsonl"resumeOutput: "text"modelArg: "--model"imageArg: "--image"sessionMode: "existing"
google-gemini-cli:
command: "gemini"args: ["--prompt", "--output-format", "json"]resumeArgs: ["--resume", "{sessionId}", "--prompt", "--output-format", "json"]modelArg: "--model"sessionMode: "existing"sessionIdFields: ["session_id", "sessionId"]
gemini on PATH (brew install gemini-cli or
npm install -g @google/gemini-cli).
Gemini CLI JSON notes:
- Reply text is read from the JSON
responsefield. - Usage falls back to
statswhenusageis absent or empty. stats.cachedis normalized into OpenClawcacheRead.- If
stats.inputis missing, OpenClaw derives input tokens fromstats.input_tokens - stats.cached.
command path).
Plugin-owned defaults
CLI backend defaults are now part of the plugin surface:- Plugins register them with
api.registerCliBackend(...). - The backend
idbecomes the provider prefix in model refs. - User config in
agents.defaults.cliBackends.<id>still overrides the plugin default. - Backend-specific config cleanup stays plugin-owned through the optional
normalizeConfighook.
Bundle MCP overlays
CLI backends still do not receive OpenClaw tool calls, but a backend can opt into a generated MCP config overlay withbundleMcp: true.
Current bundled behavior:
claude-cli:bundleMcp: truecodex-cli: no bundle MCP overlaygoogle-gemini-cli: no bundle MCP overlay
- loads enabled bundle-MCP servers for the current workspace
- merges them with any existing backend
--mcp-config - rewrites the CLI args to pass
--strict-mcp-config --mcp-config <generated-file>
Limitations
- No OpenClaw tools (the CLI backend never receives tool calls). Some CLIs
may still run their own agent tooling. Backends with
bundleMcp: truecan still receive a generated MCP config overlay for their own CLI-native MCP support. - Streaming is backend-specific. Claude CLI forwards partial text from
stream-json; other CLI backends may still be buffered until exit. - 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
--jsonrun. OpenClaw sessions still work normally.
Troubleshooting
- CLI not found: set
commandto a full path. - Wrong model name: use
modelAliasesto mapprovider/model→ CLI model. - No session continuity: ensure
sessionArgis set andsessionModeis notnone(Codex CLI currently cannot resume with JSON output). - Images ignored: set
imageArg(and verify CLI supports file paths).