piz 开发日志(一):为什么要做一个用自然语言操控终端的 CLI 工具
这是 piz 开发日志系列的第一篇。piz 是一个用 Rust 编写的终端命令翻译器——用自然语言描述你想做什么,它帮你生成精确的 shell 命令。
痛点
作为开发者,我经常遇到这些场景:
- 知道要”找出当前目录下所有大于 100MB 的文件”,但
find的参数记不住 - 知道要”压缩 src 目录”,但
tar的-czf-xvf每次都要查 - 知道要”杀掉占用 8080 端口的进程”,但不同系统命令还不一样
- Windows 上用 PowerShell、Linux 上用 bash,语法切来切去头大
终端用户面临两个核心痛点:
- 记不住命令:不同 OS、不同 Shell 的命令语法差异巨大(Linux
lsvs Windowsdir、bash$VARvs PowerShell$env:VAR) - 命令执行有风险:一条
rm -rf /就能摧毁整个系统,而 LLM 如果被 Prompt 注入,可能会生成这样的命令
于是我决定用 Rust 写一个终端命令翻译器——piz。
设计哲学
在动手写代码之前,我先确定了五条设计原则,它们贯穿整个项目的每一个决策:
安全第一
这是最重要的原则。一个能自动执行 shell 命令的工具,如果没有安全防护,后果不堪设想。piz 采用三层安全防护:
- 第 1 层:Prompt 级别拒绝 —— LLM 自身判断,非命令请求直接拒绝
- 第 2 层:本地注入检测 —— 12 种恶意模式的正则匹配,完全离线,不依赖 LLM
- 第 3 层:危险分级 + 用户确认 —— 正则 + LLM 双重分级,取最大值
宁可误报,也不放行恶意命令。
非侵入性
很多工具会修改用户的 Shell 环境(比如注入 chcp 65001 或修改 OutputEncoding),piz 不做这种事。Windows 上的中文乱码问题,通过 GBK 解码回退来解决,不动用户的任何环境配置。
容错优先
LLM 的输出格式不完全可控。有时它会在 JSON 外面包一层 markdown 代码块,有时 Windows 路径中的反斜杠会破坏 JSON 解析。piz 采用 4 级回退解析策略,最大程度提取有效命令,而不是简单地报错。
零配置启动
首次运行自动触发配置向导,内置 12 个 API 供应商预设(OpenAI、DeepSeek、硅基流动、Moonshot、智谱、通义千问等),选一个、填个 Key 就能用。
跨平台一致性
同一份代码运行在 Windows/macOS/Linux 上,通过运行时环境检测适配不同平台。不是写三份代码,而是用条件编译和运行时判断。
功能全景
经过从 v0.1.0 到 v0.2.6 的迭代,piz 目前的功能矩阵如下:
| 功能 | 描述 | 示例 |
|---|---|---|
| 自然语言翻译 | 将自然语言转为 Shell 命令 | piz 列出所有大于100MB的文件 |
| 三层安全防护 | 注入检测 + 危险分级 + 用户确认 | 自动拦截 rm -rf / |
| 智能缓存 | SHA256 键 + TTL + LRU 驱逐 | 相同问题秒回 |
| 自动修复 | 命令失败后自动诊断并修复 | piz fix |
| 交互式聊天 | 多轮对话上下文保持 | piz chat |
| Shell 集成 | cd/export/source 在当前 Shell 生效 | eval "$(piz init bash)" |
| 命令解释 | 结构化解释命令含义 | piz -e 'tar -czf a.tar.gz src/' |
| 多候选选择 | 生成多个命令方案供选择 | piz -n 3 find large files |
| 管道模式 | 无 UI 输出,可嵌入脚本 | piz --pipe list files |
| 自动更新 | 后台检查 + 交互式升级 | piz update |
| 多后端支持 | OpenAI/Claude/Gemini/Ollama + 12+ 兼容商 | 国内外 API 都能用 |
技术选型:为什么是 Rust
选择 Rust 主要基于以下考虑:
- 单二进制分发:编译出来就是一个可执行文件,没有运行时依赖,用户不需要装 Python、Node.js 之类的
- 跨平台编译:Cargo + cross 可以方便地为三平台编译
- 性能:CLI 工具的启动速度很重要,Rust 的零成本抽象和无 GC 确保了毫秒级启动
- 类型安全:108 个国际化翻译字段、12 种注入检测模式,编译器帮你检查完整性
- 生态:clap(CLI 解析)、reqwest(HTTP)、rusqlite(SQLite)、tokio(异步)都是成熟的 crate
当前代码规模约 5500 行 Rust 代码,177 个测试(169 单元 + 8 集成),CI 在 Ubuntu/Windows/macOS 三平台跑。
项目演进时间线
从 git 历史来看,piz 的开发大致经历了以下阶段:
v0.1.0 — 核心功能成型
- 自然语言转 Shell 命令的核心翻译流程
- 多后端 LLM 支持(OpenAI/Claude/Gemini/Ollama)
- 双重危险检测(正则 + LLM)
- SQLite 缓存
- 交互式配置向导
- 中英双语 UI
v0.1.1 — Windows 适配
- 修复 Windows 控制台 GBK 编码乱码
- 命令失败自动修复(最多 3 次重试)
v0.2.0 — 功能大扩展
- 交互式 Chat 模式
- 多候选命令选择
- 执行历史记录
- Shell 补全生成
- 管道模式
- 缓存 LRU 淘汰
- 注入检测国际化
- API 重试与指数退避
v0.2.1 ~ v0.2.3 — 平台打磨
- Windows Shell 检测修复
- 自更新功能
- Shell 集成(eval 模式)
- 结构化正则回退解析
- 非侵入式编码处理
v0.2.5 ~ v0.2.6 — 开源治理
- 新增注入检测模式
- 安全策略、行为准则、PR 模板
- CI 优化
- 代理/镜像支持
下一篇预告
在下一篇中,我会深入讲解 piz 的分层架构设计和 LLM 抽象层——如何用一个 Trait 统一四种完全不同的 LLM API,以及提示词工程中那些有趣的细节。
本文是 piz 开发日志系列的第 1 篇,共 5 篇。
项目地址:GitHub