如何写 Skill 第11课,实战工坊:痛点验出来,骨架偷出来

0 阅读21分钟

封面

摘要:做 skill 的第一道坎不是「怎么写」,是「写什么」。这一课摊开选题全过程:拿 skills.sh 安装量验痛点,五判据过堂圈定 using-git-worktrees(21.6 万安装);拿 GitHub API 对质标本——单文件、167 行、零脚本;逐门解剖三段序与四道门,偷骨架、找软肋;最后立项四项,把标本变成自己的。全文一把尺子:验过的才算数。

共约 6131 字 · 阅读约 15 分钟

  老规矩,先放声明:经历全是真的,身份一概没有——公司、内部路径与真人代号全部脱敏,数字保留 2026-10-23 当日实测原值。

1、开场:三张罚单

  十课练完,按计划该真做一个自己的 skill 了。我以为第一道坎是「怎么写」,坐下来才发现人倒在更前面——「写什么」。

  我不信选题这事需要方法,拍脑袋圈了三个热门候选,按安装量从高到低排,打算从最大的下手。罚单当天到了三张:

  • 第一张,systematic-debugging,304.3K 安装。名字越看越眼熟,点开想了三秒:我家技能库里躺着 diagnosing-bugs——撞自家领地,一票否决。
  • 第二张,verification-before-completion,249.7K 安装。通篇判断、零脚本,我后面要练的脚本位,它一个格子都腾不出来。
  • 第三张,changelog-generator,7.3K 安装。选题本身不坏,坏在需求:7.3K 这个数,是市场投完票之后的得票。

  三张罚单,罚出同一个道理:「写什么」不是口味问题,是验证问题。这一课我把全过程摊开——验痛、对质、补课、解剖、偷与留、立项,六道工序;每道工序我踩过的坑,就地埋在那个环节里,你走到哪,坑就看到哪。

2、验痛:安装量是需求的证据

  开头把结论放这:痛点不是想出来的,是验出来的;你脑补的需求,和安装量投出来的需求,经常不是同一个。

  工具就两样:skills.sh 的排行榜,加 npx skills find <关键词> 的定向检索。安装量是市场需求投的票,每一票背后是一次真实的安装决策,比任何「我觉得大家需要」都硬。

  我先把生态的家底对了一遍账。我自己装的库里,光方法论系前排就一串:grilling 1.4M、grill-with-docs 1.2M、tdd 1.1M、handoff 1.0M、code-review 783K(截至 2026-10-23 的 skills.sh 快照)。头部清一色是「怎么跟 agent 共事」的方法论,领域型 skill 靠后。为什么方法论系霸榜?我有个没验证的猜测:共事方法每个 agent 用户都要,领域知识只圈各自领域的人——当猜测听,别当结论用。真空白怎么圈?我立了五条判据,逐条过堂:

  1. 安装量验痛——没有安装量,就没有需求证据;
  2. 不撞已装库的领地——再热,跟现有 skill 抢同一块地就毙;
  3. 六站练得满——工坊六站(需求定性、description、骨架、脚本、调试、评测)每站都得有活干,没脚本位就练不满;
  4. 作者可信——读得懂他为什么这么设计,学得来;
  5. 贴自己的日常——自己用得上,才测得动。

  四个候选过堂,生死全在这张表里:

01-SHORTLIST·五判

  表上最扎眼的是 systematic-debugging:304.3K 安装,死在第二条。另两张的死因同样干脆:verification-before-completion 死在判据 3(没脚本位),changelog-generator 死在判据 1(没安装量)。安装量是必要条件,不是充分条件——它只证明「有人要」,不证明「该你做」。

  活口只有一个:obra/superpowers 仓库里的 using-git-worktrees,216.4K 安装(skills.sh,2026-10-23 快照,随页面浮动),五条全过,装前过一道 Socket/Snyk 审计。仓库整体 303,963 stars(GitHub API,当日——star 数的是仓库人气,安装数的是单个 skill,口径不同,但都指向同一件事:不是冷门),skills 目录下 15 个技能,README 开头一句自己交的底:

