OpenClawSkills
GitHub
Gateway / Operations β€’ TutorialHeader.readTime

CLI Backends

CLI backends: text-only fallback via local AI CLIs

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:

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.

  • **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.

Use it when you want "always works" text responses without relying on external APIs.

Tutorial.step

Beginner-friendly quick start

You can use Claude Code CLI without any config (OpenClaw ships a built-in default):

Bash
openclaw agent --message "hi" --model claude-cli/opus-4.5

Codex CLI also works out of the box:

Bash
openclaw 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.

Tutorial.step

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), OpenClaw will try the CLI backend next.
Tutorial.step

Configuration overview

All CLI backends live under:

Terminal
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:

Terminal
<provider>/<model>
Tutorial.step

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,
        },
      },
    },
  },
}
Tutorial.step

How it works

  1. Selects a backend based on the provider prefix (claude-cli/...).
  2. Builds a system prompt using the same OpenClaw 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.
Tutorial.step

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.
Tutorial.step

Images (pass-through)

If your CLI accepts image paths, set imageArg:

Json5
imageArg: "--image",
imageMode: "repeat"

OpenClaw will write base64 images to temp files. If 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 Code CLI behavior).

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 Code CLI behavior).

Tutorial.step

Inputs / outputs

Output modes:

  • output: "json" (default): parse JSON and extract text + session id.
  • output: "jsonl": parse JSONL streams (Codex CLI --json) and extract the last agent message plus thread_id when present.
  • output: "text": treat 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 long and maxPromptArgChars is set, stdin is used.
Tutorial.step

Defaults (built-in)

OpenClaw ships built-in defaults so you usually only need to override what's necessary.

Built-in defaults for claude-cli:

  • command: "claude"
  • args: ["-p", "--output-format", "json", "--dangerously-skip-permissions"]
  • ReferenceGatewayCliBackendsPage.steps.defaults.claude.resumeArgs
  • modelArg: "--model"
  • systemPromptArg: "--append-system-prompt"
  • sessionArg: "--session-id"
  • systemPromptWhen: "first"
  • sessionMode: "always"

Built-in defaults for codex-cli:

  • command: "codex"
  • args: ["exec", "--json", "--color", "never", "--sandbox", "read-only", "--skip-git-repo-check"]
  • ReferenceGatewayCliBackendsPage.steps.defaults.codex.resumeArgs
  • output: "jsonl"
  • resumeOutput: "text"
  • modelArg: "--model"
  • imageArg: "--image"
  • sessionMode: "existing"

Only override what's needed (usually the absolute command path).

Tutorial.step

Limitations

  • No OpenClaw tools (CLI backends don't receive tool calls). However, the CLI itself may run its own tools.
  • No streaming (CLI output is collected before returning).
  • Structured output depends on the CLI's JSON format.
  • Codex CLI sessions resume via text output (no JSONL), which is less structured than the initial --json run. OpenClaw sessions still work normally.
Tutorial.step

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).