CLI · TUI · GUI —— 程序跟人打交道的三张脸
普通课约 35 分钟
本课导读
这三个缩写描述的是同一个问题的三种答案:程序怎么跟人交互。你其实三种全都天天在用——npm run dev 是 CLI,Claude Code 是 TUI,VS Code 是 GUI——只是没人把这张地图摊开给你看过。本课把三张脸各自的解剖结构、为什么最古老的 CLI 至今统治开发者世界、以及"桌面应用为什么都是 Electron"讲清楚。预计 35 分钟。
三张脸一览
| CLI | TUI | GUI | |
|---|---|---|---|
| 全称 | Command-Line Interface 命令行界面 | Text-based UI 终端文本界面 | Graphical UI 图形界面 |
| 交互方式 | 敲一条命令 → 输出文字 → 结束 | 终端里用字符"画"出的持续界面 | 窗口、按钮、鼠标 |
| 你用过的 | git、npm、claude 命令本身 | Claude Code 的对话界面、htop | VS Code、浏览器、微信 |
| 诞生年代 | 1960s | 1980s | 1980s |
解剖 CLI:一条命令的五脏六腑
拿一条你敲过无数遍的命令开刀:
npm install --save-dev eslint
│ │ │ │
程序 子命令 选项(flag) 参数
- 程序:
npm是一个可执行文件,操作系统按PATH环境变量里列出的目录顺序找到它 - 子命令/参数:告诉程序做什么、对谁做
- 选项(flag):
--xxx长写法、-x短写法,调整行为细节
程序运行完还会留下三样东西,这是 CLI 世界的"社交协议":
- 标准输出(stdout):正常结果往这打
- 标准错误(stderr):报错和日志往这打(跟 stdout 分开,所以"结果"能被干净地存下来而不混进报错)
- 退出码(exit code):0 = 成功,非 0 = 失败。你项目 CI 里"测试挂了就不许部署",判断依据就是测试命令的退出码
CLI 凭什么 60 年不死
答案一个词:可组合(composable)。CLI 程序遵守一个天才约定——我的输出可以变成你的输入,用管道符 | 连接:
# 管道:把三个各干一件小事的程序串成一条流水线 # 「列出进程 → 筛出包含 node 的行 → 数有几行」 # macOS / Linux / Git Bash: ps aux | grep node | wc -l # 同样思想的 PowerShell 版(Windows): # Get-Process | Where-Object { $_.Name -match "node" } | Measure-Object # 再来一个你能直接用的:找出项目里最大的 5 个文件 # du -ah . | sort -rh | head -n 5
每个小程序只做一件事,但像乐高一样任意拼装——这就是 Unix 哲学。由此衍生出 CLI 的三大不可替代性:
- 可脚本化:能敲的命令就能写进脚本自动执行。GUI 里"点这里、再点那里"没法自动化,CLI 天生就是自动化的原料——你项目的 CI/CD、
package.json里的 scripts,全是 CLI 命令的编排 - 可远程:服务器没有显示器,SSH 连上去只有终端——运维世界 100% 是 CLI 的
- 对机器友好:文本输入文本输出,程序容易调用程序。AI agent 时代这条突然升值——Claude Code 能替你干活,正是因为开发世界的一切都有 CLI 接口可调
提示
所以"学命令行"不是学古董,而是学开发者世界的通用总线。GUI 是给人看的门面,CLI 是程序之间、人与自动化之间的接口。越往工程深处走,CLI 浓度越高。
TUI:终端里长出来的"伪 GUI"
TUI 介于两者之间:还是在终端里、还是纯字符,但不是"一问一答就结束",而是持续运行、可交互的界面——用字符画出边框、列表、进度条,响应你的按键。
你最熟的例子就是 Claude Code 本身:它运行在终端里(CLI 的壳),但有持续的对话界面、彩色面板、快捷键(TUI 的魂)。其他名角:htop(服务器资源监控仪表盘)、lazygit(终端里的 Git 图形操作)、vim。
TUI 存在的理由:在只有终端的环境(SSH 远程、纯键盘流)里,提供接近 GUI 的信息密度和交互效率。近年终端工具复兴(开发者回流终端 + AI 工具都长在终端里),TUI 正在小规模文艺复兴。
GUI:图形界面的技术路线之争
GUI 本身你太熟了,值得上雷达的是桌面 GUI 怎么做出来的路线之争——这直接解释"为什么 VS Code 吃内存"这类日经话题:
- 原生(native):用操作系统自家的 UI 框架(Windows 用 WinUI、macOS 用 SwiftUI)。性能和质感最好,但每个平台要写一遍,成本三倍
- Electron:把一个完整的 Chrome 浏览器 + Node.js 打包进你的应用,界面用网页技术写。一套代码全平台跑,前端工程师直接上手——VS Code、Slack、Discord、Figma 桌面版全是。代价:每个应用自带一个浏览器,安装包几百 MB、内存几百 MB 起步
- Tauri:上一课的老朋友 Rust 登场——思路和 Electron 一样"用 Web 技术画界面",但不打包浏览器,复用操作系统自带的 WebView,原生侧用 Rust。安装包能从几百 MB 缩到几 MB。是 Electron 目前最有声量的挑战者
说明
看到没有,雷达上的点开始连线了:Rust(第 1 课)→ Tauri(本课)。零散知识变成网络的瞬间,就是它们开始互相解释的时候。
亲手看一眼 CLI 的原料
一个最小的 Node CLI,看看"命令行参数"到底怎么进入程序的:
#!/usr/bin/env node // greet.ts —— 一个最小 CLI:读取参数和选项,打印结果,返回退出码 // process.argv = ["node 路径", "脚本路径", ...你敲的参数] const args = process.argv.slice(2); if (args.length === 0) { console.error("用法:greet <名字> [--loud]"); // 报错走 stderr process.exit(1); // 非 0 退出码 = 失败 } const name = args[0]; const loud = args.includes("--loud"); const msg = loud ? `你好,${name}!!!`.toUpperCase() : `你好,${name}`; console.log(msg); // 结果走 stdout process.exit(0); // 0 = 成功(不写也默认 0) // 运行:npx tsx greet.ts 站长 --loud // 或者用上一课的 Bun:bun greet.ts 站长 --loud
就这么多:参数从 argv 进来,结果从 stdout 出去,成败用退出码表态。npm 上那些著名 CLI(eslint、vite……)的骨架和这 20 行没有本质区别,只是多了参数解析库和漂亮的彩色输出。
够用判断线
一句话总结:CLI 是可组合、可自动化的文字接口(开发世界的总线),TUI 是终端里的持续交互界面,GUI 是给大众的图形门面;桌面 GUI 三条路线 = 原生(贵而精)、Electron(Web 技术 + 自带浏览器,重)、Tauri(Web 技术 + 系统 WebView + Rust,轻)。 值得深入的信号:你想把重复劳动自动化(学 shell 脚本),或想把自己的工具发布给别人用(学写 CLI)。
随堂测验
1. CLI 诞生 60 年仍统治开发者世界,最核心的原因是?
2. 一个 CLI 程序运行结束后退出码是 3,这意味着什么?
3. Claude Code 的界面属于哪一类?为什么?
4. 「VS Code / Slack / Discord 为什么都那么吃内存?」——最准确的回答是:
划选正文任意文字可高亮、批注或加入复习卡
讨论
载入中…