An agentic skills framework & software development methodology that works.

  作者 Jesse Vincent,工单系统 Request Tracker 就是他的——判据第四条不用再找佐证。第五条最私人:我自己的日常里,「同一个仓库并行跑两条线」是隔三差五就要应对的麻烦,在途分支改到一半,线上急修插进来,stash 来 stash 去。有体感的痛点,才测得动。

  这一环我留一句话,给全文当筛子:验过的才算数。它当场毙掉三个候选,后头每一节还要用它筛:没抓取过的不引,没实测过的不说,没验证过的设计不抄。

  验痛环节的翻车就两种:一种不验,拍脑袋,我开场示范过了;一种只看一个数,见安装量大就上。排查入口:npx skills find 敲你自己的关键词,数安装量,再拿五判据过一遍——第一判据自带减法,验不出痛点的方向当场毙掉——这套方法,同样用来否决。

3、对质:页面说的不算,仓库说的才算

  选题过了堂,货还没验。skills.sh 的页面告诉我标本是单文件,我差点直接信了。这毛病跟看 Swagger 文档猜接口行为一个样:文档是观察,响应才是契约。今天的检索就先给了我一个现成反例:检索摘要言之凿凿说 martinfowler.com 有篇 worktrees 专文,我点过去,404,站内搜个遍也没有。教训一句:没二次抓取过的「来源」,都不算数。

  对质两步。

  第 1 步,直查目录清单:

curl -s https://api.github.com/repos/obra/superpowers/contents/skills/using-git-worktrees

  判据:返回的 JSON 数组里只有一项,name 是 SKILL.md,size 是 6813——单文件,坐实(若返回的是 API rate limit exceeded 的报错对象,是未认证限流——每小时 60 次——不是标本变了,歇一会或带 token 再来)。

  第 2 步,拉本体数行数(当天 raw 域名 DNS 抽风,请求头带 Accept: application/vnd.github.raw+json 走 API 兜底):

curl -s -H "Accept: application/vnd.github.raw+json" \
  https://api.github.com/repos/obra/superpowers/contents/skills/using-git-worktrees/SKILL.md \
  | wc -l

  判据:167。零脚本、零附件,一个 SKILL.md 扛下全部(行数哪天漂了,以第 1 步的单文件判定为准,机制结论不靠 167)。

  打开文件,frontmatter 薄得出奇,只有两个键:

name: using-git-worktrees
description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans…

  课程里说的「标准六」(name、description、license、compatibility、metadata、allowed-tools),它只打底用了最简两样。description 全文 196 字符(不含键名与换行,当日实测口径),上面截的是前半——两个触发场景:feature 开发要隔离、跑实施计划之前;后半还补了一句能力:能用宿主原生工具就用,不行退回 git。

  拆到这我停了一下:正例有两个,负例呢?单线开发的别建、已在隔离区的别再建、被宿主接管的别插手——一个都没写。description 只画了领地的一半。这个洞先记账上,到第六节再点名。

  对质环节的翻车只有一种:拿转述当文物。排查入口也唯一:请求打到 artifact 本体——页面、摘要、别人的笔记,都只是观察,不是契约。

4、补课:worktree 和 branch 差在哪

  解剖前,先垫一块地基。工坊现场第一个举手的问题是学员原话:「worktree 和 branch 差在哪」——不深,但它是全员地基,地基不齐,第五节的四道门就是天书。第二问紧跟着来:「prune 会不会误删」。两问我都拿一次性实验仓实测过,跑完即删,过程照录(实测环境:git 2.53、Git Bash、Windows)。

4.1 worktree 是什么

  一句话:branch 是指针,worktree 是目录。branch 本质是 40 字节的小文件,指着某个 commit;但一个工作目录同时只能挂一条 branch,想切分支,先得安顿手里的半成品。worktree 是给同一个仓库开第二个工作目录,各挂各的 branch——它不是 clone:clone 是把整间仓库复印一份搬走,worktree 是同一间仓库在隔壁开的第二个门面,库房共享,货架各管各的。

  第 1 步,起一个干净的实验仓:

git init demo && cd demo && echo a > a.txt && git add . && git commit -m init

  判据:打出一个提交哈希,主仓就绪(Windows 开着 autocrlf 的会多一行 LF/CRLF warning,无害)。

  第 2 步,开第二个门面:

git worktree add -b feature-x ../demo-wt

  判据:输出有 Preparing worktree (new branch 'feature-x'),../demo-wt 目录真实生成。

  第 3 步,点验登记:

