OpenClaw Config CLI: Read, Write, Patch, and Validate

Reference for the openclaw config command, covering get, set, patch, unset, file, schema, and validate operations. Useful for developers managing openclaw.json settings non-interactively.

Read this when

  • You want to read or edit config non-interactively

Non-interactive utilities for openclaw.json: read, write, patch, or clear a value using a path, output the schema, run validation, or show the path of the active file. Calling openclaw config without any subcommand opens the same step-by-step wizard as openclaw configure.

Note

When OPENCLAW_NIX_MODE=1, OpenClaw considers openclaw.json fixed and unchangeable. Read-only operations (config get, config file, config schema, config validate) remain functional; write commands are rejected. Modify the Nix source for the installation instead; for the official nix-openclaw package, refer to the nix-openclaw Quick Start and configure values under programs.openclaw.config or instances.<name>.config.

Root options

  • true, " type="string"> Repeatable filter for guided-setup sections when openclaw config runs without a subcommand.

Guided sections: workspace, model, web, gateway, daemon, channels, plugins, skills, health.

Examples

openclaw config file
openclaw config file --json
openclaw config --section model
openclaw config --section gateway --section daemon
openclaw config schema
openclaw config schema --json
openclaw config get browser.executablePath
openclaw config set browser.executablePath "/usr/bin/google-chrome"
openclaw config set browser.profiles.work.executablePath "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
openclaw config set agents.defaults.heartbeat.every "2h"
openclaw config set logging.audit.executionIdentity true
openclaw config set 'agents.entries.main.tools.exec.node' "node-id-or-name"
openclaw config set agents.defaults.models '{"openai/gpt-5.4":{}}' --strict-json --merge
openclaw config set channels.discord.token --ref-provider default --ref-source env --ref-id DISCORD_BOT_TOKEN
openclaw config set secrets.providers.vaultfile --provider-source file --provider-path /etc/openclaw/secrets.json --provider-mode json
openclaw config patch --file ./openclaw.patch.json5 --dry-run
openclaw config unset plugins.entries.brave.config.webSearch.apiKey
openclaw config set channels.discord.token --ref-provider default --ref-source env --ref-id DISCORD_BOT_TOKEN --dry-run
openclaw config validate
openclaw config validate --json

Paths

Use dot or bracket notation. In shell examples, quote bracket paths so zsh does not glob-expand [0]:

openclaw config get agents.defaults.workspace
openclaw config get agents.entries.main
openclaw config get agents.entries
openclaw config set 'agents.entries.work.tools.exec.node' "node-id-or-name"

For agent modifications, prefer agents.entries.<id> paths. The older agents.list[0] syntax and full-list inputs remain compatible with set, patch, and unset; any write persists the canonical keyed roster. Edits by index follow the roster's current order. Inside a batch, a submitted list keeps its sequence across later keyed edits, even when agent IDs are numeric strings. Existing protections for roster deletion and $include ownership remain in force.

config get

Pulls a value from the redacted config snapshot (secrets are never displayed). --json outputs the same redacted value as JSON; otherwise strings/numbers/booleans print as-is and objects/arrays print as formatted JSON.

A path that is schema-valid but not set indicates the runtime default applies; an unknown path recommends openclaw config schema. With --json, both cases use the standard CLI JSON failure envelope on stdout and exit with status 1. Without --json, diagnostics go to stderr.

openclaw config get browser.executablePath
openclaw config get agents.defaults.model --json

config file

Shows the active config file path, determined from OPENCLAW_CONFIG_PATH or the default location. The path points to a regular file, not a symlink; consult Write safety.

With --json, stdout holds an object with the resolved path under path.

config schema

Outputs the generated JSON schema for openclaw.json to stdout.

What it includes

  • The current root config schema, plus a root $schema string field for editor tooling.
  • Field title / description docs metadata used by the Control UI.
  • Nested object, wildcard (*), and array-item ([]) nodes inherit the same title / description metadata when matching field docs exist.
  • anyOf / oneOf / allOf branches inherit the same docs metadata too.
  • Best-effort live plugin + channel schema metadata when runtime manifests can be loaded.
  • A clean fallback schema even when the current config is invalid.

