背景
本周用了一个 CLI 工具 AI Agent 技能包(Skills),它可以安装目前 GitHub 上被 skills.sh 收录的 Skills,且支持不同平台。这个工具省去了自己去下载技能包和挪动到对应 Agent Skills 目录的步骤,还是很方便的。
使用方法
本机没有安装,直接让 Claude Code 执行 npx skills --help 出一个这个工具的使用说明文档。以下是 npx skills 工具的使用说明:
npx skills 使用说明
skills 是一个用于管理 AI Agent 技能包(Skills)的 CLI 工具。
命令概览

常用选项

典型用法示例
- 安装技能包(项目级):skills add vercel-labs/agent-skills
- 安装到全局:skills add vercel-labs/agent-skills -g
- 只安装到指定 agent:skills add vercel-labs/agent-skills --agent claude-code cursor
- 只安装包中的特定技能:skills add vercel-labs/agent-skills --skill pr-review commit
- 交互式卸载: skills remove
- 按名称卸载:skills remove web-design
- skills rm --global frontend-design
- 列出项目技能:skills list
- 列出全局技能:skills ls -g
- 按 agent 过滤:skills ls -a claude-code
- JSON 格式输出:skills ls --json
- 搜索技能:skills find / skills find typescript
- 更新所有技能:skills update
- 更新指定技能:skills update my-skill
- 只更新全局技能:skills update -g
- 初始化新技能:skills init my-skill
- 从 lock 文件恢复:skills experimental_instal
- 从 node_modules 同步:skills experimental_sync -y
技能包来源
支持以下格式指定包来源:
- GitHub 短路径:vercel-labs/agent-skills
- 完整 GitHub URL:https://github.com/vercel-labs/agent-skills
更多技能可在 https://skills.sh/ 发现。
知识扩展
掘金上看到这个工具的作者实现这个工具的过程,就在想实现一个 npm CLI 工具是什么样的流程呢?技术栈如何?我能不能自己实现一个?命令需要发布到 npm 的仓库吗?
直接对话,问出了 npm CLI 工具的实现流程,然后让 claude 写了一个利用 scp 上传文件到服务器的 CLI 工具。扩展学习内容如下:
npx 的工作原理分两层
1.npx 的解析逻辑
npx skills
├── 先查本地 node_modules/.bin/skills
├── 没有 → 去 npm registry 查包名 "skills"
├── 下载到临时缓存目录
└── 执行 package.json 中 bin 字段指向的脚本
所以 是的,需要发布到 npm(或者用其他方式,见下文)。
2. 关键:package.json 的 bin 字段
发布一个 CLI 工具,核心就是这个字段:
javascript
{
"name": "skills",
"version": "1.0.0",
"bin": {
"skills": "./bin/cli.js"
}
}
npm install -g skills 或 npx skills 时,npm 会把 skills 这个命令名映射到
./bin/cli.js。cli.js 第一行必须有 shebang:
javascript
#!/usr/bin/env node
// 下面就是普通 Node.js 代码
3. 发布流程
npm login
npm publish # 发布到 registry.npmjs.org
包名就是 name 字段,之后 npx skills 就能找到它。
4. 不发布到 npm 的替代方案
npx 也支持直接从 GitHub 运行,不需要发布:
npx github:vercel-labs/skills-cli 或
npx https://github.com/vercel-labs/skills-cli
npx 会 clone 仓库、npm install、然后执行 bin。
5. CLI 框架
实际开发中一般用现成框架解析参数,不手写:

6.发布仓库时,仓库会审核吗?
不审核,发布是即时生效的。npm publish 执行后几秒内包就能被全球安装,没有人工审核环节。npm 有的机制
- 自动化恶意代码扫描:npm 有机器检测,但不是人工 review
- 事后下架:发现违规包会删除,但已经被安装的无法召回
- 举报机制:任何人可以向 npm 举报可疑包
这带来的问题,正因为没有审核,npm 历史上出现过大量安全事件:
- typosquatting:注册 lodahs、requst 等拼写相近的包名,等人装错
- 依赖投毒:event-stream 事件,维护者转让包权限后被植入恶意代码
- 依赖混淆攻击:注册与公司内部包同名的公开包,利用 npm 优先级漏洞
实际影响,对你自己发布工具来说没什么影响,发完就能用。但这也是为什么安装第三方包时要注意:
- npm audit # 检查已安装依赖的已知漏洞
- npm install --ignore-scripts # 禁止安装时执行 postinstall 脚本
其他主流仓库(PyPI、crates.io、Maven Central)也基本是同样的策略------自动化检测 +事后处理,没有人工预审。
实现 scp 的 CLI工具
1.核心思路
Node.js 调用系统命令用 child_process 模块,关键是选对方法:

scp 有进度输出,用 spawn。
2.实现
javascript
#!/usr/bin/env node
const { spawn } = require('child_process')
const { program } = require('commander')
program
.name('myupload')
.argument('<local>', '本地文件路径')
.argument('<remote>', '远程路径,格式:user@host:/path')
.option('-i, --identity <file>', '指定私钥文件')
.option('-P, --port <port>', '端口', '22')
.action((local, remote, opts) => {
const args = ['-P', opts.port]
if (opts.identity) {
args.push('-i', opts.identity)
}
args.push(local, remote)
// 用数组传参,不拼字符串,避免命令注入
const proc = spawn('scp', args, {
stdio: 'inherit' // 直接继承父进程的 stdin/stdout/stderr
// scp 的进度条、密码提示都能正常显示
})
proc.on('close', (code) => {
if (code !== 0) {
console.error(`上传失败,退出码 ${code}`)
process.exit(code)
}
console.log('上传完成')
})
})
program.parse()
stdio: 'inherit' 是关键------让 scp的进度输出和密码提示直接透传到终端,不需要自己处理。
3.在指定目录实现

4.注册方式
npm link 已经把命令注册到全局 PATH 了,这个是通过什么命令注册的,怎么查看全局 ?
通过 echo $PATH 看到 nvm 的命令目录:

进入 bin 目录,里面有一行软连接指向了自定义模块的 bin 下的 cli.js:
powershell
lrwxr-xr-x 1 xxx staff 41 5 21 10:28 scp-upload@ -> ../lib/node_modules/scp-upload/bin/cli.js
继续看自定义模块目录,这个 node_modules/scp-upload 是个link :
powershell
scp-upload@ -> ../../../../../../../../Applications/2026NewYear/AICode/scp-upload
真实的模块定义结构:
scp-upload/
├── bin/cli.js # 入口,参数解析
├── lib/upload.js # scp 调用逻辑
└── package.json
启示录
Claude 用来学习是个不错的用途,知识丰富,hello world 很快就能看到 demo,不理解的问题,追问到明白为止。