git worktree list

  判据:两行登记,一行主仓、一行新目录。

  第 4 步,验「共享」,两端各跑一次:

git rev-parse --git-common-dir

  判据:主仓端打 .git,worktree 端打出一个指回主仓的绝对路径——对象库是同一份,这不是 clone。顺带看一眼:主仓自己也是登记在案的一条 worktree,这个细节第五节要用。顺手把账算清:多工作树时,$GIT_DIR 下多数文件各挂各的(HEAD、index 归这半边,这一项是我按手册总纲推的,手册没逐字点名),common 目录下的全仓共享。

  第 5 步,验「互斥」,worktree 挂着 feature-x 的当口,回主仓敲:

git checkout feature-x

  判据:git 亲自拦下,报错点名该分支已被某路径上的 worktree 占用——原话 already used by worktree at … 收在节末终端实录里。分支互斥没死,一个分支不能同时挂两个目录。

  共享、互斥各有实验作保;并行不用单测——第 2、3 步那两行登记就是它:两个目录、两条分支,同时在线。三验收工。把 worktree 当 clone 的代价是心理上的:以为要多占一份磁盘、要重新 fetch,于是明明有正解却不敢用——学员那一问,解开的正是这个心结。

4.2 删除会误删吗

  先给结论:prune 不删任何东西,只收尸。git 手册原文:

prune — Remove worktree information in $GIT_DIR/worktrees for worktrees whose working trees are missing.

  它只动 $GIT_DIR/worktrees 里的登记条目,而且只动「working trees are missing」的——活目录、分支、提交,职权范围外一个不碰。不放心就带 --dry-run,它只报告会删什么,自己不动手。

  真正的删除另有其人,是 remove,默认自带安全门:

remove refuses to remove an unclean worktree unless --force is used. To remove a locked worktree, specify --force twice.

  不干净(有未提交改动或未跟踪文件,带子模块的同理)直接拒;lock 过的要按两次 --force;主工作树压根不可移除。remove 拆得掉目录,拆不掉分支——分支是 ref,留在共享 refs 里。

  手册读完,实验仓里把删除链走一遍,光读不算验。

  第 6 步,给 worktree 塞个未提交改动再删:

echo dirty >> ../demo-wt/a.txt && git worktree remove ../demo-wt

  判据:当场拒绝——fatal 原话 fatal: '../demo-wt' contains modified or untracked files, use --force to delete it,要求显式 --force 才放行(实录块里也有这句)。

  补半步,显式给 --force:

git worktree remove --force ../demo-wt && git branch --list feature-x

  判据:这回删得动,feature-x 原地还在——branch --list 的预期输出是一行行首带两空格的 feature-x,输出为空就是分支没了,回来重查。force 拆得掉目录,拆不掉分支,提交过的一切躺在共享对象库里,force 也够不着。

  第 7 步,另开一个干净 worktree(add 会照常打一行 Preparing,走的 stderr,别慌),这回不走 remove,直接手动删目录:

git worktree add -b feature-y ../demo-wt2 && rm -rf ../demo-wt2 && git worktree list

  判据:demo-wt2 那条登记还在,多了一枚 prunable 标记——目录没了,登记成尸(prunable 注记在 git 2.53 实测可见;老版没有注记,可用 git worktree prune --dry-run 复核)。

  第 8 步,收尸加验尸:

git worktree prune && git worktree list && git branch

  判据:登记摘掉,feature-x、feature-y 都原地还在——prune 只收尸,分支从来不在它职权里。

02-TERMINAL·一次性

  实测钉成一句安全梯度:prune 清白,只收尸;remove 恋家,脏了就拒;唯一丢数据的组合是 --force × 未提交改动——提交过的一切都在共享对象库里,force 也拿不走。这三条先记住,第六节它们要变成收摊脚本的现成规格。

  补课环节两种翻车:把 worktree 当 clone,不敢用;把 prune 当删除,错位恐惧——真危险的 --force 捷径反而没设防。排查入口就一条命令:git worktree list,prunable 标记在,是尸;不在,不给 --force 谁也删不了你的活目录。

5、解剖:三段序与四道门

  地基垫完,进正题:167 行、零脚本的纯判断正文,凭什么 216.4K 安装?把标本从头读到尾,骨架其实只有一行:

