跳转至

openclaw path

对 oc:// 寻址方案的 Shell 访问:一种按文件类型分派的路径语法,用于检查和编辑可寻址的工作区文件(markdown、jsonc、jsonl、yaml/yml/lobster)。自托管用户、插件作者和编辑器扩展可以用它来读取、查找或更新某个局部位置,而无需为每种文件手写解析器。

path 由随附的可选 oc-path 插件 提供。首次使用前启用:

openclaw plugins enable oc-path

CLI 动词与寻址模型对应:

  • resolve 是具体、单匹配的。
  • find 是用于通配符、并集、谓词和位置展开的多匹配动词。
  • set 只接受具体路径或插入标记;通配符模式会在写入前被拒绝。
  • validate 仅解析路径,不访问文件系统。
  • emit 将文件通过“解析 + 输出”往返处理(字节保真诊断)。

为什么使用它

OpenClaw 的状态分布在人工编辑的 Markdown、带注释的 JSONC 配置、追加写入的 JSONL 日志,以及 YAML 工作流/规格文件中。脚本、钩子和代理常常只需要这些文件中的一个小值:frontmatter 键、插件设置、日志记录字段、YAML 步骤,或某个命名小节下的列表项。

openclaw path 为这类调用方提供一个稳定地址,而不是为每种文件临时编写 grep、正则或解析器。同一个 oc:// 路径可以在终端中验证、解析、搜索、试运行和写入,从而让局部自动化保持可审查、可重放。它保留文件其余部分不变,因此写入一个叶子节点不会干扰注释、行尾符或周边格式。

当你想要的目标具有逻辑地址、但文件形状不固定时,可使用它:

  • 钩子从带注释的 JSONC 中读取一个设置,并在写回值时不会丢失注释。
  • 维护脚本在 JSONL 日志中查找所有匹配的事件字段,而无需将整个日志加载到自定义解析器。
  • 编辑器按 slug 跳转到 Markdown 小节或列表项,然后渲染解析出的那一行。
  • 代理在应用小范围工作区编辑前先试运行,并在审查中显示变更的字节。

对于普通的整文件编辑、复杂的配置迁移或特定记忆写入,请跳过 openclaw path;这些应使用所属命令或插件。path 适合小规模、可寻址的文件操作,此时一条可重复的终端命令优于另一个定制解析器。

如何使用

从人工编辑的配置文件中读取一个值:

openclaw path resolve 'oc://config.jsonc/plugins/github/enabled'

预览一次写入而不触碰磁盘:

openclaw path set 'oc://config.jsonc/plugins/github/enabled' 'true' --dry-run

在追加写入的 JSONL 日志中查找匹配记录:

openclaw path find 'oc://session.jsonl/[event=tool_call]/name'

按小节和条目而不是按行号定位 Markdown 中的指令:

openclaw path resolve 'oc://AGENTS.md/runtime-safety/openclaw-gateway'

在脚本读取或写入前,于 CI 或预检脚本中验证路径:

openclaw path validate 'oc://AGENTS.md/tools/$last/risk'

这些命令旨在可直接复制到 Shell 脚本中。当调用方需要结构化输出时使用 --json,当人工查看结果时使用 --human。

工作原理

  1. 将 oc:// 地址解析为各槽位:file、section、item、field,以及可选的 session 查询。
  2. 根据目标扩展名选择对应文件类型的适配器(.md、.jsonc、.json、.jsonl、.ndjson、.yaml、.yml、.lobster)。
  3. 根据该文件类型的结构解析槽位:Markdown 标题/列表项、JSONC 对象键/数组索引、JSONL 行记录,或 YAML 映射/序列节点。
  4. 对于 set,通过同一适配器输出编辑后的字节,因此在支持的类型中,文件未触及的部分会保留注释、行尾符和周边格式。

resolve 和 set 需要一个具体目标。find 是探索性动词:它将通配符、并集、谓词和序数展开为具体匹配项,你可以先检查这些匹配项再选择要写入的一个。

子命令

