The Bun rewrite in Rust caused quite a stir on the technical internet today. If you are not a chronically online technical person, you may have missed it. This one story contains enough bait to keep us busy for weeks: Bun, Zig, Rust, Anthropic, 64 Claudes and a million lines of generated code. It should have become a boring language war with AI sprinkled on top. Unfortunately, it is much more interesting than that.
Some context. Bun is a JavaScript runtime originally written mostly in Zig and acquired by Anthropic in December 2025. In May, Jarred Sumner used a pre-release version of Claude Fable 5 to mechanically port Bun’s Zig code to Rust. According to Bun’s account of the rewrite, roughly 50 dynamic workflows ran continuously for 11 days, with about 64 Claudes working in parallel at the peak. They translated 1,448 Zig files and more than 535,000 lines of Zig into a diff containing just over one million new lines. The pre-merge work consumed an estimated $165,000 at API pricing. At the end, the same language-independent test suite passed on all six supported platforms without tests being deleted or skipped. The port is now available in the Bun 1.4 canary, which is not the same thing as a stable release.
That is not a weekend refactor. It is industrial-scale code generation.
It is also not quite accurate to say an AI simply rewrote Bun by itself. Sumner designed a fairly elaborate development factory around it. A porting guide mapped Zig patterns to Rust. A separate workflow traced lifetimes through the original codebase. Each implementation agent was followed by at least two adversarial review agents working in separate contexts, then another agent applied the corrections. Compiler errors became a distributed work queue. Later loops fixed test failures across every platform. Sumner says he monitored the workflows, manually read their outputs, adjusted their rules, verified that the tests were actually running and performed local checks before merging.
The code was generated by AI and reviewed primarily by AI, but the process itself was designed and supervised by a person. That distinction matters. Sixty-four Claudes did not wake up one morning with a shared sense of taste and decide to improve a runtime. A person built a machine that used models as workers, then used the compiler and test suite as the factory’s measuring equipment.
I am not an AI hater, and I am not an AI lover either. Translating a codebase of this size, getting it to compile and making the complete test suite pass is astonishing. The methodology may be even more interesting than the result. This is far beyond asking a coding assistant to add an endpoint while you go make coffee.
It does not automatically make me comfortable.
Today, Andrew Kelley, the creator of Zig, published his response to the Bun rewrite.
Ouch.
The post is personal, blunt and clearly carrying several years of frustration about the relationship between Bun and the Zig project. I understand why he wrote it that way, but I also worry that the tone makes his strongest arguments easier to dismiss. It is the kind of post people will screenshot and use as evidence that Zig is hostile, even though the most important parts have very little to do with defending Zig as a language.
Kelley pushes back on the idea that Bun had to choose between style guides in Zig and compiler-enforced ownership in Rust. His argument is that the missing ingredient was sustained engineering effort: review the code, fix the bugs, pay down the technical debt, fuzz the dangerous parts and give stability the time it requires. He also questions how much of the reported performance and binary-size improvement belongs to Rust, since the rewrite happened alongside new linker settings, ICU work, cleanup and a massive burst of attention. He says LTO was already available in Zig, disputes Bun’s account of its previous fuzzing efforts and asks why the rewrite announcement omitted build-time comparisons.
Some of those claims rely on private conversations and a long, broken relationship, so they should be read as Kelley’s account rather than neutral fact. His central technical question, however, is very difficult to avoid: if Bun’s test suite was not sufficient to catch the stability problems in the Zig codebase, why should the same test suite be considered sufficient evidence for roughly a million lines of Rust that were not reviewed line by line by humans?
He is right. A green copy of the old test suite cannot certify a rewrite of this size.
But that is not the whole answer, because a test suite and Rust’s compiler verify different things.
A test asks whether the program produced the expected behavior for a case somebody thought to encode. Even a suite with more than a million assertions is still a finite collection of remembered situations. Many of the bugs Bun describes required a particularly unfortunate sequence: a re-entrant JavaScript callback, a buffer being detached during coercion, an asynchronous operation completing after an object was destroyed, an allocation failing on an unusual error path or two threads arriving in precisely the wrong order. If that path never executes under the test, the sanitizer or the fuzzer, the bug stays invisible.
Safe Rust asks a different question: can this ownership state exist at all? Ownership and
borrowing can rule out broad classes of use-after-free and double-free. Drop makes
routine cleanup across control-flow paths harder to forget, while Send and Sync prevent many data races in safe code. The compiler applies those rules throughout
safe code, including branches no test exercises. The test suite tells us that the new Bun behaves like
the old Bun where somebody thought to look. Rust can prevent certain ways of failing even where nobody
thought to look.
That is the most convincing answer to Kelley’s question. The tests did not suddenly become more complete. Rust added a second verifier. The tests act as a regression oracle for behavior, while the type system forces Bun to explain many of its ownership and lifetime assumptions in a form the compiler can reject. A style guide asks every contributor and reviewer to remember an invariant forever. Rust makes some of that good engineering mandatory on every future compilation, as long as the relevant code remains inside Rust’s safe subset.
This does not mean Rust proved Bun correct. Not even close.
Bun still embeds JavaScriptCore and several C and C++ libraries. At the time of the announcement,
about 4 percent of the Rust code sat inside unsafe blocks, representing roughly
27,000 lines and 13,000 uses of the unsafe keyword. Bun notes that 78 percent of those
blocks are a single line, usually wrapping a pointer from C++ or a call into a C library. Percentages
are not how trusted boundaries work. One unsound wrapper can invalidate assumptions made by a very large
amount of safe code.
Bun’s own article contains the perfect example. One generated implementation passed a Rust Box to libuv, which kept the raw pointer for a later asynchronous callback. Rust then
did exactly what it was instructed to do and dropped the Box at the end of the scope,
leaving the C library with an invalid pointer. The code compiled cleanly. An adversarial review
agent caught the resulting use-after-free and double-free risk. Drop can prevent us from
forgetting to release something, but across a foreign-function boundary it can also release it too early
if we described the lifetime incorrectly.
Rust cannot understand a contract we never expressed. It cannot prevent deadlocks, logical races, re-entrancy mistakes, authorization bugs, path traversal or an incorrect protocol implementation. A bounds check may turn memory corruption into a panic, which is safer, but a remotely triggered panic can still become a denial-of-service problem. Rust does not prove that a program is correct. It simply refuses a surprisingly large category of ways it can be wrong.
The rewrite itself introduced 19 known regressions, all reported as fixed before the announcement. Many came from Zig and Rust code that looked almost identical but behaved differently. That number could be astonishingly low for a port this large, or it could be the portion found so far. The word “known” is doing important work.
So yes, the Rust port probably improves the shape of Bun’s risk. It does not eliminate the dangerous surface, but it makes many unchecked operations explicit and searchable while allowing most of the Rust code to be checked under safe rules. That is meaningful. It is not the same as saying that the port is secure, semantically identical or ready to be trusted simply because CI is green.
Kelley is right in another important way: this was not a controlled experiment. The language changed, but so did the ownership model, the code organization, the compiler and linker configuration, the binary-size work, the audit intensity, the security reviews, the fuzzing infrastructure and the amount of engineering attention. Bun reports that version 1.4 fixes 128 bugs reproducible in 1.3.14, runs around 2 to 5 percent faster in its own benchmarks and is roughly 20 percent smaller on Linux and Windows after combining the rewrite with ICU and linker work. Those are encouraging results, but Rust did not cause all of them.
The fair comparison is not the Zig version as it existed against the Rust version after an enormous cleanup campaign. It would be the Zig version receiving the same focused engineering effort against the Rust version. We do not have that comparison. Some of the improvements could almost certainly have happened in Zig. Andrew’s argument is that good engineering could have fixed the Zig code. Bun’s argument is that Rust makes part of that good engineering mechanically enforceable. Both can be true.
This is also where the disagreement becomes less about programming languages and more about what people want from programming.
Kelley holds the craft of writing code to an extremely high standard. Zig’s ban on LLM-assisted contributions is largely about scarce review attention and long-term accountability. Open-source projects are not short on people who can generate a plausible patch anymore. They are short on maintainers who understand the patch, can defend it, will learn from the review and will still be around when it breaks six months later. Sixty-four agents multiply output. They do not multiply accountability.
Sumner’s approach is almost the opposite. He is optimizing for the end product. The models are replaceable workers inside a process; the compiler and tests are the judges; Bun’s users are the reason to do any of it. This was not a drive-by pull request submitted by somebody unable to explain it. The project’s lead designed the process, monitored it and remains responsible for what ships. That is a very different context from flooding an open-source project with generated patches and asking volunteers to sort out the consequences. The Zig policy can make complete sense, and the Bun experiment can still be worth doing.
I use both Zig and Rust professionally, for different reasons.
Zig is wonderful when the hard part is mine. It is excellent for parsers, storage engines, compact data structures, file formats, custom allocators and core products where explicit control is the point. It makes very little happen behind my back. It asks me to decide how things live and die, and then trusts me with the answer.
Zig can absolutely be used for networked systems, but its smaller and still-evolving ecosystem means that more of TLS, cancellation, backpressure, protocol behavior and connection lifetimes may become my problem. If I am willing to do that work, the control is fantastic. If I am trying to test a product idea before I know whether anybody wants it, it can be a fairly scenic route to an HTTP response.
I hate that I like Rust. It gives me much of what I want from Zig, often in the same broad performance class, while letting me remain productive. Its ecosystem lets me build networked prototypes and half-baked experiments quickly, while the compiler prevents many of my half-baked lifetime decisions from becoming production risk. Rust does not let me know that my program is correct. It lets me know that it is not wrong in several extremely annoying and expensive ways. For long-lived services, concurrency, networking and systems that touch many external libraries, that trade is difficult to ignore.
Which brings me to the uncomfortable practical conclusion: I can admire this rewrite and still decide not to trust Bun with anything important yet.
I have no evidence that the Rust port is insecure. It has a large test suite, has gone through eleven rounds of AI-assisted security review, now runs 24/7 coverage-guided fuzzing across its parsers and is already being used by Claude Code and in Prisma’s public beta. Those facts deserve to be acknowledged. They are also not the same as an independent human security audit or years of boring production use.
The process asks me to place confidence in a million-line generated translation, a substantial unsafe and C++ boundary, reviews performed largely by the same model family, and a public
experiment whose success is now part of the product narrative. That is more trust than I am currently
comfortable placing in a production toolchain. I can admire the stunt without volunteering my own systems
as its stabilization environment.
The most important result may not be that AI can write a JavaScript runtime. It may be that AI has made language choice less permanent. Historically, rewriting more than half a million lines would have frozen a team for a year and therefore would never have been approved. Bun claims it crossed the initial migration barrier in 11 days for about $165,000 at API pricing. If this approach holds up, mature unsafe codebases may be able to move toward safer foundations when a human rewrite would never be funded. That is enormous.
But the bottleneck moved. Code generation became cheap. Trust did not.
Rewriting code is not merely translating syntax. It is re-specifying everything the old tests never specified, and those gaps are often where security bugs live. The agents were effective because they had two unusually strong deterministic oracles: a compiler that refused certain invalid states and a test suite that rejected known behavioral differences. Anything the compiler, tests and subsequent reviews could not see was still something the generation loop could optimize straight past.
Andrew Kelley is right to push back against the clean marketing story that Rust arrived and fixed what Zig could not. Bun is right that Rust provides enforceable guarantees that materially change the maintenance problem. And the rewrite remains an extraordinary technical achievement even if it turns out to have been reckless.
I can be impressed by what was built, agree with the person criticizing it and still choose not to run it in production. Those positions are not contradictory. They are what happens when code can be produced much faster than confidence can.
The rewrite took 11 days. Trust still has to run in real time.