Core principle: Detect existing isolation first. Then use native tools. Then fall back to git. Never fight the harness.

  先检测既有隔离,再用宿主原生工具,最后回退到 git,永不跟 harness 对着干。167 行正文,全是给这四句打的下手。

5.1 三段序

  顺序本身就是设计:检测→原生→回退,不可换。分流画出来是这样:

03-WORKTREEFLOW

  图上最反直觉的是第一岔口。顺序是安全性,不是效率——检测排第一,不是查一下便宜,是跳过它的代价最贵:两类事故同时开门,一类「建了又建」,在已是 worktree 的地方再叠一层;一类在子模块里误判,把宿主目录当成隔离区。省下的半秒,跟这两类事故比,不叫钱。

5.2 四道门

  判断句往下落,是四道门,一个模板讲完:判什么、怎么判、翻车长什么样。

  第一道,检测门。机械判定:对比 git rev-parse --git-dir 和 --git-common-dir,相等说明你站在主仓,不等说明你已经在 worktree 里。主仓自己也是登记在案的一条 worktree(补课第 4 步看过),所以站在主仓时两个 flag 天然相等;你亲手打的那两行路径,是这道门的输出形状——worktree 端的 --git-dir 指向主仓的 .git/worktrees/<id>(这条按手册总纲推,手册没逐字点名),门本身比较的则是同一端的两个 flag。机制课和标本课在这里会师。但机械判定必有反例:子模块里这个不等式同样成立,会把子模块误判成 worktree——这道门的翻车现场。所以标本补了 guard:

git rev-parse --show-superproject-working-tree

  再查一次自己是不是站在别人的超级项目里。机械判定必有反例,检测要带 guard,这句抄走就能用。

  第二道,consent 门:先问,再建。标本给的理由就一句:

It protects your current branch.

  建隔离区是动工作区的动作,不问自取,agent 就在你没点头的地方改了目录结构——这就是这道门的翻车。

  第三道,原生优先门:宿主有装置,就用装置,轮不到手搓 git。绕过宿主手搓,造出来的是幻影状态——宿主文件树里没有这个目录、不追踪你的分支,出了事两边互相看不见的平行世界——这道门的翻车,连报错都不给。各家装置长什么样,5.3 摆在一起看。

  第四道,安全门,管两件事。头一件,目录从哪来,优先级四档写死,不留现场发挥:

  • 用户显式指定的,最优先;
  • 项目里已有的 .worktrees/;
  • 退一档的 worktrees/;
  • 都没有,才用默认位置。

  第二件事,建前查忽略:git check-ignore -q .worktrees 没过,就把 .worktrees 补进 .gitignore 并提交,再动手——不查这个,新目录会把整棵树带进版本库。

  门之外还有两处细活顺手记下。标本正文的 Step 2(装依赖)认包管理器不靠猜,看 manifest——package.json 认 npm,Cargo.toml 认 cargo,requirements.txt 认 pip,go.mod 认 go;Step 3(基线)建完跑测试,报告固定三行:路径、测试数、就绪与否。判断型 skill 的产出规格,也能抠到这个份上。

  解剖环节的翻车:读到「机械判定」就照抄,不带 guard——skill 上线那天,子模块用户替你发现反例。排查入口:给每条机械判定找一个反例,找到了,guard 就有着落。

5.3 「Never fight the harness」是趋势不是怪癖

  先把出处钉透,这里有个以讹传讹:这句话常被说成 superpowers 全体系的设计原则。我核过,逐字出处只是 using-git-worktrees/SKILL.md 正文那一行;README 的 philosophy 里另列四条,TDD、Systematic over ad-hoc 之类,两份清单不是一回事。引文引到行,这是硬规矩。

  然后是正题:这行字不是 obra 的个人怪癖。我把三家宿主的官方文档翻了一遍,他们各自造了原生 worktree 装置:

