A leading product engineering company, creating adaptive software solutions to improve operations, providing businesses with expert development services from across domain.
A leading product engineering company, creating adaptive software solutions to improve operations, providing businesses with expert development services from across domain.
GitHub ported Copilot to Rust in 128 PRs; Bun ported 535,496 lines of Zig in 11 days. What each AI code migration teaches about rewriting legacy code.

Two of the largest AI code migration projects yet were published within weeks of each other, and they took opposite routes. GitHub moved its Copilot agent runtime from TypeScript to Rust in 128 pull requests over about fourteen and a half weeks, shipping all the while. Bun moved its entire Zig codebase to Rust in eleven days and merged it in one go. Both worked. The choice between their approaches — not the choice of model — is the decision anyone planning an agent-assisted rewrite of a legacy system actually faces.
One caveat before the numbers: GitHub sells Copilot and Bun is owned by Anthropic, whose Claude did the work. Both write-ups are detailed and candid, but each is also a showcase for the vendor's own agents. Read them as evidence of what is possible with unusual resources, not as a quote for your project.
In GitHub's account, Stephen Toub describes a runtime that was originally TypeScript on Node.js. It powers the Copilot CLI and the Copilot SDK, which ships in six languages. Embedding it meant launching Node and V8 as a subprocess. GitHub wanted a library that could be called through a C ABI, with low startup cost and predictable resource use, and chose Rust for those reasons. Toub is explicit that this is not a claim that every large TypeScript program should become Rust.
By 21 August the runtime was entirely Rust: 832,378 lines of production code and 468,689 lines of Rust unit tests, alongside 174,675 lines of end-to-end TypeScript tests. Roughly 430,000 lines of production TypeScript passed through the port. During the same window the main branch shipped 135 releases, 35 of them stable, at about 1.3 releases a day.
The mechanism that made this possible was a temporary seam. Every time a function moved to Rust, the remaining TypeScript still had to call it, and Rust sometimes had to call back into TypeScript. GitHub bridged the two with N-API bindings generated by the napi-rs project. That seam peaked on 3 August at 2,019 internal exports and 3,356 TypeScript call sites. At completion it was zero and zero: the scaffolding existed only to let the port proceed one slice at a time.
This is the strangler fig pattern applied at the function level. The team did not port "components" so much as waves of behaviour: pure logic first, then state ownership, then orchestration, then removal of fallbacks, then simplification once the interop was gone. Each pull request was small enough for a person to review, and each release exposed a small amount of new Rust to real users. Toub notes that regressions were found and fixed quickly for exactly that reason — "faster is not always better".
The most useful number in the post may be this one: across file reading, search and diagnostics versus editing, the agents did ten times as much exploration as mutation. An agent porting code spends most of its effort establishing what the old code actually does.
Toub is equally precise about his own role. He chose the destination architecture, decided which behaviour mattered, partitioned the work, resolved ambiguous trade-offs, reviewed high-risk areas by hand and made every merge decision. Tests and static analysis checked what could be checked mechanically; human review concentrated on architecture, API contracts and risk. In one merge loop an agent deleted a function exposed to the SDK, saw the schema-compatibility check fail, and applied the repository's "break is OK" label to make it pass. A person caught it.
Two further details are worth borrowing. The runtime contains 158 unsafe blocks, concentrated at genuine boundaries — the C ABI, operating-system calls, SQLite — and none of the known regressions involved one. And about 60 npm dependencies were removed because only ported code had used them, which is a reminder that a typescript to rust migration is also a dependency migration.
Bun's post by Jarred Sumner starts from the conventional view: rewrites are a terrible idea. Excluding comments, Bun was 535,496 lines of Zig. By hand, Sumner estimates, three engineers with full context would have needed about a year, during which the product would have stood still.
Instead he ran the port in eleven days, from 3 May, using Claude Code's dynamic workflows. The pattern was fixed: one implementer, at least two adversarial reviewers whose only job was to find reasons the code did not work, and one fixer to apply their findings. The implementer never reviewed; the reviewers never implemented. At peak, four workflows ran in separate worktrees with sixteen Claude instances each — about 64 at once.
Preparation mattered as much as parallelism. Before translating all 1,448 Zig files, Sumner had agents write a porting guide and trace the lifetime of every struct field, then piloted the process on three files. Splitting the codebase into roughly 100 crates exposed about 16,000 compiler errors. When agents began stubbing out functions to make things compile, he changed the reviewers' rules rather than fixing the code by hand.
The merged diff was +1,009,272 lines across 6,502 commits, excluding merges. Bun's test suite — language-independent, with about a million assertions — passed on every platform in CI, with no tests skipped or deleted, before Sumner pressed merge. The token bill was around $165,000 at API prices. After further linker work the binary is about 20% smaller on Linux and Windows.
Not everyone was persuaded. The Register reported that Zig's creator called the result "unreviewed slop". Sumner's own figures give the critique something to hold: about 4% of Bun's Rust sits inside unsafe blocks, because the port deliberately reads like transpiled Zig and idiomatic Rust is planned for later. Every line was reviewed — by other instances of the same model. Whether that counts as review is a fair argument, and it is the argument your own team will have.
The two projects look like a contest between speed and caution. They are better read as two answers to one question: what tells you the new code is right?
That gives a practical rule for a legacy code rewrite with AI. A big-bang port is only viable when you already have tests strong enough to serve as the specification, run against the old and new systems alike. Most legacy business systems do not. Their behaviour lives in the code, in stored procedures and in the heads of the people who use them. For those, an incremental migration behind an interop seam — or an API boundary, or a message queue — is the safer default, because it lets production tell you what the tests missed.
If your suite is thin, the first milestone of any AI-assisted rewrite should be characterization tests that pin down what the current system does, including the behaviour nobody would design on purpose.
The $165,000 token bill is striking but misleading as a benchmark. It bought eleven days of work by one of the few engineers who knew the codebase end to end, using a pre-release model, on a project whose test suite already existed. GitHub did not publish a token cost; its post does note that prompt caching can cut input costs by an order of magnitude, which is the difference between a viable and an absurd bill on long sessions.
For planning purposes the larger costs are the ones neither post can show you: writing the tests you do not have, deciding which behaviours matter, and reviewing output. Toub's session logs record roughly 2,600 human interventions over the port. That is the budget line to plan for. Agents change how much code one engineer can supervise; they do not remove the supervision. We have argued the same about where the bottleneck moves when coding gets faster.
Drawing on both projects, a sensible sequence for a client weighing an agent-assisted modernisation looks like this:
None of this is specific to Rust. Toub observes that the compiler errors agents leaned on were ordinary static typing that C#, Java or Go would have caught as well. The transferable lesson is about process, which is also the argument in our guide to modernising legacy systems without breaking the business.
If you are weighing a rewrite of a system your business depends on, our legacy application modernisation team starts with that safety-net assessment before anyone writes a line of new code.
AI agents can now port very large codebases, as GitHub and Bun showed in 2026, but only with strong human supervision. Both projects relied on a person to set architecture and make merge decisions, and on tests or incremental production rollout to prove the new code behaved like the old.
An AI assisted rewrite can be fast in elapsed time. Bun ported 535,496 lines of Zig in eleven days with up to 64 agents, while GitHub took about fourteen and a half weeks for its incremental Copilot runtime port. Preparing tests and review capacity usually takes longer than the translation.
A big bang rewrite is worth considering only when an existing test suite is strong enough to act as the specification for both old and new code. Bun had a language-independent suite with about a million assertions. Most legacy business systems lack that, so an incremental migration is usually safer.
Review AI generated migration code in layers: separate adversarial reviewing agents from implementing agents, let tests and static analysis check mechanical properties, and keep human review on architecture, API contracts, risky areas and merge decisions. Watch for suppressed checks, skipped tests and stubbed functions.
Bun's rewrite to Rust used about 5.9 billion uncached input tokens and 690 million output tokens, around $165,000 at API pricing according to Jarred Sumner. That figure excludes the engineer's time and relied on an existing test suite, so it is not a general benchmark.
Ready to take the first step towards unlocking opportunities, realizing goals, and embracing innovation? We're here and eager to connect.
11th Floor, O-Hub, Chandaka Industrial Estate, Infocity, Bhubaneswar, Odisha 751024
Level 4, 11 York Street Sydney Startup Hub Sydney, NSW – 2000
30 N. Đinh Nghệ, Phước Mỹ Sơn Trà, Đà Nẵng / Da Nang City – 550000
Level 25, AIDP Business Tower, Dubai Marina, United Arab Emirates
50 Beauchamp Street, Wellington, WGN 5028, New Zealand