最近,Bun 在 Claude Fable 5(预发布版本)的加持下,用了不到两周时间,将整个项目从 Zig 迁移到了 Rust。

Bun 原来的代码仓库包含约 53.5 万行 Zig 代码,而最终合并的迁移 PR 新增了约 100.9 万行代码。从 5 月 3 日开始,到 5 月 14 日合并,整个过程只用了 11 天。
迁移累计消耗了 59 亿个非缓存输入 Token 和 6.9 亿个输出 Token。按照 API 价格计算,成本大约为 16.5 万美元。
为什么离开 Zig
Bun 最初能快速发展起来,Zig 发挥了非常重要的作用。它提供了接近底层的控制能力,也让开发团队可以在一年内完成一个范围极大的 JavaScript Runtime。
问题在于,JavaScriptCore 使用垃圾回收机制,而 Bun 自身的大量 Zig 代码采用手动内存管理,这种组合逐渐产生了大量稳定性问题。
开发者需要递归判断一段内存由该谁管理,什么时候释放,是否仍然被 JavaScriptCore 引用,是否正确执行了清理逻辑。
而 Rust 的价值就在于,它可以把其中一部分问题提前到编译阶段。
AI 是如何完成迁移的
准备工作
正式编写代码前,Jarred(Bun 创始人)花了大约三个小时与 Claude 讨论 Zig 和 Rust 之间的类型、内存生命周期、常见写法应该如何对应等问题,并将讨论结果整理成了一份 PORTING.md。
然后,Claude 自主分析了代码库中的所有结构字段的生命周期,并将它们记录到 LIFETIMES.tsv 中。
试运行
在制定好规则后,Jarred 没有先直接迁移全部 1448 个 Zig 文件,而是先选择了三个文件进行试验。
每个文件由一个 Agent 负责实现,两个处于独立上下文中的 Agent 负责审查,最后再由一个 Agent 根据审查意见修复。试验暴露出来的问题会先写回迁移规则,然后才开始大规模执行。
正式迁移
正式迁移时,工作流基本可以概括为:实现代码,独立审查,应用修改,提交结果。
Jarred 将任务拆到四个 Git worktree 中,每个 worktree 同时运行 16 个 Claude Agent。高峰时期,Claude 每分钟可以写入约 1300 行代码,每段代码还会经过两个独立 Agent 审查。

不过,第一轮生成的代码基本无法运行。完成文件翻译之后,代码库仍然存在约 1.6 万个编译错误。
错误修复
于是,Rust 编译器就变成了任务生成器。

工作流按照 crate 运行 cargo check,将编译错误按文件整理,再分配给不同的修复代理。代码通过编译后,继续运行命令行冒烟测试,然后运行本地测试,最后在 CI 的不同平台上逐步消除失败用例。
这里有一个很重要的原则:当多个文件反复出现同一种错误时,AI 不会逐个修改这些文件,而是修改产生错误的迁移规则,再重新生成受影响的代码。
AI 不只是生成代码,也在不断修改生成代码的方法。
人类在迁移中参与了什么
从结果看,这是一场高度自动化的迁移。
但在这 11 天里,Jarred 持续阅读工作流输出,检查代码和审查结果,发现代理之间互相覆盖 Git 状态时修改执行规则,发现 Claude 为了通过编译而创建空实现时增加审查约束,并根据失败模式不断调整任务循环。
AI 负责并行执行,人类负责设计系统、定义正确性,以及判断什么时候可以继续推进。
这次迁移最终能够成立,还有一个重要前提,就是 Bun 的测试套件主要使用 TypeScript 编写,不依赖底层实现语言,因此同一套测试可以同时验证 Zig 版本和 Rust 版本。测试套件中包含超过一百万个用例,成为了两套实现之间的共同裁判。
如果一个项目没有足够完整的测试,或者大量行为只存在于开发者经验中,那么 AI 即使完成了语法迁移,也很难证明新版本真的保持了原有行为。
最后
过去,重写一个大型基础设施项目通常意味着暂停新功能开发,同时维护两套实现,并额外投入一个团队持续工作数年。项目进行到一半时,即使发现方向错误,也很难放弃已经投入的成本。
Bun 的迁移表明,大型重构正在 AI 的参与下变成一种可以快速推进的工程。
但这并不意味着代码重构的成本变低了,毕竟 Bun 花费了约 16.5 万美元,同时还需要一位非常熟悉代码库的人持续监督。更关键的是,它拥有足够强大的测试套件,可以为百万行新代码提供相对可信的验收标准。
一百万行代码只是最终留下来的产物。真正重要的,还是能够持续发现错误、修正规则并重新生成代码的方法。