自动化与脚本
需要从 Node.js/TypeScript 安全调用任意…
把已安装的 CLI 二进制或静态帮助文本通过 cli-to-js 包装成可调用、可校验、可流式读取输出的 JavaScript/TypeScript API,适合 agent 或脚本避免拼接 shell 字符串。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
需要从 Node.js/TypeScri特定
解决思路
- 安装依赖:`npm install cli-to-js`。
- 核心转换:调用 `convertCliToJs(binary)` 运行该二进制的 `--help`,解析输出为 schema,返回基于 Proxy 的完整类型 API。
- 静态帮助文本转换:调用 `fromHelpText(binary, text)`,从手动提供的帮助字符串得到同样的 API。
- 子命令调用:把每个子命令当作方法调用,例如 `api.subcommand({ flag: value })`。
- 位置参数:用 `_` 键传递位置参数,例如 `api.command({ _: ["file.txt"] })`。
- 参数命名:camelCase 键自动转 kebab-case flag,例如 `{ dryRun: true }` → `--dry-run`。
- Flag 映射:`{ verbose: true }` → `--verbose`;`{ verbose: false }` → 省略该 flag。
- Flag 映射:`{ output: "file.txt" }` → `--output file.txt`;`{ dryRun: true }` → `--dry-run`。
- Flag 映射:`{ v: true }` → `-v`;`{ include: ["a","b"] }` → `--include a --include b`。
- Flag 映射:`{ _: ["file.txt"] }` → `file.txt`。
- 基本用法:`import { convertCliToJs } from "cli-to-js";` 然后 `const git = await convertCliToJs("git"); const npm = await convertCliToJs("npm");` 包装已安装二进制。
- 调用子命令:`const result = await git.status();` 从 `result.stdout` / `result.exitCode` 读取结果。
- 传 flags:`await git.commit({ message: "fix: update logic", all: true });` 等价 `git commit --message "fix: update logic" --all`。
- 传位置参数:`const { stdout } = await git.diff({ nameOnly: true, _: ["HEAD~1"] });`,再按需解析 `stdout`,例如 `stdout.trim().split("\n")`。
- TypeScript 泛型:`const git = await convertCliToJs<{ commit: {...}; push: {...}; diff: {...}; }>("git");` 获得子命令选项的自动补全和类型检查。
- 类型检查示例:`await git.commit({ message: "hello", all: true });`、`await git.push({ force: true });` 合法;`await git.push({ foobar: true });` 会编译报错。
- 输出 helper `.text()`:`const branch = await git.branch({ showCurrent: true }).text();` 返回去除首尾空白后的 stdout 字符串。
- 输出 helper `.lines()`:`const files = await git.diff({ nameOnly: true, _: ["HEAD~1"] }).lines();` 返回 stdout 按行拆分数组。
- 输出 helper `.json<T>()`:`const packages = await npm.outdated({ json: true }).json<Record<string, { current: string }>>();` 将 stdout 解析为 JSON。
- 原始结果:`const result = await git.log({ oneline: true, n: "5" });` 可读 `result.stdout`、`result.stderr`、`result.exitCode`。
- 校验选项:`const git = await convertCliToJs("git", { subcommands: true });` 后调用 `git.$validate("commit", { massage: "fix typo" })`,返回如 `unknown-flag`、`suggestion: "message"` 和 did-you-mean 消息的错误数组。
- Agent 使用前校验:先 `const errors = claude.$validate({ print: true, model: "sonnet" });`,若 `errors.length === 0` 才执行;否则用 `errors[0].suggestion` 自我纠正。
- 校验根命令选项:`git.$validate({ unknownFlag: true })`。
- 子命令解析 eager:`const git = await convertCliToJs("git", { subcommands: true });`,然后从 `git.$schema.command.subcommands.find((s) => s.name === "commit")?.flags` 读取 commit flags。
- 子命令解析 lazy:`const git2 = await convertCliToJs("git"); const commitSchema = await git2.$parse("commit"); console.log(commitSchema.flags);`。
- 懒解析全部子命令:`await git2.$parse();`。
- 流式输出 callbacks:`await api.build({ watch: false }, { onStdout: (data) => process.stdout.write(data), onStderr: (data) => process.stderr.write(data) });` 实时输出并缓冲结果。
- 流式输出 async iterator:`const proc = api.$spawn.test({ _: ["--watch"] }); for await (const line of proc) { ... if (line.includes("failed")) proc.kill(); } console.log("Exit code:", await proc.exitCode);`。
- 直接 spawn:`import { spawnCommand } from "cli-to-js"; const dev = spawnCommand("npm", ["run", "dev"]); for await (const line of dev) { if (line.includes("ready")) { console.log("Server started"); break; } }`。
- 每次调用执行配置:用 `AbortController` + `setTimeout(() => controller.abort(), 5000)` 准备取消信号。
- 调用时传执行配置:`await api.build({ minify: true }, { cwd: "/my/project", env: { ...process.env, NODE_ENV: "production" }, timeout: 60_000, signal: controller.signal, stdio: "inherit" });`,其中 `stdio: "inherit"` 可把交互式 CLI 透传到终端。
- 只生成命令字符串不执行:`git.$command.commit({ message: "deploy", all: true });` 返回 `"git commit --message deploy --all"`。
- 组合脚本:`import { script } from "cli-to-js"; const deploy = script(git.$command.commit({ message: "deploy", all: true }), git.$command.push({ force: false })); console.log(`${deploy}`);` 生成 `"git commit --message deploy --all && git push"`。
- 执行组合脚本:`deploy.run();` 顺序执行,失败即停止。
- 从帮助文本字符串创建 API:`import { fromHelpText } from "cli-to-js"; const helpText = \`...\`; const api = fromHelpText("mytool", helpText, { cwd: "/project" }); await api({ output: "dist", minify: true });`。
- CLI 代码生成:`npx cli-to-js git` 输出 TypeScript wrapper 到 stdout。
- 写入文件:`npx cli-to-js git -o git.ts`。
- 生成普通 JavaScript:`npx cli-to-js git --js -o git.js`。
- 包含每个子命令 flags:`npx cli-to-js git --subcommands -o git.ts`。
- 只生成类型声明:`npx cli-to-js git --dts -o git.d.ts`。
- 导出原始 schema JSON:`npx cli-to-js git --json`。
- 生成文件特性:生成文件是 standalone,零运行时依赖 `cli-to-js`。
- Agent 工作流模式:在 `agentTask()` 中 `const git = await convertCliToJs("git", { subcommands: true }); const claude = await convertCliToJs("claude");`。
- 获取变更文件:`const files = await git.diff({ nameOnly: true, _: ["HEAD~1"] }).lines();`。
- 遍历文件前校验 Claude 调用:`const errors = claude.$validate({ print: true, model: "sonnet" }); if (errors.length > 0) { console.error("Invalid flags:", errors); continue; }`。
- 执行 review:`const review = await claude({ print: true, model: "sonnet", _: [`Review ${file} for bugs`] });`。
- 处理 review 结果:`if (!review.stdout.includes("no issues")) { console.log(`Issues in ${file}:`, review.stdout); }`。
- Schema 检查:`const git = await convertCliToJs("git", { subcommands: true }); console.log(git.$schema);`,结构为 `{ binary: "git", command: { name: "git", flags: [...], subcommands: [...] } }`。
- 列出子命令和 flags:`git.$schema.command.subcommands.forEach((s) => { console.log(s.name, s.flags.map((f) => f.name)); });`。
- 包装默认配置:`const docker = await convertCliToJs("docker", { cwd: process.env.PROJECT_DIR, env: { ...process.env, DOCKER_BUILDKIT: "1" }, timeout: 120_000 });`。
- 根命令调用(无子命令):`const result = await api({ version: true });` 或 `const result = await api("subcommand", { flag: true });`。
- 交互式 CLI 透传:`const gh = await convertCliToJs("gh"); await gh.auth({ login: true }, { stdio: "inherit" });`。
- 排障 Binary not found:确保二进制在 `PATH`;在终端用 `which <binary>` 测试。
- 排障 Help text 无法解析:用 `fromHelpText` 配合手动获取的帮助文本,或设置正确 `helpFlag`,例如 `const api = await convertCliToJs("mytool", { helpFlag: "-h" });`。
- 排障 子命令 flags 缺失:只有设置 `subcommands: true` 或调用 `$parse("sub")` 后才会填充;`await git.$parse("commit");` 后 `git.$validate("commit", opts)` 才可用。
- 排障 动态子命令类型错误:给 `convertCliToJs<T>` 传泛型,为各子命令选项定义类型。
- 排障 慢帮助输出超时:增大 help 获取超时,例如 `const api = await convertCliToJs("slow-tool", { timeout: 30_000 });`。
适用边界 · 注意事项
- 目标 CLI 二进制不在 PATH、无法安装或无法执行时。
- 目标 CLI 没有稳定可解析的 `--help` 输出,且你又不能提供 `fromHelpText` 所需帮助文本时。
- 需要完全避免执行外部命令/禁止子进程的场景,因为该方案本质是包装并执行 CLI。