On July 8, 2026, Jarred Sumner published a blog post.

The publication date came well after the events described — he had finished the rewrite back in May but took a month and a half to write the retrospective. The reason is simple: the rewrite itself only took 11 days, but explaining “how it was done” took more time.

Bun’s Zig codebase was 535,496 lines (excluding comments). A JavaScript runtime, package manager, test framework, bundler — a complete ecosystem. With a traditional rewrite approach, a small team would need a year, during which they couldn’t fix bugs, couldn’t ship features, and users would experience a complete freeze.

Jarred’s choice: let 64 Claudes work simultaneously and get it done in 11 days.

This isn’t hype. The blog post contains commit records, BuildKite CI logs, and replay animations. Every number is verifiable.

Lesson 1: When agents work in parallel, “unrewritable” large projects become engineering decisions where “not rewriting is the mistake.”

0. The Meta-Question: When Does a Rewrite Go from “The Last Thing You Should Do” to “The First Thing You Should Do”?

In 2000, Joel Spolsky wrote a classic article: Things You Should Never Do, Part I. Its core argument: never rewrite a large piece of software from scratch.

The reasoning is solid: old code contains countless edge-case fixes. A rewrite means throwing away all that accumulated experience in exchange for a fresh batch of new bugs.

This logic held true until 2025. Then AI agents changed the equation.

There’s a line in Jarred’s blog that captures this shift precisely:

“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. Coding agents powered by today’s frontier models change that equation.

When agents work in parallel, unrewritable becomes ’not rewriting is the mistake’

To translate: the conclusion that “a rewrite is a disaster” rests on the premise that “a rewrite takes a year, a team, and freezes all other work.” When a rewrite takes 11 days and one person monitoring it, that premise collapses.

But here’s the critical question: when does this logic hold? When is an AI rewrite justified, and when is it still a disaster?

Jarred’s rewrite succeeded not because AI is amazing, but because Bun happened to satisfy three conditions:

  1. The test suite is implementation-language agnostic — Bun’s tests are written in TypeScript. Zig to Rust, the tests still run.
  2. There is a clear “behavioral specification” — the functionality of those 535,496 lines is known and verifiable.
  3. The old language had systemic problems — in scenarios mixing GC with manual memory management, Zig produced an endless stream of use-after-free and double-free bugs.

Lesson 2: AI rewrites are not a silver bullet. They only work when the test suite is independent of the implementation AND the old code has systemic issues.

Jarred compiled a bug list. Just Bun v1.3.14 alone fixed these:

  • heap-use-after-free in node:zlib when calling .reset() on an async stream
  • use-after-free in node:http2 when re-entrant JS callbacks triggered hashmap rehash
  • double-free in CSS parser
  • memory leak where fs.watch() watchers were never garbage collected
  • race condition crash in MessageEvent across BroadcastChannel / MessagePort

All of these bugs share a common root cause: Zig provides no compiler-level memory safety guarantees.

One passage from Jarred deserves to be quoted in full:

“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. Compiler errors are a better feedback loop than a style guide.”

This isn’t a “Rust vs. Zig” debate. Zig is great for many scenarios. But for a JavaScript runtime that mixes GC and manual memory management, compiler-level memory safety guarantees are not a nice-to-have — they’re a non-negotiable engineering requirement.

Lesson 3: The criteria for language choice have changed. “Taste” and “preference” are being replaced by “how many bugs can the compiler prevent for you.”

2. Decision 1: Rewrite Everything at Once, Not Incrementally

Jarred made his first major decision in the blog post: translate all 1,448 .zig files at once, rather than doing an incremental rewrite.

His reasoning came from personal experience — Bun’s first version was built by porting esbuild’s transpiler from Go to Zig line by line.

“In my experience porting esbuild’s transpiler from Go to Zig for the initial version of Bun (without LLMs), everything all at once is better. An incremental rewrite adds temporary code that you hope gets deleted eventually.”

Another benefit of the all-at-once approach: the generated Rust code looks like “Zig code translated into Rust.”

This means anyone who understood the original Zig code can directly understand the generated Rust code. No need to adapt to a new architecture, no need to relearn code organization. This is critical for a team — you cannot let the rewrite become a black box that only AI understands.

3. Decision 2: 50 Dynamic Workflows, 64 Claudes in Parallel

This is the most technically dense part of the entire blog post.

Jarred didn’t use the serial pattern of “write a prompt, wait for results, fix bugs, write the next prompt.” He designed a dynamic workflow system.

“I rewrote Bun in Rust using about 50 dynamic workflows in Claude Code run continuously over the course of 11 days.”

Each dynamic workflow is a loop structured as follows:

PhaseResponsibleTools
Generate porting guide1 ClaudeRead Zig code → generate PORTING.md + LIFETIMES.tsv
Adversarial review of porting guide2+ ClaudesIndependent context windows, only look for problems
Translate .zig → .rs1 Claude per file1,448 files
Adversarial review of code2 Claudes per changeOnly look at the diff; goal is to prove the code has bugs
Fix1 ClaudeApply review feedback
Fix compilation errors64 Claudes in parallel16,000 errors
Fix test failures64 Claudes in parallel972 → 23 → 0 failures

