humanlayer/skills 怎么用
5 个 markdown 文件、两条互斥的安装路线,和一份只有 3,297 字节却规定了六种画法的技能
📅 更新于 2026-09-13
本文校对于 humanlayer/skills @ main 3c26291(2026-08-13)· show-me 插件 v1.0.1 · skills CLI v1.5.26 · 官方源:github.com/humanlayer/skills
0030 秒速览:这 5 个东西能替你干什么
读完这一篇,你能做出三个判断:这 5 个技能里哪几个值得你装、它们各自在治哪一种毛病、以及为什么整仓 15 万个安装里有八成集中在最短的那一个文件上。这篇讲的是一整套技能包怎么用(含 5 个文件逐个拆解),不是某一个技能的内部实现细节。
① 这个仓库里没有程序,只有 5 个 markdown 文件(markdown 是一种纯文本排版写法,文件名以 .md 结尾)——所谓"安装"就是把文件复制到 agent(替你干活的 AI 程序)会去读的目录里,没有依赖、没有构建、没有守护进程(在后台一直跑着的程序);② 这 5 个分两类:三个是"敲一次就改完"的动作(重写项目说明、收窄 React 类型、把重复任务造成一台循环机器),两个是"表达规范"(要求 agent 用最小的图把话说清、以及先用控制论把"该自动改进什么"讨论清楚);③ 全部安装量里 八成以上落在最短的那一个(show-me,3,297 字节),因为它零依赖、不写你的仓库、当天见效——越短越通用的技能传播越广。
你现在的处境 → 直接用这个
| 你现在的状态 | 直接用这个 | 为什么 / 前置条件 |
|---|---|---|
| agent 又在用三段话解释一个本该一张图说完的东西 | 装 show-me,然后敲 /show-me | 零依赖、不写你的仓库、不需要密钥。这是唯一一个"当天见效、没有前提"的技能(04) |
你发现 CLAUDE.md(给 AI 看的项目说明书)里的规则没被遵守 | 装 improve-claude-md | 前提是它确实被"这条上下文可能相关也可能不相关"的框架稀释掉了;它只提高遵守率,不改事实对错(11) |
你的 React 组件(React 是做网页界面的 JavaScript 工具库)props(组件对外的入参)里全是 ?,而应用真实路径根本走不到那些分支 | 装 narrow-react-prop-types | 前提是"非测试、非 Storybook(一个把组件单独拿出来看效果的开发工具)的调用点就是全部真相"——这对应用成立,对公开发布的组件库不成立(12) |
| 已经能一句话说清"找什么、改什么、怎么验" | 用 build-iterated-agentic-loop | 它会往你仓库里写技能 + GitHub Actions 工作流(定时跑的自动化任务),要求配密钥(API key,一串让程序代表你调用外部服务的通行证)(13) |
| 想让 agent 反复改善某个指标,但还没想清楚怎么量 | 用 design-control-loop | 它会先访谈你一轮,把"驱动什么属性、谁来量"讨论清楚再动手;这是全仓最长的一份(14) |
| 想先试一次再决定要不要装 | npx skills use humanlayer/skills@show-me | claude | 不安装,只生成一段提示词(你写给 agent 的那段指令)喂给 agent(04) |
| 只想知道"这技能到底改了什么" | 按 commit(一次代码存档)的哈希取几份原文互相 diff(差异对比) | 这个仓库没有 changelog(更新日志);对短文本文件这是成本最低的考古方式(08) |
一条可执行的上手路径
它零风险:只有一个 markdown 文件,不写你的仓库、不需要密钥、不改你的代码。装完立刻能敲 /show-me。命令与落点见 04。
一组关键数字:先给量级
说清"skill / 插件 / CLI"这三样东西为什么是三种不同的东西;独立选对安装路线与作用域;讲出 show-me 的六种视图与四种 diff 各自该在什么时候用;并且知道哪些数字是本文实算的、哪些是平台统计的(复核方式都写在正文里)。
01这 5 个 skill 到底是什么
humanlayer/skills 是 HumanLayer 这个团队放在 GitHub 上的一个技能仓库:里面没有应用代码,只有一份"市场清单"、5 个插件目录,以及每个插件里的一份技能说明书(本文把 skill 与"技能"当同一个词用:它就是一份写给 agent 看的说明书文件)。它创建于 2026-03-18,用 MIT 许可(一种很宽松的开源授权,你可以随便改、随便商用),本文核对时 GitHub 的接口返回 3,889 stars / 114 forks(stars 是收藏数,forks 是别人把它复制到自己账号下的份数),最后一次推送是 2026-08-13。
先破掉四个错误印象
既然是"安装",那应该是个程序,有自己的配置中心和卸载程序。
没有依赖、没有构建、没有 package.json、没有 CI(持续集成:代码一推上去就自动跑检查的那套东西)、没有安装脚本。所谓"安装"就是把文件复制到 agent 会读的目录里。这也正是它能同时被 70 多家不同 agent 使用的原因——技能就是 markdown。
"装一个插件"和"装一个技能"听起来是一件事的两种说法。
根目录的 .claude-plugin/marketplace.json(2,730 字节)是给 Claude Code 原生插件市场看的;而 plugins/<插件>/skills/<技能>/SKILL.md 这套目录习惯是给 vercel-labs 的 skills 命令行工具看的。两套机制各读一半文件——理解这条,后面"装不上""装了两个版本"基本都能自己解释。
附件嘛,就是给人类读的补充阅读。
长模板、示例、脚本放进同级的 references/ 目录,由 SKILL.md 按文件名点名引用。装技能时会一并复制过去。于是附件数直接反映复杂度:show-me 与 improve-claude-md 是 0 个,narrow-react-prop-types 3 个,两个循环技能 8 与 10 个。
HumanLayer 是个商业产品,这个仓库大概是它的客户端。
HumanLayer 自己介绍为"多人协作的 coding agent IDE(集成开发环境,也就是写代码的那个编辑器)加云端"。但这个仓库里最有价值的那个技能(show-me)唯一的动作是写一个 HTML 文件然后打开它——不依赖任何 HumanLayer 服务。这个解耦是它后来拿到大量安装的结构性原因(见 08 的一手 diff)。
整个仓库长什么样:35 个文件、25 个目录
我用 GitHub 的文件树接口一次性取回全部条目(git/trees/main?recursive=1),数出来是 35 个文件、25 个目录。结构简单到可以背下来:
humanlayer/skills
├── .claude-plugin/marketplace.json # 市场清单:5 个插件的入口与分类
├── README.md / LICENSE / .gitignore
└── plugins/
├── show-me/
│ ├── .claude-plugin/plugin.json # 插件元数据:名字、版本、关键词
│ └── skills/show-me/SKILL.md # 技能本体(唯一文件)
├── improve-claude-md/ # 结构同上:2 个文件
├── narrow-react-prop-types/ # 2 + 3 个 references
├── build-iterated-agentic-loop/ # 2 + 8 个 references
└── design-control-loop/ # 2 + 10 个 references
这个结构里有三个设计决定值得单独说
| 设计决定 | 具体规则 | 为什么重要 / 别当什么用 |
|---|---|---|
| 插件与技能同名同层 | 目录名、plugin.json 里的 name、SKILL.md 头部的 name 三者必须一致。两个循环技能在文档里都写了加粗提醒:the name field in the SKILL.md frontmatter must match the skill slug(frontmatter 就是文件头部那段元数据;slug 这里指技能名)——技能叫 fix-eslint-issues,它就必须住在 .../skills/fix-eslint-issues/SKILL.md |
何时用:你要自己加一个技能、或者改技能名时。这不是洁癖——安装器是按路径找文件的(锁文件里的 skillPath 就是证据,见 04)。别当什么用:它不是"风格要求",改错了技能就装不上 |
| references 是"多出来的篇幅"的去处 | SKILL.md 只放有序步骤与判断规则;长模板、示例、脚本放进同级 references/,用文件名在正文里点名引用 |
为什么重要:附件数反映"产物能不能容忍自由发挥"。0 附件的 show-me 是在"教模型一种表达法",模型本来就会写字;带 8–10 个附件的循环技能是在"生成一整套会长期运行的文件",模板不写出来就只能靠模型自由发挥。别当什么用:不是参考资料库 |
| 除了 references,没有别的东西 | 没有测试、没有构建、没有 package.json、没有 CI、没有 install 脚本 |
为什么重要:这是它能被几十家 agent 通吃的原因,也是它风险低的原因——整个仓库只有 markdown,没有可执行脚本。别当什么用:换成别的仓库就要留意 references/ 里有没有脚本(见 16 第 5 条) |
看一个技能靠不靠得住,先看它有没有 references。0 附件的技能通常是在"教一种表达法",说明可以很短;带一堆附件的技能是在"生成一整套会长期运行的文件",它的产物稳定性取决于模板写得多死。附件数的多少,反映的是产物能不能容忍自由发挥。
一个容易忽略的事实
这个仓库自己既没有 CLAUDE.md 也没有 AGENTS.md(文件树里查不到),却携带一个专门帮你重写 CLAUDE.md 的技能。CLAUDE.md 和 AGENTS.md 都是"放在仓库根、给 AI 读的项目说明书"。这不矛盾——它把"仓库里的说明文件"当成用户侧的产物,而不是自己的文档。
02它解决什么问题:一个 skill 治一种毛病
这 5 个技能不是"五个功能",而是五种具体毛病。先看它们各自的一句话,再决定要不要往下读。
五个 skill 一手对照表
| skill | 它治的毛病 | 官方 description 的实质 | 读完/用完你能做什么 | SKILL.md 字节 | 附件数 |
|---|---|---|---|---|---|
show-me |
agent 又在用三段话解释一个本该一张图说完的东西 | 用简洁的图表、代码形状草图和聚焦的 HTML 产物解释"当前话题" | 把一段讲不清的东西换成一张看得懂的图/树/diff | 3,297 | 0 |
improve-claude-md |
你发现项目说明书里的规则没被遵守 | 用 <important if> 条件块重写 CLAUDE.md,提高指令遵守率 |
把一份又长又被忽略的项目说明改成"条件触发"的短文件 | 9,450 | 0 |
narrow-react-prop-types |
组件的 prop 类型被 Storybook/测试/mock 撑宽了 | 把 React 组件的 prop 类型收窄到真实代码路径(live 路径) | 删掉那些只为 Storybook/测试而存在的可选 prop | 7,764 | 3 |
build-iterated-agentic-loop |
你有一个明确的重复任务,想让它每天自己开 PR(合并请求:把改动提出来给别人评审) | 建一个仓库内技能,加一套会反复跑的 coding agent 工作流、提示词与记忆文件 | 把一个重复任务交给每天自己开 PR 的 agent | 13,553 | 8 |
design-control-loop |
你想让 agent 自动改善某个指标,但还没想清楚怎么量 | 访谈你把控制回路设计出来,再落成可本地运行 + 定时跑的实现 | 用控制论(传感器/控制器/执行器)想清楚"该自动改进什么属性" | 15,495 | 10 |
砍成两类:三个"一次性动作" + 两个"造一台机器"
这五个可以再砍成两类,而这个分类直接影响你怎么读它们的说明文件:
你敲一次,它改完文件就结束。show-me 产出一张图,improve-claude-md 重写一个文件,narrow-react-prop-types 收窄一批类型。它们没有后续、没有密钥、没有定时任务。
它们产出的不是一次改动的结果,而是未来会反复运行的东西:一个技能、一支定时工作流、一份跨运行存活的记忆文件、一组模板。所以它们的篇幅是前两个的 1.5–2 倍,多出来的全是模板与安全边界——无人值守的自动化比一次性改写承担更大的风险。
文件体量把这件事说得很清楚
| skill | SKILL.md 字节 | references 数 | 插件总字节 | 读它时的心理准备 |
|---|---|---|---|---|
show-me | 3,297 | 0 | 3,691 | 三分钟读完;规范靠示例,不靠条款 |
improve-claude-md | 9,450 | 0 | 9,847 | 一半篇幅是一个完整的"改前/改后"范例 |
narrow-react-prop-types | 7,764 | 3 | 21,336 | 十一步工作流 + 检查表 + 反模式 |
build-iterated-agentic-loop | 13,553 | 8 | 48,163 | 主要是"要产出哪些文件、每个占位符填什么" |
design-control-loop | 15,495 | 10 | 62,488 | 最长的一份;A–H 八个阶段,含访谈问题 |
5 份 SKILL.md 合计 49,559 字节(复核:用文件树接口筛出 SKILL.md 把 size 相加)。整个仓库的知识密度集中在不到 5 万字节的说明里,剩下的全是给生成物用的模板。
这些技能能替你省下的到底是什么
把它们翻译成"没有它你会怎样",会更清楚:
- 没有 show-me:你得到三段散文 + 一个 60 行的完整文件引用 + "总结一下,主要有以下几点"。读者要在文字里自己重建结构,而往往真正想问的只有"这个函数在第几步被调用"。
- 没有 improve-claude-md:你的项目说明书继续被一句"这份上下文可能与你的任务相关,也可能不相关"的框架包着,文件里越杂,模型越可能连相关的那部分一起忽略。
- 没有 narrow-react-prop-types:类型系统(在代码运行之前就用"类型"检查它的一层机制)继续允许那些应用真实路径永远不会进入的状态——每一个可选 prop 都是组件必须处理的一个额外分支。
- 没有两个循环技能:重复任务继续靠你手动想起来、手动跑、手动开 PR;而它们要解决的是"在你没盯着的时候也往前走"。
03什么场景该用、什么场景别装
先把结论说了:这 5 个技能里,只有 2 个值得大多数人装——show-me 和 improve-claude-md;另外 3 个是给特定处境的人准备的。下面这张表按"你的处境"来分,比按技能名分好查。
按处境选:四种典型场景
装 show-me。它解决的是"agent 长篇大论讲不清"这个高频摩擦:投入是敲一次命令,产出是一张能贴进 PR(合并请求)或群聊的图。
装 improve-claude-md。它的前提很明确:你的项目说明确实被"这条上下文可能相关也可能不相关"的框架稀释掉了。
装 narrow-react-prop-types。它的整套推理建立在"存在明确的真实调用点,也存在只服务 Storybook 的宽化"这个前提上。
用那两个循环技能。判断标准很硬:你能不能用一句话说出"找什么、改什么、怎么验"。说不出来就别从自动化开始。
也要说实话:它不适合谁
- 不用 Claude Code 的人,只剩一半功能。
show-me的收尾动作写成Bash(open …),那是 Claude Code 的工具调用记法;换到别的 agent 框架你得自己翻译(见 07)。plugin.json/marketplace.json那套也只为 Claude Code 插件市场服务。 - 想要"一套完整方法论"的人会失望。这里没有编排、没有阶段门、没有进度账本。它更像 5 把独立的工具,不是一条流水线。
- 没有 CI(持续集成,代码一推就自动跑检查的那套东西)、不想让 agent 开 PR 的人,别碰后两个。它们会往你的仓库里写 GitHub Actions、要求配置密钥、并使用绕过权限的 agent 模式。装完不配,只会得到一排红色的失败记录。
- 只想要"生成一篇学习文章"的人应该用别的东西。
show-me的产物是一次性的图与 HTML,不落库、不带校对日期、没有质量门槛。对照见 09。
先装 show-me(零风险、当天见效);有被忽略的项目说明书再装第二个;只有当你已经能一句话描述一个重复任务时,才考虑那两个会开 PR 的循环技能。
04怎么装:两条路,先选一条
同一个技能有两条完全不同的安装路。它们的区别不在"装到哪",而在"谁在读这个仓库"——选一条,用同一条更新。
路 A:skills 命令行工具(CLI,即在终端里敲命令用的界面)(README 官方推荐)
仓库 README 给的就是这一条:
npx skills add humanlayer/skills --skill show-me
这里的 skills 不是 Claude Code 的一部分,而是一个独立的 npm 包(vercel-labs/skills,自称 "The open agent skills ecosystem")。npx 是 npm(Node 的包管理器)自带的一个命令,意思是"临时下载这个包并执行它",所以你不需要先全局安装。本文核对时它最新版是 1.5.26(2026-09-11 发布)。它的 README 写着:Supports OpenCode, Claude Code, Codex, Cursor, and 75 more——也就是点名 4 家、另外还有 75 家,合计 79 家 agent;我数了它文档里的"支持列表"表格,共 70 行(有些行一行覆盖多个 agent 名)。这条路不绑定 Claude Code,这是它相对插件市场的最大优势。
先只看不装:用 --list 把仓库里的技能列出来
我实际跑过一次(npx -y skills@1.5.26 add humanlayer/skills --list),它把仓库里 5 个技能连同各自的 description 全部列了出来,顺序是:improve-claude-md、narrow-react-prop-types、build-iterated-agentic-loop、design-control-loop、show-me。
CLI 列出的 description 与 README 里的简介不完全一样——CLI 读的是 SKILL.md 头部那段元数据,README 是人工写的。两者不一致时,以 SKILL.md 为准,因为那才是模型真正读到的东西。
我实测的安装结果(可复核)
在一个空目录里执行 npx -y skills@1.5.26 add humanlayer/skills --skill show-me -a claude-code -y 之后,目录里只多了两样东西:
.claude/skills/show-me/SKILL.md # 技能本体(3,297 字节)
skills-lock.json # 记账文件
CLI 自己打印的是 ✓ show-me (copied) → ./.claude/skills/show-me。注意是 copied 不是 symlink:交互安装时它会让你在"符号链接(一个指向真实文件的快捷方式,推荐,单一真相)"与"复制(各 agent 独立副本)"之间选,非交互模式下的结果就是复制。锁文件长这样:
{
"version": 1,
"skills": {
"show-me": {
"source": "humanlayer/skills",
"sourceType": "github",
"skillPath": "plugins/show-me/skills/show-me/SKILL.md",
"computedHash": "de32a72f802801f08a84641b467f2c6306d35a58ce5e59ea607ac3a993a18c91"
}
}
}
skillPath 这一行顺手回答了一个常见疑问:为什么仓库要把技能埋在三层目录里。因为一个仓库可以有很多插件,CLI 需要精确知道"这个技能到底在哪个文件",这样同一个仓里的 5 个技能才能被分别安装、分别记账、分别升级。
装到哪儿:项目内还是全局
| 作用域 | 写法 | 落点 | 什么时候用它 |
|---|---|---|---|
| 项目(默认) | 不加参数 | ./<agent>/skills/,即 .claude/skills/ 这类 | 团队共享:跟着仓库走,评审里能看到技能变更,新人 clone 就有 |
| 全局 | -g / --global | ~/<agent>/skills/ | 个人跨项目常用:像 show-me 这种跟具体仓库无关的技能 |
把 design-control-loop 这种会往仓库里写 GitHub Actions 的技能装成全局,等于让它在任何一个你打开的仓库里都可能被触发。团队里别人看不见你装了什么,技能一升级行为就悄悄变了。
与具体代码库绑定的(narrow-react-prop-types、两个循环技能)装项目内,随仓库提交;纯通用的表达类技能(show-me)才值得装全局,这样每个项目都能用,且不污染任何仓库。
路 B:Claude Code 插件市场
因为仓库里有 .claude-plugin/marketplace.json,Claude Code 可以把它整个当市场加入,然后按插件安装(插件名与目录名一致:show-me、improve-claude-md、narrow-react-prop-types、build-iterated-agentic-loop、design-control-loop)。这条路的特点是它会连 plugin.json 一起用——也就是说,走市场安装时,插件版本号(1.0.1 之类)与关键词是有意义的;走 CLI 安装时它们基本被忽略,因为 CLI 只读 SKILL.md 目录。
同一个技能用插件市场装一次、再用 CLI 装一次,你会得到两份可能已经不同步的副本(一份在插件目录、一份在 .claude/skills/),而 agent 看到的是两份说明。选一条路,然后用同一条路更新。
后续维护:四条命令
| 命令 | 做什么 | 为什么需要它 |
|---|---|---|
npx skills list | 列出已装技能(项目 + 全局) | 在你怀疑"到底装没装、装的哪一份"时,这是唯一权威来源 |
npx skills update | 把已装技能更新到最新 | 本仓是活跃仓库(最后推送 2026-08-13),show-me 曾在 4 天内被改过 3 次 |
npx skills remove <名> | 卸载 | 试完不合适的循环技能记得清掉,否则它会一直在你的技能目录里 |
npx skills use <源>@<技能> | claude | 不安装,直接生成一段提示词喂给 agent | 想先试一次再决定要不要装 |
这几条命令在 CLI 自己的文档里都有对应小节(skills list 可带 -g 只看全局、-a 按 agent 过滤;skills update 可带 -g/-p/-y)。
05show-me:3,297 字节里到底写了什么
这是全文的重点。它的全部内容是 3,297 字节、127 行、460 词(我下载后直接数的)。开头只有三句话,但这三句话就是它的全部哲学:
"Help the user understand the current topic of conversation visually. Skip the preamble and keep prose brief. Pick the smallest view that makes the key point clear."
用可视化的方式帮用户理解当前正在讨论的话题;跳过铺垫、把散文压短;挑那个刚好能说清要害的最小视图。
这三句话各干掉一类毛病
| 原文片段 | 它排除了什么默认行为 | 你该知道的边界 |
|---|---|---|
| "the current topic of conversation"(当前话题) | 排除了"我替你去研究一下这个主题"——它不负责研究、不负责查证。锚点是你们的对话本身,不是某个主题 | 所以它没有参数。你写 /show-me 什么是闭包 时,那个"闭包"只在它能从上下文里找依据时才有意义 |
| "Skip the preamble, keep prose brief"(跳过铺垫、散文压短) | 它禁止的是长段落,不是禁止文字 | 规范里明确要求"把每张图放在它所支撑的那句短文字旁边":图不是文字的替代品,而是让那几句短文字变得不必再展开 |
| "the smallest view"(最小视图) | 直接排除了"把整个文件贴出来"和"画一张大而全的架构图"这两种默认行为 | 这是全文最关键的约束,它逼模型先回答"读者此刻卡在哪一句" |
它管的是"媒介选择",不是"画图技术"
很多人以为 show-me 是个画图技能。它其实规定的是媒介映射:什么类型的疑问,默认该用哪种表达。全文给出了六种视图加一种 diff 形态,没有一句在讲怎么把图画好看——配色、字体、间距这些只出现在最后那个 HTML 分支里,而且写的是"匹配你的产品",不是给一套自己的样式。
换句话说:它是一份"解释的排版规则"。它的价值不在于教会模型新东西(行数、缩进、Mermaid 语法它都会),而在于收窄选择空间——把"要不要写 800 字"这个每次都摇摆的决定,换成一个查表动作。
三段散文 + 一个 60 行的完整文件引用 + "总结一下,主要有以下几点"。读者要在文字里自己重建结构,而且往往真正想问的只有"这个函数在第几步被调用"。
一句结论 + 一棵调用树(4 行)或一张 diff(5 行)。读者三秒扫完,发现自己想问的那一层就在第二行。篇幅减少不是目的,是副产品。
show-me 全篇没有一个字提到"核实事实""查官方文档""标注来源"。它假设上下文里的东西是对的。如果那段对话本身建立在一个错误前提上,它会把错误画得非常清楚——一张漂亮的错图比一段含糊的错话更危险,因为图看起来更可信。需要核对事实的场合,别用它来替代查证。
06六种视图 + 四种 diff:我该让它画什么
这是 show-me 的全部"语法"。左列是它给出的形态,右列是判断依据——原文只给了示例,没给这张对照表(全文的代码块标记数就是证据:4 个 text、1 个 tsx、1 个 mermaid、4 个 diff、1 个 ts)。所以下面后两列是把它的示例反推成规则,是本文的归纳,不是官方表述。
六种视图 + 整块代码:一张查表
| 视图 | 用什么包起来 | 什么时候用它 | 别拿它当什么用 |
|---|---|---|---|
| 伪代码(逻辑/算法) | ```text |
要说清"顺序与分支"时用。原文示例是一段"内容没变就返回缓存,变了就写入"的判断 | 别写成真代码——一旦写成 TypeScript(给 JavaScript 加上类型检查的语言),读者会开始关心语法细节,而你要讲的是"先判断后写、命中缓存就返回" |
| 调用树(运行时控制流) | ```text |
回答"谁调用了谁、按什么顺序"时用。用缩进表达嵌套,不必画出返回值 | 别拿它当架构图——它描述一次执行的路径,不是模块的长期关系 |
| 组件树(UI 结构) | ```tsx |
讲前端界面如何拼装时用,可以顺带标出状态来源与模块边界(哪个组件来自哪个包) | 只写与本问题有关的那几层,别把整页组件都列上 |
| 文件树(职责/重构) | ```text |
讲"哪个目录负责什么"时用,每个目录后面跟一句职责注释,是这份形态的灵魂 | 深度要浅——它的用途是"分工"而不是"穷举" |
| Mermaid(交互/控制流/数据流) | ```mermaid |
有多个参与者来回传递时用(原文示例是时序图:用户→界面→守护进程→回流结果) | 别用它画一张只有一个方向的流程图——那种情况伪代码更快 |
| diff("变的到底是什么") | ```diff |
当周边形状已经存在、读者只需要看变化时用 | 别在大多数内容都是新的时候硬用 diff——那时应该整块贴(见下一行) |
| 整块代码(可复制的目标形状) | ```ts |
当"大部分是新的""省略上下文会隐藏归属或顺序""读者需要一个可以抄走的完整形状"时用 | 别把它当默认——原文把这块放在最后,前面全是"更小的形状" |
术语补一句:Mermaid 是一种用纯文本描述图表的语法,支持它的阅读器会把那段文字渲染成图;diff 是"两份文本的差异",+ 开头的行是新增、- 开头是删除、没标记的是原有内容。
diff 的四种形态(同一个 diff,四种内容)
原文给了四个 diff 示例,分别对应四类"变化"。这是全文最实用的一段——因为你问 agent"这次改了什么"的时候,它给的东西质量差别极大:
| # | diff 形态 | 它回答的问题 | 为什么这样画 |
|---|---|---|---|
| ① | 组件变化 | "这次改动挂在哪个位置" | 在组件树里加/删一个子组件,保留父层作为定位坐标,读者不必重建整棵树 |
| ② | 文件布局变化 | "这个功能放哪去了" | 把一个文件拆成目录,或用带行内注释的 diff 树新增一个文件 |
| ③ | 调用树/调用栈变化 | "新加的那步插在流程的哪里" | 在某一步中间插入一次调用、替换尾部的下一步 |
| ④ | 状态/控制流变化 | "逻辑为什么变成这样" | 把"直接写入"改成"先判断是否变化、命中就返回缓存" |
四种形态都遵守同一条规矩:未改动的行照旧显示,只让变化行带标记。这让读者不必重建整个结构,就能把注意力锁在变更上——这也是它比"贴改后的完整文件"强的地方。
同一个问题、三种形态:并列看一眼
假设问题是"用户点保存之后发生了什么"。三种形态的取舍是这样的(这三段直接来自原文的示例形状):
# 形态 A:调用树(回答"顺序")
submitForm
createSession
persistPrompt
launchAgent
navigateToSession
# 形态 B:Mermaid 时序图(回答"谁跟谁来回说话")
User -> UI : 选择命令
UI -> Daemon : 发送展开后的提示词
Daemon --> UI : 流式返回结果
# 形态 C:伪代码(回答"判断逻辑长什么样")
on(save)
if content is unchanged
return cached result
write new content
return fresh result
三个都对,问题只在于读者此刻卡在哪一层:卡在"我不知道后面还有几步"→ A;卡在"这俩组件到底谁请求谁"→ B;卡在"为什么它有时候不写盘"→ C。show-me 的整篇规范,说到底就是让模型先回答这个前置问题,再选形态。
tsx、diff、mermaid 都是"带语言标记的代码块",在纯文本终端里就是代码。Mermaid 只在支持它的阅读器(GitHub、多数 Markdown 预览器)里会变成图。如果你的读者是在终端里看,优先用 text 那几种(伪代码/调用树/文件树)——它们在哪儿都长得一样。
07它什么时候才会去写一个 HTML 文件
前面六种视图都是"在对话里输出文本",不碰文件系统。只有一条分支会真的写文件,原文是这么说的:
"For a visual UI, layout, state comparison, or concept too dense for Mermaid, write one focused HTML file — a diagram, an infographic, or a short slide deck, whichever fits the point. Match the product's colors, type, spacing, and components; use real labels and data; support desktop and mobile. Then open it for the user."
当要讲的是界面视觉、布局、状态对比,或者密到 Mermaid 表达不了的概念时,写一个聚焦的 HTML 文件(示意图/信息图/短幻灯片,看哪个合适);配色、字体、间距、组件都要匹配产品;用真实的标签与数据;桌面和移动端都要能看;然后为用户打开它。
触发条件有四个,缺一个就别用 HTML
| # | 条件 | 为什么文本表达不了 |
|---|---|---|
| ① | 视觉性 UI | 讲的是"长什么样",不是"怎么流转" |
| ② | 布局 | 元素之间的相对位置本身是信息 |
| ③ | 状态对比 | 同一界面的两个状态并排看才看得懂 |
| ④ | 密到 Mermaid 表达不了的概念 | 兜底条款,也是最容易被滥用的一条 |
四条里前三条都是"文本天然表达不了"的情形。第四条给了模型很大的自主权,但它同时被前面的 "one focused"(一个、聚焦)和 "Pick the smallest view" 夹住——一个文件、聚焦一个点。
打开动作:原文写的是 Bash(open …)
文件写完之后,原文给的动作是这样的(代码块里就这一行):
Bash(open path/to/show-me-{description}.html)
Bash(...) 是 Claude Code 的工具调用记法——它的意思是"用 Bash 工具执行括号里的命令"。这一行揭示了 show-me 的出身:它是为 Claude Code 写的,且默认你在 macOS(open 是 macOS 的打开命令)。
在别的 agent 里,Bash(open …) 这个字面量什么也不是。翻译方式:Linux 用 xdg-open <文件>;Windows 用 start <文件>;而像本文所在的这套工具那样、把文件操作交给专用工具的框架,就改成"告诉我路径,我自己用浏览器打开"。不改这一行,你会得到一个写好了但没人打开、你也不知道在哪的 HTML 文件。
文件落在哪里,规范没说
现在的写法是一个相对路径 path/to/show-me-{description}.html。这条规范之前不是这样的(见 08 的一手 diff):旧版把路径钉死在 .humanlayer/tasks/{task-slug}/show-me-{description}.html,也就是 HumanLayer 自己的任务目录。改成相对路径之后,技能才能脱离 HumanLayer 使用,但代价是落点没人管——它可能出现在仓库根目录、也可能在临时目录。
实用做法:在项目里先约定一个目录(例如 docs/ 或 .scratch/),并把这句约定写进你的项目说明;或者干脆把它加进 .gitignore(一个告诉 git"这些文件不用管"的清单),因为这类产物通常不该被提交。
边界:"匹配产品配色"对没有设计系统的仓库是空指令
"Match the product's colors, type, spacing, and components" 的前提是你有一个可被识别的产品视觉。仓库里没有设计变量、没有组件库、agent 也没见过你们的界面时,这条指令无着落,模型只能自由发挥——出来的东西大概率是一份"通用好看的网页",而不是"你们的界面"。这种场合下,与其让它猜,不如直接给它一份截图或现有页面文件。
最后一段 guidance:它其实在限制你
全文最后一段(也是最后一次修订新增的小节)写的是两件事:把每张图放在它所支撑的短文字旁边;只保留回答当前问题所需的调用、文件、props(组件的入参)、状态和边界。末尾两句话很关键:
"You may use one of these, you may use several, it is unlikely you will use all of them. Use your judgement and don't overwhelm the user."
你可以只用其中一种,也可以用几种,但几乎不可能全部都用上。用你的判断力,别把用户淹了。
这句话是写给模型的"刹车":六种视图是选项集合,不是清单。它防的是模型最常见的偷懒替代品——"我全都给你来一遍",看似周到,实际上把"挑出最小视图"这个职责又推回给了读者。
08它被改过四次:一手 commit 逐字节对照
下面的数据是我直接从 GitHub 拉取该文件在四个提交(commit,即一次代码存档)上的原始版本、逐字节比对得到的。它回答一个文档里不会写、但对使用者很要紧的问题:这个技能是往哪个方向演化的。
四个提交的字节数(实测)
| 提交(前 7 位) | 日期 | 字节 | 改了什么 |
|---|---|---|---|
a2e3bf7 |
2026-08-09 | 2,977 | 技能首次加入。此时 HTML 分支写的是 task-artifact 语法块,路径固定为 .humanlayer/tasks/{task-slug}/show-me-{description}.html——即"在 HumanLayer 的任务里内联展示" |
d3138e5 |
2026-08-09 | 3,168 | 把上面那句改成"写一个聚焦的 HTML 文件……然后为用户打开它",动作从 task-artifact 换成 Bash(open …);同时新增"你可以只用一种,几乎不可能全用上"的提醒 |
4d8d644 |
2026-08-11 | 3,230 | 纯字形修正:文件树示例从 ASCII(最基础的一套计算机字符)的 |-- / `-- 换成真正的制表符 ├── / └── |
6ab9013 |
2026-08-13 | 3,297 | 把结尾那段散落的提醒升格为独立的 ### guidance 小节,并把"回答当前问题"扩写成"回答当前问题或用来解决当前讨论点的几个选项" |
四次修订,总量只涨了 320 字节(+10.8%)。这个数字本身就是一个判断:作者没有往里加功能,改的全是措辞与形态。我核对过:仓库当前的 main 分支(提交 3c26291,2026-08-13)上的 show-me 文件,与 6ab9013 的版本逐字节相同(SHA-256 一致),也就是说自 8 月 13 日起它没有再被改过。
从 diff 里读出的三条结论
最大的一次改动(a2e3bf7 → d3138e5)是把产物路径从 HumanLayer 私有目录里搬出来,换成通用路径加一个打开动作。这让同一个技能可以被几十家 agent 使用——技能的价值随"不依赖任何特定产品"而上升,这正是它后来拿到大量安装的结构性原因。
后两次改动(树形字形、把提醒升格为小节)都不增加任何新能力。字形修正说明作者真的看过输出——ASCII 树在等宽字体下对不齐;升格为小节说明那条"别全用上"的提醒原来太容易被略过。
"回答当前问题" → "回答当前问题或用来解决当前讨论点的几个选项"。这意味着 show-me 也开始承担第二种用途:把讨论中的几个方案并排画出来,帮人做选择,而不只是解释已经发生的事。这个用法比"解释"更值钱,因为它出现在决策点。
你怎么自己复核(三条命令)
不需要克隆仓库,按提交哈希取原始文件即可:
curl -s https://raw.githubusercontent.com/humanlayer/skills/<提交哈希>/plugins/show-me/skills/show-me/SKILL.md -o sm-<哈希>.md
wc -c sm-*.md # 对照上表的字节数
diff -u sm-a2e3bf7.md sm-d3138e5.md # 看第一次改了什么
# 校验某一个版本是否被改动过(取当前 main):
shasum -a 256 plugins_show-me_skills_show-me_SKILL.md
# 当前 main 上的 show-me SKILL.md 应为 bea6da70a58096730b9aeb0bae293ddf4726103a98efc9ce13c481619942a810
我按这三条重跑了一次,四个版本的字节数分别是 2,977 / 3,168 / 3,230 / 3,297,与上表完全一致;当前 main 的 SHA-256 也确实是 bea6da70…。SHA-256 是一种"指纹"算法:把任意长度的内容压成一串固定长度的字符,内容变一个字节,指纹就完全不同——所以拿它对比就能判断文件有没有被改过。顺便记下另外三版的指纹,方便你对照:a2e3bf7 是 19643862…、d3138e5 是 343a1029…、4d8d644 是 2a20c9c8…。
任何时候你想知道"一个技能到底在改什么",都不用读 changelog(这个仓库根本没有 changelog):按 commit 取几份原始文件互相 diff 即可。对 SKILL.md 这种纯文本、又短的文件,这是成本最低的考古方式。
09show-me 与 /learn:两个都产 HTML,验收方式完全不同
如果你手上有多个会生成 HTML 的技能,最该先分清的是这一组。本仓的 /learn(就是写出你正在读的这篇文章的那个技能)与 show-me 都能产出 HTML,因此常被混为一谈,但它们从锚点到验收没有一处相同。
六个维度逐条对照
| 维度 | show-me | /learn(本仓) |
|---|---|---|
| 锚点 | 当前对话——没有参数,内容来自上下文 | 一个主题——必须明确给出,含糊就反问 |
| 是否联网核对 | 不做。它假设上下文是对的 | 必须做,至少两个高可信来源,失败就停止 |
| 产物去向 | 一个临时 HTML/一段对话内的图,不落库 | 固定目录下的 .html,并登记到主页 |
| 是否可复习 | 不可。看完即弃,靠对话历史找回 | 可。带校对日期、按日期倒序陈列在主页 |
| 质量门槛 | 没有。唯一的验收是你当场看懂没 | 有硬门槛:契约检查脚本(元数据、锚点、可见校对日期、术语表第三列……)不通过不算完成 |
| 篇幅倾向 | 越小越好,明文写着 "the smallest view" | 越全越好,明文反对"随便搜一点贴上去" |
你得到一个漂亮的图解,但它没有出处、没有边界说明、下个月就找不到了。想复习时只能翻对话记录,而且不知道里面哪句已经过时。
救急理解一个正在讨论的东西 → show-me;要留下一份能复习、能被别人读、会随版本刷新的东西 → 用 /learn 这类有契约的流程。
公平地说,反过来的误用同样存在:用 /learn 去问"这个函数在第几步被调用"是拿大炮打蚊子——它会联网、会写一篇带术语表和参考来源的文章,而你真正需要的是一棵四行的调用树。
问自己一句:这个话题下个月还在吗?在 → 用有契约、有日期的流程;不在(只是现在这一刻没看懂)→ 用 show-me,越快越好。
10最小例子:敲下 /show-me 之后发生了什么
下面这个场景可以直接照抄:你正在读一个技能目录,想知道"它一次运行到底经过哪些步骤"。
场景
你刚下载了这个仓库,看着 show-me 那 127 行,心里的问题是:"我敲下 /show-me 的那一刻,到屏幕上出现一张图,中间发生了什么?"
两种要法:同一件事,问法决定结果
你:"解释一下这个 skill 的工作流程。"
得到:三段散文,讲技能是什么、markdown 如何被读取、模型如何选择视图……你读完仍然不知道"敲下去之后第一件事是什么"。
问题出在:你没告诉它你要的是顺序还是原理,它只能给最稳的那种——概述。
你:"/show-me 用调用树讲一下这个技能从被触发到产出图,中间经过哪几步。"
得到:一棵树。你一眼看到"选形态"发生在"写字"之前——这正是你卡住的那一步。
它实际会输出的东西(可以直接当模板)
左边这棵树对应上面"好的要法",右边的 diff 对应另一种常见疑问——"新版和旧版差在哪"。两段都是可以直接拿去当模板的形状:
# 形态一:回答"经过哪几步"(调用树)
/show-me 被触发
读当前对话,锁定"当前话题"
判断话题属于哪一类
算法/逻辑 → 伪代码
运行时控制流 → 调用树
UI 结构 → 组件树
文件职责/重构 → 文件树
多参与者交互 → Mermaid
"变了什么" → diff
视觉/布局/密概念 → 写一个 HTML 文件并打开
产出该视图(保持散文极短)
自查:是不是"最小的那个视图"
# 形态二:回答"新旧版差在哪"(文件布局 diff)
show-me/SKILL.md
HTML 分支的写文件动作
- task-artifact .humanlayer/tasks/{task-slug}/show-me-{description}.html
+ Bash(open path/to/show-me-{description}.html)
结尾的提醒
- 一段普通段落
+ ### guidance 小节
一次完整的调用长什么样(三步)
打开你要讲的那个文件,或把那段代码贴进对话。这是 show-me 唯一的"输入源"——它不搜、不读文档,锚点就是当前对话。上下文里没有的东西,它画不出来。
/show-me 用调用树讲一下 XXX 的执行顺序。指定形状这一步不是必须的(模型会自己挑),但指定之后输出稳定性明显更高,也省掉一次来回。
说"这块用 diff 重画"比说"再详细一点"有效得多。"详细"会把它的刹车松掉,而 show-me 的全部价值就在于那个刹车。
把它当成"生成一张好看的架构图"的工具:/show-me 给我画一张整个系统的架构图。这和它的规范直接冲突——它要的是"刚好说清要害的最小视图","整个系统"不是最小视图。结果通常是一张拥挤、你又不敢删除任何部分的图。正确做法是把它拆成几次小问题:这次只问数据怎么流,下次只问部署边界。
11improve-claude-md:把"长清单"改成"条件触发"
插件市场里的原始描述是:"Rewrite a CLAUDE.md file using <important if> blocks to improve instruction adherence"——重写 CLAUDE.md,用条件块提高指令的遵守率。
它针对的具体毛病:你的说明被"允许忽略"包着
Claude Code 在你每次对话时注入 CLAUDE.md 的内容,但注入的不是"原文照读",而是带着一句限定:这句话的大意是"这份上下文可能与你的任务相关,也可能不相关;除非高度相关,否则不要理会它"。技能文档把这句话原文引了出来,并给出推论:文件里跟当前任务无关的内容越多,模型越可能连相关的那部分一起忽略。
所以问题不是"你的 CLAUDE.md 写得不好",而是"它被一段允许忽略的框架包着,而你没有给模型任何区分信号"。
解法:给条件性内容套上 XML 条件块
把"只在某类任务下才相关"的内容包进 <important if="条件">,利用与系统提示同类的 XML 标记(一种用尖括号包住内容的结构化写法),给模型一个明确的"现在这条适不适用"的判据。
五条原则(浓缩)
| 原则 | 具体怎么做 | 为什么 / 别当什么用 |
|---|---|---|
| 基础上下文裸着放,领域规则才包 | 项目身份、目录地图、技术栈对 90% 以上的任务都相关 → 保持普通 markdown;测试规范、API 约定、状态管理这类只在特定任务相关 → 包起来 | 条件的意义是"区分相关与不相关",全都包等于都没包 |
| 条件要窄 | 一个 if="你在写任何代码" 等于没写条件,必须拆成"改导入时""新建组件时""新建文件时" | 条件越宽,模型越无法分辨哪条此刻适用,退回成背景噪音 |
| 少用渐进披露 | 别为了省 token(模型处理文字的计量单位)把内容拆成一堆要 agent 去点开的小文件 | 条件块的意义正是"全都看得见,但只对相关的那部分加权" |
| 能删就删 | linter(检查代码风格的工具)/formatter(自动排版工具)/pre-commit(在提交前自动跑一遍的钩子)能管的一律删;代码里已经一致体现的惯例删(模型会模仿现有代码);代码片段删(会过期),改成指路 | 把一个能被工具强制的规则写进说明书,等于把机器能做的事交给概率 |
| 命令一条不许丢 | 命令表是基础参考,哪怕某些命令很少用也要保留 | 表回答"有哪些选项",规则回答"什么时候用",两者不可互换 |
错误与正确:条件块怎么写
<important if="你在写或改任何代码">
- 用绝对导入
- 用函数组件
- 文件名用 camelCase
</important>
三条无关的规则共用一个过宽条件,等于告诉模型"写代码时这些都对"——它无法分辨哪条此刻适用,退回成普通的背景噪音。
<important if="你在新增或修改导入">
- 用 @/ 绝对导入
</important>
<important if="你在新建组件">
- 用函数组件 + 显式 props 接口
</important>
<important if="你在新建文件或目录">
- 用 camelCase
</important>
命中哪个条件就听哪条,模型的注意力分配变得可预测。
它自带一个完整的改前/改后范例
技能的后半篇是一份 Express(Node 上的网页服务框架)+ React(前端界面库)的样例(项目用 Turborepo 把多个包放在同一个仓库里管理) CLAUDE.md 改写。范例里最值得学的是它明确写出"删了什么、为什么":
| 删掉的 | 理由 | 你该怎么用这条判断 |
|---|---|---|
| camelCase/PascalCase(两种连写命名法,区别只在首字母大小写)、const 优于 let、严格等于、模板字符串、JSDoc(从代码注释生成文档的写法)、barrel 导出(把一个目录下的模块统一从一个文件再导出) | linter 和 formatter 的地盘,或从现有代码就能看出来 | 把你 CLAUDE.md 里"能被工具强制"的条目全删掉,改成装一个钩子 |
| 整块 "Coding Standards" 章节 | 被打散进各自触发条件的小块里 | 别按"主题"分组,按"什么时候需要"分组 |
| ——(保留)全部命令,含 dev、storybook、analyze | 命令表是查得到的参考,不是规则 | 宁多勿少 |
| ——(保留)目录地图裸着放 | 它属于"每次都需要"的那 90% | 基础上下文不包条件 |
整个技能建立在一个具体机制上——"某个框架在注入项目说明时会加一句允许忽略的限定语"。这个机制是会被改的(一句提醒的措辞变化就足以让整套做法失效),而且别的框架未必这样注入。搬用前先用一句话验证:在你的 agent 里,项目说明文件是不是被当成"可忽略的上下文"?不是的话,<important if> 顶多是一层有用的分组,不再是"激活开关"。
重写解决的是注意力分配问题。如果原文写的是"本项目用 Webpack(一个把源码打包成成品的工具)"而实际上早就换成 Vite(另一个同类工具)了,改写后它会被更可靠地执行——错误也一起被放大了。先核对事实,再谈形式。
12narrow-react-prop-types:让类型只描述真实会走到的路径
它处理的是一个很具体的病症:组件 props 被 Storybook、mock、测试、demo 撑宽了,于是类型系统开始允许那些应用真实路径永远不会进入的状态。先解释三个词:props 是父组件传给子组件的入参;Storybook 是一个"把组件单独拿出来看"的开发工具;mock 是假的替身数据。
核心要求(原文的六条,重述)
- 改类型之前,先找出真实的、非测试非 Storybook 的调用点;
- 把真实代码路径当作 prop 契约的唯一真相;
- 不要为了让 Storybook/测试/mock 好写而保留可选 prop;
- 只有当"某个非 Storybook、非测试的调用点确实不传它、且有不传的理由"时,才让 prop 保持可选;
- 类型不应该能表达出真实调用点里观察不到的状态;
- 类型越严,代码就能越简单;能推导就推导,别手写重复的形状。
推理链条:为什么"可选"是有代价的
它给出的理由是全文最值得记住的一句推理:每一个可选 prop 都是组件必须处理的一个额外分支。可选 prop 越多,组件要思考的状态越多,要测试的分支越多,要维护的正确性越多。
顺带一个容易搞混的点,技能里专门点出来了:可空(nullability)与可选(optionality)是两件事。如果真实代码总是传这个 prop,但值本身可能是空的,那正确写法是"必需的、可为 null 的 prop"(focusedItem: Item | null),而不是"可选且可为 null"(focusedItem?: Item | null)。前者表达"一定会传,但可能没有当前焦点";后者多出来一个"压根没传"的状态,而那个状态并不存在。
十一步工作流的压缩版(五步)
| # | 做什么 | 关键判据 / 别当什么用 |
|---|---|---|
| 1 | 找嫌疑组件 | 信号:props 接口很大且一堆 ?;出现 onSelect?.(…) 这种可选调用;到处是 items ?? []、count ?? 0 兜底;界面上的按钮永远在,但它的回调(被传进去、之后会被调用的函数)是可选的。不允许只凭 story 或测试来选定目标——它们只能当"类型被撑宽了"的证据,不能当"这个状态是真实的"的证据 |
| 2 | 给所有调用点分类 | 真实路径 = 应用路由、被接线的组件、provider(向下层提供共享数据的组件)、hooks(React 里以 use 开头的状态函数)、生产包导出;支撑代码 = Storybook 故事、测试、fixture(写死的假数据文件)、mock(假的替身对象)、demo。只有真实路径能决定组件 API 支持什么 |
| 3 | 按真实调用点给每个 prop 定级 | 所有真实调用点都传 → 必需;至少一个真实调用点不传、且那是真实运行状态 → 可选;没有任何真实调用点使用 → 删除 |
| 4 | 收紧公开类型,然后清掉为此而生的兜底 | props 变必需之后,那些只为宽类型而存在的防御式代码就要一起删(例如 new Set(expandedIds ?? defaultExpandedIds ?? []) → new Set(expandedIds))。只改类型不清兜底,等于留了一堆永远不会触发的分支 |
| 5 | 让测试和 story 去适配,而不是反过来 | story 因为收窄而崩了,就给它补上真实的 handler(处理函数:按钮被点时要执行的那段代码)和状态;嫌啰嗦就写一个测试辅助函数——辅助放支撑代码里,绝不因为测试麻烦而把组件 API 重新放宽 |
错误与正确:一对典型改法
interface RowProps {
onRename?: (id: string, name: string) => void
items?: Item[]
}
// 永远渲染这个按钮,但回调可能是 undefined
<button onClick={() => onRename?.(id, name)}>
重命名
</button>
const list = new Set(expandedIds ?? defaultIds ?? [])
结果:一个看得见、点了没反应的菜单项;一个永远不会触发的兜底分支;以及一个能表达"惰性"状态、而真实代码进不去的类型。
interface RowProps {
onRename: (id: string, name: string) => void
items: Item[]
}
<button onClick={() => onRename(id, name)}>
重命名
</button>
const list = new Set(expandedIds)
类型现在只描述真实存在的状态;"点了没反应"这种状态根本无法被表达出来,也就不需要被测试。
它的附件里藏着一个真实运行的例子
三个附件中有一个是完整可用的定时工作流(references/agent-narrow-component-props.yml,11,103 字节),它是这个仓库"技能 + 定时 agent"这套打法的原始样板,也是另外两个循环技能自称参照的"具体参考模式"。我逐条读过里面的真实细节:
- 触发器是每天一次 + 手动派发 + PR 上
/iterate评论三种(/iterate指维护者在 PR 下留言/iterate <反馈>,让当初开这个 PR 的那支工作流按反馈再改一次)(定时的 cron 表达式是0 13 * * *,即每天 13:00 UTC(协调世界时,比北京时间晚 8 小时)跑一次); - 运行机器用的是
blacksmith-8vcpu-ubuntu-2404(不是 GitHub 默认的运行机器); - agent 走 CodeLayer,模型写死为
claude-opus-4-8;运行环境是 Node 24(Node 是让 JavaScript 在浏览器之外运行的程序)+ bun 1.3.14(另一个更快的同类工具); - 配的记忆文件(
narrow-component-props-memory.md,213 字节)全文只有一行有效内容:Focus only onapps/riptide-ui; do not make changes inapps/riptide-cloud. 这是"记忆文件应该写什么"的最好示范——一条永久性的范围约束,而不是任务日志。
它的前提是"非测试、非 Storybook 的调用点就是全部真相"。这对应用成立,对公开发布的组件库不成立:库的消费者就是它的真实调用点,而你看不到他们。把内部应用里那 3 个调用点当成全部真相去收窄公共 API,等于替所有下游用户做决定。库、设计系统、被外部依赖的包,用之前要先重定义"真实路径"等于什么。
"没有任何真实调用点使用 → 删除"是把双刃剑。某个可选 prop 可能正是下一个功能要用的接口。技能的取舍很明确——类型应该反映今天真实存在的状态,而不是为想象中的未来预留。如果你的团队习惯"先把接口留宽",这套做法会与你们的约定冲突,需要先对齐这一点再跑。
13build-iterated-agentic-loop:把一个重复任务变成每天开 PR 的机器
它不是自己执行任务,而是给你造一台机器:一个定义"agent 该怎么判断"的技能,一支会定时运行的 GitHub Actions 工作流(GitHub 自带的自动化:满足条件就自动跑一串命令),一份承载长期反馈的记忆文件,以及一组参考模板。
它会往你的仓库里写四个文件
| 产物 | 作用 | 为什么必须在仓库里 |
|---|---|---|
.claude/skills/<名>/SKILL.md | agent 的判断力:怎么找目标、怎么改、怎么验、怎么汇报 | 它是"无人值守时唯一的判断依据",所以要能被人评审与修改 |
.github/workflows/agent-<任务>.yml | 定时/手动//iterate 三条触发路径 | 调度、密钥、权限都在这里,必须与应用代码同一个版本历史 |
.github/agent-memory/<任务>.md | 跨运行存活的反馈:永久范围限制、已知误报区 | 它是"人在环上"的转向通道——改它等于调未来的行为,而不只是这一个 PR |
.../references/(可选) | 模板、示例、长材料 | 让 SKILL.md 保持短,长内容仍可被点开引用 |
九个步骤里,三个值得单独讲
它要求先摸清包管理器、安装命令、校验命令、已有工作流约定,然后带着建议去问,而不是甩一张空表让你填。它要你确认的九项里,包括用哪家 agent(Claude Code/Codex/OpenCode/CodeLayer)、节奏(每天/工作日/每周/只手动/自定义 cron)、范围、校验命令、PR 边界、PR 元数据、汇报格式、是否启用 /iterate。
这是整套设计里最实用的一条。原文的理由很直白:不设界,每天一个的 agent 一周能堆出 5 个以上没人评审的 PR,制造评审疲劳与合并冲突。做法是给每个循环的 PR 打标签,定时运行前先查"这个标签还有没有开着 PR",有就跳过;手动触发绕过这个闸门,以便需要时强制跑一次。
GitHub Actions 的 workflow_dispatch("允许手动点一下就跑"的开关)在一个工作流从未运行过之前是点不动的。它给的绕法很具体:临时加一条 push(把本地提交推送到远端仓库)触发器 → 推上去让它跑一次 → 确认成功后把那行 push 触发器删掉,此后就能手动派发了。
四家 agent 的接法不一样,附件里全给了
最后一个附件(agent-runner-templates.md)按 agent 给出无头运行命令("无头"指不弹界面、直接在命令行里跑)、密钥名与响应提取方式。这里的差异是实打实的——每个 agent 输出格式不同,把最终回复取成 PR 正文的方法就不同:
| agent | 密钥 | 输出格式 | 怎么取到 PR 正文 |
|---|---|---|---|
| Claude Code | ANTHROPIC_API_KEY | stream-json(一行一个 JSON——一种纯文本的数据格式) | 用 jq(命令行 JSON 解析工具)取最后一条 assistant 的 text 块 |
| Codex CLI | OPENAI_API_KEY | 自带最后消息输出 | 直接 --output-last-message /tmp/pr-body.md |
| OpenCode | 视 provider 而定 | --format json | jq 取 messages 里最后一条 assistant 的 content |
| CodeLayer | 通常是 ANTHROPIC_API_KEY | 带 ANSI 颜色的纯文本(终端着色码) | 去 ANSI 色码(或写一个解析脚本) |
附件里四家 agent 的示例都用了完全放权的模式(--permission-mode bypassPermissions、--sandbox danger-full-access、--dangerously-skip-permissions)。而这一份附件开头第一句就说明了适用条件:宽权限模式只适合受信任的、隔离的运行环境。把它搬到你自己的机器或一个能访问内网与生产密钥的机器上跑,是这套流程里风险最高的一步。
技能对它的好坏给了明确判据:好条目是永久范围排除、已知误报区、应该改变未来选择的评审反馈;坏条目是一次性任务指令、单次运行的校验输出、以及技能里已经写过的规则(那会造成两处真相)。自检方法是它给的那句:删掉这个文件,你会不会真的丢掉有用的未来上下文?只是丢掉历史记录,那就是写错了地方。
14design-control-loop:先把"要驱动什么"讨论清楚,再动手建
它是本仓最长的一份,也是最"不像模板"的一份。原文明确说了:没有固定工具集,也没有可复制的模板;你要做的是访谈用户、和用户一起设计,然后再替他实现出来。
五件套:把"agent 偶尔跑一下"变成一台可观测的机器
它借用控制论(研究"系统怎么自我调节"的学科)的词汇,把循环拆成五样东西,外加一个"人在环上":
| 部件 | 它回答的问题 | 本仓举例(仅为示例,不是推荐) |
|---|---|---|
| 设定值 Set point | 要把什么属性推到什么目标?是不变式、阈值,还是方向? | "某个 app 不再有高影响的 React 问题"(方向而非阈值) |
| 传感器 Sensor | 怎么测量与目标之间的差距?可重复吗?能不能被悄悄关掉? | 一个静态扫描命令行工具 + 配置文件 |
| 控制器 Controller | 这次改多少、改哪些、按什么排序? | 完全确定性(脚本排序取前 N)到完全 agentic(按自然语言标准选)都可能 |
| 执行器 Actuator | 谁来改?用什么凭证?改完靠什么验? | coding agent + 仓库内技能 + 提交前的校验命令 |
| 扰动 Disturbance | 什么东西在循环之外改变系统? | 同事持续提交、依赖升级、生成代码——循环要"带着它们"前进 |
| 阻尼器 Dampener | 怎么保证问题在变好之前不会先变坏? | 在 PR 上比对基线,只报新增偏差;默认只提示不拦截 |
它还专门说明了一件事:组件可以融合,而且应该允许融合。一个既能报问题又能按影响排序的工具,就同时干了传感器和控制器的活;一个既选目标又动手改的 agent,就是控制器加执行器。不要人为制造设计里并不存在的分离——这一句直接把它和"为了好看而画三条独立步骤"的做法区分开了。
A–H 八个阶段
流量控制在这里指"限制同时开着多少个 PR",防止评审积压。阶段 D 是它和别的"自动化技能"最不一样的地方:在接进 CI 之前,传感器、控制器、执行器必须各自能在本地单独跑一遍——先跑传感器确认测量稳定,再拿真实测量结果跑控制器确认选出的目标合理,最后用无头命令让执行器改一个目标并跑通校验。原文的说法是:工作流只应该编排那些你已经能手动运行的东西,这样循环才可调试。
附件里那个完整范例:它到底长什么样
十个附件里有一个是"逐部件注解的一个真实生产循环"(React 代码质量,单应用)。它明确写着这是插图不是模板,但里面的取舍很值得看:
- 传感器选了一个独立于编辑器/lint 配置的扫描器,理由是可以被配置文件集中控制——一个顺手的内联注释关不掉它。原文特意强调这个理由"对这个团队重要,而不是对所有传感器的要求"。
- 控制器与传感器融合:没有独立控制器,工具返回"影响最大的前 3 类规则",而循环的策略是"这次最多修这 3 类里的 5 个问题",选择逻辑写在执行器的提示词里。
- 执行器给 agent 三个诚实的选项:修掉、忽略(并在配置文件里写明理由)、跳过(留给人类)。每改一处都单独校验、单独提交。
- 阻尼器是第二支工作流:在每个 PR 与推送到主分支时运行,对比合并基线,只对新增的问题评论,默认只提示(不会把同事的 PR 变红),并留了一条"团队信任信号之后可以升级为拦截"的路。
- 流量控制:所有 PR 打同一个标签,定时运行发现已有开着 PR 就跳过;手动派发绕过。
这个范例的结尾也值得抄:它把"可复用的形状"与"不可复用的细节"分开列出——可复用的是设定值 → 传感器 → 控制器 → 执行器 + 阻尼器 + 记忆文件 + /iterate 转向 + 单 PR 流量控制;不可复用的是那个具体扫描工具、bun 命令、"前 3 类 / 5 个修复"的策略、以及那个应用的包名。这几行恰好就是"该抄什么"的答案。
15两个循环 skill 差在哪:我逐文件比对过
这两个技能看起来很像(都会产出技能 + 工作流 + 记忆文件 + 模板),文档里也互相引用(前者说"某个具体技能是参考模式",后者说"借用控制论词汇")。到底该用哪个?我把两边的全部附件下载下来逐个比对,结果很清楚。
附件对照(含哈希)
| 附件 | build-iterated-agentic-loop | design-control-loop | 是否相同 |
|---|---|---|---|
agent-iteration.ts(/iterate 助手) | 5,896 字节 · b7a4b53d… | 5,896 字节 · b7a4b53d… | 完全相同(SHA-256 一致) |
example-skill.md | 7,466 | 7,466 | 完全相同 |
skill-template.md | 1,847 | 1,847 | 完全相同 |
response-template.md | 2,442 | 2,442 | 完全相同 |
agent-runner-templates.md | 4,369 | 4,841 | 不同(后者更长) |
memory-template.md | 178 | 456 | 不同(后者多了"这是人在环上的转向通道"的说明) |
prompt-template.md | 1,456 | 1,521 | 不同 |
workflow-template.yml | 10,521 | 12,081 | 不同(后者多两段,差 1,560 字节) |
| 独有附件 | — | control-loop-taxonomy.md(5,593)、example-control-loop.md(4,241) | 后者多 2 个 |
复核方式:curl 取两个插件各自 references/ 下的同名文件,用 shasum -a 256 比较,或用 diff 看差异。我按这条重跑了一次,agent-iteration.ts 两边都是 5,896 字节、指纹都是 b7a4b53d388faef2a677b11d8b38e44ac53bc8a6734ef905b76afa2f4a0fc6ec。
工作流模板差了哪两段
两者差出来的 1,560 字节,具体落在两处(我 diff 出来的):
- 常规路径被拆成三个显式步骤:Sensor — measure current state → Controller — select the next increment → Actuator;而 build-iterated 版本只有一个 Run coding agent。
/iterate那条路也单独拆成了一个 Actuator — iterate on feedback 步骤,理由是:迭代是对一段评审意见做一次执行,不是一趟全新的"感测→控制→执行"循环。 - 多了一句免责:如果传感器与控制器本来就融合在 agent 里,就把这三步折叠成一步,别发明设计里没有的分离。
其余差异是措辞:注解里多了"(流量控制)"的标注、"setup 假设是 bun/Node 仓库,请替换成本仓运行时"的提醒。
该用哪个
它的九步流程假设"任务已经明确":找什么、改什么、怎么验都说得出。你的问题如果其实是"我们到底该盯住哪个指标",这个技能会跳过最贵的那一步——它不会问你设定值是什么,因为你没被要求定义它。
一句话说得出"找什么、改什么、怎么验" → 用 build-iterated-agentic-loop,它更短、流程更直。还在讨论"驱动什么属性、谁来量" → 用 design-control-loop,它会先用控制论追问一轮,再落成可本地运行的东西。
design-control-loop 是 build-iterated-agentic-loop 的控制论重写版:四个核心附件逐字节相同,说明基础设施(/iterate 脚本、技能模板、响应模板)是共用的;变的只是"怎么想"(多出控制论词汇与访谈)与"怎么编排"(把感测/控制/执行显式拆开)。这也解释了两者装机量为什么接近(689 与 617)——它们是同一个东西的两个入口,而不是两个独立方案。
16九个坑与边界(按踩到的概率排序)
1. 用 show-me 之前,上下文里得先有东西
它没有参数、不联网、不读文件。你在一个空对话里敲 /show-me,它只能拿最近读过的内容来画。先用一句话给它锚点,或先让它读那个文件。
2. Bash(open …) 出了 Claude Code 就不成立
见 07。Linux 换 xdg-open、Windows 换 start,或者干脆让它只报路径。不改这一行,HTML 会静静地躺在某个目录里没人看。
3. HTML 产物没有指定的落点
相对路径 path/to/…html 意味着它可能出现在仓库的任何地方。提前约定目录或加进 .gitignore,否则你的 git status 里迟早会冒出几个不相干的 HTML。
4. "再详细一点"是 show-me 的反向指令
它的全部价值建立在"最小视图"上。不满意时提形状("用 diff 重画""换成时序图"),不要提信息量。
5. 技能以完全权限运行
skills CLI 在安装完成后自己打印了提醒:"they run with full agent permissions"——技能是以 agent 的完整权限运行的,装之前该看一眼内容。CLI 会显示第三方扫描(我在安装时看到的是"Safe / 0 alerts / Low Risk"),但那只是启发式检查,不能替代你自己读一遍。这个仓库只有 5 个 markdown 技能、没有可执行脚本,风险很低;但换成别的仓库就要留意 references/ 里的脚本。
6. 循环型工作流要求配置密钥,且默认放权
四家 agent 的示例都使用绕过审批的模式。这类工作流只应跑在受信任的隔离机器上,密钥要按最小必要配置——不要给一个只是改代码风格的 agent 配生产环境凭证。
7. 定时工作流首次点不动
workflow_dispatch 在工作流从未运行过之前不可用,必须先用一次 push 触发 bootstrap(13 的第 ③ 点)。不知道这条的人会以为自己写错了 YAML(配置文件的格式)。
8. 不设 PR 边界,一周后你会有一堆无人评审的 PR
两个循环技能都推荐"每个循环最多 1 个开着 PR"。这不是保守,是原文给出的经验判断:不设界时,每天一次的运行能在一周内堆出 5 个以上待评审 PR。
9. 别把 skill 当成"模型会自动想起的能力"
本仓 5 个技能的 description 都是陈述功能的写法,没有声明触发条件。多数情况下你需要显式敲命令,或明确说"用 show-me 讲"。指望它在你需要时自动出现,多半会落空。
| 触发方式 | 本仓的 5 个 skill 是否支持 | 后果 |
|---|---|---|
你敲 /show-me 这类斜杠命令 | 全部支持(README 逐个给了调用示例) | 你控制时机,行为可预测 |
| 模型自己判断"该用这个技能" | 取决于你的 agent 框架怎么暴露那段 description;本仓的 description 都是陈述句("Help the user…"),没有写"当用户要求 X 时使用" | 多数情况下要靠你敲命令,或明确说"用 show-me 讲一下" |
这条差别值得留意:仓库里的 description 是陈述功能的写法,不是声明触发条件的写法。它把"什么时候用"交给了你,而不是模型——对 show-me 这种影响输出形态的技能,这是合理的选择:你不会希望模型在解释任何东西时都自作主张改画图。
17什么情况下不要用这些技能
上面讲的是"怎么用"。这张表讲"什么时候别用"——它比前一张更重要,因为装错了技能的成本不是零:它会一直在你的技能目录里,被模型按名字看到。
| 你的处境 | 结论 | 为什么 |
|---|---|---|
| 要一份能长期复习、会随版本刷新的资料 | 别用 show-me | 它不落库、无日期、无来源,下个月就找不到了 |
CLAUDE.md 里写的事实本身是过时的 | 先修事实,别用 improve-claude-md | 它优化的是遵守率,会把错误一起放大 |
| 你维护的是对外发布的组件库 | 别直接用 narrow-react-prop-types | "非测试调用点即真相"的前提在库上不成立 |
| 你还没有任何 CI,也不知道校验命令是什么 | 先别用两个循环技能 | 执行器的验收标准就是校验命令;没有它,agent 改完没有对错可言 |
| 团队不接受 agent 直接开 PR | 只做阶段 D(本地跑) | 控制回路可以先用人工触发的方式跑,不必先接进 CI |
| 你用的 agent 框架会把项目说明当"必须遵守"而不是"可忽略上下文" | improve-claude-md 的价值会打折 | 条件块的作用是"激活开关",没有那个机制它只是一层分组 |
18装对了没:本机实测记录(含 SHA-256 核对)
下面每一行都是我在核对日(2026-09-13)实际执行过的,不是转述文档。
| 检查项 | 我看到的结果 | 你怎么复核 |
|---|---|---|
| CLI 能列出这 5 个技能 | 输出 5 条,顺序为 improve-claude-md / narrow-react-prop-types / build-iterated-agentic-loop / design-control-loop / show-me | npx -y skills@1.5.26 add humanlayer/skills --list |
| 安装落点 | 只写了 .claude/skills/show-me/SKILL.md 与 skills-lock.json 两个文件 |
空目录里装一次,看 git status 或 find . -type f |
| 装下来的文件与上游是否一致 | 逐字节一致:安装副本与 raw.githubusercontent.com 上的原文 SHA-256 都是 bea6da70a5809673…(前 16 位) |
shasum -a 256 .claude/skills/show-me/SKILL.md,与 08 给出的上游指纹对比 |
| 锁文件里的 computedHash | 与文件自身的 SHA-256 不同(锁里是 de32a72f…,文件是 bea6da70…) |
把锁里那串和 shasum 结果对比即可复现 |
| 带 references 的技能会不会一起装 | 会。装 build-iterated-agentic-loop 时落地 9 个文件(SKILL.md + 8 个 references) |
装完 find .claude/skills/<名> -type f |
| 装机量口径是否自洽 | 各技能相加 16,400+1,400+689+617+539 ≈ 19,645,与页面总数 "19.6K" 一致(16.4K 与 1.4K 是页面四舍五入后的显示值,所以这里是约等) | 打开 skills.sh 的 humanlayer/skills 页面,把右侧数字相加 |
| 仓库文件树 | 35 个文件、25 个目录(truncated: false,即接口未截断) |
curl -s "https://api.github.com/repos/humanlayer/skills/git/trees/main?recursive=1" 后统计 type 字段 |
| 插件版本号 | show-me 是 1.0.1,其余四个是 1.0.0 |
读 .claude-plugin/marketplace.json 或各插件的 plugin.json |
锁文件里的 computedHash 不等于文件自身的 SHA-256,这是实测事实。合理的解释是:它算的是整个技能目录的清单哈希(把目录内各个文件的路径与内容一起算进去),这样一个技能里任何一个文件变了它都会变——否则带 references/ 的技能就没法用单文件哈希来判断是否被更新过。
请把这句话当作推断而不是结论:我没有读到 CLI 的源码去确认它的哈希构造方式(该包发布的是打包后的产物)。不要拿这个值去和 shasum 对比来判断文件有没有被篡改——两边本来就不同源。
与上次核对的差异(本文改掉了哪些旧事实)
本文的上一版写于 2026-09-10。这次重核,有四处数字变了,其余一手料(提交字节数、SHA-256、附件哈希、文件树)完全没变:
| 项 | 2026-09-10 的读数 | 2026-09-13 的读数 | 说明 |
|---|---|---|---|
| GitHub stars / forks | 3,692 / 107 | 3,889 / 114 | 仓库还在被人收藏,属正常增长 |
skills CLI 最新版 | 1.5.25(2026-09-08) | 1.5.26(2026-09-11) | 我用新版重跑了安装与 --list,结果与旧版完全一致(落点、锁文件字段、文件哈希都一样) |
| 各技能装机量 | 15.4K / 1.3K / 645 / 572 / 497,合计 18,414 ≈ 18.4K | 16.4K / 1.4K / 689 / 617 / 539,合计 ≈19,645 ≈ 19.6K | 页面只显示四舍五入到 0.1K 的值;两次各自的"分项之和 ≈ 页面总数"都成立,所以这个口径是自洽的 |
| show-me 装机占比 | 83.7%(15,400 ÷ 18,414) | 83.5%(≈16,400 ÷ ≈19,645) | 结论不变:八成以上集中在最短的那个技能上 |
另外一处旧版措辞我改准了:旧版说 CLI 支持"80 家 agent",其实 CLI 自己的 README 写的是 "Supports OpenCode, Claude Code, Codex, Cursor, and 75 more"——点名 4 家加 75 家,合计 79 家;它的支持列表表格共 70 行(有些行一行覆盖多个 agent 名)。"80 家"是四舍五入,不够准,本文改成 79。
19常见问题
show-me 是零依赖的:只有一个 markdown 文件,不写仓库、不需要密钥、不改你的代码。其余四个都要求你具备某种前提(被忽略的项目说明书、React 组件库、CI 与校验命令)。/show-me 与直接说"画个图"有什么区别?show-me 会额外遵守三条纪律:跳过铺垫、散文压短、挑最小视图(05)。实际差别通常体现在铺天盖地的完整文件引用消失了,只剩那几行关键结构。show-me 记的是 1.0.1,其余四个是 1.0.0——这与提交历史吻合:它在 8 月 9–13 日之间被连续修订了四次(08)。npx skills update(可带技能名)。插件市场那条路取决于 Claude Code 的更新机制。无论哪条路,本仓是活跃仓库,建议隔一段时间跑一次 update。Bash(open …)、加上你自己的目录约定,就是一个私有版本。代价是你从此要自己跟上游同步(用 diff 的方法在 08)。.claude-plugin/marketplace.json,skills CLI 那条只认 SKILL.md 目录树。两套发现机制各读一半——所以两条路都走,就会得到两份可能不同步的副本(04)。20术语对照表
| 术语 | 定义 | 为什么重要 / 何时用 · 别当什么用 |
|---|---|---|
| Agent Skill(技能) | 一份带 YAML 头部(name + description)的 SKILL.md,用来给 agent 补充一套特定任务的指令 |
为什么重要:它是本仓唯一的知识载体,一个技能 = 一个 markdown 文件。别当什么用:它不是代码插件——没有依赖、没有构建、没有沙箱,所谓"安装"只是把文件放到 agent 会读的目录里 |
| frontmatter(文件头元数据) | SKILL.md 最上面用三条短横线夹住的一小段键值信息(name、description) |
何时用:CLI 列出技能、agent 判断"这个技能是干什么的"时读的就是它。别当什么用:它和 README 里的人工简介不是同一份真相——不一致时以它为谁 |
插件市场清单 marketplace.json |
声明"本仓库是一个市场、内含哪些插件"的 JSON,放在仓库根的 .claude-plugin/ 下(本仓 2,730 字节) |
何时用:走 Claude Code 原生插件安装这条路的唯一入口。别当什么用:skills CLI 完全不理它——两条安装路读的是不同的文件,这也是"同一个技能能装出两份"的根源 |
| plugin.json | 每个插件目录里的元数据文件:名字、版本、作者、关键词 | 为什么重要:版本号(1.0.1 之类)只在这条路上有意义,它也是本文判断"哪个技能被改过"的依据之一。别当什么用:走 CLI 安装时它基本被忽略 |
| references 附件 | 技能目录下 references/ 里的模板、示例、脚本,由 SKILL.md 按文件名点名引用 |
为什么重要:它决定技能的体量与产物是否稳定——本仓从 0 到 10 个附件,对应"教一种表达法"到"生成一整套会长期运行的文件"。别当什么用:不是参考资料库,是 SKILL.md 的延伸部分,装技能时会一并复制过去 |
| skills CLI | npm 包 skills(vercel-labs/skills),一个负责"找仓库 → 选技能 → 放进你的技能目录"的命令行工具 |
何时用:你想跨 agent 用同一批技能、或想把技能文件写进自己仓库时。别当什么用:它不是 Claude Code 的一部分,也不认识 marketplace.json |
| skills-lock.json | 安装 CLI 留下的记账文件,记录每个技能的来源、skillPath 与 computedHash |
何时用:想知道"这个技能从哪来、升级时该去哪个路径取"时看它。别当什么用:里面的 computedHash 不是文件的 SHA-256(18 实测),别拿它做校验和比对 |
| SHA-256 | 一种把任意长度内容压成固定长度"指纹"的算法,内容变一个字节指纹就完全不同 | 何时用:判断"我装到的文件与上游是不是同一个"时。别当什么用:它是同一份内容的一致性证明,不是"文件安全"的证明——内容本身有害的话指纹照样一致 |
| harness(agent 框架) | 运行 AI agent 的那层外壳:它决定读哪些文件、怎么把技能暴露给模型、允不允许执行命令 | 为什么重要:同一个技能在不同框架里行为可能不同——Bash(open …) 只在 Claude Code 里成立就是例子。别当什么用:不要假设"技能是通用的"就等于"行为是通用的" |
| 显式调用(user-invoked) | 由你敲命令(/show-me)才触发的技能 |
为什么重要:本仓 5 个技能实际都倾向这条路径——description 写的是功能而非触发条件。别当什么用:不是说模型永远不会自己用它,只是没有明确的条件声明时不要指望它自动出现 |
| live 路径(真实调用路径) | 应用真正会走到的那条代码路径(路由、被接线的组件、生产包导出),相对于只为 Storybook/测试存在的支撑代码 | 何时用:判断"这个可选 prop 该不该保留"时,它被当作唯一真相。别当什么用:对公开发布的组件库,外部使用者也在这条路径上,而你看不到他们(12) |
| 设定值 / 传感器 / 控制器 / 执行器 | 控制论五件套里的四个:目标、测量、决策、动手 | 何时用:设计任何"让 agent 反复改进某个属性"的流程时,它能逼你把"改什么、谁来量、怎么算改好了"分开想清楚。别当什么用:它们不要求真的拆成四个独立步骤——design-control-loop 明确说了组件可以融合 |
| 阻尼器(回归闸门) | 在 PR/推送时把测量结果与基线比较,只报新增偏差的检查 | 为什么重要:循环每天只改一点点,阻尼器负责"在变好之前别先变坏"。别当什么用:它和流量控制(限制同时开着的 PR 数)是两回事——一个防质量下滑,一个防评审积压 |
| PR 边界(流量控制) | 定时运行前先查"本循环还有没有开着的 PR",达到上限就跳过 | 何时用:任何定时开 PR 的自动化都必须有。本仓两个循环技能的默认值是 1。别当什么用:它不是限速器——手动派发会被有意放行,以便需要时强制跑一次 |
| 记忆文件(agent memory) | 放在 .github/agent-memory/ 下、每次运行都被注入执行的 markdown |
为什么重要:它是"人在环上"唯一的持久转向通道——改它等于改未来所有运行的选择,而不只是这一个 PR。别当什么用:不是日志,也不是技能的第二份副本;删掉它若只丢历史记录,就说明写错了内容 |
| workflow_dispatch | GitHub Actions 里"允许手动点一下就跑"的触发器开关 | 何时用:你想按需强制跑一次定时工作流时。别当什么用:工作流从未运行过之前它是不可用的,必须先被 push 触发一次(13) |
| 无头运行(headless) | 不弹界面、直接在命令行里把一个 agent 跑完并拿到输出 | 何时用:把 agent 接进自动化流水线时,它就是"执行器"的实现方式。别当什么用:无头模式通常要配"跳过权限确认"的参数,只应在受信任的隔离环境里跑 |
| /iterate 评论 | 维护者在 agent 开的 PR 下留言 /iterate <反馈>,对应的那支工作流就更新这个 PR |
为什么重要:它解决"多个 agent 工作流都在听同一句命令"的问题——PR 正文里埋了一个隐藏标记,只有当初开 PR 的那支工作流会响应。别当什么用:它不是重新跑一遍完整的循环,而是对一段评审意见做一次执行 |
| Mermaid | 一种用纯文本描述图表的标记语法,支持它的阅读器会把文字渲染成图 | 何时用:有多个参与者来回传递信息时(时序图最典型)。别当什么用:在纯文本终端里它就是一段代码,读者什么图也看不到(06) |
| diff | 两份文本的差异:+ 开头是新增、- 开头是删除、没标记的是原有内容 |
何时用:周边结构已经存在、读者只需要看"变了什么"时。别当什么用:大多数内容都是新的时候不要硬用 diff——那时应该整块贴 |
21参考来源与证据边界
我实际读了什么
- github.com/humanlayer/skills 仓库
main分支(最新提交3c26291,2026-08-13)的全部 5 份SKILL.md与全部 21 个 references 附件,以及根README.md、LICENSE、.claude-plugin/marketplace.json、5 份.claude-plugin/plugin.json。 - GitHub REST API(GitHub 提供的网址接口:用一条 URL 就能取回仓库数据):仓库元数据(stars / forks / 创建与最后推送时间)与提交列表(用于 08 的四个提交);
git/trees/main?recursive=1用于 35 文件 / 25 目录与全部字节数。 - raw.githubusercontent.com:按提交哈希取
show-me的四个历史版本做逐字节 diff,并取两个循环技能的同名附件做哈希比对。 - skills.sh 的 humanlayer/skills 页面:5 个技能的装机量与仓库总量(页面显示的是四舍五入到 0.1K 的值)。
- vercel-labs/skills 的 README 与 npm registry:CLI 版本、支持的 agent 数与安装作用域、各子命令、
--list/--copy等选项。 - 本机实测:用
npx skills@1.5.26列出、安装(空目录)、检查落点与锁文件、用shasum与上游原文比对,并另装一次带 references 的技能确认附件会一起落地。 - humanlayer.dev 首页:用于确认 HumanLayer 是什么产品(多人协作的 coding agent IDE 加云端)。
本文实算的数字(复核方式都写在正文里)
35 个文件 / 25 个目录;5 份 SKILL.md 合计 49,559 字节;各技能字节数(3,297 / 9,450 / 7,764 / 13,553 / 15,495);各插件总字节(3,691 / 9,847 / 21,336 / 48,163 / 62,488);show-me 四版字节数(2,977 / 3,168 / 3,230 / 3,297);show-me 的行数/词数(127 / 460);两个循环技能共用附件的 SHA-256 比对;装机量分项之和与页面总数的两次交叉验证;安装副本与上游原文的 SHA-256 一致性。全部由本地脚本、curl、diff、shasum 算出,不依赖任何二手摘要。
证据边界与时效
- 版本口径。所有事实的读取时间是 2026-09-13;上游
main当时最新提交是3c26291(2026-08-13)。这是一份会过时的资料——5 个技能里有 4 个仍是 1.0.0 的初版,show-me在 8 月 9 日至 13 日之间被改过四次,说明这个仓库还在活跃修改。 - 明确的推断(未验证)。18 里"
computedHash可能是整目录清单哈希"是从"它不等于文件哈希"这一实测事实推出的,文中已就地标注为推断;我没有读 CLI 源码确认它的构造方式。 - 没有验证的东西。① Claude Code 插件市场那条安装路径我没有真实执行——
plugin.json与marketplace.json的字段含义来自文件内容与插件规范的常识,没有跑通安装验证;② 两个循环技能生成的 GitHub Actions 我没有在一个真实仓库里跑过,"首次不能手动派发"这条来自技能文档的自述与 GitHub 的公开行为,不是我实测;③show-me的 HTML 分支在真实项目里的产出效果我没有现场对照过。 - 一处口径说明。装机量(installs)是 skills.sh 平台自己统计的数,页面只给出四舍五入到 0.1K 的值;本文只转述并标明来源与日期,不做趋势判断——同一技能在插件市场那条路上的安装不在这个数里。
这是一篇会过时的文章(shelf-life=evolving)。最值得重核的三处:① show-me 的 SKILL.md 是否又被改(对比 SHA-256 前 16 位 bea6da70a5809673);② 各插件的版本号(4 个仍是 1.0.0,任一升到 1.0.1 就意味着有内容变更);③ skills CLI 的大版本(本文实测基于 1.5.26,命令与落点若变,04 需重跑)。
你自己验的那一条
上面所有结论你都能自己复核。唯一一条只有你能验:把本文的例子换成你自己场景里的例子——打开你正在改的那个文件,用 /show-me 用调用树讲一下 XXX 的执行顺序 问一次,看它给你的树是不是"刚好说清要害的最小视图"。如果它给了你一张大而全的东西,说明那个刹车在你这里没有生效——那正是本文要你留意的地方。
99一句话总结
humanlayer/skills 是 35 个文件、5 个 markdown 技能的两类工具:三个"一次性动作"(重写项目说明、收窄 React 类型、把重复任务造成一台循环机器)和两个"表达规范";而其中被装得最多的 show-me,全文只有 3,297 字节,它做的唯一一件事是收窄选择空间——禁止铺垫、压缩散文、永远挑"刚好说清要害的最小视图"(六种视图 + 四种 diff 查表,密到文本表达不了时才写一个 HTML 文件并打开它)。它的四次修订(+320 字节)验证了这个方向:一次把产物从 HumanLayer 私有目录解耦成通用 HTML + 打开动作,其余全在修模型的默认坏习惯。用它要记住三条边界:锚点是当前对话(不会替你查证)、Bash(open …) 是 Claude Code 记法(换框架要翻译)、HTML 落点没有约定(自己定目录或忽略掉)。而它与"生成一篇能长期复习的教程"是两件完全不同的事——后者要的是契约、来源与校对日期,show-me 两者都没有,也不该有。