AI 编程应用:实现 npm CLI 工具 scp-upload

背景

本周用了一个 CLI 工具 AI Agent 技能包(Skills),它可以安装目前 GitHub 上被 skills.sh 收录的 Skills,且支持不同平台。这个工具省去了自己去下载技能包和挪动到对应 Agent Skills 目录的步骤,还是很方便的。

使用方法

本机没有安装,直接让 Claude Code 执行 npx skills --help 出一个这个工具的使用说明文档。以下是 npx skills 工具的使用说明:

npx skills 使用说明

skills 是一个用于管理 AI Agent 技能包(Skills)的 CLI 工具。

命令概览

常用选项

典型用法示例

  1. 安装技能包(项目级):skills add vercel-labs/agent-skills
  2. 安装到全局:skills add vercel-labs/agent-skills -g
  3. 只安装到指定 agent:skills add vercel-labs/agent-skills --agent claude-code cursor
  4. 只安装包中的特定技能:skills add vercel-labs/agent-skills --skill pr-review commit
  5. 交互式卸载: skills remove
  6. 按名称卸载:skills remove web-design
  7. skills rm --global frontend-design
  8. 列出项目技能:skills list
  9. 列出全局技能:skills ls -g
  10. 按 agent 过滤:skills ls -a claude-code
  11. JSON 格式输出:skills ls --json
  12. 搜索技能:skills find / skills find typescript
  13. 更新所有技能:skills update
  14. 更新指定技能:skills update my-skill
  15. 只更新全局技能:skills update -g
  16. 初始化新技能:skills init my-skill
  17. 从 lock 文件恢复:skills experimental_instal
  18. 从 node_modules 同步:skills experimental_sync -y

技能包来源

支持以下格式指定包来源:

更多技能可在 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 skillsnpx skills 时,npm 会把 skills 这个命令名映射到
./bin/cli.jscli.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,不理解的问题,追问到明白为止。

相关推荐
清钟沁桐2 小时前
mlir 编译器学习笔记之十 -- 数据类型
笔记·学习·mlir
red_redemption2 小时前
自由学习记录(190)
学习
Pizza_Lawson2 小时前
spinningup学习笔记(二)
笔记·学习
吃好睡好便好2 小时前
在Matlab中绘制饼状图
开发语言·学习·matlab·3d·信息可视化
nashane2 小时前
HarmonyOS 6学习:外接键盘CapsLock键“失灵”?一招解锁大写输入
学习·华为·计算机外设·harmonyos
清钟沁桐2 小时前
mlir 编译器学习笔记之九 -- 后端生成
笔记·学习·mlir
叶~小兮2 小时前
Zabbix 7.0 深度原理与生产进阶运维学习笔记
运维·学习·zabbix
我想我不够好。2 小时前
2026.5.21 消防监控学习 1.5hours
学习
燐妤2 小时前
前端HTML编程6:ES6与前后端交互
前端·javascript·学习·html5