跳转至

Mini CLI

从 4683 行的 src/main.tsx 提炼到 ~200 行 的 CLI 框架。 演示 argv 解析 + subcommand 路由 + --help 生成 + 4 命令 20+ flags

文件

mini-cli/
├── src/
│   ├── parser.ts  parseArgv + Cli class + Command + help(~150 行)
│   └── cli.ts     4 子命令 20+ flags demo
└── README.md

npm install && npm start
# 或
node dist/cli.js --help
node dist/cli.js greet --name=Alice --loud --times=2
node dist/cli.js search "hello" --limit=5 --json
node dist/cli.js config --set theme=dark
node dist/cli.js version --json

真实代码对照

Demo 真实文件 简化
parseArgv main.tsx:500 parseArgv (~300 行) 30 行
Cli.command() main.tsx:1500 subcommand router (~800 行) 50 行
printHelp / printCommandHelp main.tsx:3500 help (~400 行) 30 行
4 commands × 20+ flags main.tsx:2801 default action (~2000 行) 1 个 demo 文件

核心 4 件套

1️⃣ 3 种 argv 形式

--flag                    # 布尔
--flag=value              # k=v
--flag value              # k 后跟 value
解析规则: - --flag → boolean true - --flag=value → k=v 形式 - --flag value → 如果下个不是 - 开头 → string

2️⃣ Flag 类型系统

type Flag = {
  type: "boolean" | "string" | "number" | "array";
  default?: ArgValue;
};
运行时校验(validateArgs):类型不匹配 → 错误信息 + 自动 --help。

3️⃣ Subcommand 路由

cli.command({
  name: "greet",
  flags: [...],
  handler: (args) => { /* ... */ }
});
第一个 positional = 命令名,其余 = 参数。--help 在每个 subcommand 也生效

4️⃣ --help 自动生成

Usage: ccmin <command> [options]

Commands:
  greet        Greet someone
  search       Search items
  config       Get/set config
  version      Show version info

Global Options:
  --help, -h Show help
  --version, -v Show version
  --verbose     Enable verbose logging
不需要手写 docstring,从 Flag 的 description 字段自动组装。

4 命令 / 20+ flags

命令 flags 行为
greet --name -n, --loud, --times 打招呼(可大写 N 次)
search --limit, --tags, --json 搜索(mock 2 结果)
config --get, --set, --unset 配置 get/set
version --json 显示版本

全局--help -h / --version -v / --verbose / --color

测试输出

$ ccmin greet --name=Alice --loud --times=2
HELLO, ALICE!
HELLO, ALICE!

$ ccmin search "hello" --limit=5 --json
{
  "query": "hello",
  "limit": 5,
  "results": ["mock1", "mock2"]
}

$ ccmin config --set theme=dark
set: theme=dark

$ ccmin foo
Unknown command: foo

已知限制

  • --tags array 简化:本 demo 多次 --tags=x 会被覆盖。真实 CC 用 commander.js / yargs 支持 array 类型累加
  • 无 sub-subcommandccmin plugin add foo 这种两级本 demo 不支持
  • 无 interactive prompts:真实 CC 会有 TUI 弹窗

进阶练习

  1. 加 sub-subcommandcli.subcommand("plugin", { subcommands: [...] })
  2. 加 array 累加:检测 array 类型时累加而非覆盖
  3. 加 validation 规则min: 0, max: 100, choices: [...]
  4. 加 env 变量回退--port 没传则读 PORT env
  5. 加 config file 加载--config=./cli.json 预填 defaults
  6. 接 commander / yargs:用成熟的库替代

相关阅读