用 Rust 重写 Bun
英文标题:Rewriting Bun in Rust
Jarred Sumner 详细介绍了将 Bun 从 Zig 重写为 Rust 的过程,借助 Claude 等 AI 代理和 TypeScript 测试套件实现自动化移植。整个重写耗费约 165,000 美元的 API 调用费用,处理了数十亿 token。Rust 版本已在 Claude Code 中上线,启动速度提升 10%,展示了前沿模型如何颠覆传统的大型软件重写观念,对开发者运用 AI 代理进行工程实践具有重要参考价值。
中文
用 Rust 重写 Bun(via)Jarred Sumner 承诺撰写这篇博客文章(自5月9日起)的时间,远比完成从 Zig 到 Rust 重写 Bun 所用的时间更长。
老实说,等待是值得的。这篇文章详细描述了一个极其复杂的代理式工程实践,涉及动态工作流、试运行、对抗性审查以及各种其他有趣的技巧。
Jarred 在文章前半部分赞扬了 Zig 让 Bun 走到今天这一步。然后我们读到文中的一个核心观点,重点为我所加:
我们的缺陷修复列表令人沮丧,我厌倦了带着对 Bun 崩溃的担忧入睡。我不怪 Zig——其他 Zig 用户没有遇到我们遇到的 bug,而且将 GC 与手动管理的内存混合使用,是软件需求中少见的情况,没有哪种语言真正为此设计。如果没有 Zig,我们不可能走到这一步,我会永远心存感激。直到最近,对于像 Bun 这样的项目,编程语言的选择一直是一条单行道。
众所周知,你永远不该停下一切、从头重写一个大型软件。Joel Spolsky 在 2000 年 4 月的 《你永远不该做的事,第一部分》 中强调过这一点!
由当今前沿模型驱动的编程 Agent 改变了这个等式。
为什么选择 Rust?一切归结于内存管理方面的挑战:
这份列表中的大部分 bug 都是释放后使用(use-after-free)、重复释放(double-free)以及错误路径中“忘记释放”。在安全的 Rust 中,这些都会变成编译错误,并通过
Drop实现类似 RAII 的自动清理。
这次重写的一个关键促成因素是,Bun 的测试套件是用 TypeScript 编写的,这意味着它可以充当 一致性套件。这使得一个代理 harness 能够自动化大部分从 Bun 到 Rust 的初始移植工作,最初只是作为一项实验,试用了我们现在可以通过 Mythos/Fable 访问的早期版模型。
一开始,我没想到这会奏效。几天后,测试套件通过的比例很高,我看到新的 Rust 代码与原始的 Zig 代码库匹配得非常好。我的看法从“这值得一试”变成了“我要合并它”。[...]
在那 11 天的大部分时间里(以及之后),我监控工作流——手动阅读输出,检查问题和 bug,并提示 Claude 编辑循环来修复问题。
如何审查一个新增超过 100 万行代码的 PR?如何开始建立信心,以便负责任地合并大量 LLM 编写的代码?
一个拥有百万断言的语言无关测试套件、对抗性代码审查,以及当出现问题时,修复生成代码的过程,而不是手工修复代码。
新的 Bun 实现已在 Claude Code 中上线近一个月:
Claude Code v2.1.181(6 月 17 日发布)及后续版本使用 Bun 的 Rust 移植版。在 Linux 上启动速度提升了 10%,但除此之外,几乎没人注意到。无聊就是好事。
在 Anthropic 工作的一个好处是你不用为 token 付费——在估算成本高达 165,000 美元时这很方便!
在合并之前,这消耗了 59 亿未缓存的输入 token、6.9 亿输出 token 以及 720 亿缓存输入 token 读取——按 API 定价约为 165,000 美元。
整件事是一个引人入胜的案例研究,展示了如何在协调并行 Agent 的帮助下承担极具雄心的项目。
English / 原文
Rewriting Bun in Rust (via) Jarred Sumner has been promising this blog post (since May 9th) about his Zig to Rust rewrite of Bun for significantly longer than it took him to finish the rewrite.
Honestly, it was worth the wait. This is a detailed description of an extremely sophisticated piece of agentic engineering, featuring dynamic workflows, trial runs, adversarial review and all sorts of other interesting tricks.
Jarred spends the first half of the post praising Zig for getting Bun this far. Then we get to a core idea in the piece, emphasis mine:
Our bugfix list felt bad and I was tired of going to sleep worrying about crashes in Bun. I don't blame Zig for that - other users of Zig don't have the bugs we had, and mixing GC with manually-managed memory is an uncommon enough thing for software to need that no language really designs for it. We wouldn't have gotten this far if not for Zig, and I'll always be grateful. Until very recently, programming language choice was a one-way decision for a project like Bun.
Everyone knows you should never stop the world and rewrite a large piece of software from the ground up. Joel Spolsky highlighted that in Things You Should Never Do, Part I back in April 2000!
Coding agents powered by today's frontier models change that equation.
Why pick Rust? It all came down to those challenges with memory management:
A large percentage of bugs from that list are use-after-free, double-free, and "forgot to free" in an error path. In safe Rust, these are compiler errors and RAII-like automatic cleanup with
Drop.
A crucial enabling factor for the rewrite was that the Bun test suite was written in TypeScript, which meant it could act as a conformance suite. This allowed an agent harness to automate much of the initial port from Bun to Rust, initially as an experiment to try out an earlier version of the model we now have access to as Mythos/Fable.
At first, I didn't expect it to work. A few days in, a high % of the test suite started passing and I saw how much the new Rust code matched up with the original Zig codebase. My opinion went from "this is worth trying" to "I'm going to merge this". [...]
For most of those 11 days (and after), I monitored workflows - manually reading the outputs to check for issues and bugs, and prompting Claude to edit the loop to fix things.
How do you review a PR with +1 million lines added? How do you start to build the confidence needed to responsibly merge large quantities of LLM-authored code?
A language-independent test suite with a million assertions, adversarial code review and when something does go wrong, fixing the process that generates the code instead of hand-fixing the code.
The new implementation of Bun has been live in Claude Code for nearly a month now:
Claude Code v2.1.181 (released June 17th) and later use the Rust port of Bun. Startup got 10% faster on Linux but otherwise, barely anyone noticed. Boring is good.
A perk of working at Anthropic is that you don't have to pay for your tokens - handy when the estimated cost is $165,000!
Pre-merge, this took 5.9 billion uncached input tokens, 690 million output tokens, and 72 billion cached input token reads — around $165,000 at API pricing.
This whole thing is a fascinating case study in taking on wildly ambitious projects with the help of coordinated parallel agents.