子命令 用途
resolve <oc-path> 打印路径处的具体匹配项(或“not found”)。
find <pattern> 枚举通配符 / 并集 / 谓词路径的所有匹配项。
set <oc-path> <value> 在具体路径写入叶子节点或插入目标。支持 --dry-run。
validate <oc-path> 仅解析;打印结构分解(file / section / item / field)。
emit <file> 将文件通过“解析 + 输出”往返处理(字节保真诊断)。

全局标志

标志 适用范围 用途
--cwd <dir> resolve, find, set, emit 针对此目录解析 file 槽位(默认:process.cwd())。
--file <path> resolve, find, set, emit 覆盖 file 槽位解析后的路径(绝对访问)。
--json 全部 强制 JSON 输出(当 stdout 不是 TTY 时默认开启)。
--human 全部 强制人类可读输出(当 stdout 是 TTY 时默认开启)。
--value-json set 将 <value> 解析为 JSON,用于 JSON/JSONC/JSONL 叶子节点替换。
--dry-run set 打印将要写入的字节但不实际写入。
--diff set(需要 --dry-run) 打印统一 diff,而非完整字节。
标志 适用于 用途

validate 仅接受 --json / --human;它不会访问文件系统,因此 --cwd 和 --file 不适用。

oc:// 语法

oc://FILE/SECTION/ITEM/FIELD?session=SCOPE

槽位规则:field 要求存在 item,而 item 要求存在 section。在所有 四个槽位中:

  • 带引号的片段 — "a/b.c" 可以保留 / 和 . 分隔符。内容为 字节字面量;引号内不允许出现 " 和 \。文件槽位也支持引号: oc://"skills/email-drafter"/Tools/$last 将 skills/email-drafter 视为单个文件路径。
  • 谓词 — [k=v]、[k!=v]、[k<v]、[k<=v]、[k>v]、[k>=v]。 数值运算符要求两侧都能转换为有限数值。
  • 联合 — {a,b,c} 匹配任一备选值。
  • 通配符 — *(单个子片段)和 **(零个或多个, 递归)。find 接受这些;resolve 和 set 会将其视为歧义并拒绝。
  • 位置 — $first / $last 解析为第一个 / 最后一个索引或 声明的键。
  • 序号 — #N 表示按文档顺序的第 N 个匹配项。
  • 插入标记 — +、+key、+nnn 用于按键 / 按索引插入 (与 set 一起使用)。
  • 会话作用域 — ?session=cron-daily 等。与槽位嵌套正交。 会话值是原始值,不进行百分号解码;不得包含控制字符或保留的查询分隔符 (?、&、%)。

引号、谓词或联合片段之外的保留字符(?、&、%)会被拒绝。控制字符 (U+0000-U+001F、U+007F)在任何位置都会被拒绝,包括 session 查询值。

formatOcPath(parseOcPath(path)) === path 对于规范化路径有保证。 非规范化查询参数会被忽略,除了第一个非空 session= 值。

硬性限制:路径上限为 4096 字节,最多 4 个槽位(file/section/item/ field),每个槽位最多 64 个点号子片段,深度 JSON 路径最多 256 层嵌套 遍历。另外,对于任何会加载文件的动词,任何超过 16 MiB 的文件输入都会在 解析前被拒绝。JSONC/JSON 保留 OC_JSONC_INPUT_TOO_LARGE 诊断;其他文件类型使用 OC_PATH_INPUT_TOO_LARGE。

按文件类型寻址

类型 文件扩展名 寻址模型
Markdown .md 按 slug 的 H2 章节,按 slug 或 #N 的列表项,通过 [frontmatter] 访问前置元数据。
JSONC/JSON .jsonc、.json 对象键和数组索引;除非加引号,点号会拆分嵌套子片段。
JSONL .jsonl、.ndjson 顶层行地址(L1、L2、$first、$last),然后在行内进行 JSONC 风格的下降。
YAML/.lobster .yaml、.yml、.lobster 映射键和序列索引;注释和流式样式由 YAML 文档 API 处理。

resolve 返回结构化匹配:root、node、leaf 或 insertion-point,并附带 1 起始的行号。叶子值以文本加 leafType 的形式呈现, 以便插件作者无需依赖每种类型的 AST 形状即可渲染预览。

