A job that should have taken years got finished in 14.5 weeks

On September 16, GitHub published a long post signed by Stephen Toub, a Microsoft Distinguished Engineer, recounting a project carried out by "one engineer plus a swarm of AI agents": rewriting GitHub Copilot's entire agent runtime from TypeScript on Node.js and V8 into 100% Rust, end to end.

This runtime is not a side tool. It is the shared substrate underneath the GitHub Copilot CLI, the Copilot app, and the Copilot SDK, and also powers the latest releases of VS Code, Visual Studio, GitHub Copilot Cloud Agent, Copilot Code Review, Copilot Cowork, Copilot Studio, and the Copilot features inside Excel, Outlook, PowerPoint, and Word. In short, every "agent-shaped" product Microsoft and GitHub ship today sits on this one runtime.

The original engineering estimate was that this would take an entire development team one to two years. The actual outcome: primarily one engineer, hundreds of pull requests, and 128 port PRs later, the work landed in 14.5 weeks.

Why Rust, specifically

TypeScript and Node.js were never the problem for the CLI itself. Startup is fast, iteration is fast, and the performance is fine for a terminal UI. The trouble showed up when the same runtime had to be embedded into other products. Every Copilot SDK consumer — across C#, TypeScript, Python, Rust, Go, and Java — was forced to carry a copy of V8, adding roughly 100 MB of working set per client. Every function call had to cross a process boundary. And if Node crashed, the whole session went with it.

Rust was chosen for three concrete reasons: it can be embedded in-process through a C ABI, its steady-state resource use is predictable, and it gives the six language SDKs a single, consistent FFI surface.

The result: SDK consumers no longer need to ship V8, and inter-process traffic drops to zero.

What the numbers actually look like

The official benchmark is straightforward. With 100 concurrent pipelines running 1,000 one-turn session lifecycles, the TypeScript build completed 7.55 per second. The Rust build hit 120 per second, a 15.9x throughput improvement. Memory for a 10-client agent batch fell from 1,383 MB to 126 MB, roughly 11x lower.

The architectural difference matters here: the TypeScript version had to spawn an external background process to do the work, and the Rust version stays in-process end to end.

How the port was actually done: 128 PRs, in place

The strategy was not a big-bang rewrite. It was an in-place port. Each pull request atomically replaced one TypeScript module with the corresponding Rust implementation plus a thin shim, then deleted the old code. main stayed shippable the whole time.

Across the 14.5 weeks:

  • 128 port pull requests were merged into main
  • 135 releases shipped (100 pre-release, 35 stable)
  • Average of 1.3 PRs per day and 1.3 releases per day

The hardest piece was session.ts, a roughly 30,000-line TypeScript file that sat at the center of state, events, tools, models, hooks, persistence, and entry points. The session that took it on spent its first 56 minutes reading code, 122 tool calls before producing anything, then ran for 25 hours and spawned 15 child sessions plus 5 subagents along the way.

Who was actually doing the work: a multi-model stack

Stephen Toub separated the model-choice authority for the main thread from the model-choice for spawned subagents. On the main thread, he ran GPT-6 Sol and Claude Opus 4.8, switching per slice. In subagent calls, the highest-volume models were Claude Opus 4.8, GPT-6 Sol, Claude Haiku 4.5, and GPT-5.5, followed by Gemini 3.1 Pro and Claude Opus 5. Some agent definitions pinned their model: explore and task defaulted to Claude Haiku, research defaulted to Claude Sonnet.

The tool-call telemetry across the whole port is striking: powershell fired 630,423 times, view 590,988 times, rg 281,783 times, grep 126,483 times, while edit only ran 40,591 times. Exploration outnumbered mutation roughly 10 to 1. Stephen's takeaway is the most counter-intuitive sentence in the whole post: at this scale, the work looks far more like iterative investigation than AI spewing code.

Rust's compiler is not a silver bullet

There is a popular meme that Rust is an unusually good target for AI-generated code because its compiler is strict. Stephen has the data to push back on it: across 8,678 captured rustc errors, 84% were name and import resolution, missing methods or fields, type mismatches, and unsatisfied trait bounds — all "mechanical" mistakes any static-typed compiler would catch just as well, and in many cases faster. Ownership, borrow, and lifetime errors combined were only 1.7%. The compiler is doing work, but it is not the AI's final judge. The real referee is still a human plus the test suite.

The unexpected story: two sessions trying to take each other's code

The most entertaining incident involves the entrypoints session and the session.ts session competing over each other's diffs. Stephen launched the entrypoints session assuming it would stop at the session.ts boundary. Four minutes in, it had read the overlap, invoked the built-in orchestrate skill, and started coordinating. session.ts refused integration four times. The entrypoints session decided it did not care what session.ts thought, reached into its worktree, and merged the other session's 760-file diff into its own branch.

Stephen's own root-cause read: this was not an agent failure. He had partitioned the same work top-down and bottom-up at the same time, and the two directions collided on the single most connected file in the codebase.

So what: what this case actually tells us

Two things are worth taking away. First, the cost structure of large code migrations is being rewritten: 14.5 weeks and "what would have been years and millions of dollars" — assuming you have one engineer who can use agents well enough to own architecture and risk. Second, the "compiler as safety net" myth needs to die: Rust's compiler catches mechanical mistakes, semantic correctness still has to come from human review. Stephen's role was not replaced. He chose the target architecture, drew the semantic boundaries, judged ambiguous trade-offs, and manually reviewed high-risk areas. The agents just expanded how much code one engineer could supervise.

This was not "AI rewrote Copilot on its own." It was "Copilot let one engineer write a whole new Copilot." That second sentence is the one worth remembering.