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.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:
openclaw config schema is generated by the installed binary. If a field appears in schema, it works.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.
~/.openclaw/openclaw.json (your telegram account, your cron bindings, your model override, your memorySearch settings, your identity)diagnosereport to give them a snapshotmyagent 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.~/.openclaw/cron/jobs.json, not openclaw.json) → use openclaw cron add/edit/rm insteadauth-profiles.json, secrets, or credentials → out of scope; ask the operatorapply → it is hard-refused (interactive only)~/.openclaw/openclaw.json (no sed, no awk, no python json.dump rewriting the file). All writes go through claw-config apply → openclaw config patch.whoami. Confirm that $OPENCLAW_AGENT_ID resolves to you. If whoami fails, stop and tell the operator. Do not guess your own identity.schema <path>. Do not write nativeSkill / enableSkills / commands.skills from memory. The real names come from the installed binary's schema.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.apply, always plan first. plan is a dry-run via openclaw config patch --dry-run. Read the diff, confirm the validate result.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.Workflow ordering: whoami → schema → docs → (compose patch) → plan → apply → report
SubcommandWhat it doesWrites?Cron-safe?claw-config whoami [--json]Agent record (id / workspace / agentDir / model) + telegram flags + bindings + cron jobs + skills inventoryNoYesclaw-config schema [<pointer>]Prints the JSON schema (or sub-tree at a JSON pointer or dot path) for the installed openclaw binaryNoYesclaw-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'dNo (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 failNoYesclaw-config plan <patch.json5>Dry-run: invokes openclaw config patch --dry-run. Prints diff at the affected paths + validation outcomeNoYesclaw-config apply <patch.json5>Versioned backup → openclaw config patch → on failure, restore from backupYes****Noclaw-config report [--json]Combines whoami + diagnose into a single markdown block suitable for pasting back to the operatorNoYes
Exit codes: 0 ok / 1 runtime error / 2 bad args or self cannot be resolved / 3 diagnose found at least one fail.
Resolution order:
$OPENCLAW_AGENT_ID environment variable--agent <id> CLI flagexit 2 with the message cannot resolve self: refusing to guessThe 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.
openclaw config patch accepts JSON5 natively: comments, trailing commas, unquoted keys, single quotes are all fine. Semantics:
null deletes the pathThe 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.
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:
text
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.
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.
stderr keywordMeaningWhat the agent should docannot resolve self``$OPENCLAW_AGENT_ID missing and no --agent flagReport to the operator; ask them to export OPENCLAW_AGENT_ID=<your-id> in the calling shellschema path not foundThe path passed to schema does not exist in the installed binary's schemaRun schema with no argument first to see the top-level shape; check field name spellingvalidate 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 breakpatch refers to other agent: <x>The patch touches another agent's sliceStop. Escalate to the operatorbackup restored from <path>``apply failed mid-flight; the previous config has been restoredThe system is in the pre-patch state. Safe to investigatedocs fetch disabled in cron and no cached copyIn cron context, the requested docs page has never been fetchedRe-run in interactive context once to populate the cache
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.