01 — 设计原则
Mesh CLI 的交互设计基于四个核心原则。每个功能在实现前都会先问:它是否符合这些原则?
友好有温度
CLI 不应该冰冷。每天不同的问候语、登录时的 ASCII 艺术、勋章通知——让终端也有人情味。
智能不打扰
拼错命令会自动建议,缺少参数会交互引导,token 过期会静默刷新——帮你纠正而不是报错。
无障碍兼容
尊重 NO_COLOR 标准,非 TTY 自动降级,--no-fun 关闭装饰输出——在任何环境都可用。
Agent 原生
所有命令支持 --format json,结构化输出让 AI Agent 能直接解析——人和机器共用一套接口。
02 — 登录欢迎体验
登录是用户与 CLI 的第一次深度接触。我们把它设计成一个有仪式感的时刻。
ASCII 艺术横幅
登录成功后展示双色渐变的 ASCII 横幅。上半部分 "CYBER" 使用蓝紫色渐变(6 行 6 色),下半部分 "POPS" 使用橙金色渐变(6 行 6 色),每行独立着色,形成视觉纵深。
每日问候语
问候语不是随机的——基于日期 + 用户名的确定性哈希,同一个人同一天永远看到相同的问候,但不同人看到不同的问候。这避免了"每次刷新都变"的廉价感。
function pickDailyGreeting(displayName: string): string { const greetings = [ "Good morning", "Hello", "Welcome back", "Hope you're having a smooth day", "Ready when you are", ]; const seed = `${new Date().toISOString().slice(0, 10)}:${displayName}`; const hash = [...seed].reduce((t, c) => t + c.charCodeAt(0), 0); return `${greetings[hash % greetings.length]}, ${displayName}.`; }
角色感知提醒
登录后根据用户角色显示不同的提醒信息。VIEWER 看到个人资料完善提示,EDITOR/ADMIN 看到系统级待办。
Viewer 看到的
Admin 看到的
--no-fun 模式
传入 --no-fun 标志后,所有 ASCII 艺术和颜色装饰被关闭,输出纯文本格式。适用于脚本环境、日志采集和无障碍场景。
03 — 命令架构
Mesh CLI 采用 verb-first(动词优先)命令结构,灵感来自 kubectl 和 docker,让操作意图先于资源类型。
命令语法
兼容入口
对外主推 verb-first 写法;resource-first 仅作为兼容入口保留,内部通过 normalizeVerbFirstArgs() 统一转换。
Preferred
mesh get employee luyu
Compatibility alias
mesh employee get luyu
命令分类
| 类别 | 动词 | 说明 |
|---|---|---|
| 查询 | get list org-chart team | 只读操作,任何角色可用 |
| 自助服务 | update add set remove | 修改自己的资料、电话、IM |
| 管理写入 | create update close | EDITOR+ 管理组织数据 |
| 系统管理 | sync audit import admin | ADMIN 专属操作 |
| 认证 | login logout whoami status | 身份与会话管理 |
04 — 帮助与纠错
好的 CLI 不会让用户在犯错后无所适从。Mesh 通过 Levenshtein 距离算法、上下文感知帮助和可操作的错误信息,构建了一套完整的纠错系统。
拼写纠错
输入错误的命令时,CLI 使用 Levenshtein 编辑距离算法在所有已注册命令中搜索最接近的匹配。阈值自适应:max(2, floor(input.length / 3))。
function suggestCommand(token: string, candidates: string[]) { let best = null; for (const c of candidates) { const d = levenshtein(token, c); if (!best || d < best.distance) best = { value: c, distance: d }; } const threshold = Math.max(2, Math.floor(token.length / 3)); return best?.distance <= threshold ? best.value : null; }
上下文帮助
mesh help 显示分类概览,mesh help <command> 显示具体命令的用法、参数和示例。裸运行 mesh 则显示当前状态和下一步建议。
错误信息设计
每个错误都包含三要素:错误码、人类可读描述、可操作的建议。API 错误还附带 Request ID 用于追查。
05 — 交互式引导
当命令缺少必要参数时,CLI 不会直接报错退出,而是进入交互式引导模式,逐步询问缺失信息。
智能参数补全
只在交互式终端(TTY)中触发提示;管道输入和 --format json 模式下直接跳过,避免阻塞自动化流程。
声明式提示注册
写命令的交互提示通过声明式注册定义,将提示文案、是否可选、默认值等元数据集中管理:
// write-command-registry.ts { name: "create", summary: "Create employment record", prompts: { reference: { message: "Employee (email / employee number)" }, entity: { message: "Legal entity" }, type: { message: "Employment type" }, start: { message: "Start date (YYYY-MM-DD)" }, office: { message: "Office (optional)", optional: true }, title: { message: "Job title (optional)", optional: true }, }, }
危险操作确认
Offboard、reinstate 等不可逆操作使用 typed-reference 确认策略——用户必须手动输入目标员工的邮箱才能执行,杜绝误操作。
06 — 勋章与庆祝
勋章系统为 CLI 注入了游戏化元素。每枚勋章都有独特的 ASCII 艺术和配色方案,登录时自动通知新获得的勋章。
勋章 ASCII 艺术
每枚勋章包含 5 行 ASCII 艺术和 5 个对应的颜色值,每行独立着色。80 枚内置设计覆盖了工龄纪念、技术成就、文化认可等多个类别。
勋章通知机制
credentials 文件中记录 last_badge_seen_at 时间戳。每次登录时,CLI 比对最新勋章的颁发时间,若有新勋章则在欢迎横幅中高亮展示。
生日与周年庆祝
mesh celebrations 显示本周和即将到来的团队庆祝日,包括生日和入职周年。让远程团队不再错过同事的重要时刻。
07 — 输出系统
CLI 的输出系统在视觉美观和机器可读之间取得平衡,支持多种输出格式和颜色模式。
表格格式化
默认输出使用自动计算列宽的 ASCII 表格。列间距 2 空格,空数据显示 "(none)" 占位。简洁清晰,无多余的边框线。
True Color 颜色系统
使用 24-bit True Color ANSI 转义码(\x1B[38;2;R;G;Bm),不依赖终端的 256 色调色板限制。支持从 hex 值直接转换:
function trueColor(r: number, g: number, b: number): string { return `\x1B[38;2;${r};${g};${b}m`; } function colorize(...codes: string[]) { if (!colorOutputEnabled) return (v) => v; // graceful degradation const prefix = codes.join(""); return (v) => `${prefix}${v}\x1B[0m`; }
颜色降级策略
| 条件 | 行为 | 场景 |
|---|---|---|
process.stdout.isTTY | True Color 全彩输出 | 正常终端使用 |
NO_COLOR=1 | 关闭所有颜色 | 遵循 no-color.org 标准 |
| 非 TTY(管道) | 自动关闭颜色 | mesh list | grep |
--no-fun | 关闭 ASCII 艺术和装饰 | 脚本环境 |
08 — 信号与优雅退出
CLI 需要正确处理中断信号。Mesh 实现了两级退出策略,确保数据完整性。
两级 Ctrl-C 策略
第一次 Ctrl-C
设置中断标志,运行注册的清理函数(逆序执行),然后优雅退出。
第二次 Ctrl-C
跳过所有清理,立即强制退出,返回退出码 130。
// signal-handling.ts const onSigint = () => { interruptCount += 1; if (interruptCount === 1) { interrupted = true; io.stderr("\nInterrupted. Cleaning up...\n"); cleanupPromise ??= runCleanup(); // run handlers in reverse order return; } io.stderr("Force exiting immediately.\n"); process.exit(130); };
09 — Shell 补全
通过 mesh completion --shell zsh 生成 Shell 自动补全脚本,实现 Tab 键补全命令名、子命令和标志。
10 — AI Agent 适配
Mesh CLI 是 Agent-native 的——所有命令都支持 JSON 输出,让 AI Agent 能直接调用 CLI 作为工具。
JSON 输出模式
任何命令加上 --format json 即可获得结构化 JSON 输出,适合程序解析。JSON 模式下自动跳过交互提示和颜色输出。
SKILL.md — AI Agent 能力声明
CLI 附带 SKILL.md 文件,以 LLM 可理解的格式描述自身能力。AI Agent 可以通过阅读此文件了解可用命令、参数和使用模式,无需人工配置。
mesh help,AI 读 SKILL.md。同一套 CLI 同时服务人类和 Agent,而不是为两者分别构建接口。这是 "Agent-native" 的核心思想。
总结
Mesh CLI 的交互设计证明了一件事:终端工具也可以是温暖的。
通过 ASCII 艺术与渐变色彩创造仪式感,通过 Levenshtein 纠错和交互引导降低门槛,通过 typed-reference 确认和两级退出保障安全,通过 JSON 输出和 SKILL.md 打通人机协作——这些设计模式共同构成了一套可复用的 CLI 交互设计系统。
它不是某个框架的产物,而是对"CLI 应该如何对待使用者"这个问题的回答。