config.schema.lookup yields a single normalized configuration path alongside a shallow schema node (title, description, type, enum, const, common bounds), associated UI hint metadata, and brief summaries of direct children. This is the tool for path-scoped drill-down in Control UI or custom clients.

openclaw config schema
openclaw config schema --json
openclaw config schema > openclaw.schema.json

In both modes, the schema is JSON. --json serves as the explicit machine-output form, leaving stdout available solely for the schema document.

config validate

Without launching the gateway, this command validates the current config against the active schema. It also verifies provider/source compatibility for each SecretRef declared in the registry, even those in disabled plugin or channel configurations. Because this strict command can flag an inactive mismatch, it may report issues that do not halt normal Gateway startup, where SecretRef resolution is confined to effectively active surfaces.

Following schema validation, it inspects the command path of every configured manual exec provider using the same non-executing trust checks applied at startup: file presence, symlinks, trusted directories, permissions, ownership, and Windows ACL availability. With config set, config patch, and config unset, these checks are limited to providers changed or referenced by the operation, including during dry runs. Replacing the secrets or secrets.providers collection triggers checks on all remaining providers. An unrelated inactive provider will not block targeted repairs or removal of that provider.

Path validation neither executes providers nor verifies their output. Passing it does not ensure successful secret resolution; testing that separately requires --allow-exec for exec dry runs.

openclaw config validate
openclaw config validate --json

Note

The exec-provider checks look at the filesystem of the host running the CLI. Execute config validate directly on the gateway host, or on a host with identical command paths, ownership, and ACLs. Paths and permissions may shift after validation; startup rechecks them before execution.

Note

If validation is already failing, begin with openclaw configure or openclaw doctor --fix. The invalid-config guard is not bypassed by openclaw chat.

Provider and runtime params bags are deliberately typed as Record<string, unknown>, since their owners define the supported keys and values. While openclaw config validate can validate the container and overall config shape, it cannot type-check provider-specific parameter names or values. Passing validation does not confirm that a param is supported; refer to the provider docs and test behavior on the chosen runtime and provider.

Values

Values are parsed as JSON5 when possible; otherwise they are treated as raw strings. To require standard JSON without the string fallback, use --strict-json (this rejects JSON5-only syntax like comments, trailing commas, or unquoted keys). On config set, --json is a legacy alias for --strict-json.

openclaw config set agents.defaults.heartbeat.every "0m"
openclaw config set gateway.port 19001 --strict-json
openclaw config set channels.whatsapp.groups '["*"]' --strict-json

config get <path> --json outputs the redacted value as JSON instead of terminal-formatted text.

When a write modifies agents.defaults.model or a per-agent agents.entries.*.model, OpenClaw resolves each changed primary or fallback through the configured catalogs and the selected provider's model resolver before writing. Provider-supported exact provider/model pins are accepted even if absent from the curated picker; validation does not replace the selected model. Unknown model references are rejected without altering the active config. To browse the picker, run openclaw models list, or consult the provider's documentation for an exact model ID. Successful validation does not prove that your account can call the model.

Note

By default, object assignment replaces the target path. Protected paths that often hold user-added entries refuse replacements that would remove existing entries unless you pass --replace: agents.defaults.models, agents.entries, models.providers, models.providers.<id>, models.providers.<id>.models, plugins.entries, and auth.profiles.

For adding entries to those maps, use --merge:

openclaw config set agents.defaults.models '{"openai/gpt-5.4":{}}' --strict-json --merge
openclaw config set models.providers.ollama.models '[{"id":"llama3.2","name":"Llama 3.2"}]' --strict-json --merge

Use --replace only when the provided value should intentionally become the complete target value.

config set modes

Value mode

openclaw config set <path> <value>

SecretRef builder mode

