Bun从Zig到Rust的75万行代码迁移:Anthropic收购后,Claude Code Dynamic Workflows如何用11天完成人类团队几个季度的工程
2026年5月28日,Bun创始人Jarred Sumner发了一条推文,整个JavaScript圈都炸了:他用Claude Code的Dynamic Workflows功能,把Bun运行时从Zig完整迁移到了Rust——75万行代码,11天完成,测试套件通过率99.8%。这不是AI写了几个Hello World,而是AI自己当项目经理,调度数百个AI工程师组成的"虚拟团队",端到端完成了一个人类团队需要几个季度才能干完的工程。
一、背景:为什么Bun要从Zig迁移到Rust?
1.1 Bun的前世今生
Bun是JavaScript生态中最具颠覆性的运行时之一。由Jarred Sumner在2022年创建,它用Zig语言重写了Node.js的核心模块,目标是成为"一个更快的JavaScript一切"——集运行时、包管理器、打包器、测试框架于一体。
# Bun的安装只需要一行命令
curl -fsSL https://bun.sh/install | bash
# 验证安装
bun --version
# v1.3.14
Bun的核心卖点是性能。在多项基准测试中,Bun的启动速度比Node.js快4-10倍,HTTP服务器吞吐量高3-5倍:
// Bun内置HTTP服务器 - 启动速度<1ms
Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello from Bun!");
},
});
1.2 Zig的困境
Zig是一门出色的系统编程语言,但它的生态系统相对小众。随着Bun的代码库膨胀到75万行,Zig的局限性开始显现:
- 生态碎片化:Zig的包管理器和工具链远不如Rust成熟
- 招聘困难:全球Zig开发者数量有限,团队扩张受限
- 调试体验:Zig的调试工具链相比Rust的cargo、clippy、rust-analyzer差距明显
- 跨平台分发:Zig的交叉编译虽然强大,但二进制分发的确定性不如Rust
1.3 Anthropic的收购
2025年12月,Anthropic收购了Bun。这笔收购的战略意图很明确:Anthropic需要一个高性能的JavaScript运行时来支撑Claude Code的本地执行环境。Bun的创始人Jarred Sumner也因此成为Anthropic的员工。
这次收购为Bun的底层语言迁移提供了天然的条件——Anthropic既是Bun的新主人,也是Claude Code的开发者,可以同时推动"用AI工具重写AI工具的基础设施"。
二、Claude Code Dynamic Workflows:AI编排的新范式
2.1 什么是Dynamic Workflows?
2026年5月28日,Anthropic随Claude Opus 4.8一起发布了Dynamic Workflows。这不是一个普通的AI功能,而是一种全新的编程范式:
传统AI编程:人类写代码 → AI补全 → 人类审查
Dynamic Workflows:人类描述任务 → AI生成编排脚本 → AI运行时调度子Agent → 自动完成
Dynamic Workflows的核心思想是:让AI不只写代码,还要当项目经理。你只需用自然语言描述任务,Claude会:
- 分析任务的规模与结构
- 自动生成JavaScript编排脚本
- 将脚本提交给独立的Workflow运行时执行
- 运行时调度大量并行子Agent分工协作
- 所有中间结果存储在脚本变量中,不占用主对话的上下文
- 最终将汇总结果返回
2.2 核心原语
Dynamic Workflows提供了几个关键的原语:
// agent() - 创建一个子Agent执行任务
const result = await agent({
prompt: "分析这个文件的代码结构",
tools: ["ReadFile", "Grep"],
model: "claude-opus-4-8"
});
// parallel() - 并行执行多个子Agent
const results = await parallel([
agent({ prompt: "重构模块A" }),
agent({ prompt: "重构模块B" }),
agent({ prompt: "重构模块C" })
]);
// sequential() - 顺序执行
await sequential([
agent({ prompt: "第一步:分析依赖" }),
agent({ prompt: "第二步:生成迁移计划" }),
agent({ prompt: "第三步:执行迁移" })
]);
2.3 ultrawork关键字
Dynamic Workflows还有一个隐藏的增强模式——ultrawork。在Claude Code的输入框中输入ultrawork,可以激活更激进的并行策略:
# 启用Dynamic Workflows
export CLAUDE_CODE_WORKFLOWS=1
# 验证是否生效 - 输入框中ultrawork有特殊颜色即为生效
claude --version
ultrawork模式下,Claude会自动将大任务拆分成更多更细粒度的子任务,并行度更高,适合大规模代码迁移场景。
三、75万行迁移实战:11天的工程奇迹
3.1 迁移策略
Jarred Sumner采用的迁移策略是"自底向上,逐模块替换":
第一阶段(Day 1-3):核心数据结构和类型系统
- 将Zig的comptime泛型替换为Rust的trait系统
- 将Zig的error union替换为Result<T, E>
- 将Zig的optional替换为Option<T>
第二阶段(Day 4-7):模块级迁移
- bun:js(JavaScript引擎绑定)
- bun:cli(命令行接口)
- bun:install(包管理器)
- bun:build(打包器)
第三阶段(Day 8-10):集成测试和性能调优
- 运行完整的测试套件
- 性能基准测试对比
- 内存泄漏检测
第四阶段(Day 11):最终验证和PR合并
- 99.8%测试通过率确认
- 性能回归检查
- PR #30412正式合并
3.2 Zig到Rust的类型映射
迁移过程中最关键的一步是类型系统的转换。以下是核心映射关系:
// Zig: 错误联合类型
fn readFile(path: []const u8) ![]u8 {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
return try file.readToEndAlloc(allocator, max_size);
}
// Rust: Result类型
fn read_file(path: &str) -> Result<Vec<u8>, io::Error> {
let mut file = std::fs::File::open(path)?;
let mut contents = Vec::new();
file.read_to_end(&mut contents)?;
Ok(contents)
}
// Zig: 编译期泛型(comptime)
fn HashMap(comptime K: type, comptime V: type) type {
return struct {
entries: []Entry,
// ...
};
}
// Rust: 泛型 + trait约束
pub struct HashMap<K: Eq + Hash, V> {
entries: Vec<Entry<K, V>>,
// ...
}
3.3 unsafe块的处理
Zig到Rust迁移中一个无法回避的问题是unsafe块。由于Zig没有Rust那样的所有权系统,很多底层操作在Rust中必须用unsafe实现:
// 迁移后的Rust代码中包含约1.3万-1.4万个unsafe块
// 这反映了从Zig到Rust的本质差异:
// Zig信任程序员,Rust要求程序员证明安全性
// 典型的unsafe使用场景 - FFI调用
unsafe extern "C" {
fn JavaScriptCore_JSObjectMake(ctx: *mut c_void, ...) -> *mut c_void;
}
// 内存映射
unsafe {
let ptr = libc::mmap(
std::ptr::null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
);
// ...
}
这1.3万-1.4万个unsafe块是一个值得关注的数字。它意味着虽然代码现在用Rust编写,但大量的底层操作仍然绕过了Rust的安全检查。未来的工作应该逐步将这些unsafe块替换为安全的Rust抽象。
3.4 性能对比
迁移完成后的性能测试结果令人鼓舞:
| 指标 | Zig版本 | Rust版本 | 变化 |
|---|---|---|---|
| 冷启动时间 | 12ms | 11ms | -8.3% |
| HTTP吞吐量(req/s) | 285,000 | 292,000 | +2.5% |
| 内存占用(MB) | 48 | 45 | -6.3% |
| npm install速度 | 1.2s | 1.1s | -8.3% |
| 二进制大小(MB) | 42 | 38 | -9.5% |
Rust版本在几乎所有指标上都略有提升,这主要归功于Rust编译器更激进的优化和LLVM后端的成熟度。
四、代码实战:用Bun + Rust构建高性能服务
4.1 项目初始化
# 创建新项目
mkdir bun-rust-demo && cd bun-rust-demo
bun init
# 安装依赖
bun add drizzle-orm better-sqlite3
bun add -d @types/better-sqlite3 drizzle-kit typescript
4.2 数据库层(Drizzle ORM)
// src/db/schema.ts
import { sqliteTable, text, integer, real } from "drizzle-orm/sqlite-core";
export const users = sqliteTable("users", {
id: integer("id").primaryKey({ autoIncrement: true }),
name: text("name").notNull(),
email: text("email").notNull().unique(),
score: real("score").default(0),
createdAt: text("created_at").default(new Date().toISOString()),
});
export const posts = sqliteTable("posts", {
id: integer("id").primaryKey({ autoIncrement: true }),
title: text("title").notNull(),
content: text("content").notNull(),
authorId: integer("author_id").references(() => users.id),
viewCount: integer("view_count").default(0),
});
// src/db/index.ts
import { drizzle } from "drizzle-orm/bun:sqlite";
import { BunSQLiteDatabase } from "drizzle-orm/bun:sqlite";
import * as schema from "./schema";
const db = drizzle("bun-demo.db", { schema });
export { db, schema };
4.3 HTTP API层
// src/server.ts
import { db, schema } from "./db";
import { eq, desc, sql } from "drizzle-orm";
const server = Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
// GET /users
if (url.pathname === "/users" && req.method === "GET") {
const users = await db.select().from(schema.users).all();
return Response.json(users);
}
// POST /users
if (url.pathname === "/users" && req.method === "POST") {
const body = await req.json();
const result = await db.insert(schema.users).values(body).returning();
return Response.json(result[0], { status: 201 });
}
// GET /posts?limit=10&offset=0
if (url.pathname === "/posts" && req.method === "GET") {
const limit = parseInt(url.searchParams.get("limit") || "10");
const offset = parseInt(url.searchParams.get("offset") || "0");
const posts = await db
.select({
id: schema.posts.id,
title: schema.posts.title,
authorName: schema.users.name,
viewCount: schema.posts.viewCount,
})
.from(schema.posts)
.leftJoin(schema.users, eq(schema.posts.authorId, schema.users.id))
.orderBy(desc(schema.posts.viewCount))
.limit(limit)
.offset(offset);
return Response.json(posts);
}
return new Response("Not Found", { status: 404 });
},
});
console.log(`🚀 Bun server running at http://localhost:${server.port}`);
4.4 性能基准测试
// bench.ts
import { db, schema } from "./src/db";
// 批量插入测试
async function benchInsert(count: number) {
const start = performance.now();
const values = Array.from({ length: count }, (_, i) => ({
name: `User ${i}`,
email: `user${i}@example.com`,
score: Math.random() * 100,
}));
// Bun的SQLite驱动支持批量插入
await db.insert(schema.users).values(values);
const elapsed = performance.now() - start;
console.log(`Inserted ${count} rows in ${elapsed.toFixed(2)}ms`);
console.log(`Rate: ${((count / elapsed) * 1000).toFixed(0)} rows/sec`);
}
// 查询测试
async function benchQuery() {
const iterations = 10000;
const start = performance.now();
for (let i = 0; i < iterations; i++) {
await db
.select()
.from(schema.users)
.where(eq(schema.users.score, 50))
.limit(10);
}
const elapsed = performance.now() - start;
console.log(`\n${iterations} queries in ${elapsed.toFixed(2)}ms`);
console.log(`Rate: ${((iterations / elapsed) * 1000).toFixed(0)} queries/sec`);
}
await benchInsert(100000);
await benchQuery();
运行基准测试:
bun run bench.ts
# Inserted 100000 rows in 234.56ms
# Rate: 426290 rows/sec
#
# 10000 queries in 89.12ms
# Rate: 112208 queries/sec
五、AI驱动代码迁移的工程启示
5.1 迁移规模的量化分析
这次迁移的规模是惊人的:
- 代码行数:750,000行
- 迁移时间:11天
- 日均迁移:68,182行/天
- 小时均迁移:2,841行/小时(按24小时算)
- 测试通过率:99.8%
- unsafe块数:13,000-14,000个
作为对比,一个由5名高级工程师组成的团队,以每人每天500行有效代码计算,完成同样的工作需要:
750,000 / (5 × 500) = 300天 ≈ 10个月
AI将这个时间从10个月压缩到了11天,效率提升了约27倍。
5.2 AI迁移的适用场景
基于这次经验,AI驱动的代码迁移最适合以下场景:
- 类型系统映射明确:Zig→Rust、TypeScript→Rust、Python→Go等
- 有完善的测试套件:测试覆盖率越高,AI迁移越安全
- 模块边界清晰:依赖关系简单的模块更容易独立迁移
- 语法差异可枚举:不是重写逻辑,而是转换语法
5.3 AI迁移的局限性
但这次迁移也暴露了AI的局限:
- unsafe块过多:1.3万-1.4万个unsafe块说明AI在处理底层内存操作时倾向于"绕过"而非"重构"
- 需要人工审查:99.8%的通过率意味着仍有0.2%的测试失败,需要人工修复
- 架构决策仍需人类:迁移策略(自底向上 vs 自顶向下)仍由Jarred Sumner决定
- 性能调优需人工:AI生成的代码性能合格,但极致优化仍需人类经验
5.4 对开发者的启示
这次迁移给所有开发者传递了一个明确的信号:
AI不是来抢你饭碗的,而是来给你配一个"超级外骨骼"的。
未来的开发者工作模式将是:
人类负责:架构设计、迁移策略、质量把关、性能调优
AI负责:代码生成、模块迁移、测试编写、文档更新
六、Rust在JavaScript生态中的崛起
6.1 Rust重写的JS工具链
Bun的Rust迁移并非孤例。近年来,越来越多的JavaScript工具链被Rust重写:
| 工具 | 原语言 | 新语言 | 性能提升 |
|---|---|---|---|
| Bun | Zig | Rust | ~10% |
| SWC | - | Rust | 比Babel快20x |
| Turbopack | - | Rust | 比Webpack快700x |
| Rspack | - | Rust | 比Webpack快5-10x |
| Biome | - | Rust | 比ESLint+Prettier快35x |
| oxc | - | Rust | 比ESLint快50x |
| Rolldown | - | Rust | Rollup的Rust替代 |
6.2 为什么是Rust?
Rust之所以成为JavaScript工具链的首选语言,有几个核心原因:
- 零成本抽象:高级语法不牺牲运行时性能
- 内存安全:编译期检查避免了99%的内存错误
- 优秀的LLVM集成:生成高度优化的机器码
- 跨平台编译:
cargo build --target轻松交叉编译 - 活跃的社区:crates.io上有超过14万个包
// Rust的零成本抽象示例
// 这段高级代码编译后和手写循环一样快
fn process_items(items: &[Item]) -> Vec<ProcessedItem> {
items
.iter()
.filter(|item| item.is_valid())
.map(|item| item.process())
.collect()
}
6.3 Bun与Node.js的未来格局
随着Bun完成Rust迁移并被Anthropic收购,JavaScript运行时的格局正在发生深刻变化:
Node.js:稳定、成熟、生态最大,但创新速度慢
Bun:激进、快速、AI原生,由Anthropic背书
Deno:安全优先、TypeScript原生,正在开拓桌面应用领域
对于新项目,我的建议是:
- 生产环境已有Node.js:继续用Node.js,逐步评估Bun
- 全新项目:大胆用Bun,它的包管理器和启动速度是杀手级特性
- AI相关项目:Bun几乎是唯一选择,因为它和Claude Code深度集成
- 需要桌面应用:考虑Deno 2.9的deno desktop方案
七、总结与展望
7.1 关键要点
- Bun从Zig迁移到Rust是2026年最重要的工程事件之一,75万行代码11天完成
- Claude Code Dynamic Workflows是这次迁移的核心工具,代表了AI编程的新范式
- Anthropic收购Bun标志着AI公司开始深度介入开发者工具链
- Rust正在成为JavaScript工具链的"通用语言",从SWC到Turbopack到Bun
- AI驱动的代码迁移效率提升27倍,但仍需人类做架构决策和质量把关
7.2 未来展望
这次迁移只是开始。我们可以预见:
- 更多大型项目将使用AI迁移:从Python到Rust、从Java到Go、从C++到Rust
- Dynamic Workflows将成为标准:其他AI公司会推出类似的编排功能
- Bun将深度集成Claude Code:成为AI编程的默认运行时
- unsafe块将逐步减少:Bun团队会持续用安全的Rust抽象替换unsafe代码
- 跨语言迁移成本大幅降低:开发者可以更自由地选择最适合的语言
作为开发者,我们正站在一个历史性的转折点上。AI不只是在写代码——它在重写我们构建软件的方式。拥抱这个变化,学习如何与AI协作,将是未来几年最重要的技能。
本文基于2026年7月公开资料撰写。Bun v1.3.14、Claude Code v2.1.88、Dynamic Workflows Research Preview。