变更契约

set 写入一个具体目标:

  • Markdown 前置元数据值和 - key: value 项字段是字符串叶子。值是字面量, 包括 $1、$& 和 $$。Markdown 插入会追加章节、前置元数据键或章节项, 并为更改后的文件渲染规范的 Markdown 形状。章节正文不能通过 set 整体写入。
  • JSONC 叶子写入会将字符串值强制转换为现有叶子类型(string、有限 number、true/false 或 null)。当 JSONC/JSON/JSONL 叶子替换需要按 JSON 解析 <value> 且可能改变结构时,请使用 --value-json,例如将字符串 secret-ref 简写替换为对象。 JSONC 对象和数组插入会按 JSON 解析 <value>,并对普通叶子写入使用 jsonc-parser 编辑路径,以保留注释和附近格式。
  • JSONL 叶子写入在行内按 JSONC 方式强制转换。整行替换和追加会按 JSON 解析 <value>。渲染后的 JSONL 会保留文件占主导的 LF/CRLF 换行约定 (对文件中的换行进行多数表决,因此以 CRLF 为主的文件即使存在少量 LF 也会保持 CRLF)。
  • YAML 叶子写入会强制转换为现有标量类型(string、有限 number、true/false 或 null)。YAML 插入使用捆绑的 yaml 包的文档 API 来更新映射/序列。带有解析器错误的格式错误 YAML 文档会在变更前以 parse-error 拒绝。

当精确字节很重要时,请在对用户可见的写入前使用 --dry-run。JSONC 和 YAML 编辑会修补现有文档(通过 jsonc-parser 或 yaml 文档 API), 因此未触及的字节通常会保留;Markdown 在任何编辑时都会根据解析后的结构重建文件, 这可能会规范化变更叶子之外的附带格式。当你希望预览以聚焦的前后补丁形式呈现, 而不是完整渲染文件时,请添加 --diff。 补丁会记录换行符变化和缺失的最终换行,因此应用它会产生与写入相同的字节。

示例

# Validate a path (no filesystem access)
openclaw path validate 'oc://AGENTS.md/Tools/$last/risk'

# Read a leaf
openclaw path resolve 'oc://gateway.jsonc/version'

# Wildcard search
openclaw path find 'oc://session.jsonl/*/event' --file ./logs/session.jsonl

# Dry-run a write
openclaw path set 'oc://gateway.jsonc/version' '2.0' --dry-run

# Dry-run a write as a unified diff
openclaw path set 'oc://gateway.jsonc/version' '2.0' --dry-run --diff

# Apply the write
openclaw path set 'oc://gateway.jsonc/version' '2.0'

# Byte-fidelity round-trip (diagnostic)
openclaw path emit ./AGENTS.md

更多语法示例:

# Quote keys containing / or .
openclaw path resolve 'oc://config.jsonc/agents.defaults.models/"anthropic/claude-opus-4-7"/alias'

# Deep JSON/JSONC paths can use slash segments; they normalize to dotted subsegments
openclaw path set 'oc://openclaw.json/agents/list/0/tools/exec/security' 'allowlist' --dry-run

# Replace a JSONC leaf with a parsed object
openclaw path set 'oc://openclaw.json/gateway/auth/token' '{"source":"file","provider":"secrets","id":"/test"}' --value-json --dry-run

# Predicate search over JSONC children
openclaw path find 'oc://config.jsonc/plugins/[enabled=true]/id'

# Insert into a JSONC array
openclaw path set 'oc://config.jsonc/items/+1' '{"id":"new","enabled":true}' --dry-run

# Insert a JSONC object key
openclaw path set 'oc://config.jsonc/plugins/+github' '{"enabled":true}' --dry-run

# Append a JSONL event
openclaw path set 'oc://session.jsonl/+' '{"event":"checkpoint","ok":true}' --file ./logs/session.jsonl

# Resolve the last JSONL value line
openclaw path resolve 'oc://session.jsonl/$last/event' --file ./logs/session.jsonl