openclaw config set channels.discord.token \
  --ref-provider default \
  --ref-source env \
  --ref-id DISCORD_BOT_TOKEN

Provider builder mode

Targets secrets.providers.<alias> paths only:

openclaw config set secrets.providers.vault \
  --provider-source exec \
  --provider-command /usr/local/bin/openclaw-vault \
  --provider-arg read \
  --provider-arg openai/api-key \
  --provider-timeout-ms 5000

Batch mode

openclaw config set --batch-json '[
  {
    "path": "secrets.providers.default",
    "provider": { "source": "env" }
  },
  {
    "path": "channels.discord.token",
    "ref": { "source": "env", "provider": "default", "id": "DISCORD_BOT_TOKEN" }
  }
]'
openclaw config set --batch-file ./config-set.batch.json --dry-run

Batch files are capped at 8 MiB.

Warning

SecretRef assignments are rejected on unsupported runtime-mutable surfaces (for example hooks.token, Discord thread-binding webhook tokens, and WhatsApp creds JSON). See SecretRef Credential Surface.

Batch parsing always treats the batch payload (--batch-json/--batch-file) as the source of truth; --strict-json / --json do not alter batch parsing behavior.

Batch assignments apply in order, then validation checks the final config. A SecretRef replaced by a later assignment is not resolved or counted in dry-run output, even with --allow-exec. Providers that remain in a changed provider collection still receive command-path trust checks.

JSON path/value mode applies to SecretRefs and providers as well:

openclaw config set channels.discord.token \
  '{"source":"env","provider":"default","id":"DISCORD_BOT_TOKEN"}' \
  --strict-json

openclaw config set secrets.providers.vaultfile \
  '{"source":"file","path":"/etc/openclaw/secrets.json","mode":"json"}' \
  --strict-json

Provider builder flags

Provider builder targets must reference secrets.providers.<alias> as their path.

Common flags

  • --provider-source <env|file|exec|store>
  • --provider-timeout-ms <ms> (file, exec)

Env provider (--provider-source env)

  • --provider-allowlist <ENV_VAR> (repeatable)

File provider (--provider-source file)

  • --provider-path <path> (required)
  • --provider-mode <singleValue|json>
  • --provider-max-bytes <bytes>

Exec provider (--provider-source exec)

  • --provider-command <path> (required)
  • --provider-arg <arg> (repeatable)
  • --provider-no-output-timeout-ms <ms>
  • --provider-max-output-bytes <bytes>
  • --provider-json-only
  • --provider-env <KEY=VALUE> (repeatable)
  • --provider-pass-env <ENV_VAR> (repeatable)
  • --provider-trusted-dir <path> (repeatable)

Here is a hardened exec provider example:

openclaw config set secrets.providers.vault \
  --provider-source exec \
  --provider-command /usr/local/bin/openclaw-vault \
  --provider-arg read \
  --provider-arg openai/api-key \
  --provider-json-only \
  --provider-pass-env VAULT_TOKEN \
  --provider-trusted-dir /usr/local/bin \
  --provider-timeout-ms 5000

config patch

Rather than issuing numerous path-based config set commands, paste or pipe a config-shaped JSON5 patch. Objects merge recursively, arrays and scalar values overwrite the target, and null removes the target path.

openclaw config patch --file ./openclaw.patch.json5 --dry-run
openclaw config patch --file ./openclaw.patch.json5

Patch files cannot exceed 8 MiB. Piped --stdin patches are capped at 1 MiB.

For remote setup scripts, pipe a patch over stdin:

ssh user@gateway-host 'openclaw config patch --stdin --dry-run' < ./openclaw.patch.json5
ssh user@gateway-host 'openclaw config patch --stdin' < ./openclaw.patch.json5

Sample patch:

