URL: /advanced/design-decisions

---
title: 项目思考
description: 记录 Zapmyco 开发过程中的设计决策和个人思考
---

本文档记录我在开发 Zapmyco 过程中的一些设计决策思考和个人见解。内容会持续扩展。

## 为什么用 Rust？

选择 Rust 作为 Zapmyco 的开发语言，并不是一开始就决定的。在最终选定 Rust 之前，我们经历了一个逐步探索和淘汰的过程。

### 1. Python — 最先被排除

最开始考虑过 Python。虽然 Python 在 LLM 领域使用广泛，但它作为 CLI 工具的语言有一些根本性问题：

- **版本和环境** — Python 的版本管理（2 vs 3）和虚拟环境碎片化严重，用户本地不一定有合适的运行环境
- **分发困难** — CLI 工具的理想形态是单一二进制文件，但 Python 不容易打包成二进制分发

### 2. TypeScript / Node.js — 推进最远，但最终放弃

我们甚至已经用 TypeScript 完成了核心 Agent 能力的开发，但仍然遇到了问题：

- **运行时依赖** — 和 Python 一样，用户本地需要安装 Node.js 才能运行
- **打包方案不理想**：
  - `pkg` — 可以将 Node.js 打包成二进制，但已停止维护，且打包体积很大
  - Node.js 自带的 **SEA（Single Executable Application）** — 目前还不够成熟
- **最终结论**：TypeScript 本身很优秀，但 Node.js 的生态和打包现状不适合 CLI 分发

### 3. Bun — 考察后放弃

我们知道 Claude Code 就是用 Bun 打包的，Bun 的优势很明显：

- 打包体积比 pkg 小很多
- 对 npm 包的兼容性不错

但当时 Bun 正在从 Zig 迁移到 Rust，这是一个非常激进的底层重构——意味着在相当长一段时间内稳定性存疑。另外，Bun 使用了 WebKit 内核（这也是体积小的原因），可能对 Windows 的兼容性不够好。而 Zapmyco 从设计之初就希望在跨平台上有很好的表现，所以我们放弃了。

### 4. Deno — 已迁移过去，因体积问题放弃

Deno 宣传为比 Node.js 更现代化的运行时，工具链集中、由 Rust 编写性能足够、新版本也逐渐提升了对 Node 生态的兼容性。我们当时认为 Deno 是一个很好的选择，甚至已经将代码从 Node.js 迁移到了 Deno，重新实现了 Agent 核心能力。

但问题出在打包上。即使我们的核心代码很少，Deno 打包出来的二进制体积也达到了 **70-100MB**。如果未来项目扩大、变得更加复杂，用户下载我们的 CLI 可能需要占据 100MB 以上的空间——这对分发来说不可接受。

### 5. Rust — 最终选择

最终我们把目光放在了 Rust 上。以下是它的核心优势：

| 优势 | 说明 |
|------|------|
| **现代化工具链** | 有自己完整的工具链（cargo、rustfmt、clippy），不像 Node 那样碎片化 |
| **编译期严格** | 编译时检查极其严格，明确的报错信息，对 AI 开发 Agent 的反馈机制非常友好 |
| **跨平台** | 在 Windows、macOS、Linux 上都能很好地运行 |
| **二进制体积小** | 打包后约 **5-10MB**，压缩后甚至只有 **3MB**，用户下载很快 |
| **无运行时开销** | 纯二进制编译，没有捆绑 V8 之类的运行时，运行效率高 |
| **包管理生态** | 有类似 npm 的 [crates.io](https://crates.io)，生态丰富 |

当然，Rust 也有缺点。目前它的生态系统不如 npm 那样完善和庞大，很多 SDK 不够成熟，有时甚至需要自己维护。但这不妨碍我们选择 Rust——整体收益远大于缺陷。

## 为什么选择 Web 而不是 TUI？

Zapmyco 最终选择 Web 而非 TUI 作为交互界面。这同样是一个经过权衡的决策。

### TUI 的优势（为什么不选它是有代价的）

TUI 确实很不错，很多优秀的 Agent CLI 都在使用——比如 Claude Code、Codex 等。选择 Web 意味着我们放弃了 TUI 的一些天然优势，比如启动快、终端内闭环操作等。

### 为什么还是放弃了 TUI

#### 1. 终端表现不一致

不同终端（Terminal）的表现差异很大，很像早期不同浏览器的兼容性问题：

- 有些终端支持鼠标交互，有些不支持
- 有些支持图像渲染，有些不支持
- 不同终端对字符编码的表现也不尽相同

这些问题很难从根本上解决，因为终端没有像 Web 那样有统一的标准化组织推动。而 Web 经过多年的标准演进，主流浏览器的表现已经基本趋同，不太会出现明显的兼容性差异。

#### 2. 远程终端的场景局限——以图片上传为例

给 LLM 发送图片是一项常见且刚需的功能。在本地终端中这很容易——图片就在本地文件系统中。但如果是远程终端（比如云服务器的 SSH 终端），问题就来了：

- 图片在本地，但终端在远端，路径不互通
- 服务器终端不太可能支持类似本地上传图片的形式

这种场景下 TUI 的使用就很有局限性，而 Web 可以天然地通过文件上传解决这个问题。

#### 3. Rust TUI 生态的兼容性成本

我们尝试了 Rust 生态中一些主流的 TUI 方案，发现仍然存在不少兼容性问题。如果自己去打磨这些兼容性问题，会非常耗时。但 Zapmyco 的本质不是打磨 TUI，而是做好 Agent 核心的 Loop、工具调用、工程约束等事情。

#### 4. 人力约束下的优先级选择

团队人力比较有限。在当下的场景中，我们需要集中精力在 Agent 核心能力上，而非 UI 打磨。Web 端有足够成熟的交互范式，可以让我们更轻装上阵。

#### 5. 降低使用门槛

Web 界面对于非极客用户（不太熟悉终端的用户）更友好，有助于降低 Zapmyco 的使用门槛。

### 总结

TUI 是很酷的技术方案，但它面临的终端碎片化、远程场景局限、以及 Rust 生态的兼容性成本，让我们决定把有限的精力放在 Agent 核心能力上。Web 是一个更务实、更普适的选择。