# Resolve a YAML workflow step
openclaw path resolve 'oc://workflow.yaml/steps/0/id'

# Update a YAML scalar
openclaw path set 'oc://workflow.yaml/steps/$last/id' 'classify-renamed' --dry-run

# Address markdown frontmatter
openclaw path resolve 'oc://AGENTS.md/[frontmatter]/name'

# Insert markdown frontmatter
openclaw path set 'oc://AGENTS.md/[frontmatter]/+description' 'Agent instructions' --dry-run

# Find markdown item fields
openclaw path find 'oc://SKILL.md/Tools/*/send_email'

# Validate a session-scoped path
openclaw path validate 'oc://AGENTS.md/Tools/$last/risk?session=cron-daily'

按文件类型划分的示例

相同的五个动词适用于各种类型;寻址方案会根据文件扩展名进行分发。

Markdown

<!-- frontmatter.md -->
---
name: drafter
description: email drafting agent
tier: core
---
## Tools
- gh: GitHub CLI
- curl: HTTP client
- send_email: enabled
$ openclaw path resolve 'oc://x.md/[frontmatter]/tier' --file frontmatter.md --human
leaf @ L4: "core" (string)

$ openclaw path resolve 'oc://x.md/tools/gh/gh' --file frontmatter.md --human
leaf @ L9: "GitHub CLI" (string)

$ openclaw path find 'oc://x.md/tools/*' --file frontmatter.md --human
3 matches for oc://x.md/tools/*:
  oc://x.md/tools/gh           →  node @ L9 [md-item]
  oc://x.md/tools/curl         →  node @ L10 [md-item]
  oc://x.md/tools/send-email   →  node @ L11 [md-item]

[frontmatter] 谓词用于定位 YAML frontmatter 块;tools 通过 slug 匹配 ## Tools 标题,并且即使源文本使用下划线,条目叶子也会保留其 slug 形式(send_email 变为 send-email)。

JSONC

// config.jsonc
{
  "plugins": {
    "github": {"enabled": true, "role": "vcs"},
    "slack":  {"enabled": false, "role": "chat"}
  }
}
$ openclaw path resolve 'oc://config.jsonc/plugins/github/enabled' --file config.jsonc --human
leaf @ L4: "true" (boolean)

$ openclaw path set 'oc://config.jsonc/plugins/slack/enabled' 'true' --file config.jsonc --dry-run
--dry-run: would write 142 bytes to /…/config.jsonc
{
  "plugins": {
    "github": {"enabled": true, "role": "vcs"},
    "slack":  {"enabled": true, "role": "chat"}
  }
}

JSONC 编辑通过 jsonc-parser 进行,因此注释和空白在 set 后仍会保留。先使用 --dry-run 运行,以在提交前检查字节内容。.json 文件使用与 .jsonc 相同的适配器和编辑路径。

JSONL

{"event":"start","userId":"u1","ts":1}
{"event":"action","userId":"u1","ts":2}
{"event":"end","userId":"u1","ts":3}
$ openclaw path find 'oc://session.jsonl/[event=action]/userId' --file session.jsonl --human
1 match for oc://session.jsonl/[event=action]/userId:
  oc://session.jsonl/L2/userId  →  leaf @ L2: "u1" (string)

$ openclaw path resolve 'oc://session.jsonl/L2/ts' --file session.jsonl --human
leaf @ L2: "2" (number)

每一行都是一条记录。当不知道行号时,使用谓词([event=action])进行寻址;当知道行号时,使用规范的 LN 段。.ndjson 文件使用与 .jsonl 相同的适配器。

YAML

# workflow.yaml
name: inbox-triage
steps:
  - id: fetch
    command: gmail.search
  - id: classify
    command: openclaw.invoke
$ openclaw path resolve 'oc://workflow.yaml/steps/0/id' --file workflow.yaml --human
leaf @ L3: "fetch" (string)

$ openclaw path set 'oc://workflow.yaml/steps/$last/id' 'classify-renamed' --file workflow.yaml --dry-run
--dry-run: would write 99 bytes to /…/workflow.yaml
name: inbox-triage
steps:
  - id: fetch
    command: gmail.search
  - id: classify-renamed
    command: openclaw.invoke

