夜雨聆风学习资料网

ARTICLE · 1181599

一个技能要装进 79 个 AI 编码助手?vercel-labs/skills 用符号链接一次搞定

一个技能要装进 79 个 AI 编码助手?vercel-labs/skills 用符号链接一次搞定

Agent Skills · 跨 Agent 分发 · 符号链接 · 双层锁文件 · npx 零安装 —— vercel-labs/skills (npm 包名就是 skills,当前版本 1.7.2)是 Vercel Labs 维护的开源技能分发工具。 它把一份 SKILL.md 技能包,按各家的目录约定装进近 80 个 AI 编码助手,并用锁文件记住来源与哈希。

技能装不进第二个 Agent

如果你同时用 Claude Code 和 Cursor,很可能已经踩过这个坑: 技能文件放在 .claude/skills/ 能让前者识别,后者却只看 .agents/skills/。 换成 Gemini CLI、OpenCode、GitHub Copilot,路径又是另一套。 同一份内容复制四份,改一处忘三处,最后谁也不知道哪份是最新的。

这里说的「技能」,是 SKILL.md 加 YAML frontmatter 的约定格式, name 与 description 是必填字段,正文写「什么时候用、按什么步骤做」。 它本质是一段给模型看的结构化提示词,而不是代码。

目录约定不统一,带来三个具体麻烦:

• 分发成本:公开技能作者要写四种安装说明,读者还得自己对号入座。

• 更新成本:技能升级后,旧副本散落在各处,没人能确认是否全部更新。

• 协作成本:团队的 .claude/skills/ 提交进仓库,用 Cursor 的同事打开却什么都看不到。

受影响的人很明确:同时使用多个 Agent 的开发者、维护公开技能仓库的作者、 以及想把团队规范固化成技能并在 CI 里复现的工程团队。

三条上手路径

最短路径:在你的项目根目录执行下面一行,剩下的交给交互式提示。

npx skills add vercel-labs/agent-skills

它会列出仓库里所有技能,让你勾选要装哪些、装给哪些 Agent、装到项目还是全局。 npx 直接运行,不需要预先全局安装,这也是它把「试用成本」压到最低的地方。

样例一:非交互式装机。CI 或脚本里用不了选择界面,把决策全部写成参数即可。 输入是一条技能源,动作是限定技能名、装到全局、只给 Claude Code、跳过确认, 结果是该技能落在 ~/.claude/skills/ 下,全程无提示。

npx skills add vercel-labs/agent-skills --skill frontend-design -g -a claude-code -y

样例二:不安装,先用一次。想先看看技能效果,可以用 use。 比如下面这条命令取出技能内容,写进临时目录,把生成的提示词只打印到标准输出, 再用管道喂给 claude,本轮对话立刻带上这份技能,磁盘上不留痕迹。

npx skills use vercel-labs/agent-skills@web-design-guidelines | claude

如果不想手工接管道,加 --agent claude-code,它会直接以该提示词启动一个交互式会话。

样例三:团队用锁文件复现。项目里提交 skills-lock.json 后, 新同事或 CI 跑一条恢复命令,就能装出完全一致的技能集合,不必逐个回忆装过什么。

npx skills experimental_install

另外 npx skills sync 能从 node_modules 里收编技能: npm 包可以在自己的 package.json 里声明 skills 字段,把技能随包发布。

常见误区:

• 不加 -g 时默认装到当前项目(.agents/skills/),换目录就看不到了。

• 默认用符号链接建立关联,Windows 或受限文件系统上需要补 --copy 改成真实复制。

• 来源不限于 GitHub 简写。GitLab、Azure Repos、任意 Git URL、本地目录, 甚至一个直接指向 SKILL.md 或压缩包的下载链接,都能作为 add 的输入。

一份实体,链接分发

先说整体流程。源码里 source-parser.ts 把用户输入的来源归一化, providers/ 下的注册表挑出可用的获取方式(Git 克隆、快照下载、well-known 索引、直接下载), skills.ts 在容器目录里逐层找出所有 SKILL.md, installer.ts 负责落盘,最后 skill-lock.ts 与 local-lock.ts 记下这次安装。

创新点一:只保留一份实体,其余全部是链接。 工具选定一个规范目录(项目内 .agents/skills/,全局 ~/.agents/skills/), 把技能内容放进去,然后从每个目标 Agent 的目录建一条符号链接指过去。 默认的 symlink 模式是「复制到规范目录 + 从各 Agent 目录建链」, copy 模式是「各装各的」,link 模式则让规范目录本身指向技能源,方便本地开发边改边试。

这么做的收益很直接:同一技能在磁盘上只有一份,更新只改一处,所有 Agent 立即同步。 把 .agents/skills/ 当通用位置的 Agent(如 Cursor、Gemini CLI、GitHub Copilot、OpenCode), 干脆直接共用规范目录,连链接都省了。 代价是符号链接的平台差异——代码里为此准备了 Windows junction 回退与复制兜底, 还要处理「父目录本身是链接」时不能用相对路径解析的情况,否则会生成断链。

创新点二:绕开 git 的快照下载。 技能通常只包含几个文本文件,为它完整克隆一个仓库代价过高。 于是存在一条快路径:先用 GitHub Trees API 定位 SKILL.md 的位置, 再从 raw.githubusercontent.com 取 frontmatter 拿到技能名, 最后向 skills.sh 的下载接口取整包快照,快照自带内容哈希。 命中缓存时,安装过程与 git 无关。代价是对中心服务的依赖, 仓库不在缓存里就自动回落到克隆,个别仓库也可以自托管下载地址。

创新点三:两层锁文件,各自解决一个冲突。 全局锁 ~/.agents/.skill-lock.json 记录来源、来源类型、ref、技能子路径, 以及一个 GitHub tree SHA——它覆盖整个技能目录,任何文件变化都会让它改变, 因此更新检测可以只比对哈希,而不必下载内容。

项目锁 skills-lock.json 走另一条路:哈希由磁盘上所有文件内容算出, 并且刻意不写时间戳、按键名排序。设计意图写在注释里—— 两个人各加一个技能,产生的是 JSON 里互不重叠的键, git 能自动合并;如果塞入时间戳,同一份文件的变更就会处处冲突而难以合并。

创新点四:把「技能来源」做成开放协议。 除了 Git 托管,工具实现了 well-known 发现机制: 站点在约定路径放置 index.json,遵循 agentskills.io 的 0.2.0 schema, 每个技能条目带类型、URL 与 digest。 这让任意网站都能发布技能,技能分发第一次摆脱了「必须有个 Git 仓库」的前提。 带路径作用域的地址若在该路径下找不到技能,会直接报错而不是回落到根索引, 避免误装整个技能目录。

安全面同样值得一提,因为技能元数据来自陌生人的 frontmatter。 代码里有专门的清洗函数,剥掉 CSI、OSC、C1 等终端转义序列与危险控制字符, 防的是 CWE-150 终端转义注入——不清洗的话,一个技能描述就能清屏、移动光标、 甚至伪装成工具的正式输出。此外还有 Git 传输协议白名单(拒绝 ext:: 这类可执行协议)、 带边界检查的解压实现,以及下载 10 MiB、解压 25 MiB、1000 个文件的默认上限, 三项都可用环境变量放开。标记 metadata.internal: true 的技能默认隐身, 需要显式设置环境变量才会被发现。

从个人到团队

场景一:团队规范只写一次。 把「提交信息格式」「API 错误码约定」这类团队约定写成技能,放在内部仓库。 每个人按自己用的 Agent 装一次,不需要知道对方的目录长什么样。 skills-lock.json 进版本库后,技能来源与内容哈希的变更会出现在代码评审里, 治理方式和依赖升级保持一致。

场景二:镜像里预热技能。 容器镜像构建阶段用 -g -a claude-code -y 把常用技能装进镜像, 运行时就不用联网拉取,离线与内网环境同样可用。

往远看,这个项目最有价值的部分可能不是 CLI 本身,而是它沉淀的两样东西: 一份近 80 个 Agent 的目录约定注册表,以及一套可校验的技能来源协议。 当 npm 包能通过 package.json 的 skills 字段随身携带最佳实践、 文档站能通过 well-known 索引直接变身技能源时, 技能就从「手动拷贝的提示词片段」,变成了可分发、可锁版本、可评审的普通依赖。

相关学习资料