{
  channels: {
    slack: {
      enabled: true,
      mode: "socket",
      botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" },
      appToken: { source: "env", provider: "default", id: "SLACK_APP_TOKEN" },
      groupPolicy: "open",
      requireMention: false,
    },
    discord: {
      enabled: true,
      token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" },
      dmPolicy: "disabled",
      dm: { enabled: false },
      groupPolicy: "allowlist",
    },
  },
  agents: {
    defaults: {
      model: { primary: "openai/gpt-5.6-sol" },
      models: {
        "openai/gpt-5.6-sol": {
          agentRuntime: { id: "openclaw" },
          params: { fastMode: true },
        },
      },
    },
  },
}

The runtime pin marks this as an embedded OpenClaw recipe. A valid fastMode value acts as a portable typed runtime control and does not independently select OpenClaw.

When a single object or array must become exactly the supplied value rather than being patched recursively, use --replace-path <path>:

openclaw config patch --file ./discord.patch.json5 --replace-path 'channels.discord.guilds["123"].channels'

Without writing anything, --dry-run performs schema and SecretRef resolvability checks. Exec-backed SecretRefs are excluded from dry-run unless you add --allow-exec to deliberately execute provider commands during the check.

Dry run

--dry-run verifies changes without writing openclaw.json. It works on config set, config patch, and config unset.

openclaw config set channels.discord.token \
  --ref-provider default \
  --ref-source env \
  --ref-id DISCORD_BOT_TOKEN \
  --dry-run \
  --json

openclaw config set channels.discord.token \
  --ref-provider vault \
  --ref-source exec \
  --ref-id discord/token \
  --dry-run \
  --allow-exec

Dry-run behavior

  • Builder mode: runs SecretRef resolvability checks for modified refs/providers.
  • JSON mode (--strict-json, --json, or batch mode): executes schema validation along with SecretRef resolvability checks.
  • Policy validation applies to the complete post-change config, so parent-object writes (such as assigning hooks as an object) cannot evade unsupported-surface validation.
  • Exec command-path trust checks run without triggering providers. Exec SecretRef resolvability checks stay off by default to prevent command side effects; pass --allow-exec to enable them (provider commands may run). --allow-exec is dry-run only and fails without --dry-run.

--dry-run --json fields

  • ok: indicates whether the dry-run succeeded
  • operations: total count of assignments that were evaluated
  • checks: flags whether schema and resolvability checks were executed
  • checks.resolvabilityComplete: indicates if resolvability checks finished completely (false when exec refs are skipped)
  • refsChecked: count of refs that were actually resolved during the dry-run
  • skippedExecRefs: count of exec refs that were skipped because --allow-exec was not configured
  • errors: structured errors when ok=false; each includes a kind of missing-path, schema, resolvability, model, or conflict (conflict means the config file was modified while the command was writing, so no changes were applied, rerun to load the updated file)

JSON output shape

{
  ok: boolean,
  operations: number,
  configPath: string,
  inputModes: ["value" | "json" | "builder" | "unset", ...],
  checks: {
    schema: boolean,
    resolvability: boolean,
    resolvabilityComplete: boolean,
  },
  refsChecked: number,
  skippedExecRefs: number,
  errors?: [
    {
      kind: "missing-path" | "schema" | "resolvability" | "model",
      message: string,
      ref?: string, // present for resolvability errors
    },
  ],
}

Successful run example

{
  "ok": true,
  "operations": 1,
  "configPath": "/home/user/.openclaw/openclaw.json",
  "inputModes": ["builder"],
  "checks": {
    "schema": false,
    "resolvability": true,
    "resolvabilityComplete": true
  },
  "refsChecked": 1,
  "skippedExecRefs": 0
}

Failed run example

{
  "ok": false,
  "operations": 1,
  "configPath": "/home/user/.openclaw/openclaw.json",
  "inputModes": ["builder"],
  "checks": {
    "schema": false,
    "resolvability": true,
    "resolvabilityComplete": true
  },
  "refsChecked": 1,
  "skippedExecRefs": 0,
  "errors": [
    {
      "kind": "resolvability",
      "message": "Error: Environment variable \"MISSING_TEST_SECRET\" is not set.",
      "ref": "env:default:MISSING_TEST_SECRET"
    }
  ]
}