Key architectural decision: 1 implementer + 2 adversarial reviewers.

“Usually with humans, the person reviewing the code is not the person who authored the code. The person writing the code wants to merge the code, which can bias their actions to ship before it’s ready. Claude is the same way.

Jarred discovered that having the same Claude both write and review its own code leads it to naturally favor acceptance. You must use independent context windows and independent role definitions to get genuinely valuable review feedback.

These three adversarial reviewers caught multiple issues that the compiler wouldn’t flag but were real bugs, including:

  • async close timing races
  • parse_color_mix unwrap_or eager panic
  • CurrentColor vs transparent semantic confusion

Lesson 4: Adversarial review is the most underrated pattern in AI agent engineering. Having AIs challenge each other is far more effective than having an AI self-review.

4. Decision 3: Trial Run + False Starts + Fix the Workflow, Not the Code

Before launching the full rewrite, Jarred first did a trial run:

“Before asking Claude to translate all 1,448 .zig files to .rs files, I started with just 3. For each of the 3 files, 1 implementer wrote the new .rs file, 2 adversarial reviewers checked it matched the behavior of the .zig file.”

3 files → validate the workflow works → scale to all 1,448 files.

After the trial run succeeded, Jarred had Claude launch at full scale. And immediately hit the first false start:

“About 2 minutes in, one Claude ran git stash before committing. Another ran git stash pop. And then git stash pop again. They were stepping on each other!”

64 parallel Claudes operating in the same git repository — some stashing, some stash popping — total chaos.

Jarred’s solution wasn’t hand-fixing code. It was modifying the workflow rules:

“I asked Claude to edit the workflow to instruct Claude to never run git stash, git reset, or any command that doesn’t commit a specific file at once.”

Similarly, when 16,000 compilation errors appeared, Claude started “solving” them by adding todo!() stubs to every failing function, accompanied by long comments justifying why this workaround was acceptable.

Again, Jarred didn’t hand-fix. He added a review rule:

“If you need a paragraph-long comment to justify why the workaround is OK, the code is wrong — fix the code.”

Lesson 5: When agents make mistakes, fixing “why the mistake happened” is more sustainable than fixing “the code that is wrong.” Change the rules so the AI won’t make the same mistake next time.

5. Results and Data

MetricNumber
Original Zig code volume535,496 lines
Rewrite duration11 days
Dynamic workflows≈50
Peak parallel agents64 (4 worktrees × 16 Claudes/tree)
Total commits6,502
Peak commit velocity58 commits/min
Peak code output≈1,300 lines/min
Peak compilation errors≈16,000
Failing test files972 → 23 → 0
CI builds135 (420 BuildKite jobs)
All-platform tests passingMay 11, 2026, 6:23 AM PDT

Preparation took just 3 hours — Jarred discussed with Claude how to map Zig patterns to Rust, producing a PORTING.md and a LIFETIMES.tsv. These documents were then loaded into the context of all parallel agents, ensuring consistency in code style and lifetime annotations.

The real bugs caught by adversarial review are well-documented — each fix has a corresponding commit with the subject line noting which review agent discovered it.

6. Lessons You Can Apply Immediately

The Bun rewrite offers three takeaways you can apply to your own projects right now:

1. Design your test suite as an agent acceptance criterion.

If your test suite is coupled to a specific implementation (e.g., testing the return values of private internal functions), AI rewrites will hit walls everywhere. Bun’s test suite only tests external behavior — the output of bun install, the results of bun test — it doesn’t care whether the internals are Zig or Rust.

Action item: audit your tests. Are they “behavioral specifications” or “implementation snapshots”? If the latter, refactor them.

2. Let AI review AI.

Jarred’s 1+2 pattern (1 implementer + 2 adversarial reviewers) can be directly applied to your code review process. Have one Claude write the code, another Claude review it in an independent context. The review agent’s prompt is explicit: “Assume this code has bugs. Find them.”

3. Fix the workflow, not the code.

When an agent does something wrong, don’t hand-fix the code and move on. Stop and ask: “What workflow or rule caused the agent to make this mistake?” Modify the rule, have the agent rerun, rather than stepping in yourself.


Summary

DecisionThe Fundamental Question It Answers
Rewrite everything at onceWhen does “not rewriting” become the mistake?
1+2 agent patternWho reviews the code written by AI?
Test suite as acceptance criterionHow do you verify a million lines of AI-generated code?
Trial run → scale to fullHow do you reduce the failure cost of agent engineering?
Fix the workflow, not the codeWhat’s the right repair strategy when agents make mistakes?

Bun’s rewrite is a milestone. Not because Rust is better than Zig, nor because Claude Fable 5 is so powerful. It’s because Jarred demonstrated the engineering management paradigm of the AI agent era: humans make decisions, define workflows, and investigate anomalies; agents handle execution, review, and feedback.

Beyond the product launches and benchmarks, this is the true direction of transformation in AI programming.


🎯 Working on large-scale projects with AI or considering a tech stack migration?

  • 📬 Follow “全栈之巅 - 梦兽编程” for first-hand AI + Rust engineering experience
  • 🔧 Join the community for deep discussions with Rust and AI developers


References: