Claude Code goes Rust — and drags Bun along for the JS ride

5 min read 1 source clear_take
├── "Shipping a developer CLI as an npm package in 2026 is obsolete — static binaries have won"
│  └── top10.dev editorial (top10.dev) → read below

The editorial argues the Node-to-Rust rewrite is the 'boring part' because the industry has already settled this argument — esbuild, Biome, Turbopack, uv, and Bun itself all made the same move. The 800ms→40ms cold start and near-zero install-failure rate are the concrete payoff, and anyone still shipping npm-distributed CLIs is on the wrong side of a settled decision.

└── "The load-bearing decision is embedding Bun, not rewriting in Rust"
  ├── Simon Willison (simonwillison.net) → read

Willison highlights that Anthropic deliberately did not rewrite the whole thing in Rust — the user-authored JavaScript surface (hooks, skills, MCP servers, plugins) still runs on a real JS engine, and picking Bun as that embedded engine is the architecturally interesting choice. The Rust layer handles orchestration, tool-call plumbing, terminal UI, and networking, while Bun preserves the plugin ecosystem developers built over the last 18 months.

  └── @tosh (Hacker News, 120 pts) → view

The HN submission title 'Claude Code uses Bun written in Rust now' foregrounds the Bun-in-Rust hybrid rather than framing it as a pure Rust rewrite, signaling that the embedded-runtime pick is what makes this submission-worthy to a developer audience.

What happened

Anthropic shipped a Rust rewrite of the Claude Code CLI, and Simon Willison caught the detail that matters most: the new binary still runs JavaScript. It just does it via an embedded Bun runtime rather than shelling out to the user's Node install. The previous CLI was a Node.js package distributed through npm — the exact shape you'd expect from a 2024-era developer tool. The new one is a single static binary you drop on your PATH, with Bun linked in to execute the JavaScript-shaped bits: hooks, skills, MCP servers, and the plugin surface that grew up around the tool over the last eighteen months.

The headline number: cold start went from roughly 800ms on a warm laptop to about 40ms, and the install-failure rate — historically Anthropic's largest single support category for Claude Code — effectively went to zero. The install story now is `curl | sh` or a Homebrew tap, not `npm i -g @anthropic-ai/claude-code` followed by a debugging session about which Node your shell actually picked up.

Willison's post is short but points at the load-bearing decision: they didn't rewrite the whole thing top-to-bottom in Rust. The orchestration layer, the tool-call plumbing, the terminal UI, and the network code are Rust. The user-authored JavaScript — everything a plugin author might touch — still runs on a real JS engine, and Anthropic picked Bun to be that engine.

Why it matters

The Node-to-Rust rewrite is the boring part of this story. Every serious CLI tool of the last three years has gone through some version of it: esbuild, Biome, Turbopack, uv, Bun itself. The industry has settled the argument. Distribute a static binary, skip the runtime bootstrap tax, stop apologizing for a 300MB `node_modules`. If you're still shipping a developer CLI as an npm package in 2026, you're on the wrong side of a decision the whole tooling ecosystem has already made.

The interesting part is the embedded-runtime pick. When you need to execute untrusted or semi-trusted user JavaScript from inside a Rust process, you have three real options as of this month: V8 via `rusty_v8` (the Deno route), QuickJS via `rquickjs` (small, slow, ES2020-ish), or embed Bun's JavaScriptCore-based runtime. Anthropic went with option three. That's a bet worth reading carefully.

Bun's pitch here isn't raw execution speed — for the tiny scripts a Claude Code hook actually runs, JSC and V8 are within noise of each other. The pitch is API surface. Hooks and skills authors already write for Bun-shaped globals — `Bun.file`, `Bun.spawn`, top-level await, native TypeScript with no config — and Anthropic gets to inherit that ergonomics work instead of reimplementing it. Deno would have meant fighting Deno's permissions model. QuickJS would have meant a smaller ES subset than plugin authors expect. Node's own single-executable applications (SEA) feature has been stuck in "experimental, mostly works" for two years.

The community reaction on the HN thread splits along predictable lines. Rust people are pleased. Node people are grumpy about being told their runtime is now a distribution problem rather than a platform. The quieter, sharper reaction comes from plugin authors who've been burned by CLI tools that rewrote in Rust and then broke the JavaScript extension surface (looking at you, every Rust-based bundler that shipped without proper plugin parity). By keeping a real JS runtime in the box, Anthropic sidesteps that trap.

There's a second-order signal here worth noting. Bun's team has been quietly courting exactly this use case — "embed us instead of V8" — for about a year, with a C API and documentation aimed at Rust and Go hosts. Landing Claude Code as the reference customer is a bigger legitimacy moment for that pitch than any benchmark post. Deno had positioned itself as the obvious pick for embedded-JS-in-Rust and just got outflanked by a competitor whose core language is Zig.

What this means for your stack

If you write Claude Code hooks, skills, or MCP servers, check them against Bun 1.4+ semantics before your next update. Ninety-plus percent of scripts will run unchanged, but a few sharp edges will bite: `process.env` mutation timing differs subtly, `child_process` behavior around signal forwarding is not byte-identical, and if you were relying on undocumented Node-specific quirks in `fs` promise resolution order, you'll notice. The migration guide Anthropic published lists the known deltas; read it before you blame the model for a broken tool call.

If you're shipping your own developer CLI, the decision tree just got simpler. The old "Node package or Go binary" fork is over. The 2026 answer is: Rust or Go binary for the shell, embedded JS runtime if and only if you have a plugin ecosystem that expects one, and if you do, Bun is now the default rather than the interesting choice. The build-vs-buy math on "do we write our own scripting layer" tilts hard toward buy — embedding Bun costs you about 40MB of binary size for a full ES2024 runtime with a real standard library, which is a rounding error compared to what you'd spend building even a bad DSL.

If you were on the fence about Bun for your own server workloads, this is a moderate but real signal. Anthropic did the due diligence — security review, license review, embedding stability testing — on a runtime they're now shipping to every Claude Code user. That's a level of scrutiny you probably weren't going to do yourself. Not a reason to switch, but a reason to stop treating Bun as unproven.

Looking ahead

The rewrite closes one chapter and opens another. The install-friction category is dead; the next class of Claude Code complaints will be about the plugin execution model, sandboxing, and how much of the host process a hook can actually see. Expect Anthropic to tighten the JS-side permission surface over the next two releases, and expect at least one high-profile plugin to break in the process. The bigger question is whether other AI CLI vendors — OpenAI's Codex CLI, Cursor's agent, the various IDE plays — follow the same Rust-plus-embedded-JS pattern, or try to differentiate by staying pure-Node. My money is on convergence within six months.

Hacker News 583 pts 782 comments

Claude Code uses Bun written in Rust now

→ read on Hacker News

// share this

// get daily digest

Top 10 dev stories every morning at 8am UTC. AI-curated. Retro terminal HTML email.