Config Path Ops (openclaw path)
Config Path Ops (openclaw path)
OpenClaw state is spread across human-edited markdown, commented JSONC config,
append-only JSONL logs, and YAML specs. Scripts, hooks, and agents constantly
need one small value from those files — a plugin setting, a frontmatter key, a
log field. The usual tools (jq + tempfile + mv, ad-hoc sed, a Python
json.load/json.dump round-trip) either can’t address the value cleanly or
destroy the file’s comments and formatting on write.
openclaw path gives every such value a stable address — oc://… — that you can
validate, read, search, dry-run, and write from the terminal, preserving the
rest of the file. It’s the recommended way to make small, surgical edits to
openclaw.json and other workspace files.
Enable it
path comes from the bundled optional oc-path plugin:
openclaw plugins enable oc-pathThe oc:// scheme
oc://FILE/SECTION/ITEM/FIELD?session=SCOPESlots nest left-to-right: field requires item, item requires section.
The adapter is chosen from the file extension — .md, .jsonc, .json,
.jsonl, .yaml, .yml, .lobster — and the slots resolve against that
kind’s structure (markdown headings/items, JSON object keys/array indexes, JSONL
line records, YAML map/sequence nodes).
Segment features:
- Quoted segments —
"a/b.c"survives/and.separators. The file slot is quote-aware too:oc://"skills/email-drafter"/Tools/$last. - Predicates —
[k=v],[k!=v],[k<v],[k<=v],[k>v],[k>=v](numeric comparisons require both sides to coerce to numbers). - Unions —
{a,b,c}matches any alternative. - Wildcards —
*(one sub-segment) and**(recursive).findaccepts them;resolveandsetreject them as ambiguous. - Ordinals —
$last,$firstaddress array/list positions.
Subcommands
| Subcommand | Purpose |
|---|---|
resolve <oc-path> | Print the concrete value at a path (or “not found”). |
find <pattern> | Enumerate matches for a wildcard / union / predicate path. |
set <oc-path> <value> | Write a leaf at a concrete path. Supports --dry-run. |
validate <oc-path> | Parse only; print the file / section / item / field breakdown. |
emit <file> | Round-trip a file through parse + emit (byte-fidelity diagnostic). |
Global flags
| Flag | Purpose |
|---|---|
--cwd <dir> | Resolve the file slot against this directory (default: cwd). |
--file <path> | Override the file slot’s resolved path — use for absolute access. |
--dry-run | (set only) print the bytes that would be written, without writing. |
--diff | (with set --dry-run) print a unified diff instead of full bytes. |
--json | Force JSON output (default when stdout isn’t a TTY). |
--human | Force human output (default when stdout is a TTY). |
Examples
Read one value:
openclaw path resolve 'oc://openclaw.json/meta/lastTouchedVersion'Preview a write before touching disk (always do this first on live config):
openclaw path set 'oc://openclaw.json/plugins/entries/policy/enabled' 'true' --dry-run --diffAppend to an array using an insertion marker:
openclaw path set 'oc://openclaw.json/plugins/allow/$append' 'policy'Find records in an append-only JSONL log:
openclaw path find 'oc://session.jsonl/[event=tool_call]/name'Address a markdown instruction by section + item instead of line number:
openclaw path resolve 'oc://AGENTS.md/runtime-safety/openclaw-gateway'Resolving the file slot
The file slot resolves against --cwd (default: the current directory), not
necessarily ~/.openclaw. To target the live gateway config from anywhere, pass
an absolute override:
openclaw path resolve 'oc://openclaw.json/meta/lastTouchedVersion' \ --file ~/.openclaw/openclaw.json# or run the command from ~/.openclaw, or pass --cwd ~/.openclawWhen to use it — and when not to
Use openclaw path for small, addressable edits where a repeatable terminal
command beats another bespoke parser, and especially when the target file has
comments you must preserve (JSONC config, markdown).
Reach for the owner command or a full rewrite instead when:
- You’re doing a rich migration — restructuring many keys, reshaping a
subtree, creating a whole new section. A
json.load/json.dumppass (or the owning plugin’s command) is clearer there. - The value isn’t a simple leaf or array insertion.
Lobster’s rule of thumb (from its AGENTS.md): 1–5 scalar leaves or array
appends → openclaw path set; structural migrations (≥10 keys, subtree reshape)
→ a scripted JSON rewrite. The old jq + tempfile + mv pattern on JSONC is
retired — it strips comments; the substrate preserves them.
Caveats
- Preview writes with
--dry-run --diffbefore applying to live config — the gateway reads these files continuously. - Deeply nested object values: the addressing favors leaves and array inserts; very deep paths and writing whole object values are weaker than scalar edits. For those, prefer a scripted rewrite.
- The gateway must be able to load the plugin. If
openclaw pathreports “does not know the command path”, theoc-pathplugin isn’t enabled (or the gateway is down because the config is currently invalid — fix the config first, then usepath).
Lobster’s wrappers
Lobster wraps the two common verbs in plugins/lobster-ops/scripts/lib.sh as
oc_path_get / oc_path_set, so ops skills can do narrow config edits without
re-deriving the addressing each time.
See also
- Policy Conformance — edit
policy.jsoncleaves surgically - Secrets Management — SecretRef objects are one
case better handled by a scripted rewrite than by
path - docs.openclaw.ai/cli/path — upstream reference