一套有价值的 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:
- 需求过三关:反复执行、有模型具备条件优势的判断、有明确交付物;不满足时重新评估是否值得固化;
- 架构上代码—模型—代码:确定性工作交脚本,判断交模型,执行确认交人,用 JSON 契约缝合;
- description 写成触发分类器:正例穷举口语说法,负例显式排除;
- 安全边界写成铁律,并预判用户诱导(「帮我删」也不能直接删);
- 风险分级映射权限分级,不可逆能力随风险上升而收缩;结构化字段同时驱动 UI 和白名单;
- 防御按对手分组设锁:外部攻击者、模型幻觉、用户手滑,三类风险三组对策;
- 知识按执行阶段分层:主文件只放流程,细节挂 references 按需加载;
- 输出规范写到字段级,把模型当成需要接口文档的组件;
- 把 agent 的常见失败模式写成排障段,把踩过的坑固化在离坑最近的位置;
- 真机跑全流程,并把「被 Agent 在后台执行」作为正式场景测一遍。
泼冷水:大多数流程还不配被固化
最后照例泼冷水。
这套方法有一个前提:要固化的流程,至少已经被手动跑通并暴露过关键失败点。从 storage-analyzer 的路径知识和排障段可以推断,作者积累过多轮实践;但仅凭公开仓库无法证明具体次数。Skill 固化的是判断和边界,没跑通的流程只会把混乱复制得更快。
所以在打开编辑器写 SKILL.md 之前,先诚实地回答:这件事你手动做过几遍?每一步的判断标准你能写出来吗?出错时你知道去哪看吗?三个问题有一个答不上来,就先回去手动做,把坑踩够。
**Skill 更适合复用你已经做对、也知道如何验收的事,而不是掩盖你尚未理解的流程。**这句话送给准备写第一个 Skill 的你,也送给拆完源码就手痒的我。
真正的安全不是把风险藏起来,而是让每一种风险都有对应的检查点,也给人留下停手的位置。





读者回响