首页
/ OpenClaw nano-pdf Skill 实战指南:用自然语言编辑 PDF 页面,及其 Skill 门控与安装机制

OpenClaw nano-pdf Skill 实战指南:用自然语言编辑 PDF 页面,及其 Skill 门控与安装机制

2026-09-06 17:55:34作者:蔡怀权

OpenClaw 的 nano-pdf Skill 为 Agent 接入 nano-pdf 这个 PDF 编辑 CLI:你只需给出"第几页 + 一句自然语言指令",即可对 PDF 的单页内容做修改。本篇以该 Skill 文档为骨架,逐段讲解其命令用法、页码陷阱,并结合 OpenClaw 源码拆解 SKILL.md frontmatter 中 requires.bins 门控与 uv 安装声明是如何被解析、校验与执行的,读完后你既会直接使用这个 Skill,也能理解 OpenClaw Skill 从"声明依赖"到"自动安装"的完整链路。

什么是 nano-pdf Skill

nano-pdf 是 OpenClaw 内置在 skills/ 目录下的一个 Skill,定义文件为 skills/nano-pdf/SKILL.md。它的作用可以一句话概括:

Use nano-pdf to apply edits to a specific page in a PDF using a natural-language instruction. (用 nano-pdf 通过自然语言指令,对 PDF 的指定页面应用编辑。)

也就是说,它不是通用 PDF 处理工具,而是聚焦于单页自然语言编辑这一场景:标题改写、错字修正、内容替换等都可以通过一句英文指令完成。Skill 的 namenano-pdfdescription 为 "Edit PDFs with natural-language instructions using the nano-pdf CLI",homepage 字段指向 nano-pdf 在 PyPI 上的项目页面(OpenClaw 会在 Skill 元数据中解析该字段,见后文 frontmatter 解析部分)。

快速上手:一条 edit 命令

Skill 文档给出的 Quick start 用法如下,这也是 nano-pdf 的核心入口:

nano-pdf edit deck.pdf 1 "Change the title to 'Q3 Results' and fix the typo in the subtitle"

三个位置参数各司其职:

参数 示例 含义
文件路径 deck.pdf 待编辑的 PDF 文件
页码 1 要修改的目标页面
自然语言指令 "Change the title to 'Q3 Results' and fix the typo in the subtitle" 描述要做的具体编辑

文档特别给出了两条实战 Notes,务必保留在操作习惯里:

  1. 页码基线随版本/配置而变:Page numbers are 0-based or 1-based depending on the tool's version/config; if the result looks off by one, retry with the other.(页码是 0 起始还是 1 起始取决于工具版本/配置;如果结果差一页,换另一种基线重试。)
  2. 发送前必须人工核验:Always sanity-check the output PDF before sending it out.(输出 PDF 在发出前一定要做 sanity-check,确认改对了页、改对了内容。)

这两条提示对 Agent 自动化尤其重要:页码 off-by-one 是最常见的出错模式,而自然语言编辑的结果天然不可完全预测,所以"编辑 → 检查 → 再发送"是必要闭环。

SKILL.md 的 frontmatter 逐字段拆解

nano-pdf 的 SKILL.md 使用 YAML frontmatter 声明 Skill 元数据,这是 OpenClaw Skill 契约的核心部分。完整结构如下(homepage 为指向 nano-pdf PyPI 项目页的外部地址,此处以注释替代):

---
name: nano-pdf
description: "Edit PDFs with natural-language instructions using the nano-pdf CLI."
homepage: # 指向 nano-pdf 在 PyPI 上的项目页面
metadata:
  {
    "openclaw":
      {
        "emoji": "📄",
        "requires": { "bins": ["nano-pdf"] },
        "install":
          [
            {
              "id": "uv",
              "kind": "uv",
              "package": "nano-pdf",
              "bins": ["nano-pdf"],
              "label": "Install nano-pdf (uv)",
            },
          ],
      },
  }
---

各字段的实际行为都可以从 OpenClaw 源码中得到印证:

  • name / description:Skill 的身份标识与摘要,用于在 Agent 侧展示与检索。
  • homepagehomepage: readStringValue(metadataObj.homepage)frontmatter 解析器 中被读取为字符串字段。
  • metadata.openclaw.emoji📄,供 UI 展示。
  • requires.bins: ["nano-pdf"]:门控条件,要求系统 PATH 上存在 nano-pdf 可执行文件,详见下一节。
  • install:一条安装声明。kind: "uv" 属于 OpenClaw 定义的 5 种安装方式之一,src/skills/types.ts 中的类型定义为 kind: "brew" | "node" | "go" | "uv" | "download"。解析入口在 frontmatter.tsparseOpenClawManifestInstallBase(input, ["brew", "node", "go", "uv", "download"]),对 uv 类型还会做完整性校验——frontmatter.ts 中明确要求 spec.kind === "uv" && !spec.package 时声明不合法,即 uv 安装必须给出 package

