Claude Code 被自己的「工具」重写:Bun 从 Zig 到 Rust 的 96 万行史诗级迁移
引言:当 AI 开始「吃自己的狗粮」
2026年5月11日,一则推文在技术圈炸开了锅:
"Bun v1.3.14 将于明日发布。如果我们合并 Rust 重写版本,这将是 Zig 的最后一个版本。"
—— Jarred Sumner,Bun 创始人
就这么简短的一句话,四年前因选择 Zig 而特立独行的明星项目,宣告了自己的「哲学转身」。
但更讽刺的还在后面:这次重写的执行者,不是传统意义上的工程师团队,而是一个叫 Claude 的 AI Agent。
这意味着什么?
意味着 Anthropic 收购 Bun 后,Claude Code(一个深度依赖 Bun 的 AI 编程工具)被 Bun 自身的内存泄漏问题搞得苦不堪言,于是 Anthropic 让 Claude 去重写 Bun,最后这个被重写的 Bun 再回来支撑 Claude Code。
一个荒诞的闭环:
Claude Code → 被 Bun 的内存泄漏坑惨 →
Claude → 重写 Bun →
Bun → 支撑 Claude Code
这不是科幻小说,而是 2026 年真实发生的工程事件。本文将深入剖析这场技术迁移的前因后果,从代码层面解读为什么 Bun 必须离开 Zig,以及 AI 重写软件这一趋势背后的工程哲学。
第一章:背景——Bun 为什么会选择 Zig?
在理解为什么离开之前,我们需要先理解当初为什么选择。
1.1 Zig 的核心承诺
Zig 由 Andrew Kelley 于 2015 年创立,定位是「C 语言的现代替代者」。它的核心哲学是:
- 零成本抽象:不给你不需要的东西
- 显式优于隐式:内存分配、错误处理、并发模型全部显式化
- 无隐藏控制流:没有隐藏的析构函数、没有垃圾回收器带来的运行时开销
- 交叉编译零配置:一个
zig cc替代 GCC/Clang,无需安装任何系统依赖
Andrew Kelley 在 2026 年的访谈中解释了 Zig 的设计初衷:
"当你想完全掌控计算机时,就会用到 Zig。你不希望浪费任何一点性能,追求极致的运行速度和内存利用率。最重要的是,你想为用户打造最出色的体验。"
1.2 Bun 的技术选型
Bun 选择 Zig 有几个关键原因:
// Zig 的 Comptime 特性让 Bun 能实现极致的构建时优化
const std = @import("std");
// 在编译期就能完成的计算,运行时零开销
fn generateOptimizer() void {
comptime {
// 代码生成在编译期完成
// 不引入任何运行时开销
}
}
性能优势:
- Zig 编译到原生代码,没有 VM 的启动开销
- Bun 的启动时间只有 3ms,而 Python 慢 15 倍
- 相比 Node.js(V8 + C++)和 Deno(V8 + Rust),Bun 选择了更轻量的 JavaScriptCore + Zig 路线
开发效率:
- Zig 的学习曲线比 Rust 平缓
- 内存管理虽然手动,但比 C 安全得多
- 构建系统比 CMake/Autotools 简洁
1.3 四年成果
从 2021 年到 2026 年,Bun 用 Zig 写下了:
- 96 万行 Zig 代码
- 覆盖:HTTP 服务器、文件系统 API、npm 兼容层、bundler、test runner
- 成为 Zig 生态最成功的生产级项目
- 被 Mitchell Hashimoto 称为「Zig 的活广告」
第二章:危机——内存泄漏与社区问题
2.1 Claude Code 的崩溃
2026年3月12日,GitHub Issue #33453 被提交到 Claude Code 仓库:
标题:严重内存泄漏
描述:Claude Code 主进程表现出严重的内存泄漏,RSS 内存在约 3 小时的短会话中从约 1.7GB 增长到 14GB 以上。
泄漏位于 Bun 运行时的 WebKit Malloc 分配器中,而非用户空间的 JavaScript 分配。
更夸张的是 Issue #11377(被机器人标记为重复并关闭):
运行 14 小时后,Claude Code 进程占用 23GB 虚拟内存,143.8% CPU,系统完全卡死。
这直接导致了用户体验的崩溃。用户抱怨:
- CLI 卡顿
- 长时间会话后 Claude Code 无响应
- 不得不频繁重启
2.2 Bun 团队的困境
尽管 Bun v1.1.13 在 2026 年 4 月宣称「通过更换内存分配器让内存占用下降了 5%」,但用户并不买账。
Reddit 用户 Xtergo 做了一个「粗糙调查」:
"Bun 的路线图看起来更像是在不断叠加新功能,而不是优先解决稳定性和 Bug 修复问题。Bun 现在已经变得非常复杂了。如果这些问题继续得不到解决,我怀疑它永远无法达到 Node.js 那种生产级成熟度。"
2.3 4700 个 Open Issues
波兰公司 Rewardo 的 CTO Wojciech Maj 做了一个令人不安的对比:
| 项目 | Open Issues | 定位 |
|---|---|---|
| Node.js | ~1700 | 驱动全球互联网的运行时 |
| Bun | ~4700 | 早期阶段的 JS 运行时 |
一个「驱动整个互联网」的运行时,积压的 issue 数量不到一个新生项目的 40%。
2.4 深层原因:Zig 的破坏性变更
Bun 面临的一个持续性问题是 Zig 的破坏性变更。
Zig 至今没有发布 1.0 版本,Andrew Kelley 在访谈中解释了原因:
"我们是一家 501(c)(3) 非营利组织,没有投资压力,没有人在背后催促我们,我们也没有退出计划。我们有时间去稳步改进,而不必被迫接受那些为了赶进度而产生的错误决策。当我们发布 1.0 时,它将是一个真正不妥协的匠心之作。"
这种哲学固然值得尊敬,但对于像 Bun 这样的生产级项目来说,代价是:
- 每隔几个月可能需要更新代码以适配 Zig 的新语法
- 无法享受「稳定版」带来的安心感
- 长期维护成本持续增加
第三章:决裂——Zig 的「反 AI」政策
3.1 社区冲突
让问题火上浇油的是 Zig 社区对 AI 代码贡献的 零容忍政策。
Zig 核心开发者 Loris Cro 公开表示:
"大量 LLM 贡献只会制造'幻觉 PR''垃圾噪音',以及动辄上万行、根本无法维护的提交。"
另一位核心开发者则批评 Bun fork 中的一些实现「不适合 upstream」:
- 并行语义分析可能导致非确定性行为
- Bun 对 LLVM backend 的模块拆分「方向错误」
3.2 Bun 的尴尬处境
Bun 团队曾尝试通过 AI 辅助做编译器优化,但这些改进 无法合并回 Zig 上游:
// Bun 的 fork 中有大量这类优化
// 但由于违反了 Zig 社区的规范,无法 upstream
// Zig 官方:不接受 AI 生成的代码贡献
// Bun 现实:AI 是提升开发效率的关键工具
// 矛盾不可调和
3.3 哲学冲突
Andrew Kelley 在 2026 年访谈中明确表达了立场:
"AI 生成的代码贡献基本上都是垃圾。它们不仅没有价值,甚至有负价值,因为它们耗费了我们核心团队极其有限的 Code Review 时间。"
"更重要的一点是,开源贡献的核心意义在于'导师制'(Mentorship)。我们希望通过 Code Review 让贡献者成长,最终成为核心团队成员或更优秀的系统程序员。而发送 AI 生成代码的人并不学习任何东西,这完全背离了我们作为教育项目的初衷。"
这段话说得很有道理,但现实是:
Anthropic 收购了 Bun,而 Anthropic 本身就是 AI coding 浪潮最激进的推动者。
第四章:重写——96 万行的六天奇迹
4.1 Phase A & Phase B 迁移策略
2026 年 5 月初,Bun 仓库出现了一个新分支 claude/phase-a-port。
团队创建了一份长达 576 行的 PORTING.md:
## Phase A:忠实翻译
- 逐文件保留 Zig 的逻辑
- Rust 代码暂时不能编译也没关系
- 重点是语义等价
## Phase B:编译与优化
- 逐个 crate 解决编译问题
- 构建和运行问题
- 性能优化
## 禁止事项
- 不许用 tokio/rayon/hyper/futures
- 不许用 async fn
- unsafe 必须写明 SAFETY 注释
- 遇到不确定逻辑时,宁可留 TODO
这个文档本身就是一份高质量的跨语言迁移指南,体现了工程团队的专业性。
4.2 六天的进度
| 日期 | 里程碑 |
|---|---|
| 5月7日 | 4000+ commits,96万行代码,只剩 3 个编译错误。bun run 和 package.json scripts 已经能跑起来 |
| 5月9日 | Linux x64 glibc 环境下通过测试套件的 99.8% |
| 5月11日 | Jarred 宣布:准备合并,Zig 版本将成为「最后一个版本」 |
4.3 核心模块迁移成功
以下模块在 6 天内完成了从 Zig 到 Rust 的迁移:
// 已经被翻译的核心模块(Rust 版本)
// 1. JSON parser - 关键基础设施
mod json {
pub struct Parser { /* ... */ }
pub fn parse(input: &[u8]) -> Result<Value, Error> { /* ... */ }
}
// 2. AST 处理
mod ast {
pub struct Ast { /* ... */ }
pub fn parse(source: &str) -> Result<Ast, ParseError> { /* ... */ }
}
// 3. Module Resolver - npm 兼容层的核心
mod resolver {
pub fn resolve(
specifier: &str,
from: &Path,
resolver: &Resolver
) -> Result<Resolved, ResolveError> { /* ... */ }
}
// 4. Logger
mod logger {
pub struct Logger { /* ... */ }
}
// 5. File System Traversal
mod fs {
pub fn walkdir(path: &Path) -> WalkDir { /* ... */ }
}
4.4 Jarred 的心声
5月9日,Jarred 终于说出了憋在心底的话:
"我真的很厌倦为内存泄漏、崩溃和稳定性问题而担忧和花费大量时间进行修复。如果编程语言能提供更强大的工具来预防这些问题,那就太好了。"
Rust 承诺的「内存安全 without GC」正是他想要的工具。
第五章:争议——unsafe 的代价
5.1 13,000 个 unsafe
最大的争议来自 t3.gg 创始人 Theo 的对比:
uv(Rust): 35 万行代码,73 个 unsafe
Bun Rust: 68.1 万行代码,13,000+ 个 unsafe
73 vs 13,000,差了接近 180 倍。
5.2 Jarred 的回应
"今天已经下降了大约 2000。我预计它会稳定在 1 万左右,因为 Bun 的大部分内容都是用 C 和 C++ 编写的,这种情况不会改变。"
这个解释在技术上有一定道理。Bun 集成了:
- JavaScriptCore 引擎(C++)
- SQLite(C)
- uSockets(C)
- OpenSSL(C)
这些底层库的大量调用,绕不开 unsafe。
5.3 社区的质疑
但开发者社区的担忧不只是数字:
"UV rust 是由真正的开发人员编写的,每一行代码都经过了审查。Bun rust 由 Agents 编写,由 Agents 审核,并由 Agents 批准和合并。完全在意料之中的结果。"
—— Aashish Ranjan Singh
"uv 不是 vibecoded 的垃圾,而且开发它的人对 Rust 非常了解。但 Bun 就完全不同了,它简直是一场风格灾难。用 Deno 吧。"
—— HSVSphere
「vibecoded disaster」这个词精准刺中了人们的担忧:六天、96万行、AI生成、AI测试、1万个unsafe,然后直接合并?
5.4 unsafe 代码分析
让我们看看 Bun Rust 版本中 unsafe 的主要来源:
// 1. FFI 调用 C/C++ 库(不可避免)
extern "C" {
fn JSGlobalContextCreateInGroup(
group: *mut JSClassRef,
globalObjectRef: *mut JSGlobalObject
) -> *mut JSContextRef;
}
// SAFETY: Caller must hold the JS runtime lock
unsafe fn evaluate_in_context(ctx: &mut Context, code: &str) -> Value {
// ...
}
// 2. 内存操作
// SAFETY: Buffer must be at least len bytes
unsafe fn copy_memory(dst: *mut u8, src: *const u8, len: usize) {
std::ptr::copy_nonoverlapping(src, dst, len);
}
// 3. 指针操作(tagged pointer 等)
// SAFETY: Tag must be valid (0-7)
unsafe fn get_tagged_value(ptr: usize) -> i64 {
let value = ptr & !TAG_MASK;
let tag = (ptr & TAG_MASK) >> TAG_BITS;
// ...
}
这些 unsafe 大部分是正确的,但问题是:谁来验证?
第六章:哲学碰撞——两种软件工程观
6.1 Zig 的哲学
Andrew Kelley 在访谈中有一段关于「完美 vs 可用」的精彩论述:
"有些博客吹嘘用 AI 几分钟写个 App,那真的很没启发性。我对软件的追求是'极致的完美',而不是'居然没出 Bug'这种低水准的惊喜。"
"我最喜欢的 App 往往都是别人在业余时间纯粹为了爱好而开发的。商业公司的软件总是在试图卖给你东西,或者通过算法控制你,而爱好者开发的软件会尊重你,让你做计算机的主人。"
这段话充满理想主义色彩,但在 2026 年的商业现实面前,显得有些苍白。
6.2 Rust 的现实主义
相比之下,Rust 选择了一条更务实的路:
- 接受 unsafe 的存在,但要显式标注
- 编译器强制检查大部分内存安全问题
- 生态系统拥抱 AI 工具(copilot、claude 等都有良好支持)
- 1.0 版本早在 2015 年就发布,稳定性有保障
6.3 两种文化的冲突
| 维度 | Zig | Rust |
|---|---|---|
| 发布周期 | 无 1.0,持续演进 | 稳定版 + Edition 机制 |
| AI 态度 | 严格禁止 | 拥抱 |
| 内存安全 | 手动,显式 | 编译期检查 + unsafe |
| 生态系统 | 小而精 | 大而全 |
| 企业采用 | 早期探索 | 主流生产环境 |
Bun 的选择,某种程度上是整个行业趋势的缩影:理想主义在商业压力面前让步。
第七章:AI 重写软件的趋势
7.1 2026 年的「AI 重写」浪潮
Bun 不是孤例。类似的 AI 驱动极限重写正在多个领域同时发生:
Cloudflare: 一周内用 AI 重新实现 Next.js API
Ladybird: 两周内将 JS 引擎从 C++ 迁移到 Rust
Bun: 六天内将 96 万行 Zig 翻译为 Rust
7.2 Jarred 的预言
2026年5月3日,Jarred 在推文中写道:
"这种 pipeline,任何 VC 支持的 OSS 或者有大量 GitHub issues 的公司都能搭建。更普遍地说,它可以用于自动修复用户报告的 bug。Opus 4.7、4.6 甚至 4.5 都能轻松做到。"
更激进的预言:
"我预计开源软件会走向完全相反的方向——未来甚至可能变成'禁止人类贡献代码'。人类依然会负责讨论问题、决定优先级,但真正写代码、提交 PR、回复和处理反馈、完成实现的工作,最终都会由 LLM 来完成。"
7.3 行业影响
当你的 CTO 说「我们要把代码库从 X 语言重写成 Y 语言」时,他不会再问「需要几个月」,而是会问「Claude 需要几天」。
这种转变带来的问题:
- 代码质量:谁来 review AI 生成的代码?
- 知识传承:如果代码是 AI 写的,人类如何理解它?
- 责任归属:出 Bug 了算谁的?
- 工程文化:「vibecoded」会成为贬义词吗?
第八章:技术深度——内存管理的本质差异
8.1 Zig 的显式分配器模式
Zig 的内存管理哲学是「让程序员完全掌控」:
const std = @import("std");
// Zig 的分配器模式:所有内存操作显式化
const allocator = std.heap.page_allocator;
pub fn processData(data: []u8) ![]u8 {
// 手动分配内存
const result = try allocator.alloc(u8, data.len);
// 处理数据
std.mem.copy(u8, result, data);
// 手动释放(或者用 ArenaAllocator 自动清理)
defer allocator.free(result);
return result;
}
// 使用 Arena 简化生命周期管理
pub fn processDataWithArena(data: []u8) ![]u8 {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const result = try arena.allocator().alloc(u8, data.len);
std.mem.copy(u8, result, data);
return result;
}
优点:
- 没有 GC 的不确定性停顿
- 程序员完全知道何时分配、何时释放
- 性能可预测
缺点:
- 手动管理容易出错
- 复杂数据结构的内存管理代码繁琐
8.2 Rust 的所有权模型
Rust 尝试在编译期解决内存安全问题:
// Rust:所有权系统 + 借用检查器
fn process_data(data: Vec<u8>) -> Vec<u8> {
let result: Vec<u8> = data.into_iter().map(|b| b * 2).collect();
// data 在这里已经被「移动」,不能再使用
// result 会在离开作用域时自动释放
result
}
// 更复杂的场景:借用
fn process_with_borrow(data: &[u8]) -> usize {
data.iter().filter(|&&b| b > 0).count()
// data 只是借用,没有所有权,不会被释放
}
fn main() {
let owned = vec![1, 2, 3, 4, 5];
// 移动语义
let processed = process_data(owned);
// println!("{:?}", owned); // 编译错误!owned 已经被移动
// 借用语义
let count = process_with_borrow(&processed);
// processed 仍然是有效的
}
Rust 的优势:
- 编译期检查,消除大部分内存安全 Bug
- 不需要 GC,也没有手动 free
- 性能与 C/C++ 相当
8.3 Bun 的选择
Bun 选择 Rust 的核心理由:
// Rust 提供了「两全其美」的可能
// 1. 编译期安全 + 运行时性能
fn safe_parse_json(input: &[u8]) -> Result<Value, ParseError> {
// 这里的内存操作都是安全的
// 没有 GC 停顿,没有手动 free
}
// 2. unsafe 用于必要场景
unsafe {
// 明确的 unsafe 代码块
// 有注释解释 SAFETY 要求
// 便于审计和审查
}
// 3. 更好的工具链
// cargo、rustfmt、clippy、rust-analyzer...
// 比 Zig 的工具成熟得多
第九章:未来展望
9.1 Bun 的下一步
Bun v1.3.14 之后:
- Zig 版本成为「legacy」
- Rust 版本成为主分支
- 目标:解决内存泄漏,提升稳定性
9.2 Zig 的未来
Andrew Kelley 依然坚定:
"我们不需要追求'快鱼吃慢鱼'或者急于变现,我们的目标是打磨一个伟大的项目并长期维护。"
Zig 的核心用户依然存在:
- TigerBeetle(分布式金融数据库)
- Ghosty(Mitchell Hashimoto 的终端模拟器)
- 追求极致性能的系统程序员
9.3 AI 编程的成熟
这次事件给我们的启示:
AI 可以加速翻译,但不能替代设计决策
- 六天翻译了代码,但为什么选择 Rust?这个决策仍然是人类做出的
unsafe 的问题是人的问题
- 1 万个 unsafe 不是技术限制,是时间和审查资源的问题
开源社区需要重新思考 AI 政策
- Zig 的「反 AI」立场在短期内不会改变
- 但拥抱 AI 的项目会获得更多商业机会
结论:速度与信任
2026 年 5 月的这场迁移,是软件工程史上的一个标志性事件。
它证明了:
- AI 可以以前所未有的速度完成跨语言迁移
- 六天 vs 三周(Jarred 当年手工移植 esbuild 的时间)
- 速度上天的时代已经到来
它也暴露了:
- AI 重写的典型问题:缺少人类审查
- 「vibecoded disaster」的担忧并非空穴来风
- 流程变成「AI 写、AI 审、AI 合」的隐患
最后,用 Jarred 自己的话来收尾:
"速度上天的时代,信任只能自己想办法落地。"
参考资料
- CSDN: 6天、96万行Rust、直接合并?Claude Code被Bun的内存泄漏拖垮后,Bun让Claude亲手重写了自己
- CSDN: 十年拒发1.0、逃离GitHub、限制AI贡献代码!Zig语言创始人回应
- GitHub: Bun Repository (claude/phase-a-port branch)
- Bun 官方文档
- Zig 官方文档
- Rust 官方文档
作者后记:本文无意评判 Zig 或 Rust 的优劣,每种语言都有自己的定位和用户群。Bun 的选择是基于其商业现实和工程需求的理性决策。作为程序员,我们应该理解这些选择背后的逻辑,而不是陷入「语言战争」的二元对立。