04-NATIVETOOLS·

  Claude Code 一条命令进隔离区:「Pass --worktree or -w with a name to create an isolated worktree and start Claude in it.」——目录建在 .claude/worktrees/<name>/,分支自动命名 worktree-<name>,会话整个搬进去,v2.1.198 起步;官方最佳实践里也写着,worktree 就是为了让多个会话 edits don't collide。Cursor 是一组 slash 命令,/worktree 开、/apply-worktree 收。Windsurf 在 Wave 13 把它列成一级支持,原话是「first-class support for parallel, multi-agent sessions」。三家的装置名、具体行为、文档出处,都收在上面表里。

  表后说判断:名字不同,姿态一致——worktree 已经是宿主的一等公民。这反过来坐实了第三道门:装置归装置的层,skill 该做的是检测它、调用它;手搓不是勤劳,是造幻影状态。装置借不来也替不了,这层边界,跟派工那课「派工=授权」是同一个道理:授权给谁的活,归谁干。

6、偷与留:软肋就是任务书

  解剖完,先掰正一个最容易读歪的点:解剖别人的 skill,是抄吗?不是。我偷的是设计判断——判断句、流程、表结构;文本一行不搬,全自己写。标本开源在仓库里,谁都能查,「偷」的是思路,不是字句。

  具体偷的是四样:第五节那行判断句、四道门的流程,加两张表。头一张,12 行决策表,「情况→动作」两列:「已在 worktree→跳过创建」「目录未忽略→补 .gitignore 并提交」「权限错→原地跑」。它把正文里带分支的判断压成查表,模型执行时不用重推推理链——查一行,动一步,是前十课磨症状表的同门手艺。

  第二张表,5 行反合理化表,「借口→现实」。借口原句全是第一人称内心戏:

「The worktree directory is surely ignored already」 「Any directory name works」 「The workspace is fresh — baseline tests can wait」

  每行都是模型会对自己说的话——它预判了自我说服,然后逐条封死。机理到这讲完了,把它跟第 3 课磨的常驻措辞配成一对,口诀:常驻措辞防忘,反合理化表防辩。

  偷完骨架,力气往哪使?拿六站标准反查,标本身上四处软肋,条条是差异化空间:

  1. 零脚本——六步带分支的检测每次内联重敲,漏一步就错;
  2. description 零负例——领地只画一半,第三节记的账在这兑现;
  3. 只有开张没有收摊——全文只管 add,list、remove、prune 一个字没有,第四节实测的安全梯度正好当收摊脚本的规格;
  4. bash-only——Windows 的 Git Bash 方言一个没兜,我工位恰恰是 Windows。

