piz 开发日志(一):为什么要做一个用自然语言操控终端的 CLI 工具

 

piz 开发日志(一):为什么要做一个用自然语言操控终端的 CLI 工具

这是 piz 开发日志系列的第一篇。piz 是一个用 Rust 编写的终端命令翻译器——用自然语言描述你想做什么,它帮你生成精确的 shell 命令。

痛点

作为开发者,我经常遇到这些场景:

  • 知道要”找出当前目录下所有大于 100MB 的文件”,但 find 的参数记不住
  • 知道要”压缩 src 目录”,但 tar-czf -xvf 每次都要查
  • 知道要”杀掉占用 8080 端口的进程”,但不同系统命令还不一样
  • Windows 上用 PowerShell、Linux 上用 bash,语法切来切去头大

终端用户面临两个核心痛点:

  1. 记不住命令:不同 OS、不同 Shell 的命令语法差异巨大(Linux ls vs Windows dir、bash $VAR vs PowerShell $env:VAR
  2. 命令执行有风险:一条 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 主要基于以下考虑:

  1. 单二进制分发:编译出来就是一个可执行文件,没有运行时依赖,用户不需要装 Python、Node.js 之类的
  2. 跨平台编译:Cargo + cross 可以方便地为三平台编译
  3. 性能:CLI 工具的启动速度很重要,Rust 的零成本抽象和无 GC 确保了毫秒级启动
  4. 类型安全:108 个国际化翻译字段、12 种注入检测模式,编译器帮你检查完整性
  5. 生态: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

本文遵守 Attribution-NonCommercial 4.0 International 许可协议。 Attribution-NonCommercial 4.0 International