{
  "title": "CLI backends (fallback runtime)",
  "content": "OpenClaw can run **local AI CLIs** as a **text-only fallback** when API providers are down,\nrate-limited, or temporarily misbehaving. This is intentionally conservative:\n\n* **Tools are disabled** (no tool calls).\n* **Text in → text out** (reliable).\n* **Sessions are supported** (so follow-up turns stay coherent).\n* **Images can be passed through** if the CLI accepts image paths.\n\nThis is designed as a **safety net** rather than a primary path. Use it when you\nwant “always works” text responses without relying on external APIs.\n\n## Beginner-friendly quick start\n\nYou can use Claude Code CLI **without any config** (OpenClaw ships a built-in default):\n\nCodex CLI also works out of the box:\n\nIf your gateway runs under launchd/systemd and PATH is minimal, add just the\ncommand path:\n\nThat’s it. No keys, no extra auth config needed beyond the CLI itself.\n\n## Using it as a fallback\n\nAdd a CLI backend to your fallback list so it only runs when primary models fail:\n\n* If you use `agents.defaults.models` (allowlist), you must include `claude-cli/...`.\n* If the primary provider fails (auth, rate limits, timeouts), OpenClaw will\n  try the CLI backend next.\n\n## Configuration overview\n\nAll CLI backends live under:\n\nEach entry is keyed by a **provider id** (e.g. `claude-cli`, `my-cli`).\nThe provider id becomes the left side of your model ref:\n\n### Example configuration\n\n1. **Selects a backend** based on the provider prefix (`claude-cli/...`).\n2. **Builds a system prompt** using the same OpenClaw prompt + workspace context.\n3. **Executes the CLI** with a session id (if supported) so history stays consistent.\n4. **Parses output** (JSON or plain text) and returns the final text.\n5. **Persists session ids** per backend, so follow-ups reuse the same CLI session.\n\n* If the CLI supports sessions, set `sessionArg` (e.g. `--session-id`) or\n  `sessionArgs` (placeholder `{sessionId}`) when the ID needs to be inserted\n  into multiple flags.\n* If the CLI uses a **resume subcommand** with different flags, set\n  `resumeArgs` (replaces `args` when resuming) and optionally `resumeOutput`\n  (for non-JSON resumes).\n* `sessionMode`:\n  * `always`: always send a session id (new UUID if none stored).\n  * `existing`: only send a session id if one was stored before.\n  * `none`: never send a session id.\n\n## Images (pass-through)\n\nIf your CLI accepts image paths, set `imageArg`:\n\nOpenClaw will write base64 images to temp files. If `imageArg` is set, those\npaths are passed as CLI args. If `imageArg` is missing, OpenClaw appends the\nfile paths to the prompt (path injection), which is enough for CLIs that auto-\nload local files from plain paths (Claude Code CLI behavior).\n\n* `output: \"json\"` (default) tries to parse JSON and extract text + session id.\n* `output: \"jsonl\"` parses JSONL streams (Codex CLI `--json`) and extracts the\n  last agent message plus `thread_id` when present.\n* `output: \"text\"` treats stdout as the final response.\n\n* `input: \"arg\"` (default) passes the prompt as the last CLI arg.\n* `input: \"stdin\"` sends the prompt via stdin.\n* If the prompt is very long and `maxPromptArgChars` is set, stdin is used.\n\n## Defaults (built-in)\n\nOpenClaw ships a default for `claude-cli`:\n\n* `command: \"claude\"`\n* `args: [\"-p\", \"--output-format\", \"json\", \"--dangerously-skip-permissions\"]`\n* `resumeArgs: [\"-p\", \"--output-format\", \"json\", \"--dangerously-skip-permissions\", \"--resume\", \"{sessionId}\"]`\n* `modelArg: \"--model\"`\n* `systemPromptArg: \"--append-system-prompt\"`\n* `sessionArg: \"--session-id\"`\n* `systemPromptWhen: \"first\"`\n* `sessionMode: \"always\"`\n\nOpenClaw also ships a default for `codex-cli`:\n\n* `command: \"codex\"`\n* `args: [\"exec\",\"--json\",\"--color\",\"never\",\"--sandbox\",\"read-only\",\"--skip-git-repo-check\"]`\n* `resumeArgs: [\"exec\",\"resume\",\"{sessionId}\",\"--color\",\"never\",\"--sandbox\",\"read-only\",\"--skip-git-repo-check\"]`\n* `output: \"jsonl\"`\n* `resumeOutput: \"text\"`\n* `modelArg: \"--model\"`\n* `imageArg: \"--image\"`\n* `sessionMode: \"existing\"`\n\nOverride only if needed (common: absolute `command` path).\n\n* **No OpenClaw tools** (the CLI backend never receives tool calls). Some CLIs\n  may still run their own agent tooling.\n* **No streaming** (CLI output is collected then returned).\n* **Structured outputs** depend on the CLI’s JSON format.\n* **Codex CLI sessions** resume via text output (no JSONL), which is less\n  structured than the initial `--json` run. OpenClaw sessions still work\n  normally.\n\n* **CLI not found**: set `command` to a full path.\n* **Wrong model name**: use `modelAliases` to map `provider/model` → CLI model.\n* **No session continuity**: ensure `sessionArg` is set and `sessionMode` is not\n  `none` (Codex CLI currently cannot resume with JSON output).\n* **Images ignored**: set `imageArg` (and verify CLI supports file paths).",
  "code_samples": [
    {
      "code": "Codex CLI also works out of the box:",
      "language": "unknown"
    },
    {
      "code": "If your gateway runs under launchd/systemd and PATH is minimal, add just the\ncommand path:",
      "language": "unknown"
    },
    {
      "code": "That’s it. No keys, no extra auth config needed beyond the CLI itself.\n\n## Using it as a fallback\n\nAdd a CLI backend to your fallback list so it only runs when primary models fail:",
      "language": "unknown"
    },
    {
      "code": "Notes:\n\n* If you use `agents.defaults.models` (allowlist), you must include `claude-cli/...`.\n* If the primary provider fails (auth, rate limits, timeouts), OpenClaw will\n  try the CLI backend next.\n\n## Configuration overview\n\nAll CLI backends live under:",
      "language": "unknown"
    },
    {
      "code": "Each entry is keyed by a **provider id** (e.g. `claude-cli`, `my-cli`).\nThe provider id becomes the left side of your model ref:",
      "language": "unknown"
    },
    {
      "code": "### Example configuration",
      "language": "unknown"
    },
    {
      "code": "## How it works\n\n1. **Selects a backend** based on the provider prefix (`claude-cli/...`).\n2. **Builds a system prompt** using the same OpenClaw prompt + workspace context.\n3. **Executes the CLI** with a session id (if supported) so history stays consistent.\n4. **Parses output** (JSON or plain text) and returns the final text.\n5. **Persists session ids** per backend, so follow-ups reuse the same CLI session.\n\n## Sessions\n\n* If the CLI supports sessions, set `sessionArg` (e.g. `--session-id`) or\n  `sessionArgs` (placeholder `{sessionId}`) when the ID needs to be inserted\n  into multiple flags.\n* If the CLI uses a **resume subcommand** with different flags, set\n  `resumeArgs` (replaces `args` when resuming) and optionally `resumeOutput`\n  (for non-JSON resumes).\n* `sessionMode`:\n  * `always`: always send a session id (new UUID if none stored).\n  * `existing`: only send a session id if one was stored before.\n  * `none`: never send a session id.\n\n## Images (pass-through)\n\nIf your CLI accepts image paths, set `imageArg`:",
      "language": "unknown"
    }
  ],
  "headings": [
    {
      "level": "h2",
      "text": "Beginner-friendly quick start",
      "id": "beginner-friendly-quick-start"
    },
    {
      "level": "h2",
      "text": "Using it as a fallback",
      "id": "using-it-as-a-fallback"
    },
    {
      "level": "h2",
      "text": "Configuration overview",
      "id": "configuration-overview"
    },
    {
      "level": "h3",
      "text": "Example configuration",
      "id": "example-configuration"
    },
    {
      "level": "h2",
      "text": "How it works",
      "id": "how-it-works"
    },
    {
      "level": "h2",
      "text": "Sessions",
      "id": "sessions"
    },
    {
      "level": "h2",
      "text": "Images (pass-through)",
      "id": "images-(pass-through)"
    },
    {
      "level": "h2",
      "text": "Inputs / outputs",
      "id": "inputs-/-outputs"
    },
    {
      "level": "h2",
      "text": "Defaults (built-in)",
      "id": "defaults-(built-in)"
    },
    {
      "level": "h2",
      "text": "Limitations",
      "id": "limitations"
    },
    {
      "level": "h2",
      "text": "Troubleshooting",
      "id": "troubleshooting"
    }
  ],
  "url": "llms-txt#cli-backends-(fallback-runtime)",
  "links": []
}