05-STEAL·偷四样(已验

  表后一句判断收拢:先偷骨架,再造差异。21 万多次安装验证过的判断,直接拿来用,不丢人;别把创造力花在已经验过的地方——重排三段序,等于拿自己的项目重赌别人赌赢过的局。

  偷与留环节的翻车是双向的:往左,把解剖做成抄写,文本照搬还觉得捡了便宜;往右,在验证过的地方自由发挥。排查入口:每动一处,先问一句「标本在这儿验证过没有」。

7、立项:四项把标本变成你的

  选题过了,立项落纸。立项四项是合议定下来的——需求句、定型与四分、负边界、目录名,一项项过,每项配一个反面教材。

  第一项,需求句。定稿版:「把「每次要在同一仓库并行跑两条线,都得手工敲五六步散装命令搭隔离环境」压成「说一句要隔离,agent 交出目录就位、依赖装好、基线干净的隔离工作区」」。判据一句话:主语是重复劳动,不是技术名词。反面教材:当场写过一版「worktree 管理」——四个字全是名词,看不见谁的哪件事被省了,废稿。

  第二项,定型与四分。定型:判断型,带从属脚本——这个 skill 的核心价值是判断链(建不建、建哪、安不安全、挂了怎么办),脚本只收敛机械段,跟把逻辑留主干、样板抽进工具类是一个分法;转换型(脚本即本体)结构正好相反,站 3、站 4 的重心全看这笔。定型完拆四分,九项活各归各位,其中两项跨类:

06-FOUR-WAYSPLI

  一句话账目:查和做进脚本,想留正文,借只调用。九行里七行单类:检测三连、子模块 guard、check-ignore 归查;该不该建、目录策略归想;worktree add 本体归借;收摊三件归做。两行跨类:装依赖——探测算查、执行算借;基线测试——命令算借、挂了怎么办算想。类计数:查 4、想 3、借 3、做 1,合计 11,正好等于九行加两个跨类,账这才对得平。

  第三项,负边界,至少三条,我们定了四条,守触发、执行、授权、环境四个面;每条都要答得出「谁会误触、最坏是什么」,答不出的负边界是免责声明:

  • 单线开发不做——触发面;
  • 已在隔离区不再建——执行面,交给 guard;
  • 未过同意门不建——授权面;
  • 非普通仓库不接,脚本退出码 2——环境面。

  第四项,目录名。硬规则照办(kebab-case、1-64 字符、无连续连字符、不以连字符开头或结尾、与目录同名),保留名也别碰——synced 任意大小写都不行,anthropic-skills 前缀是雷。真正要紧一条:用户嘴里说的词必须在名字里。我查过重名:71 个已装 skill 里 grep worktree 和 wt,零占用;但 wt-kit 这种短打型还是毙了——「wt」不是所有人的口头词,触发面弱半档。正主的名字也不能碰,using-git-worktrees 是 obra 的。最后定名 worktree-flow:worktree 是口头词根,flow 标领地——全生命周期,跟标本「只建不收」划清界线。

  立项四项都过了,还有一道暗闸要交代:选题判据和立项四项是两道独立的闸,过了后一道,不等于过了前一道。我拿 changelog-generator 当过对照样本:需求句、四分、负边界、名字全能答得漂亮,回头一看安装量,7.3K——立项再正规,救不回没需求的选题。

  这一课的实操现在轮到你,输入、动作、产出都定好:

  1. 输入:你自己想做的那个方向,一句话写下来;
  2. 执行:五判据过堂,过了再填立项四项的空;
  3. 预期输出:一张立项单——需求句、定型与四分、负边界至少三条(它们以后直接变站 5 盲测的 should-not 靶子)、目录名。

07-CHARTER·立项四项

  模板就这四格,拿你自己的题目填——哪一格填不出来,哪里就还没想清楚。立项环节的翻车清单:需求句写成技术名词、负边界凑免责声明、名字里没有口头词,三种废稿我各见过一次;排查入口:立项单每格拿「谁、哪件事、省了几步」过一遍,答不出就回炉。

8、收口

  六道工序走完,判断句打包,一句一个环节:

  1. 验痛:痛点不是想出来的,是验出来的——验不出来,就是没有;
  2. 对质:页面说的不算,仓库说的才算——没对质过的观察,只是巧合的信任;
  3. 补课:branch 是指针,worktree 是目录——prune 只收尸,remove 恋家,--force 是唯一的丢数据组合;
  4. 解剖:先检测既有隔离,再原生,再回退——机械判定必有反例,检测要带 guard;
  5. 偷与留:先偷骨架,再造差异——力气只花在软肋上;
  6. 立项:四项落纸才算立项——需求句、定型与四分、负边界、名字,缺一格回炉。

  六句背后是同一句判据,中段筛内容用的是它,你现在带走也用它:验过的才算数——没验过的选题不做,没验过的结论不写,没验过的观察不引。

带走三样

  1. 选题五判据:安装量、不撞领地、六站练得满、作者可信、贴日常,配上 npx skills find,选题从口味变成验证;
  2. 标本骨架:三段序判断句加四道门——检测带 guard、先问再建、原生优先、安全两查,21 万次安装验证过,直接搬;
  3. 立项四项模板:需求句、定型与四分、负边界、目录名,拿你自己的题目就能填。

临走三问

  1. 检测三连、子模块 guard、check-ignore 这类机械检查,立项四分时该记进「查」还是「想」?尺子是哪句话?
  2. 反合理化表那五行借口全是第一人称内心戏——它防的是用户、作者,还是模型自己?为什么非用它自己的口吻?
  3. 三段序若把「检测」挪到最后、先建再查,哪两类事故会同时开门?省下的半秒,最后付给了谁?

  三道都答对了,这一课才算真的带走。

  第一课到第十课,判据都是拿别人嚼过的案例练;这一课头一回对活标本动刀,工坊六站,站 1 走完。下几课进站 2 到站 4:description 怎么把领地画全——第三节记的那笔 196 字符的账,到时候还;骨架怎么从标本改出差异,脚本怎么捆进判断型——【下篇钩子占位】。


如果这篇文章对你有帮助,欢迎转发给需要的同事和朋友。