If dry-run fails

  • config schema validation failed: your post-change config structure is invalid; correct the path/value or provider/ref object layout.
  • Config policy validation failed: unsupported SecretRef usage: return that credential to plaintext/string input; only use SecretRefs on supported surfaces.
  • SecretRef assignment(s) could not be resolved: the referenced provider/ref cannot be resolved at this time (missing env/store name, bad file pointer, exec provider failure, or provider/source mismatch).
  • model reference validation failed: a changed text-model primary or fallback is not recognized; execute openclaw models list and pick an available model.
  • Dry run note: skipped <n> exec SecretRef resolvability check(s): run again with --allow-exec if you require exec resolvability validation.
  • In batch mode, correct the failing entries and rerun --dry-run before writing.

Applying changes

Following every successful config set / config patch / config unset, the CLI outputs one of three hints so you can tell whether the gateway needs a restart:

HintMeaning
Restart the gateway to apply.The modified path requires a full restart.
Change will apply without restarting the gateway.Hot reload applies it automatically.
No gateway restart needed.No runtime-relevant changes were made.

Changes that effectively alter plugins.entries (or any subpath) demand a restart, because the CLI cannot confirm that every plugin's reload metadata is loaded. Successful config set or config unset operations that result in no effective config diff print No change and leave the JSON5 file completely unchanged. A config unset target that is missing from the authored config exits with status 1 and also leaves the file untouched. Setting an absent key to a value equal to its runtime default still counts as an authored change and persists the explicit value.

Write safety

openclaw config set and other OpenClaw-owned config writers validate the complete post-change config before writing it to disk. If the new payload fails schema validation or appears to be a destructive clobber, the active config is left untouched and the rejected payload is stored beside it as openclaw.json.rejected.*.

OpenClaw-owned writes that change config reserialize JSON5 as standard JSON. When the source includes comments, the writer warns immediately before removing them; use a direct editor when preserving comments is important.

Warning

The active config path must be a regular file. Symlinked openclaw.json layouts are not supported for writes; use OPENCLAW_CONFIG_PATH to point directly at the real file instead.

Prefer CLI writes for small edits:

openclaw config set gateway.reload.mode hybrid --dry-run
openclaw config set gateway.reload.mode hybrid
openclaw config validate

If a write is rejected, inspect the saved payload and fix the full config shape:

CONFIG="$(openclaw config file)"
ls -lt "$CONFIG".rejected.* 2>/dev/null | head
openclaw config validate

Direct editor writes are still permitted, but the running Gateway treats them as untrusted until they validate. At startup, eligible single-file configs can receive deterministic legacy-key migrations if the complete result validates, with the previous config kept in the .bak ring. Other invalid direct edits fail startup; hot reload skips invalid edits without rewriting openclaw.json. Run openclaw doctor --fix to repair prefixed/clobbered config or restore the last-known-good copy. See Gateway troubleshooting.

Whole-file recovery is reserved for doctor repair. Plugin schema changes or minHostVersion skew stay loud instead of rolling back unrelated user settings such as models, providers, auth profiles, channels, gateway exposure, tools, memory, browser, or cron config.

Repair loop

After openclaw config validate passes, use the local TUI to have an embedded agent compare the active config against the docs while you validate each change from the same terminal:

openclaw chat

Inside the TUI, a leading ! runs a literal local shell command (after a one-time per-session confirmation prompt):

!openclaw config file
!openclaw docs gateway auth token secretref
!openclaw config validate
!openclaw doctor

Compare with docs

Ask the agent to compare your current config with the relevant docs page and suggest the smallest fix.

Apply targeted edits

For precise modifications, use openclaw config set or openclaw configure.

Re-validate

Execute openclaw config validate again following every adjustment.

Doctor for runtime issues

Should checks succeed yet the environment remains unstable, invoke openclaw doctor or openclaw doctor --fix to get assistance with migrations and fixes.

2,940 words · updated Sep 1, 2026