# Claw Config

> A grounded self-diagnosis and safe self-modification skill for any OpenClaw agent. Lets the calling agent answer "who am I, what do I own, what does my config look like, and how do I change a field without breaking it?" — without hallucinating field names, identity, or paths. Before patching openclaw.json, the agent must run `claw-config whoami` (self-identification) → `schema <path>` (real field name + type from the installed binary) → `docs <topic>` or `docs search:<keyword>` (official semantics from docs.openclaw.ai). Read-only and diagnose subcommands are cron-safe; `apply` (destructive write) refuses to run under `OPENCLAW_CRON_CONTEXT`.

- Skill: `lord1egypt/claw-config` (Agent Skill)
- Install (CLI): `npx skillmds@latest add lord1egypt/claw-config`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lord1egypt/claw-config/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: Lord1Egypt (https://skillmd.com/u/lord1egypt)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/lord1egypt/claw-config

---


# /claw-config

A grounded toolkit that lets any OpenClaw agent reliably answer:

> *"Who am I, what does my own config look like, and how do I change it safely?"*

**Design principle: no hallucination.** Every field name, every JSON pointer, every current value is read from the installed `openclaw` CLI at call time (`openclaw config schema`, `openclaw config get`). Every write goes through `openclaw config patch` (which validates against the schema internally). When the agent needs to know what a field *does*, the skill fetches the official documentation from `docs.openclaw.ai` (Mintlify `.md` raw + full-content index `llms-full.txt`) — never the model's training memory.

**Comparison with `openclaw doctor`**: `doctor` is a system-wide health check (gateway / secrets / channels), human-readable output. `claw-config` is **agent-scoped** (sliced by `$OPENCLAW_AGENT_ID` — only sees the caller's own config) and supports `--json` for downstream tooling. They are complementary, not duplicates.

**Cron behaviour**: `apply` is hard-refused under `OPENCLAW_CRON_CONTEXT=1` (destructive write). All other subcommands run anywhere (read-only or cache-only); `docs` will serve a cached page in cron context but never makes a fresh HTTPS request.

## ⚠️ Docs vs installed schema — trust the schema when they disagree

`docs.openclaw.ai` is a **single-version site** that always reflects the latest published release (no `/v2026.5/...` history URLs, no `/changelog` — only `/announcements` for breaking changes). The installed `openclaw` binary may lag (stable channel) or lead (dev channel). So docs and the installed binary can drift:

- **Schema is truth** — `openclaw config schema` is generated by the installed binary. If a field appears in schema, it works.
- **Docs are guidance** — they may describe fields your version does not have yet, or omit new fields you do have.
- **When they disagree, trust schema.** Treat docs as background context.

**The skill defends against this drift**: cache files live under `~/.openclaw/.maintenance-cache/docs/<openclaw-version>/<slug>`. When you upgrade `openclaw`, the previous version's cache directory is auto-removed on the next `docs` call. Each `docs` call also reports cache age on stderr so the calling agent can decide whether to `--refresh`.

**After upgrading openclaw**, run `claw-config docs announcements` to see breaking changes.

## When to invoke

- An operator (the human running the agents) asks you (the agent) to check whether your own config is correct
- You are about to modify a field that belongs to you in `~/.openclaw/openclaw.json` (your telegram account, your cron bindings, your model override, your memorySearch settings, your identity)
- You suspect something is wrong with your own setup but cannot describe it precisely (telegram not receiving messages? skill not visible? binding not routing?) → run `diagnose`
- An operator reports an incident like "the agent silently lost access to its workspace skills" → run `report` to give them a snapshot

## When NOT to invoke

- The field you want to change does **not belong to you** (e.g., agent `myagent` trying to edit `other-agent`'s telegram account) → escalate to a coordinator agent or the operator. The skill statically refuses such patches at the `plan` step.
- The change is to a **cron job** (lives in `~/.openclaw/cron/jobs.json`, not `openclaw.json`) → use `openclaw cron add/edit/rm` instead
- The change involves **agent-level `auth-profiles.json`, secrets, or credentials** → out of scope; ask the operator
- You are in **cron context** and want to call `apply` → it is hard-refused (interactive only)

## Hard rules

1. **Never hand-edit `~/.openclaw/openclaw.json`** (no `sed`, no `awk`, no `python json.dump` rewriting the file). All writes go through `claw-config apply` → `openclaw config patch`.
2. **Before composing any patch, run `whoami`.** Confirm that `$OPENCLAW_AGENT_ID` resolves to you. If `whoami` fails, stop and tell the operator. **Do not guess your own identity.**
3. **If you do not know what a field is called, run `schema <path>`.** Do not write `nativeSkill` / `enableSkills` / `commands.skills` from memory. The real names come from the installed binary's schema.
4. **Before composing a patch, read the docs.** Run `docs <topic>` (e.g., `cli/config`, `channels/telegram`, `tools/skills`, `cli/cron`, `gateway/config-agents`, `announcements`). If you do not know which page is relevant, run `docs` (no argument, prints the site index) or `docs search:<keyword>` (greps the full-content corpus across every page). **`--help` is not enough.** Many field semantics are documented only in the prose docs, not in `--help` output or schema descriptions. The canonical motivating example: a production incident where `commands.nativeSkills: false` silently hid an agent's workspace skills from its Telegram dispatch table — `--help` did not describe the field at all, and the schema only said `boolean | "auto"`. The actual semantics lived in `tools/slash-commands`, reachable via `docs search:nativeSkills`.
5. **Before `apply`, always `plan` first.** `plan` is a dry-run via `openclaw config patch --dry-run`. Read the diff, confirm the validate result.
6. **If `apply` fails, the backup is automatically restored.** Quote the stderr verbatim to the operator. **Do not retry the patch with guessed adjustments** — that is the start of the hallucination spiral the skill exists to prevent.

## Seven subcommands

Workflow ordering: `whoami` → `schema` → `docs` → (compose patch) → `plan` → `apply` → `report`

| Subcommand | What it does | Writes? | Cron-safe? |
|---|---|---|---|
| `claw-config whoami [--json]` | Agent record (id / workspace / agentDir / model) + telegram flags + bindings + cron jobs + skills inventory | No | Yes |
| `claw-config schema [<pointer>]` | Prints the JSON schema (or sub-tree at a JSON pointer or dot path) for the installed `openclaw` binary | No | Yes |
| `claw-config docs [<topic>\|search:<kw>] [--refresh] [--max-age <h>]` | Official documentation as raw markdown from `docs.openclaw.ai` (Mintlify `.md`). No argument prints the site index. `search:<kw>` greps the full-content corpus and groups hits by source page. Cache is keyed by installed openclaw version and TTL'd | No (writes cache) | Yes (cache-only in cron) |
| `claw-config diagnose [--json]` | 12 structural self-checks. Each result reports a dot-path pointer that can be pasted directly into `openclaw config get`. Exits `3` on any `fail` | No | Yes |
| `claw-config plan <patch.json5>` | Dry-run: invokes `openclaw config patch --dry-run`. Prints diff at the affected paths + validation outcome | No | Yes |
| `claw-config apply <patch.json5>` | Versioned backup → `openclaw config patch` → on failure, restore from backup | **Yes** | **No** |
| `claw-config report [--json]` | Combines `whoami` + `diagnose` into a single markdown block suitable for pasting back to the operator | No | Yes |

Exit codes: `0` ok / `1` runtime error / `2` bad args or self cannot be resolved / `3` `diagnose` found at least one `fail`.

## Self-identification (refuses to guess)

Resolution order:

1. `$OPENCLAW_AGENT_ID` environment variable
2. `--agent <id>` CLI flag
3. If neither is set → `exit 2` with the message `cannot resolve self: refusing to guess`

**The skill never infers identity from `cwd`, hostname, or the first entry in `agents.list[]`.** The reason: writing the wrong agent's config (e.g., `myagent` accidentally editing `other-agent`'s telegram bot token) is the highest-impact failure mode this skill is designed to prevent. Forcing the caller to declare its identity makes that class of bug impossible by construction.

## Patch format: JSON5 recursive merge

`openclaw config patch` accepts JSON5 natively: comments, trailing commas, unquoted keys, single quotes are all fine. Semantics:

- Objects merge recursively
- Arrays and scalars **replace** entire value at that path
- `null` **deletes** the path

The skill writes patches as JSON5 files (typically in `/tmp/`) and passes them to `plan` / `apply`. The patch file itself is your audit trail — start it with a comment explaining *why* you are making the change.

**Example patch** (sets `commands.nativeSkills` to `true` for agent `myagent`'s Telegram account):

```json5
// re-enable native skill dispatch on telegram so workspace skills become visible
{
  channels: {
    telegram: {
      accounts: {
        myagent: {
          commands: { nativeSkills: true }
        }
      }
    }
  }
}
```

Three meaningful tokens (`myagent`, `nativeSkills`, `true`). Everything else is structural path framing — the agent already retrieved the canonical path from `schema channels/telegram/accounts/myagent/commands` and confirmed semantics with `docs search:nativeSkills`.

## Cross-agent safety

`plan` and `apply` statically walk the top-level paths inside the patch. If the patch references **another agent's slice** (`channels.<chan>.accounts.<other>`, `agents.list[i].id != self`, `bindings[i].agentId != self`), the skill refuses with `exit 1` and a message like:

```
patch refers to other agent(s):
  - channels.telegram.accounts.other-agent
self is 'myagent'. refusing — wrong-agent writes are the #1 risk class.
```

Patches touching **shared** sections (`agents.defaults`, `gateway`, `secrets`, `auth`, etc.) are also refused unless you pass `--force-shared`. This is to make agent-level vs. system-level changes ergonomically distinct.

## Backup naming

Backups go to `~/.openclaw/.maintenance-backups/openclaw.<YYYYMMDD-HHMMSS>.pre-<patch-stem>.json`. They live in a dedicated directory to **avoid** being caught by openclaw's own rotating backup scheme (which rotates files matching `openclaw.json.bak[.N]`). On `apply` failure the file is `cp`-restored to `~/.openclaw/openclaw.json` before the script exits non-zero.

## Failure modes

| stderr keyword | Meaning | What the agent should do |
|---|---|---|
| `cannot resolve self` | `$OPENCLAW_AGENT_ID` missing and no `--agent` flag | Report to the operator; ask them to export `OPENCLAW_AGENT_ID=<your-id>` in the calling shell |
| `schema path not found` | The path passed to `schema` does not exist in the installed binary's schema | Run `schema` with no argument first to see the top-level shape; check field name spelling |
| `validate failed: <reason>` | Schema validation rejected the patch (during `plan` dry-run or live `apply`) | Quote the patch file and the validator output verbatim to the operator. **Do not edit the patch and retry on guesswork** — that is the hallucination loop this skill exists to break |
| `patch refers to other agent: <x>` | The patch touches another agent's slice | Stop. Escalate to the operator |
| `backup restored from <path>` | `apply` failed mid-flight; the previous config has been restored | The system is in the pre-patch state. Safe to investigate |
| `docs fetch disabled in cron and no cached copy` | In cron context, the requested docs page has never been fetched | Re-run in interactive context once to populate the cache |

## Invocation

```bash
OPENCLAW_AGENT_ID=myagent claw-config whoami --json
OPENCLAW_AGENT_ID=myagent claw-config schema channels/telegram/accounts/myagent/commands
claw-config docs                                  # site index
claw-config docs cli/config                       # one page
claw-config docs channels/telegram                # one page
claw-config docs search:nativeSkills              # corpus search
claw-config docs announcements                    # breaking changes
OPENCLAW_AGENT_ID=myagent claw-config diagnose
OPENCLAW_AGENT_ID=myagent claw-config plan  /tmp/fix.json5
OPENCLAW_AGENT_ID=myagent claw-config apply /tmp/fix.json5
OPENCLAW_AGENT_ID=myagent claw-config report
```

If you want a shorter command name in your own shell, symlink it:

```bash
ln -s ~/.local/bin/claw-config ~/.local/bin/oclm
```

Stdout is structured plain text by default, or JSON with `--json` (where the subcommand supports it). All informational notes (cache age, fetch URLs, hints) go to stderr so they do not pollute the structured output.