门控(Gating):requires.bins 如何决定 Skill 是否可见

requires.bins: ["nano-pdf"] 是 nano-pdf 能被加载的前提。OpenClaw 的门控规则在 docs/tools/creating-skills.md 有完整表格:

字段 语义
requires.bins 所有列出的二进制必须存在于 PATH
requires.anyBins 至少一个二进制存在于 PATH
requires.env 每个环境变量必须存在于进程或配置中
requires.config 每个 openclaw.json 路径必须为真值
os 平台过滤:["darwin"]["linux"]["win32"]
always 即使 requires.* 检查失败,在兼容 OS 上仍包含该 Skill

从源码结构看,二进制检测由 src/skills/discovery/bins.ts 承担(status.ts 中即通过 hasBinary(...) 判断 brew 等命令是否可用)。对 nano-pdf 而言,语义很直接:PATH 里没有 nano-pdf 时,该 Skill 不会被视为"就绪",OpenClaw 转而提示安装——这正是下面 install 声明发挥作用的地方。

安装链路:从声明到 uv tool install nano-pdf

当门控不满足时,OpenClaw 会依据 install 声明执行安装。nano-pdf 声明了 uv 方式(package: "nano-pdf",安装标签 "Install nano-pdf (uv)"),其执行命令的构造位于 src/skills/lifecycle/install.ts

case "uv": {
  if (!spec.package) {
    return { argv: null, error: "missing uv package" };
  }
  const err = assertSafeInstallerValue(spec.package, "uv package", SAFE_UV_PACKAGE);
  if (err) {
    return { argv: null, error: err };
  }
  return { argv: ["uv", "tool", "install", spec.package.trim()] };
}

即最终执行的是 uv tool install nano-pdf,且包名会先经过 assertSafeInstallerValue 白名单式安全校验,防止 frontmatter 注入恶意参数。

安装方式的选择并非只看声明本身。src/skills/discovery/status.ts 中有一条表驱动(table-driven)的偏好链,"first match wins":

  1. 用户偏好 brew 且系统存在 brew 时用 brew 声明;
  2. uv 声明(nano-pdf 命中的就是这一级)
  3. node 声明;
  4. 系统存在 brew 时的 brew 声明(避免在 Linux/Docker 上 brew 必然失败);
  5. go 声明;
  6. download 声明;
  7. 最后兜底到 brew 并给出描述性错误。

nano-pdf 只有 uv 一种安装声明,因此必然落在第 2 级。此外 install-types.ts 定义了 SkillInstallSkipReason = "brew" | "go" | "uv",说明某些环境下 uv 安装可能被整体跳过(例如无 uv 运行时),此时 Agent 侧会收到手动安装提示。

这套链路的端到端证据在 src/commands/onboard-skills.test.ts 中:onboarding 流程以 nano-pdf 为夹具构造 Skill 条目(bins: ["nano-pdf"]installLabel: "Install nano-pdf (uv)"),用户多选 nano-pdf 后,安装备注会输出 uv: nano-pdf。作为对照,内置的 weather Skill 使用 kind: "brew"formula: "curl" 声明安装,直观展示了同一 frontmatter 契约下不同安装方式的差异。

使用建议与边界

结合文档原文与仓库证据,使用 nano-pdf Skill 时注意三点:

  1. 页码语义以实测为准:不同版本可能是 0 起始或 1 起始,编辑结果差一页时换基线重试即可(见 Quick start 的 Notes)。
  2. 输出必检:自然语言编辑的结果在发出前必须 sanity-check 输出 PDF;自动化流程中应把"检查产物"作为固定步骤。
  3. 第三方 Skill 视为不可信代码:OpenClaw 官方文档在 docs/tools/skills.md 的安全章节明确警告 "Treat third-party skills as untrusted code. Read them before enabling."——nano-pdf 本身是内置 Skill,但同样的原则适用于你引入的任何外部 Skill;对不可信输入与高风险工具,优先在沙箱中运行。

延伸阅读

登录后查看全文
热门项目推荐
相关项目推荐