Skip to main content
On this page

@std/cli

Overview Jump to heading

Tools for creating interactive command line tools.

import { parseArgs } from "@std/cli/parse-args";
import { assertEquals } from "@std/assert";

// Same as running `deno run example.ts --foo --bar=baz ./quux.txt`
const args = parseArgs(["--foo", "--bar=baz", "./quux.txt"]);
assertEquals(args, { foo: true, bar: "baz", _: ["./quux.txt"] });

Add to your project Jump to heading

deno add jsr:@std/cli

See all symbols in @std/cli on

为什么使用 @std/cli? Jump to heading

此包帮助你构建具有极佳开发者体验的命令行工具。 它专注于核心功能:

  • 解析标志和参数(parseArgs),无需使用庞大的框架
  • 提示输入敏感信息(promptSecret
  • 可靠测量显示宽度(unicodeWidth),以实现整洁的终端输出
  • 不稳定的增强功能以改善用户体验:加载动画、进度条、ANSI 光标控制 以及交互式选择菜单

当你想要一个轻量且可组合的命令行工具包时使用它。 对于包含子命令、丰富帮助和配置系统的更复杂命令行工具, 你仍然可以从 parseArgs 开始,并在此基础上构建自己的结构。

示例 Jump to heading

import { parseArgs } from "@std/cli/parse-args";
import { promptSecret } from "@std/cli/prompt-secret";

const args = parseArgs(Deno.args, {
  alias: { v: "verbose" },
  boolean: ["verbose"],
  string: ["out"],
});

if (args.verbose) console.log("启用详细模式");
const token = await promptSecret("请输入 API 令牌:");
console.log(`写入到:${args.out ?? "标准输出"}`);
  • parseArgs 轻量且无特定设计约束——非常适合简单工具; 对于复杂的命令行请考虑子命令和帮助文本模式。
  • 布尔值默认为 false,除非存在对应标志;如果需要,可以通过 booleanNegation 选项支持 --no-flag
  • 使用 stopEarly-- 视为参数结束标志,并将剩余参数直接传递。

parseArgs:别名、默认值、收集、多选、否定、未知标志和 -- Jump to heading

import { parseArgs } from "@std/cli/parse-args";

const argv = [
  "-v",
  "--out=dist/file.txt",
  "--tag",
  "alpha",
  "--tag",
  "beta",
  "--no-cache",
  "--",
  "--literally-a-file-flag",
];

const args = parseArgs(argv, {
  alias: { v: "verbose" },
  boolean: ["verbose", "cache"],
  string: ["out"],
  default: { out: "stdout" },
  collect: ["tag"],
  negatable: ["cache"],
  unknown: (flag) => {
    if (flag.startsWith("--") && flag !== "--") {
      console.warn(`未知标志: ${flag}`);
      return false; // 从解析结果中丢弃它
    }
    return true;
  },
  "--": true,
});

// args.tag -> ["alpha", "beta"]
// args.cache -> false (因为有 --no-cache)
// args.verbose -> true (因为有 -v)
// args.out -> "dist/file.txt"
// args["--"] -> ["--literally-a-file-flag"] (直接传递的参数)

promptSecret:掩码输入与清除提示行 Jump to heading

import { promptSecret } from "@std/cli/prompt-secret";

const token = await promptSecret("请输入令牌:", { mask: "*" });
// 可选:输入完成后清除提示行
await promptSecret("按回车继续", { mask: "", clear: true });

unicodeWidth:简单的列对齐 Jump to heading

import { unicodeWidth } from "@std/cli/unicode-width";

const rows = [
  ["名称", "宽度"],
  ["hello", String(unicodeWidth("hello"))],
  ["你好", String(unicodeWidth("你好"))],
  ["🐙octo", String(unicodeWidth("🐙octo"))],
];

const col1Width = Math.max(...rows.map((r) => unicodeWidth(r[0])));
for (const [a, b] of rows) {
  const pad = " ".repeat(col1Width - unicodeWidth(a));
  console.log(`${a}${pad}  ${b}`);
}

不稳定的 UI 辅助:加载动画和进度条 Jump to heading

这些 API 标记为不稳定,可能会发生变化。

// 加载动画
import { Spinner } from "@std/cli/unstable-spinner";

const spinner = new Spinner({ message: "获取数据中..." });
spinner.start();
await new Promise((r) => setTimeout(r, 800));
spinner.stop();

// 进度条
import { ProgressBar } from "@std/cli/unstable-progress-bar";

const bar = new ProgressBar({ max: 5 });
for (let i = 0; i < 5; i++) {
  await new Promise((r) => setTimeout(r, 300));
  bar.value = i + 1;
}
bar.stop();

你找到了你需要的东西吗?

编辑此页面
隐私政策