YAML 使用 yaml 包的 Document API,而不是手工编写的解析器,因此普通的解析/输出往返过程会保留注释和编写格式,而解析后的路径使用与 JSONC 相同的映射键/序列索引模型。同一适配器处理 .yaml、.yml 和 .lobster 文件。

子命令参考

resolve <oc-path>

读取单个叶子或节点。通配符会被拒绝——请使用 find 处理这些情况。匹配时退出码为 0,未命中时退出码为 1,解析错误或模式被拒绝时退出码为 2。

openclaw path resolve 'oc://AGENTS.md/tools/gh/risk' --human
openclaw path resolve 'oc://gateway.jsonc/server/port' --json

find <pattern>

枚举通配符/谓词/联合模式的所有匹配项。至少有一个匹配时退出码为 0,零匹配时退出码为 1。文件槽位通配符会被拒绝,并返回 OC_PATH_FILE_WILDCARD_UNSUPPORTED,退出码为 2——请传入具体的文件路径。

openclaw path find 'oc://AGENTS.md/tools/**/risk'
openclaw path find 'oc://session.jsonl/[event=action]/userId'
openclaw path find 'oc://config.jsonc/plugins/{github,slack}/enabled'

set <oc-path> <value>

写入叶子。与 --dry-run 配合使用,可在不修改文件的情况下预览将要写入的字节内容。添加 --diff 以获取统一差异预览。成功写入时退出码为 0,如果底层拒绝(例如命中哨兵保护)时退出码为 1,解析错误时退出码为 2。

openclaw path set 'oc://gateway.jsonc/version' '2.0' --dry-run
openclaw path set 'oc://gateway.jsonc/version' '2.0' --dry-run --diff
openclaw path set 'oc://gateway.jsonc/version' '2.0'
openclaw path set 'oc://AGENTS.md/Tools/+gh/risk' 'low'

+key 插入标记会在命名子项尚不存在时创建它;+nnn 和单独的 + 分别用于索引插入和追加插入。

validate <oc-path>

仅解析检查。不访问文件系统。适用于在替换变量之前确认模板路径格式正确,或需要获取结构分解以便调试:

$ openclaw path validate 'oc://AGENTS.md/tools/gh' --human
valid: oc://AGENTS.md/tools/gh
  file:    AGENTS.md
  section: tools
  item:    gh

有效时以 0 退出,无效时以 1 退出(并返回结构化的 code 和 message)。缺少必需参数时,Commander 会以退出码 1 拒绝。

emit <file>

通过按类型划分的解析器和输出器对文件进行往返处理。对于正常文件,输出应与输入逐字节一致;出现差异表示解析器存在 bug 或命中了哨兵值。适用于在真实输入上调试底层行为。

openclaw path emit ./AGENTS.md
openclaw path emit ./gateway.jsonc --json

退出码

Code Meaning
0 成功。(resolve / find:至少有一个匹配项。set:写入成功。)
1 无匹配项、validate 输入无效、缺少必需参数,或 set 被底层拒绝。
2 路径或文件解析错误、模式被拒绝,或变更选项无效。

输出模式

openclaw path 支持 TTY 感知:在终端上输出人类可读格式,当 stdout 被管道或重定向时输出 JSON。--json 和 --human 会覆盖自动检测。

备注

  • set 在写入或 dry-run 预览之前,会拒绝包含 __OPENCLAW_REDACTED__(完整匹配或作为子串)的字符串叶值。这包括用于 frontmatter、条目和标题的 Markdown 插入值。普通编辑会保留无关的既有标记文本。
  • JSONC 解析和叶值编辑使用插件本地的 jsonc-parser 依赖,因此普通叶值写入会保留注释和格式,而不是经过手工编写的解析器/重新渲染路径。
  • path 不感知最后已知正常(LKG)配置跟踪或恢复;该生命周期由其他位置管理。如果你通过 path 编辑的文件也受 LKG 跟踪,则下一次配置读取会决定是提升还是恢复它;请将 path 编辑视为对该文件的其他任何直接写入。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw