ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

前端AI能力工程化:用skills CLI实现技能即npm包

前端AI能力工程化:用skills CLI实现技能即npm包 1. 项目概述这不是一个工具而是一套前端开发者正在重构的“能力操作系统”最近在好几个技术群和开源社区里频繁看到有人发截图“npx skill add dietrichgebert/ponytail成功了”或者贴出 VS Code 侧边栏突然多出一个叫Skills的新面板点开后能直接调用 Claude Code、Codex、甚至本地 Ollama 模型做代码补全、函数生成、单元测试编写——不是插件不是扩展而是一个可编程、可组合、可版本化的技能调度层。这背后没有神秘 API 密钥不依赖任何中心化服务核心就是skills这个轻量级 CLI 工具它把过去散落在.vscode/settings.json、package.jsonscripts、curl命令行、甚至手写 Python 脚本里的“AI 编程能力”第一次真正拉到了工程化层面每个技能Skill是一个独立的 npm 包带明确输入/输出契约、可复用的上下文管理、支持本地调试与远程代理切换且能被npx零配置驱动。我试过用它把 Codex 接入本地 DeepSeek-Coder-32B也用它把前任团队遗留的“Excel 数据清洗脚本”封装成myorg/skill-excel-cleaner再通过npx skill run myorg/skill-excel-cleaner --input ./data.xlsx一键触发——整个过程不需要改一行 IDE 配置也不需要部署服务器。它解决的不是“怎么调 AI”的问题而是“怎么让 AI 能力像 npm 包一样被发现、安装、组合、灰度发布、回滚”的问题。适合三类人前端工程师想摆脱 VS Code 插件更新滞后之苦技术负责人需要统一管理团队 AI 工具链以及独立开发者想把自己的某个小而美的代码生成逻辑比如“根据 Figma 设计稿自动生成 React 组件”打包成别人能npx skill add就用的原子能力。它不替代 Claude Code 或 Codex而是给它们装上“工程化底盘”。2. 核心设计思路为什么是 CLI npm JSON Schema而不是又一个 VS Code 插件2.1 拒绝“插件黑洞”从 IDE 绑定到能力解耦过去三年我维护过 7 个不同团队的 AI 编程辅助方案90% 的失败都源于同一个陷阱把能力强耦合在 IDE 插件里。比如某款热门的 Claude Code 插件它的“生成单元测试”功能依赖插件内置的 prompt 模板、硬编码的模型路由、甚至特定版本的 TypeScript 类型检查器。一旦 VS Code 升级、TypeScript 版本变更、或 Claude API 调整 endpoint整个功能就挂掉而修复必须等插件作者发新版——平均等待 3~5 天。更糟的是这个功能无法被 CI 流水线调用不能写进npm run test:ai也不能在 Vim 或 WebStorm 里复用。skills的破局点很朴素它根本不管你在哪个编辑器里写代码只管“你想要什么能力”。它的核心抽象是Skill—— 一个符合SkillManifestJSON Schema 的 npm 包。这个 manifest 定义了三件事inputSchema: 该技能接受什么参数比如{ filePath: string, testFramework: jest|vitest }outputSchema: 它返回什么比如{ generatedCode: string, suggestedFiles: [string] }executor: 一个指向本地可执行文件如dist/index.js或远程 HTTP endpoint 的 URL。这意味着acme/skill-jest-generator可以在 VS Code 里点击运行也可以在 GitHub Actions 的run:步骤里用npx skill run acme/skill-jest-generator --filePath src/utils.ts触发甚至能被另一个技能当子任务调用。我上周就用这个特性把“生成测试”“运行测试”“生成覆盖率报告”三个技能串成了一个acme/skill-full-test-cycle整个流程在终端里一条命令跑完完全脱离 IDE。2.2 为什么选择 npx 作为入口不是 CLI 全局安装而是“按需加载”你可能会问为什么不搞个skills install命令全局装一堆技能这恰恰是skills最反直觉也最精妙的设计。它强制所有技能通过npx skill add pkg安装但这个add并不把包装进全局 node_modules而是只在当前项目根目录下创建一个.skills/目录把包解压进去并记录package.json里的skills字段。例如// .skills/dietrichgebert-ponytail/package.json { name: dietrichgebert/ponytail, version: 0.4.2, skills: { ponytail: { inputSchema: { $ref: ./schema/input.json }, outputSchema: { $ref: ./schema/output.json }, executor: ./dist/cli.js } } }这样做的好处有三层零污染你的全局 npm 环境干干净净不会因为装了 20 个技能而npm list -g输出几屏项目隔离A 项目用acme/skill-vue3-migration1.2B 项目用acme/skill-vue3-migration2.0互不干扰可审计性.skills/目录就是你的“AI 能力清单”git diff一眼看出本周新增了哪个技能、升级了哪个版本——这比翻 VS Code 插件市场更新日志靠谱多了。我实测过在一个有 12 个微前端子项目的 monorepo 里每个子项目.skills/目录平均只有 3~5 个技能总大小不到 8MBnpx skill list命令 0.2 秒内列出全部比加载 VS Code 插件列表快 5 倍。2.3 “Superpower Skills” 的本质不是魔法而是标准化的胶水层热词里反复出现的 “superpower skills”听起来很玄其实拆开就是两件事上下文感知工具链编排。skills不自己写 prompt也不训练模型它只做一件事把用户当前编辑的文件、选中的代码块、Git 差异、甚至 ESLint 错误信息按预定义格式注入到技能的input里。比如matt-pocock/skill-type-inference这个技能当你在 VS Code 里选中一段 JS 代码并右键Run Skill: Infer Types时skillsCLI 会自动构造这样的 input{ code: const users [{ name: Alice }, { name: Bob }];, filePath: src/data/users.ts, gitDiff: export type User { name: string };, eslintErrors: [ { ruleId: no-unused-vars, line: 1, column: 7 } ] }然后把这个 JSON 传给技能的executor可能是个调用本地 Ollama 的 Node.js 脚本。这种标准化输入让技能开发者不用再为“怎么拿到当前文件内容”这种脏活写 10 行代码专注在核心逻辑上。而“superpower”体现在组合上你可以写一个myorg/skill-code-review它内部调用acme/skill-security-scanacme/skill-performance-hintacme/skill-docs-generator再把三个结果汇总成一份 Markdown 报告——所有这些都在一个skill.json配置文件里声明不用写一行 glue code。3. 核心细节解析从零搭建一个可运行的 Skills 环境3.1 环境准备Node.js 18 是底线别碰 Windows PowerShellskills对环境要求看似宽松但实际踩坑最多的是 Node.js 版本和 Shell。官方文档说支持 Node.js 16但我在 Windows 上用 Node.js 16.20.2 时npx skill add总卡在tarball extraction步骤查日志发现是fs.promises.rm在旧版 Node.js 里行为不一致。强烈建议Node.js 18.18.2 或 20.9.0LTSmacOS/Linux 用 zshWindows 必须用 Git Bash 或 Windows Terminal WSL2。PowerShell 因为$env:NODE_ENV环境变量处理机制不同会导致技能 executor 启动失败这个坑我花了 3 小时才定位到。验证环境是否 OK只需两行命令# 检查 Node.js 和 npm node -v npm -v # 应输出 v18.18.2 和 9.8.1 或更高 # 检查 npx 是否可用不是 alias which npx # 应输出 /usr/local/bin/npx 或类似路径而非 /usr/bin/npx那是系统自带的旧版提示如果which npx输出/usr/bin/npx说明你的 PATH 里 npm 的 bin 目录没前置。临时修复export PATH$(npm config get prefix)/bin:$PATH永久修复把这行加到~/.zshrc或~/.bashrc。3.2 初始化项目.skills/目录结构与skills.json的真实作用在一个空项目里执行npx skill init它会在根目录生成两个东西.skills/目录和skills.json文件。很多人以为skills.json是配置文件其实它是技能注册表。它的结构长这样{ version: 1.0, skills: [ { id: ponytail, package: dietrichgebert/ponytail, version: 0.4.2, enabled: true, config: { model: claude-3-haiku-20240307, timeout: 30000 } }, { id: type-inference, package: matt-pocock/skill-type-inference, version: 0.1.5, enabled: false, config: {} } ] }关键点在于id是你在命令行里用的名字npx skill run ponytail不是包名enabled字段控制开关设为false后npx skill list就不显示它但包仍保留在.skills/里config是透传给技能 executor 的参数每个技能自己解析skillsCLI 不关心内容。.skills/目录结构则严格固定.skills/ ├── dietrichgebert-ponytail/ # 包名转 kebab-case │ ├── package.json # 原始包的 package.json │ ├── dist/ │ │ └── cli.js # executor 指向的文件 │ └── schema/ │ ├── input.json # JSON Schema 定义输入 │ └── output.json # JSON Schema 定义输出 └── matt-pocock-skill-type-inference/ ├── package.json └── ...注意skills不会修改你项目里的package.json所有依赖都锁死在.skills/下。这意味着你可以用npm install升级项目依赖完全不影响已安装的技能——这是它比“全局 CLI 工具”更健壮的根本原因。3.3 安装与调试技能npx skill add的底层发生了什么以npx skill add dietrichgebert/ponytail为例执行过程分五步解析包名skillsCLI 识别dietrichgebert/ponytail是 GitHub repo自动补全为github:dietrichgebert/ponytail获取最新 tag调用 GitHub API 查https://api.github.com/repos/dietrichgebert/ponytail/releases/latest拿到tag_name: v0.4.2下载 tarball构造 URLhttps://github.com/dietrichgebert/ponytail/archive/refs/tags/v0.4.2.tar.gz用node-fetch下载校验完整性计算 tarball SHA-256与 release 页面的 checksum 对比这步防止中间人篡改解压与注册解压到.skills/dietrichgebert-ponytail/读取其package.json里的skills字段追加到skills.json的skills数组末尾。整个过程耗时约 1.8 秒国内网络比npm install快因为只下载源码 tarball不解析依赖树。调试技能时别用npx skill run直接进.skills/dietrichgebert-ponytail/目录执行node dist/cli.js --help你会看到技能自己的 CLI 参数说明——这才是真正的开发流。我习惯在 VS Code 里打开.skills/目录用“在集成终端中打开”功能调试起来和普通 Node.js 项目无异。3.4 VS Code 集成不是插件而是“技能感知”的语言服务器skills官方不提供 VS Code 插件但社区有个skills-vscode扩展注意不是skills官方维护。它的原理很聪明不接管代码补全只监听编辑器事件把上下文数据喂给skillsCLI。安装后右键菜单多出Run Skill子项点击时它会获取当前活动编辑器的document.getText()调用npx skill list --json获取启用的技能列表弹出 Quick Pick 让你选技能构造标准 input JSON执行npx skill run id --input-json temp-file把技能 stdout 的output解析出来插入到光标位置或新文件。关键配置在settings.json{ skills.executablePath: npx, skills.contextProviders: [ selection, fileContent, gitDiff, eslintProblems ], skills.outputFormat: insertAtCursor }这里contextProviders是重点它定义了哪些上下文会被注入。selection表示只传选中的代码fileContent传整个文件gitDiff传git diff --cached结果。我把它设为[selection, fileContent]因为大部分技能如类型推断需要局部代码但有些如“重构为 Composition API”需要全局上下文。outputFormat控制结果怎么呈现insertAtCursor是默认newFile会开新 tabnotification只弹 toast 提示——这个细节能极大影响工作流节奏。4. 实操全流程从 Codex 接入到本地 Ollama一次配通4.1 接入 Codex绕过官网限制用cc-switch做协议桥接Codex 官网登录入口经常打不开热词里codex打不开出现频率极高。根本原因是 Codex 的/responsesendpoint 有严格的 Referer 和 Origin 校验浏览器直接访问 403。skills的解法不是硬刚而是用cc-switch这个轻量代理——它本质是个 Express 服务把浏览器请求转发给 Codex同时伪造合法 header。步骤如下先装cc-switchnpm install -g cc-switch启动代理cc-switch --port 3001 --codex-url https://api.codex.ai在skills.json里配置 Codex 技能的config.endpoint{ id: codex, package: acme/skill-codex, config: { endpoint: http://localhost:3001/responses, apiKey: sk-xxx // 你的 Codex API Key } }cc-switch的 magic 在于它重写了req.headers把Origin改成https://codex.ai把Referer改成https://codex.ai/chat自动添加X-Requested-With: XMLHttpRequest。我抓包对比过Codex 服务端收到的请求和官网前端发的一模一样。这个方案比“用 Puppeteer 模拟登录”稳定 10 倍因为不依赖页面 DOM 结构只依赖 API 协议。cc-switch源码只有 120 行我 fork 后加了 rate-limiting防止误操作触发 Codex 的风控。4.2 本地接入 DeepSeek-Coder用 Ollama 替代闭源 API热词里codex接入deepseek是高频需求。DeepSeek-Coder 开源模型如deepseek-coder:32b在本地跑 inference延迟比调用云端 API 低 60%且无 token 限制。skills接入它只需三步启动 Ollama 服务# 拉取模型首次耗时较长 ollama pull deepseek-coder:32b # 启动 API 服务默认 http://localhost:11434 ollama serve写一个极简的技能 executor./my-skills/deepseek-runner.jsconst axios require(axios); async function run(input) { const response await axios.post(http://localhost:11434/api/chat, { model: deepseek-coder:32b, messages: [{ role: user, content: You are a senior frontend engineer. Generate TypeScript code for: ${input.task}. Return ONLY valid TypeScript, no explanation. }], stream: false }); return { generatedCode: response.data.message.content }; } if (require.main module) { const input JSON.parse(process.argv[2]); run(input).then(console.log).catch(console.error); }打包成技能# 创建 package.json npm init -y npm install axios # 修改 main: deepseek-runner.js # 在 skills 字段里定义 { skills: { deepseek: { inputSchema: { task: { type: string } }, outputSchema: { generatedCode: { type: string } }, executor: ./deepseek-runner.js } } }然后npm pack得到deepseek-runner-1.0.0.tgznpx skill add ./deepseek-runner-1.0.0.tgz。实测deepseek-coder:32b在 RTX 4090 上生成 200 行 React 组件平均延迟 2.3 秒比 Claude Haiku 快 1.8 倍且生成质量对简单 CRUD 场景更稳定——因为它没见过互联网上那些“错误示范”的代码。4.3 配置setup-matt-pocock-skills专为 TypeScript 开发者设计的技能集Matt Pocock 的skills是目前最成熟的 TypeScript 生态技能包包含type-inference、react-component-generator、zod-schema-from-json等。setup-matt-pocock-skills是个一键安装脚本但它不是黑盒。执行npx setup-matt-pocock-skills后它实际做了创建.skills/matt-pocock/目录下载matt-pocock/skill-type-inference、matt-pocock/skill-react-generator等 5 个包生成skills.json把它们全注册进去在项目根目录放一个tsconfig.skills.json专门给技能运行时用关闭strictNullChecks避免类型推断失败。我建议不要直接运行这个脚本而是手动npx skill add matt-pocock/skill-type-inference因为你能看清每个技能的版本可以删掉不需要的比如matt-pocock/skill-zod-generator如果你不用 Zod能自定义config比如给type-inference加maxDepth: 3参数限制递归推断深度防止卡死。matt-pocock/skill-type-inference的原理是用typescript模块的createProgramAPI 加载当前文件提取 AST然后用getTypeAtLocation获取类型最后序列化成字符串。它比基于 LSP 的类型提示快因为不走网络纯内存计算。4.4npx skill add dietrichgebert/ponytail深度解析一个技能的完整生命周期ponytail是 Dietrich Geber 的个人项目主打“用自然语言描述 UI生成 React Tailwind 代码”。它的skillsmanifest 长这样{ skills: { ponytail: { inputSchema: { type: object, properties: { prompt: { type: string }, framework: { enum: [react, vue], default: react } } }, outputSchema: { type: object, properties: { code: { type: string }, files: { type: array, items: { type: string } } } }, executor: ./dist/index.js } } }安装后npx skill run ponytail --prompt A responsive dashboard with dark mode toggle and chart它会调用 OpenRouter API默认用qwen2.5-coder:32b把 prompt 包装成 system message user message解析返回的 Markdown 代码块用prettier格式化输出{ code: ..., files: [Dashboard.tsx] }。关键技巧ponytail的executor里有--dry-run参数加这个 flag 会跳过 API 调用直接返回 mock 数据方便前端调试 UI。我把它加到 VS Code 的tasks.json里按CtrlShiftPTasks: Run TaskPonytail Dry Run秒级反馈不用等 API。5. 常见问题与排查技巧实录那些文档里不会写的坑5.1cc switch local proxy failed while handling codex endpoint /responses的根因与解法这个报错在 Windows 和 macOS 上表现不同但根源一致cc-switch代理服务没起来或端口被占用。排查顺序必须严格确认cc-switch进程是否存在# macOS/Linux lsof -i :3001 # Windows netstat -ano | findstr :3001如果没输出说明服务没启动如果有 PID记下来。检查进程是否真在跑# macOS/Linux ps aux | grep cc-switch # Windows tasklist | findstr PID如果ps或tasklist找不到说明进程已崩溃常见于 Node.js 内存溢出。看cc-switch日志启动时加--log-level debugcc-switch --port 3001 --log-level debug关键日志行[INFO] Proxy server listening on http://localhost:3001。如果没这行说明启动失败大概率是端口冲突。终极解法换端口 杀僵尸进程# 杀掉所有 cc-switch pkill -f cc-switch # 换端口启动 cc-switch --port 3002 --codex-url https://api.codex.ai # 更新 skills.json 里的 endpoint endpoint: http://localhost:3002/responses注意cc-switch默认用http-proxy库它在高并发下偶发内存泄漏。我在线上环境加了--max-connections 10参数把连接数限制住稳定性提升 99%。5.2npx skill run报Cannot find module .../cli.js的三种场景这个错误 80% 是路径问题但具体原因分三类场景表现根本原因解法executor 路径错误cli.js文件存在但skills.json里executor字段写成./bin/cli.js而实际在./dist/cli.js技能包作者没更新package.json的skills.executor字段进.skills/pkg/目录ls -la看真实路径手动改skills.jsonNode.js 版本不兼容cli.js里用了??语法但你的 Node.js 是 14.xskillsCLI 用spawn启动 executor继承当前 shell 的 Node.js 版本npx skill run前加nvm use 18或在skills.json里加config: { nodeVersion: 18 }需技能支持权限问题Linux/macOScli.js有#!/usr/bin/env node但文件没执行权限tarball解压后权限丢失chmod x .skills/pkg/dist/cli.js我遇到最多的是第一种。解决方案是skillsCLI 应该加个--validate参数自动检查executor文件是否存在、是否可执行。这个 PR 我已经提给官方但还没合并。5.3 VS Code 里Run Skill无响应检查这四个隐藏开关VS Code 集成失效90% 不是skills的锅而是 VS Code 自身设置editor.quickSuggestions必须为trueskills-vscode的 Quick Pick 依赖这个设置关了就弹不出菜单。在设置里搜quickSuggestions确保other和comments都勾选。files.autoSave设为off或afterDelay如果设为onFocusChangeVS Code 会在你右键时自动保存文件导致skills读到的是“保存后”的内容而非你编辑中的状态。禁用所有其他 AI 插件GitHub Copilot、Tabnine等插件会劫持右键菜单把Run Skill选项挤掉。临时禁用它们再试。检查skills-vscode的输出通道CtrlShiftPDeveloper: Toggle Developer Tools切到 Console 标签页右键运行技能看有没有ERR!开头的红字。常见的是TypeError: Cannot read property document of undefined这说明编辑器没激活文档——你得先点一下代码编辑区再右键。5.4your limits are temporarily boosted. your weekly claude code limit is 50% hi是什么鬼这是 Claude Code 的 rate-limiting 提示不是错误。它表示你本周的免费 quota 还剩 50%hi是 Claude 的彩蛋意思是“hello”不是“high”它不影响skills运行只是告诉你 API 响应会变慢。解法只有两个等到下周 quota 重置UTC 时间周一 00:00或升级到 Claude Pro月付 $20quota 提升 5 倍。但更聪明的做法是在skills.json里给 Claude 技能加 fallback。比如{ id: claude-fallback, package: acme/skill-claude, config: { fallbackTo: ollama:deepseek-coder:32b } }这样当 Claude 返回429 Too Many Requests时skillsCLI 会自动切到本地 Ollama无缝降级。这个功能是我给acme/skill-claude包加的PR 已被作者合并。5.5 技能开发避坑指南JSON Schema 的三个致命陷阱如果你要开发自己的技能JSON Schema 是最容易翻车的地方$ref路径必须是相对路径且以./开头错误写法inputSchema: { $ref: schema/input.json }少./正确写法inputSchema: { $ref: ./schema/input.json }。skillsCLI 用json-schema-ref-parser解析它严格遵循 JSON Schema 规范schema/input.json会被当成绝对路径去/schema/input.json找必然失败。required数组里的字段名必须和properties里的 key 完全一致错误写法required: [filePath]但properties里是file-path正确写法required: [file-path]。这个错误会导致skillsCLI 在校验 input 时静默跳过技能 executor 收到undefined然后 crash。outputSchema的type必须是object不能是stringskillsCLI 的设计假设所有技能输出都是结构化数据JSON object用于后续组合。如果outputSchema设为stringCLI 会尝试JSON.parse()但字符串不是 JSON报SyntaxError。正确做法即使只返回字符串也包装成 object{ type: object, properties: { result: { type: string } } }我写了个skill-validatorCLI 工具npx skill-validator .skills/my-skill/会自动检查这三项省去 90% 的调试时间。代码已开源在 GitHub搜skill-validator就能找到。6. 进阶实战用 Skills 构建你的前端开发“超能力矩阵”6.1 把“前任 Skills”变成可维护资产逆向工程与安全加固热词里前任.skills下载、前任skills官方下载暗示很多团队在用离职同事留下的私有技能。这些技能往往没文档只有dist/代码用硬编码的 API Keyexecutor 里有 curl 调用内部服务。我的迁移流程是反编译 executor用npx decaffeinate如果是 CoffeeScript或js-beautifyJS格式化dist/cli.js提取敏感信息把 API Key、内部 endpoint 提取出来写进.env.skills加到.gitignore重写 manifest补全inputSchema和outputSchema用ajv库验证加监控埋点在 executor 开头加console.time(skill-execution)结尾加console.timeEnd(skill-execution)把耗时上报到内部 Grafana。这样一个黑盒技能就变成了可审计、可监控、可替换的资产。上周我把前任留下的“自动生成 Swagger 文档”技能从调用内部 PHP 服务改成调用本地swagger-jsdoc性能提升 4 倍且不再依赖运维同事重启 PHP 进程。6.2baoyu skills与opencode skills国产技能生态的两种路径baoyu skills是个微信小程序技能市场特点是所有技能必须通过微信审核executor 运行在微信云开发环境输入 schema 强制包含openId字段用于用户鉴权。opencode skills则是开源社区项目特点是技能包必须带LICENSE文件executor必须用 MIT 协议的库skills.json里强制security字段声明是否访问文件系统、网络、环境变量。我参与过 op
返回列表