最近“CLI-Anything”这个词频繁出现在技术社区和热搜里。它到底会收敛成某个具体开源项目,还是演变成一种泛化的方法论,目前还没有定论。但对我来说,这个词恰好精准地概括了我过去大半年的工作方式:把所有能在终端里完成的事情,尽量都搬进终端。文件搜索、批量重命名、日志分析、接口联调、数据库查询,甚至跟 AI 助手对话,全部塞进一个黑色窗口里解决。这半年下来,我的鼠标使用时间减少了一半以上,效率提升反而是次要的,更重要的是整个工作过程变得异常透明——每一步做了什么、为什么这么做,都有迹可循。
这篇文章不是要说服所有人放弃图形界面,而是把我实际使用的工具选型、组合技巧、脚本习惯以及踩过的坑,原原本本分享一下。适合谁看?已经掌握 cd、ls、grep 这些基础命令,但还没有系统建立命令行工作流的人;听说过 fzf、jq 这类工具却不知道怎么串起来用的人;以及好奇 AI 与 CLI 结合到底能带来什么变化的人,应该都能从中找到点参考价值。
1. CLI 的真正优势:可组合、可复现、可追溯
1.1 为什么说命令行是“厨房”而不是“外卖APP”
很多人把命令行当成落后于图形界面的老古董,这是理解偏差。图形界面更像外卖APP:每个功能都被封装成按钮,点起来确实方便,但你想让外卖APP把三份订单合并、自动加上备注、再转发给同事,几乎不可能。命令行更像厨房:每个工具都是食材和锅碗,单看都不起眼,但你掌握组合方式之后,可以做出任何菜式。
这里把 CLI 的底层优势拆成三点,它们共同决定了 CLI 为什么值得花时间:
- 可组合性:命令行工具的输入输出基本都是纯文本或结构化数据,一个命令的结果可以自然成为下一个命令的输入,管道把工具像乐高积木一样拼起来。而 GUI 的数据通常封存在内存和界面层里,外部脚本很难介入。
- 可复现性:你敲过的命令、跑过的脚本,本身就是一份操作日志。昨天怎么处理的数据,今天原样再跑一遍,结果一致。图形界面的操作则很难留下完整的过程记录,“我点了哪八个按钮”这种话基本等于没有记录。
- 资源占用与速度:终端工具通常比同等功能的 GUI 程序轻一个数量级,不需要加载几百兆的框架,很多小工具都是毫秒级返回结果。
这三条合在一起,指向一个非常实用的结论:命令行适合“批量、定期、需要追溯”的工作,图形界面适合“一次性、探索式、依赖直觉”的工作。所以我的个人原则很简单:同一件事做第二次,就考虑把它改成命令;做第三次,就一定写成脚本。
1.2 边界意识:什么任务不适合命令行
“万物皆可 CLI”更适合被理解为方向而非教条。真正常年用命令行的人,反而比外行更清楚它的边界。我过去半年总结出三类不适合强行命令行化的任务:
- 强图形依赖的创意工作,比如图像精修、视频剪辑、UI 设计。ImageMagick、ffmpeg 确实强大,适合做批处理和管线化,但前期创意决策阶段,手点效率更高。CLI 更适合作为后置的批量处理环节,而不是取代创意过程。
- 多人协同的轻量文档编辑。团队一起改方案、填表格,在线协作工具比终端里 vim 高效得多,因为实时可见的多人交互体验是 CLI 无法替代的。
- 没有稳定输入输出结构的数据。命令行擅长处理确定格式,如果数据源连格式都不稳定,你会花大量时间在解析规则上,不如先用 GUI 打开看一眼内容到底长什么样。
我建议每个打算“命令行化”的人都先画一张自己的边界清单。这样反而能让你更坚定地使用 CLI——因为你知道哪些场景是它的主场,哪些不是,不会因为一次踩坑就全盘否定。
1.3 一张拦截清单:第二件事之后就该考虑脚本化
每天混在终端里处理琐事后,我把“是否要命令行化”的决策收敛成了一组判断信号。每当重复操作出现,就快速过一遍:
- 这个操作这个星期已经出现第二次了吗?
- 它是不是超过五个步骤,并且中间有容易漏的参数?
- 它需不需要发给别人执行,或者以后还会被再次找出来?
只要命中任意一条,我就立刻停下,花几分钟把它固化为 alias 或脚本。这件事看似不起眼,却是 CLI-Anything 整个体系最重要的起点:它不是某个工具的功劳,而是“遇到重复就抽象”的思维习惯。没有这个习惯,你装再多工具也只会停留在“临时输入命令”的阶段。
2. 文件与文本的四个配角:ripgrep、fd、fzf、bat
2.1 四个工具各管哪一段
命令行工作流里,最基础也最容易立刻见效的领域就是文件与文本操作。我平时最依赖四个开源小工具:ripgrep(rg)、fd、fzf 和 bat。
| 工具 | 替代谁 | 核心价值 |
|---|---|---|
| ripgrep (rg) | grep / 编辑器内搜索 | 默认尊重 .gitignore,速度极快,输出格式干净 |
| fd | find | 语法直观,默认排除隐藏文件和 git 忽略项,输出带颜色 |
| fzf | 可直接接管 Ctrl+R 历史搜索 | 命令行模糊查找器,让“选择”操作变得极其顺手 |
| bat | cat | 带语法高亮、行号、Git 变更标记的文件查看工具 |
安装方面,macOS 上用brew install ripgrep fd fzf bat一行搞定;Linux 上 apt 源版本可能偏旧,我建议直接去 GitHub Releases 下载二进制,或者用 mise 这类统一管理工具安装;Windows 可以用 winget,配合 Windows Terminal 和 PowerShell 也能获得不错的体验。
这里特意提醒一句:fzf 安装完并不算配置完。新版 fzf 提供--zsh、--bash这类参数,你需要把它绑定到 shell 的 Ctrl+R 上,才能真正接管历史命令搜索。很多人装完 fzf 之后照样用系统默认搜索,等于买了一把好刀放抽屉里没开封。
2.2 三个高频组合拳
工具单独用都很简单,真正的价值在组合。我平时使用频率最高的三个组合:
组合一:忘记文件名,只记得里面有句话
rg -l "关键词" ~/projects/ | fzf --preview 'bat --color=always {}'rg -l列出包含关键词的文件路径,fzf把列表变成可交互的选择器,选中文件时右侧预览窗口自动用bat高亮显示。整个流程从“盲目翻文件”变成“边搜边看”,定位效率完全不在一个量级。
组合二:快速打开最近改过的文件
以 zsh 为例(zsh 默认支持**递归通配):
ls -t ~/projects/**/*.md | head -20 | fzf --preview 'bat --color=always {}'ls -t按修改时间倒序,head只取前 20 条,再交给fzf选择。选中前可以靠预览区确认内容,确认后再进入编辑。这个组合一天用几十次,比在文件管理器里一层层点开快太多。
组合三:zoxide 配合 fzf,实现“模糊跳目录 + 选文件”连续动作
z src | fzf --preview 'bat --color=always {}'先通过 zoxide 快速跳到目标目录,再通过 fzf 选择文件。这种“跳转 + 选择”连招,在图形界面里很难复制,因为你需要切换多个窗口才能完成同样的事。
这里有一个容易踩的细节:在非交互管道里调用 bat 做预览,记得加--color=always,否则 bat 检测到输出不是终端时会自动丢弃颜色,预览界面就变成了一堆无高亮的文字。
2.3 让命令历史变成“第二大脑”
命令行操作的另一个隐藏价值是历史记录,但默认 history 只有最简单的搜索,效率很低。我把历史命令的沉淀分成两层。
第一层,把 fzf 接到 Ctrl+R 上做模糊搜索。这比上下箭头翻几百条记录舒服得多,而且支持关键词模糊匹配,不需要完整回忆命令原文。
第二层,把真正高频但容易忘的长命令写进~/cheatsheet.md,再用alias cheat='bat ~/cheatsheet.md'随时查阅。我看过自己三个月的终端历史统计,80% 的操作来自不到 20 个命令模板,而这些模板最终都沉淀在 alias 和脚本里。CLI-Anything 听起来像“万物”,真正高频的其实非常有限,关键是先覆盖那 20%。
3. 接口、数据与管道:CLI 如何接管数据处理
3.1 curl 与 jq 的标准流水线
日常开发离不开接口联调。过去我会打开图形化 API 工具,填参数、点发送、看响应区;现在这套操作基本沉淀成一条命令:
curl -s https://api.example.com/v1/users?page=1 | jq '.data[] | {id, name}'-s让 curl 进入静默模式,不打印进度条;jq负责解析 JSON 并格式化输出。很多人对 jq 有心理门槛,其实核心就几个概念:字段访问用.key,数组遍历用[],筛选用select(.status == "active"),分组统计用group_by(.type)。
我日常最高频的 jq 模式大致有这几类:
# 统计接口返回中各类物品数量 curl -s https://api.example.com/v1/items | jq '.data | group_by(.type) | map({type: .[0].type, count: length})' # 筛选 pending 状态,并只取指定字段 curl -s https://api.example.com/v1/orders | jq '.data[] | select(.status == "pending") | {id, amount}' # 输出原始字符串,配合循环做后续操作 curl -s https://api.example.com/v1/users | jq -r '.data[].id'做接口联调时,我还会在 curl 末尾加上-w '\n%{http_code}\n',把 HTTP 状态码打到输出末尾,一眼就能看到请求是否成功,不用再去响应头里翻找。
3.2 配置文件与表格数据:yq 和 sqlite3 实战
JSON 世界用 jq,那 YAML 呢?直接用 yq 就行。注意我推荐的是 mikefarah 的 Go 版 yq,语法与 jq 几乎一致,对用过 jq 的人没有学习成本:
yq eval '.services.nginx.image' docker-compose.yml处理 CSV 表格,我常常直接用 sqlite3 的临时内存数据库。一条命令完成“导入 + 查询 + 分类统计”,不需要打开 Excel,也不需要写 Python:
sqlite3 :memory: -cmd ".mode csv" -cmd ".import data.csv records" \ "SELECT category, COUNT(*) FROM records GROUP BY category;"这两条命令解决了我九成以上的“看配置、算数据”需求。CLI-Anything 的思想在这里体现得最直接:数据文件就在磁盘上,本机又有强大的文本处理工具,为什么要打开一个重型软件绕一大圈?
当然,命令行方式的缺点是需要花点时间适应语法。我的应对方式是建立一份“数据处理速查表”,把这些常用的 yq、sqlite3、jq 片段全部记下来,需要时直接复制改参数。这个速查表我用 markdown 维护,放到 dotfiles 仓库里,换机器也不会丢。
3.3 管道可观测性:别让错误静默消失
命令行管道有个天然缺点:数据为空时输出也是空,你很难分清楚到底是网络挂了、权限拒绝,还是数据本来就没有。如果不做任何防御,排查问题的成本会相当高。我的做法是三层防御:
- 流程分段可见:在命令链里显式插入
echo "== 开始拉取数据 =="这类标记,让执行过程分段可读。 - 脚本开启
set -euo pipefail:放在脚本最顶部,任何命令失败或管道中途断开都会立刻中断,阻止错误一路静默。 - 输出退出码:用
echo "exit: $?"或在 trap 里捕获最终状态,方便定位。
这些细节让我的数据处理脚本从“窗口闪现一下就跑完”变成“可以交付给别人使用的稳定工具”。这也是 CLI 和脚本的另一个分水岭:能跑的脚本很多,可维护的脚本很少。
4. 从长命令到脚本:消灭重复劳动的完整路径
4.1 三个信号决定是否写脚本
很多人不爱写脚本,觉得“写脚本的时间比手动操作还久”。这个认知忽略了复利效应。我的判断标准是三个信号,命中任意一个就动手:
- 同样的操作这个星期已经出现第二次;
- 操作步骤超过五个,且中间有容易出错的参数;
- 这个流程需要交给别人执行,或者未来的自己还会再次执行。
一次手动操作可能只要 10 秒,但当它每周重复三十次,且偶尔还会漏步骤时,用一个 30 分钟写好的脚本替换它,几天内就回本了。
4.2 一个“发布前检查”脚本的诞生过程
拿我团队里的真实场景举例。前端项目每次发版前,都要确认工作区干净、lint 通过、测试通过、版本号格式正确。以前这些检查靠每个人手动敲,经常漏一项。我把整个流程抽成一个脚本:
#!/usr/bin/env bash set -euo pipefail echo "== 检查工作区状态 ==" git status --porcelain | head -20 echo "== 运行 lint 和测试 ==" npm run lint && npm test echo "== 检查未合并的远程分支 ==" git branch -r --merged main | grep -v 'main' | head -20 || true echo "== 校验版本号格式 ==" VERSION=$(node -p "require('./package.json').version") echo "$VERSION" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' > /dev/null \ && echo "版本号格式正确: $VERSION" || { echo "版本号格式错误!"; exit 1; }这个脚本没有任何高难技巧,但把“发布前容易遗漏的步骤”固定了下来。团队统一执行./scripts/precheck.sh,新人来了也不用反复讲解流程。这才是 CLI 脚本最有价值的地方——它不只是提升个人效率,还可以成为团队流程的载体。
4.3 脚本仓库的维护为什么比脚本本身更重要
脚本写完只是开始,更关键的是存放、命名和维护。我的经验是:
- 个人通用脚本放
~/bin,加入 PATH;项目内专用脚本放项目scripts/目录,并纳入 Git 版本管理。 - 命名用动词短语,比如
deploy-preview.sh、backup-db.sh、clean-logs.sh,避免tmp.sh这种三个月后谁也不知道干什么的文件。 - 脚本头部写几行注释,说清楚用途、用法、依赖的外部命令。这几十个字往往比脚本本身更值得保留。
- 项目相关的脚本一定要写进 README,让团队知道有这个工具,别自己重复造轮子。
还有一条反直觉的经验:脚本不要过度抽象。很多人喜欢写“万能脚本”,参数一大堆、case 分支无数,结果改一处崩三处。CLI-Anything 的精神是快速解决问题,脚本复杂度应当与问题复杂度成正比。宁可写两个简单脚本,也不要硬造一个“超级工具”。
5. AI 遇上 CLI:自然语言正在填平命令行的最大门槛
5.1 传统 CLI 的记忆门槛与 AI 的补位
命令行什么都好,唯一一道天然门槛是要记命令。我用命令行十几年,到现在还要靠--help和 man 页面过日子。这个门槛把大量的人挡在门外。AI 助手的出现,恰好把这道门槛大幅降低:你只需要用自然语言描述意图,AI 帮你生成命令、解释命令,甚至在授权下执行命令。
现在市面上主流的 AI 工具大多推出了命令行版本,本质上是“终端里的对话代理”。它不改变 CLI 的底层逻辑,只是改变了人和 CLI 之间的交互方式——记忆负担交给模型,操作自由度保留在终端里。
5.2 三种落地形态:生成命令、调度管道、执行闭环
我把 AI CLI 的实际用法归纳成三种形态。
第一种,生成命令。比如“找出当前项目里占用磁盘空间最大的 10 个文件”,AI 给出du -h --max-depth=1 | sort -rh | head -10,我确认后执行。这种用法保留了 CLI 的可复现性,因为命令仍然是真实管道,执行记录还在,之后想复制就很容易。
第二种,调度复杂管道。我可以要求“用 jq 把接口返回里 pending 状态的数据筛出来,并按用户统计任务数”,AI 直接生成一条完整的管道命令,而不是给我几段碎片信息让我自己拼装。这个能力比搜索引擎式的分散教程高效得多。
第三种,Agent 模式下的主动执行。部分 AI 工具允许直接操作 Shell,完成类似“跑测试 → 看报错 → 修复 → 重跑测试”的闭环。这个能力很强,但风险也最大,需要非常清晰的边界约束。
5.3 我在 AI CLI 上划的三条安全红线
使用 AI CLI 时,我给自己立下了三条硬规矩。
第一,写操作必须“先预览、后执行”。凡是涉及删除、修改、安装、上传的命令,AI 只允许先生成命令,由我确认后再执行,绝不授权它自由发挥。AI 的路径假设和上下文理解仍然会出错,尤其是删除类命令,一次误判可能造成不可逆的损失。
第二,敏感信息不进 Prompt。命令行工具天然能访问环境变量、密钥文件,AI 也可能顺手读取。我会给.env、id_rsa这类文件设置显式忽略规则,提问时也避免让 AI 读取证书、token 相关内容。
第三,所有 AI 操作必须留日志。我会配置 AI 工具把每次会话和执行的命令都记录下来。这不只是安全需要,也是调试需要——AI 偶尔会出现类似“幻觉式执行”的情况,日志就是纠偏的证据。
这三条红线让我敢用 AI CLI,又不会把安全命脉完全交出去。AI 不会让 CLI-Anything 变成“不需要思考”,它只是把死记硬背的部分移除掉,剩下的权衡和判断,仍然需要人来做。
6. 落到日常:把“万物皆CLI”变成可持续的工作系统
6.1 从 20% 高频操作开始的迁移路径
很多人看到“万物皆可 CLI”就想着一次性把所有工作都搬进去,结果往往是坚持三天就放弃。我的建议正好相反:先记录一周自己重复做的事情,找出最集中的那个 20%。
我当时的高频清单是:打开项目目录、搜索引用、看 git 状态、跑测试、看接口返回。这 5 件事大约占日常操作的一半。我给每一件事找一个对应的 CLI 操作或 alias,先从最简单的一条开始改习惯。比如打开项目目录,可以先写一个 alias:
alias goproj='cd ~/work/myproj && ls -la'一个小习惯坚持两三周,就会变成肌肉记忆,然后再迁移下一个。“CLI-Anything”不是一场冲刺,而是一个缓慢但不可逆的迁移过程。
6.2 一个让人愿意打开终端的舒适环境配置
CLI-Anything 不等于朴素。一个丑到不想打开的终端,不可能让你坚持用下去。我自己的配置组合是:zsh + starship + zoxide + fzf + eza。starship 提供好看的提示符,zoxide 优化目录跳转,fzf 负责各种选择,eza 替代 ls 让列表更清晰。整套配置下来不到一小时,但每次打开终端的愉悦感会持续回报很久。
如果你刚上手,建议先装 starship 和 eza,这两个工具改动小、感受直观。等习惯之后再引入 zoxide 和 fzf,避免一次配置太多反而不知道是哪个工具带来的体验提升。
6.3 沉淀 dotfiles 仓库:换机五分钟恢复全套环境
CLI 工作流最大的风险是“换台机器,环境就没了”。我的解法是维护一个 dotfiles 仓库,把.zshrc、aliases、scripts/、相关配置文件全部放进去,用 Git 管理,并在 README 里写清楚安装步骤。换新机器时,clone 下来跑一次安装脚本,五分钟恢复熟悉的终端环境。
这个仓库是我 CLI-Anything 体系里最重要的一环。它意味着“万物皆 CLI”不再是一堆散落的即兴操作,而是一套可移植、可版本化、可分享的工作系统。对团队也一样,一个共享的脚本集合就是一份活文档,任何人都能查看、改进、复用。
6.4 防“工具焦虑”,也防过度抽象
最后泼一点冷水:命令行生态更新太快了,今天有 ripgrep,明天有 fd,后天又冒出新的替代品。如果每天追新工具,只会陷入工具焦虑,最后类似“收藏了一百个工具,每天用的还是 cd、ls”。我现在引入新工具的唯一标准是:它至少要同时覆盖三个使用场景,并能显著改善现有工作流,否则就是收藏夹里的装饰品。
我个人踩过最大的坑,是喜欢把脚本越写越“灵活”,加无数参数和分支,最后连自己也记不住。后来全部重写,一个脚本只解决一个问题,参数越少越好。CLI-Anything 的快乐不是来自工具复杂度,而是来自“把复杂事情拆成简单步骤”的掌控感。
实际上,我写这篇文章时,电脑上开着三个终端会话:一个在跑接口轮询脚本,一个用 fzf 快速切换项目,还有一个在跟 AI 助手讨论某个正则表达式的优化方案。它们各司其职,互不干扰。这种体验在图形界面里很难复制——GUI 是窗口的堆叠,而终端更像一块无限延伸的画布,工具、脚本和流程都在这块画布上自由编排。CLI-Anything 对我来说早就不只是一个热搜词,而是日常工作默认的效率底座。如果你也想试试,不用一次到位,先从记住第一个快捷方式开始,慢慢把它变成自己的东西。