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 confi...
---
name: claw-config
description: 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`.
user-invocable: true
---
# /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.
don't have the plugin yet? install it then click "run inline in claude" again.
extracted 6 implexa components (intent, inputs, procedure, decision points, output contract, outcome signal) from the original dense reference doc, added explicit edge cases (network failures, cache expiry, version drift, cron guards), clarified self-identification logic, and structured 10-step procedure with explicit inputs/outputs per step.
claw-config is a read-only and write-safe config introspection and patching toolkit for any OpenClaw agent. use it when you need to answer "who am I, what does my own config look like, and how do I safely change it?" the skill prevents hallucination by binding every field name, JSON pointer, and current value to the installed openclaw CLI at call time. every write goes through openclaw config patch (which validates against schema internally). when you need semantics, fetch from the official docs at docs.openclaw.ai, never from training memory. the skill is cron-safe for read operations but refuses destructive writes (apply) in cron context.
environment variables:
OPENCLAW_AGENT_ID (required for most subcommands except docs, schema, whoami --json): your agent's unique identifier. resolves from env var, or --agent <id> CLI flag, or fails with exit code 2 if neither is set. the skill refuses to infer identity from cwd, hostname, or config file order.OPENCLAW_CRON_CONTEXT (optional): set to 1 if running under cron. hard-refuses apply in cron. serves cached docs only.external connections:
openclaw binary: the skill shells out to openclaw config schema, openclaw config get, and openclaw config patch --dry-run / openclaw config patch. requires openclaw in $PATH.docs.openclaw.ai (Mintlify): fetches raw markdown and the full-content index (llms-full.txt) for official field semantics. only invoked in interactive context; cron context uses cached pages or fails gracefully.files and paths:
~/.openclaw/openclaw.json: the agent config file. read by whoami, schema, diagnose, plan. written only by apply (via openclaw config patch).~/.openclaw/.maintenance-cache/docs/<openclaw-version>/<slug>: versioned doc cache. auto-cleaned on version upgrade. each docs call reports cache age on stderr.~/.openclaw/.maintenance-backups/openclaw.<YYYYMMDD-HHMMSS>.pre-<patch-stem>.json: versioned backup directory (separate from openclaw's own rotating scheme). created before every apply; auto-restored on patch failure.schema reference:
step 1: resolve self
$OPENCLAW_AGENT_ID env var (or --agent <id> CLI flag)docs and standalone schema callsstep 2: retrieve current config state
~/.openclaw/openclaw.json, agent id from step 1openclaw config get to fetch the full config as JSONstep 3: retrieve installed schema
openclaw binaryopenclaw config schema [<pointer>] to get the schema (or sub-tree if a path argument was passed)step 4: fetch official docs (if docs subcommand is invoked)
cli/config, channels/telegram) or search:<keyword>~/.openclaw/.maintenance-cache/docs/<version>/<slug>. if cache miss and in cron context, exit 1 with "docs fetch disabled in cron and no cached copy"--max-age (default 24h), log "cache age --refresh flag passed: fetch from docs.openclaw.ai via HTTPS. if in cron context, skip and exit 1 (cron-safe guard)search:<keyword>: grep the full-content corpus (llms-full.txt); group results by source pagestep 5: compose patch (if apply or plan subcommand is invoked)
schema output), new value, reason for change/tmp/fix.json5) with recursive merge structurechannels.telegram.accounts.myagent.commands.nativeSkills) or JSON pointersnull deletesstep 6: static cross-agent check (plan / apply only)
channels.<chan>.accounts.<other-id>, agents.list[i].id != self, bindings[i].agentId != self), exit 1 with "patch refers to other agent(s): ..."agents.defaults, gateway, secrets, auth), warn and require --force-shared flagstep 7: dry-run validation (plan subcommand)
openclaw config patch --dry-run <patch.json5> against the current configstep 8: versioned backup (apply subcommand only)
~/.openclaw/.maintenance-backups/openclaw.<YYYYMMDD-HHMMSS>.pre-<patch-stem>.jsonstep 9: live patch (apply subcommand only)
openclaw config patch <patch.json5> against the live configcp <backup> ~/.openclaw/openclaw.json. log "backup restored from step 10: combined report (report subcommand)
whoami and diagnose subcommandsif self-identification fails (no env var, no flag):
OPENCLAW_AGENT_ID=<your-id>if the patch references another agent's config slice:
applyif running in cron context and apply is invoked:
openclaw cron add/edit/rm, not via claw-configif running in cron context and docs are requested but not cached:
if docs and schema disagree on field semantics:
if a network request to docs.openclaw.ai fails and a cached copy exists:
if plan validation fails:
if apply fails mid-flight:
whoami subcommand:
--json flag): same data as structured JSON objectschema subcommand:
schema channels/telegram to drill down")docs subcommand:
diagnose subcommand:
--json flag): array of check objects with path, status, reasonplan subcommand:
apply subcommand:
report subcommand:
all subcommands:
whoami succeeds:
schema succeeds:
docs succeeds:
--refresh if the page is stalediagnose succeeds with all ok:
plan succeeds and validation passes:
apply with the same patch fileapply succeeds:
whoami or diagnose in the next stepapply fails and backup is restored:
report succeeds: