Xinwei Xiong · 2026 年 7 月 18 日
9 分钟 · 4200 字 · | EN

Agent Skill 与 SKILL.md 设计:我拆了一个敢删文件的插件

从 storage-analyzer 的 SKILL.md 与源码出发,拆解 Agent Skill 的需求筛选、代码—模型—代码架构、触发描述、结构化契约、风险分级和权限白名单。结合 macOS 真机测试,分析后台进程、输出缓冲与挂载重复计数,并给出可复用的设计、审查和验收清单,适合开发高风险 Skill 的工程师。

Agent Skill 与 SKILL.md 设计:我拆了一个敢删文件的插件

一套有价值的 Skill,核心不在 prompt 多精妙,而在三件事划分得多干净:确定性的工作交给代码,语义判断交给模型,执行确认交还给人,再用结构化契约把三者缝起来。这个结论来自我最近拆解的一个存储清理 Skill。删文件是 Agent 的高风险能力,而它能让我从「本能警惕」走到「愿意确认」,靠的是设计,不是信任。

这篇文章把这次拆解还原成一套可复用的方法:找需求、定架构、写 SKILL.md、建安全模型、真机验证,最后再回头检视我自己的 Skill。它不是一份「照抄就安全」的模板,而是一套把假设摊开、让风险有地方被检查的方法。

一个敢删文件的插件,反而是最好的教材

事情的起点很日常:磁盘快满了,我装了卡兹克开源的 storage-analyzer 固定版本 ,让它分析我的电脑。它扫完 296 GB 的已用空间,生成了一份交互式网页报告:微信更新器藏了 8.9 GB 旧升级包、Xcode 构建缓存 6.1 GB,还有一个 UUID 目录被追查为已卸载编辑器的残留。每一项都有红黄绿分级,绿灯项旁边提供「移到废纸篓」和「直接删除」按钮。本文涉及的源码事实均以提交 a061851f5ace9b100c4586c03e2feece220a8673 为准,访问日期为 2026-07-31。

我在点下第一个删除按钮之前停了一下。一个从 GitHub 上装来的 skill,正在请求删除我本地的文件。这个动作背后如果有任何一环是含糊的——模型幻觉写错路径、网页被恶意页面伪造请求、我自己看走眼——代价都是真实的数据。

于是我读完了它的七个文件:SKILL.md、两份平台参考、三个 Python 脚本和一份报告模板。结论不是「这个 Skill 不会出错」,而是:它用分权和校验,在既定边界内显著降低了不可信环节造成误伤的概率与范围。需求真实、判断复杂、操作高危,所以它恰好把 Skill 设计中最难躲开的几个问题都摆到了桌面上。

找需求:先让流程过三道筛子

先回答最前置的问题:什么需求值得做成 Skill?

拆完这个案例,再对照我自己写 Skill 的经验,我更愿意用三个条件筛选:

第一,流程会被反复执行。磁盘隔一阵就要排查:看哪里占空间、判断能不能动、再清理。一次性任务通常直接在对话里解决即可,过早固化只会增加维护成本。

第二,流程中有模型具备条件优势的判断du 计算目录大小应交给脚本;识别 org.sparkle-project.Sparkle 的用途、追查 UUID 沙盒属于哪个 App,则需要知识检索和语义推理。若全程都是确定性操作,脚本通常更可靠;若没有稳定工序,一段 prompt 也许就够。Skill 适合落在两者的交界处。

第三,产出有明确的交付物和验收标准。storage-analyzer 交付一份固定阅读流的报告:现状、诊断、处方、操作、预防。只有结果可验收,迭代才有落点;「给一段更好的回答」很难承担这个角色。

三条不是公理,只是一把节省维护成本的筛子。能留下来的流程,才值得继续设计。

定架构:代码—模型—代码的三明治

storage-analyzer 的整条流水线是四段,每段的执行者不同:

scan.py(确定性代码)   → 扫描磁盘,输出事实 JSON
Claude(模型)          → 解读事实、分级判断,产出 analysis JSON
server.py(确定性代码) → 渲染网页 + 白名单约束下的删除 API
用户(人)              → 网页上逐项确认、点击执行

这个结构可以叫**「代码—模型—代码」三明治**。上游扫描 JSON 提供事实,下游 analysis JSON schema 约束提案,让确定性代码能够消费结果,而不必解析自由文本。两份契约还有一个常被忽略的作用:出错时可以判断是采集错、判断错,还是执行错。没有中间产物,三类错误最后只会混成一句「Agent 做坏了」。

它没有承诺消灭幻觉,而是把模型输出降级为提案。待删路径要通过 server.py 的 realpath 白名单与目录护栏,最后再由浏览器确认。这样不能保证零误删,却能在白名单正确、用户认真确认等条件成立时缩小破坏半径。

让 Agent 在对话里直接跑 rm -rf,等于把判断、执行、确认三权合一。分权首先是安全设计,其次才是效率选择。

写 SKILL.md:它是给模型看的 PRD,不是给人看的 README

拆解中最颠覆我认知的部分是 SKILL.md 本身。它不只是一份传统说明文档,更像一份面向模型的产品需求文档,每一段都有明确的工程意图。

description 是触发路由。它覆盖「磁盘满了」「C 盘满了」「清缓存」「占空间」等口语,也处理「内存满了」的歧义:可能指存储空间,但明确询问 RAM 进程占用时不应触发。正例覆盖加负例排除,目标是减少漏触发和误触发;具体效果仍应由真实调用样本验证。

铁律区定义不可绕过的边界SKILL.md 开头四条铁律中,有一条要求:即使用户说「帮我删」,也要先确认,不得直接代跑。它把执行期最危险的捷径提前封住。

知识按执行阶段分层供给SKILL.md 本体约百行:分析时才读平台布局参考,写报告时再看脚本头部的 schema。模型在扫描阶段不必背负输出字段,这正是渐进式披露的价值。

UI 契约也写进 prompt。前端从自然语言字段中解析 GB 数字来绘制进度条,所以 SKILL.md 要求三个统计值以可解析数字开头,并统一估算表述。prompt 在这里已经承担接口文档的一部分:模型既然是系统组件,输出约束就要写到字段级。

排障预案写给未来的执行者。「没有删除按钮」被收敛为两个常见原因:打开了静态报告,或绿灯项漏了 trash_paths。把症状、原因和修复放在一起,Agent 才不必每次从头猜。

建安全模型:风险分级映射权限分级

这个 skill 处理高危操作的方式,值得单独立一节,因为它给出了一个可以直接套用的模式:把风险分级精确映射成权限分级。

它把所有清理项分成三灯,每一灯对应一组严格递减的能力:

级别语义能做什么
🟢 可自动清理纯缓存、可再生、不丢数据移废纸篓 + 直接删除
🟡 需人工判断含用户数据、有判断成本在访达打开;核实过的安全子路径才能移废纸篓
🔴 谨慎清理该走正规卸载流程的应用只能「在文件管理器打开(去卸载)」

注意其中的层次:按当前实现,黄灯不能直接删,只能走可逆的废纸篓;红灯连废纸篓也不给,因为应用卸载可能涉及自带卸载器、残留和管理员权限。它只把用户送到正确位置,让人完成最后一步。风险每升一级,不可逆能力就收一级。

同一份分析 JSON 同时驱动 UI 和权限:trash_paths 决定按钮是否出现,也是后端删除白名单的来源。数据即权限声明能减少前后端错位,但正确性仍取决于分析 JSON 与服务端校验是否都写对。尤其要警惕「字段通过 schema」被误认为「路径语义正确」:schema 只能证明形状合规,不能证明某个缓存目录真的可再生;后者仍需要参考知识、现场证据和人的确认。

在这之外还有八层防线:本地回环绑定、随机端口、会话 token、Host 头校验,降低外部页面发起请求的风险;realpath 后的分级白名单与目录范围护栏,拦截越界提案;浏览器确认与废纸篓优先,减少手滑的代价。这里要补一个代码细节:删除操作限于用户目录,而只读的「打开」还允许 /Applications。八层措施彼此补位,但它们降低风险,不等于证明系统绝对安全。

真机验证:我发现了它的三个盲区

源码只能说明作者想怎么做,运行才会暴露环境怎么反驳它。我在自己的机器上跑了扫描、分析、报告、网页清理和停服务,也遇到三个盲区:

一是 stdout 缓冲:服务用 print 输出报告地址,在 agent 的后台任务管道里被块缓冲吞掉,agent 根本读不到 URL。二是前台进程假设:服务设计成「前台跑、Ctrl+C 停」,这是给人用终端的心智模型;agent 的后台任务管理在回合结束时清理子进程,服务被杀了两次,最后要用 nohup 脱离会话才稳住。三是挂载视图重复计数:OrbStack 把虚拟机数据挂载成家目录下的一个视图目录,du 把同一份 12 GB 数据算了两遍,扫描脚本没有挂载点去重,全靠模型在分析阶段自己识破。

三个盲区指向同一件事:Agent harness 与人类终端不是同一种运行环境。前台进程、stdout、Ctrl+C 这些假设不一定成立。把后台执行列为正式场景,意味着输出可落盘、服务可管理、状态可查询;具体方案仍取决于宿主如何管理子进程。比如 URL 同时写入状态文件,服务提供健康检查与显式停止命令,都比把关键状态只打印到终端更容易被 harness 接管。

用这套方法回检我自己的 skill

拆完别人的,就该照镜子了。我自己的博客仓库里有一个自产的 skill:article-covers,从文章的 front matter 生成封面图。在上一篇兵工厂 里我还写了四个内容创作 skill。用这篇文章的方法论回检,及格的地方和不及格的地方都很清楚。

及格的地方:封面反复要做,视觉隐喻是模型相对擅长的判断,产出又有固定尺寸。早期封面一出现书或杂志,图像模型就常生成乱码,于是我把「隐喻用形态,不用印刷品」写进规则。它和 storage-analyzer 把 UUID 容器案例写入参考文档做的是同一件事:把一次侦查的成本沉淀为可复用的先验。

不及格的地方也清楚:description 只有功能,没有触发边界;输出契约依赖「模型自觉」,缺少 schema 校验;封面路径出错时也没有排障段。这些不是审美问题,是工程债。

拆解的价值正在这里:得到一面镜子,而不只是围观一个答案。

可以直接抄走的设计清单

把整篇收敛成一张清单。如果你要写一个「高危操作 + 模型判断」类的 Skill:

  1. 需求过三关:反复执行、有模型具备条件优势的判断、有明确交付物;不满足时重新评估是否值得固化;
  2. 架构上代码—模型—代码:确定性工作交脚本,判断交模型,执行确认交人,用 JSON 契约缝合;
  3. description 写成触发分类器:正例穷举口语说法,负例显式排除;
  4. 安全边界写成铁律,并预判用户诱导(「帮我删」也不能直接删);
  5. 风险分级映射权限分级,不可逆能力随风险上升而收缩;结构化字段同时驱动 UI 和白名单;
  6. 防御按对手分组设锁:外部攻击者、模型幻觉、用户手滑,三类风险三组对策;
  7. 知识按执行阶段分层:主文件只放流程,细节挂 references 按需加载;
  8. 输出规范写到字段级,把模型当成需要接口文档的组件;
  9. 把 agent 的常见失败模式写成排障段,把踩过的坑固化在离坑最近的位置;
  10. 真机跑全流程,并把「被 Agent 在后台执行」作为正式场景测一遍。

泼冷水:大多数流程还不配被固化

最后照例泼冷水。

这套方法有一个前提:要固化的流程,至少已经被手动跑通并暴露过关键失败点。从 storage-analyzer 的路径知识和排障段可以推断,作者积累过多轮实践;但仅凭公开仓库无法证明具体次数。Skill 固化的是判断和边界,没跑通的流程只会把混乱复制得更快。

所以在打开编辑器写 SKILL.md 之前,先诚实地回答:这件事你手动做过几遍?每一步的判断标准你能写出来吗?出错时你知道去哪看吗?三个问题有一个答不上来,就先回去手动做,把坑踩够。

**Skill 更适合复用你已经做对、也知道如何验收的事,而不是掩盖你尚未理解的流程。**这句话送给准备写第一个 Skill 的你,也送给拆完源码就手痒的我。

真正的安全不是把风险藏起来,而是让每一种风险都有对应的检查点,也给人留下停手的位置。

常见问题

03
什么样的需求值得做成一个 Agent Skill?

优先选择会反复执行、包含模型擅长的语义判断、又有明确交付物和验收标准的流程。磁盘清理就是一例:脚本扫描,模型辅助判断目录性质,最终交付分级报告。

SKILL.md 的 description 应该怎么写才能提高触发率?

把 description 当成路由规则:覆盖常见口语正例,也写明容易混淆的负例。例如“内存不够”可能指磁盘空间;用户明确询问 RAM 进程占用时则不应触发。

让 LLM 提议删除文件,如何防止幻觉造成误删?

让模型只提交提案:服务端以 realpath 后的分级白名单和目录范围护栏限制操作,网页再次确认,并优先使用可逆的废纸篓。回环绑定、随机端口、会话 token 与 Host 校验则降低恶意网页发起请求的风险。

读者回响

加入讨论

新文章写好,先寄给你

每有新文章,寄一封信到你的邮箱。双重确认,随时退订。