# Cottontail, Electrobun 2.0, and Why I Decided to Jian-Yang Anthropic

> Source: <https://blackboard.sh/blog/electrobun-2-0/>
> Published: 2026-08-22 18:55:12+00:00

Electrobun is a small, fast, batteries-included desktop app framework that I’ve been working on and off on for the past three years.

You can [read the docs](https://electrobun.dev), and since it’s open source, [visit the repo](https://github.com/blackboardsh/electrobun) and give it a star if you haven’t already.

Originally I was building an early version of Dash and got so frustrated with Electron’s size, performance, and distribution story that I decided to build something better. I’ve spent 20+ years as an engineer and engineering leader at startups and unicorns, systems I’ve architected and single-handedly built 10+ years ago still power billions of pageviews and hundreds of thousands of people’s working days. That gave me just enough hubris to think building a cross-platform desktop app framework from scratch before agents were a thing was a reasonable side quest that I could take on in addition to the other things I’m building at my lab.

After getting positive traction from people who discovered what I was building, I took some time to polish it up enough for other people to use and released Electrobun 1.x in February, that was 6 months ago and still mostly pre-agent. Wait until you see what I’ve been cooking up for Electrobun 2.0 now that we’re fully in the agentic era.

For those reading this that are new to Electrobun, the basic idea is that you should be able to build and ship a tiny, fast desktop app, with familiar technologies without accepting all the baggage that has historically come with doing that.

Back in February Electrobun 1.x gave you:

**System webviews or pinned Chromium.** You could use the system webview and keep your app tiny, or bundle a specific version of CEF when cross-platform browser consistency mattered.**Tiny differential updates.** Electrobun has a batteries-included update system built around zstd and an optimized Zig implementation of bsdiff I originally wrote by hand to learn Zig before LLMs. The tiniest possible distributable size, and[even tinier updates as small as 2KB](https://x.com/YoavCodes/status/2090075163718983977?s=20)so you can ship as often as you like.**A custom OOPIF architecture.**`<electrobun-webview>`

gives you isolated webviews that behave like super-iframes. At the time Electron was still using Chromium’s long-deprecated`<webview>`

tag and I set out to build my own. In Electrobun you can build something like a multi-tab browser where every tab is actually isolated in its own webview and composite them into the same UI, using the same API whether you’re using system webviews or CEF.**A fast end-to-end toolchain.** Dev, build, packaging, code signing, updates and distribution were part of the framework. Bring S3, R2 or basically any static file host and the Electrobun CLI handled the rest.

The launch was explosive. 10k stars in a few weeks. Electrobun is now approaching 13k GitHub stars, hundreds of apps have been built with it, and the star chart basically went vertical at launch and stayed that way for months.

I wanted to see how far I could push the architecture and prove out the renderer modularity so in March I added WGPU support, enabled by just setting bundleWGPU to true. This put a custom build of Dawn (Chrome’s WGPU implementation) in your app bundle and exposed it to TypeScript.

Electrobun could now create native GPU windows on macOS, Windows, and Linux and drive them directly from Bun. I added Three.js and Babylon adapters so you could use their APIs without putting a WebGL canvas in a browser.

More interestingly, the architecture I’d already built for `<electrobun-webview>`

turned out to work for GPU surfaces too, so I added `<electrobun-wgpu>`

. Super GPU surfaces to go with your super-iframes.

You could now take a native WGPU surface and composite it directly into a normal web UI in the same way you could composite another isolated webview into it. Your settings panel might be HTML, your editor might be HTML, and the viewport in the middle could be a native GPU surface driven directly from the main process.

People used this to build game IDEs and other applications I hadn’t anticipated. I ported DOOM to Electrobun two ways and built a little GPU digit classifier template you can try out. Some developers went further and shipped custom Zig sidecars that used Electrobun’s WGPU and native libraries directly, passing window handles around and taking over from there.

After 1.x I took a step back and went back to Dash, the app that started this whole side quest in the first place. The world had materially changed and my original idea of building a workspace that unified Code and NoCode was obsolete. More on that below.

For the last two months I’ve been building at agent speed shaping how Electrobun and Dash fit together into a new platform. Today I’m announcing the first half of that platform, the foundation, which I’m calling Electrobun 2.0.

## What’s new

Before we dive into how I got here I’ll give you a quick lay of the land.

**Hutch** is Electrobun’s new CLI. It still handles building and packaging but can now operate outside of npm, handle all the new main process technologies and toolchains like Rust, Zig, Go, and Odin, and since the JS ecosystem doesn’t have a canonical nonprofit npm client, Hutch has a lightweight npm resolver built in so you can do `hutch install`

to install your npm packages. And for times when you need more you can specify a fuller npm client like npm, Bun, pnpm, or Yarn.

**Cottontail** is a new JavaScript runtime written around JavaScriptCore and Zig. It has Node and Bun compatibility where it makes sense so most packages should just work, is competitive performance-wise and already smaller than Bun on macOS, Windows, and Linux. It exists so Electrobun can have a small JS runtime designed around applications rather than inherit the architecture and roadmap of a server runtime.

**Electrobun 2.0** moves the core of the framework into Zig so it’s faster, and lets you choose Cottontail, Bun, Zig, Rust, Go, or Odin for your main process, independently of whether your UI uses system webviews, pinned Chromium, native WGPU, or some combination of them.

**Warren** is an experimental fine-grained reactive UI framework inspired by SolidJS that makes reactivity more explicit, doesn’t require a compiler, and works both in the DOM in a webview and directly against Electrobun’s native GPU UI primitives directly in the main process.

**Dash,** built with Electrobun 2.0 is a new take on a multi-machine workspace for humans and AI to build together, it’s currently in private beta and needs its own blog post when I launch it to talk about all the moving parts. Dash is the second half of the platform.

Now a little about the journey:

## Zig Core and Electrobun 2.0

GUI applications have a core architectural constraint: the platform event loop generally needs to block the main thread.

The original version of Electrobun solved this with two processes. Bun ran your application and communicated over Unix sockets with a Zig process that owned the native event loop.

By Electrobun 1.0 Bun’s FFI had gotten good enough that I could flip the architecture upside down. Bun blocked its main thread running the native event loop while a Bun worker running in a separate thread ran your application code and FFI’d directly into the native libraries. Bun workers share an in-memory read-only copy of the runtime, so the additional thread was basically free, and I got to delete the Unix sockets and that original Zig layer while keeping the places where Zig made sense, like the custom bsdiff implementation behind Electrobun’s updater and some of the other performance-sensitive pieces.

For 2.0 I reintroduced a Zig Core, but for a different reason and in a different way.

In order to enable a first-class experience for developers that were already shipping Rust, Zig, and Go sidecars and had no use for the Bun runtime in their apps I moved the core state and native application logic out of Bun and into a new Zig core. What was left on the Bun side became a thin SDK wrapper around the same core. I then added SDKs for Rust, Zig, Go, and Odin.

You can now leverage the same Electrobun magic and core with a wide range of main process technologies and rendering layers. You can use Cottontail + TypeScript + system webviews and have something that feels like the Electrobun people already know, except smaller and purpose built.

You can use Zig + system webviews and ship an entire uncompressed Electrobun application as small as a few MB.

You can use Rust + Chromium, or Go + system webviews, or write your main process in Odin and drive WGPU windows, and build a cross-platform reactive GUI application that never starts a JavaScript runtime or opens a webview.

You can also mix these things and build advanced IDEs. A normal HTML application can have isolated child webviews and native GPU surfaces composited into it using Rust, Zig, Go, or Odin.

## Cottontail

While I was doing the main-process work I started thinking about what the default TypeScript option should actually look like. I had lots of people complaining about how big Bun was getting, suddenly over 100MB on Windows and they just kept adding things. I think they’re up to 3 SQLite clients now. While I generally agree with Bun’s batteries included philosophy, I disagree that every app should have a client for SQLite, MySQL, Postgres, and Redis, where does it end?

I’d originally planned to keep Bun as the batteries-included JS option and build a tiny experimental runtime around Zig + QuickJS for applications that didn’t need all of Bun. But Sol Ultra, Fable, and Kimi 3 let me skip a few years ahead and do it in reverse. I could start with a sort of Bun fork and work backwards to make it smaller and more composable over time. Let me explain.

Cottontail + QuickJS got surprisingly far. I had the Electrobun Kitchen Sink tests passing and Dash running on it.

It was also hilariously slow.

It was tiny at around 1MB, but experiencing it in a real application made it obvious I couldn’t ship it. The JSC JIT is one of the most incredible pieces of technology of the modern era so writing my own JIT on top of QuickJS was a much bigger side quest than I wanted. There’s not a lot of room for reinventing a better JIT, nor was that in scope for me as a single person, so I replaced QuickJS in Cottontail with JavaScriptCore.

And that made it Bun fast.

I use Dash to build both Electrobun 2.0 and Dash itself, and I couldn’t tell the difference between Dash running on Bun and Dash running on Cottontail.

Here is the current release comparison against [Bun 1.4.0](https://github.com/oven-sh/bun/releases/tag/bun-v1.4.0), released yesterday:

Cottontail is already smaller everywhere and competitive in several paths, there is still a lot of work to be done on startup, memory, and runtime performance.

At first the plan was still for Cottontail to be something small and new while letting people choose Bun for compatibility with the ecosystem.

The more I looked at the two runtimes sitting next to each other the less that made sense.

Bun already treats Node compatibility as a spec. It took Node’s APIs and tests and implemented enough compatibility that most software written for Node also runs in Bun. Deno did the same with Node, and [even Electrobun for their new Deno Desktop](https://x.com/YoavCodes/status/2064737418972889367?s=20). Open Source is a circle.

So what if Cottontail was actually Node and Bun compatible from day one, and moved toward the tiny, modular, built-for-Electrobun vision from there.

This happened at a particularly funny moment because while I was thinking about it Anthropic acquired Bun and Bun’s million-plus-line Zig implementation was rewritten in Rust using AI agents. You could now rewrite millions of lines of code in a week, and Rust Bun’s “battle-tested” clock was just reset to zero.

Which brings me to:

## Why I decided to Jian-Yang Anthropic

There has been plenty of arguing about Rust Bun, how quickly it was merged, Zig, Rust, AI-generated code, review practices, segfaults, and whether any of this is a good idea. I’m not going to reproduce the entire internet argument here. I will just say that everyone is wrong.

For Electrobun it mostly clarified a dependency problem I was already trying to solve.

I’d experimented with soft-forking Bun a few months earlier for upcoming Dash functionality. I added worker sandboxing, changed how ICU was packaged, shaved 30MB from the binary, and played with some other things that made sense for Electrobun.

The experiments worked. The problem was imagining maintaining those changes while Bun’s codebase changed at AI-lab agent speed.

And now the entire implementation had changed languages.

There wasn’t really an LTS-style Zig Bun I could pin forever either. Bugs and memory leaks in the old implementation were only being fixed in the new one, so depending on Bun meant following Bun wherever it went.

That’s perfectly reasonable for Bun.

It’s not the foundation I want for Electrobun.

So naturally I spent half a trillion dollars worth of tokens in Dash porting Rust Bun back to Zig.

Ok not really.

What I actually did was take a single, carefully chosen token, metaphorically speaking: the Node and Bun tests, mapped out a different architecture around what Electrobun needs, and used primarily ChatGPT 5.6 Sol Ultra with a bit of Fable, Qwen 3.8 Max, and Kimi 3, to push that architecture toward compatibility. By the time I had finished I achieved 100% compat with Bun and Node’s test suites, and then I began chopping.

Cottontail is a spiritual Zig fork of Bun in roughly the same sense that Bun was a spiritual fork of Node.

It isn’t Bun’s old Zig architecture. It uses JavaScriptCore, has its own APIs and internal architecture, and implements Node and Bun compatibility where that’s useful.

This path gives me room to make choices that don’t make sense for Bun.

For example Cottontail has its own streaming HTML rewriter written in Zig rather than using `lol-html`

(a Rust library) through FFI. Cottontail’s JSC fork exposes the internal methods Cottontail actually needs instead of Bun’s approach of mapping internal memory layouts and hoping they remain stable across JSC updates. On Windows and Linux I’ve been able to make JSC much smaller than even Rust Bun by being more aggressive about how ICU data is handled.

And build-time functionality doesn’t have to be there at all. Most people don’t want to run `npm install`

or `npm publish`

in their already-shipped and code-signed app.

Which brings me to Hutch.

## Hutch

One thing I’ve never particularly liked about the all-in-one runtime direction is putting package management, bundling, runtime APIs, transpilation, and everything else into the binary you eventually ship to users.

It’s convenient while developing. I don’t think that means all of it belongs in the runtime.

Electrobun 2.0 also makes the npm-centric version of this increasingly weird. If I write an Electrobun app in Rust with a small GPU UI, why should the architecture of my entire project pretend to be an npm application?

Hutch is the build-time layer that solves this. It handles the polyglot build graph, toolchains, and dependencies, the bundling and package-resolution pieces Electrobun needs without making them properties of whichever main-process runtime you happened to choose.

A Zig project can remain a Zig project.

A Rust project can remain a Rust project.

If one of those projects has a webview that imports an npm package, Hutch can deal with that too.

And because Cottontail doesn’t have to absorb all of this functionality, the thing that actually ships inside your application can stay focused on running JavaScript.

## Warren

One more thing. The world needs a good cross-platform UI layer with fine-grained reactivity. I thought about using Servo or Ladybird or something to ship my own cross-platform webview but it bothers me that there’s so much duplicate functionality in a JS runtime like Cottontail, Node, or Bun, and a webview like WebKit, Chromium, or Servo. And even when bundling a pinned version of Chromium there are still subtle differences between OSes.

I like fine-grained reactivity, but the reactive frameworks I like generally assume that eventually you’re updating a DOM.

Warren is my take on fine-grained reactivity for all the ways you can build an Electrobun UI.

It’s inspired by SolidJS, but makes the reactivity more explicit. There aren’t hidden property access getters, you don’t have to keep remembering whether the thing you’re holding is secretly an accessor, and state doesn’t need to be immutable just to make updates ergonomic. Signals and stores should feel familiar, with produce-like mutation built in.

More importantly for Electrobun, Warren doesn’t require a compiler and isn’t tied to HTML.

The same reactive system can drive DOM elements inside a webview or cross-platform UI rendered directly to an Electrobun WGPU surface from your main process. Goodbye RPC, goodbye webview, hello direct-to-GPU fine-grained reactive UIs in TypeScript.

So in Electrobun 2.0 you can ship a TypeScript app with a cross-platform UI with fine-grained reactivity and no webview in sight. Try `hutch electrobun init ui-color-picker`

to see it in action.

And you can mix and match. A Warren GPU UI that embeds OOPIF webviews and Three.js driven GPU surfaces, or a webview UI with embedded OOPIFs, embedded direct to GPU super canvases, and now also embedded fine-grained reactive UI surfaces.

This is one of the areas I’m most excited to keep pushing because there’s no particular reason a reactive application model needs to stop at the webview boundary or require RPCing into a webview at all.

## Seeing all of this

At this point there are enough combinations that a list starts sounding more complicated than the thing actually is.

So I made templates for the different ways you can build an Electrobun 2.0 app.

Since Bun left us with no LTS edition and Electrobun has only had a public release for 6 months, the best I can do for the Electrobun community was take ownership of more of the stack to prevent this happening again, and ship it as a major 2.x version bump.

I’m excited for the thousands of developers who’ve built incredible apps with Electrobun 1.x to migrate to 2.x, open GitHub issues when you run into issues so we can stabilize 2.0 in the wild as soon as possible. And I’m excited for a new group of Rust, Zig, Go, and Odin developers to join us on this journey.

## Dash

The reason I built all of this is still Dash.

Originally I set out to build a new kind of IDE that combined Code and NoCode into a single experience for your whole team.

Then your team expanded to include AI agents.

And more recently it expanded again to include a class of agents that can work for long periods, steer fleets of subagents, source their own proof and increasingly carry a goal through to completion.

From March through June I was embedded as a fractional researcher at a unicorn advising them on their internal agentic transformation while using the opportunity to research Dash. I wrote 18,000+ words for them covering everything from what to build internally to how humans and AI should work together, and I came away with two things that now sit at the center of what I’m building.

Agents need building blocks.

Code editor, terminal, browser, Git, remote machines and applications are capabilities that should be composable rather than separate silos. This matters for humans, but it also matters for token efficiency and for letting cheaper and faster models accomplish more with less work.

And humans and agents need GUIs.

If I want you to make *that button* blue, selecting it is much faster than writing a paragraph explaining which button I mean, where it is, what state the app has to be in before it appears, and hoping we both mean the same thing.

Dash Desktop today already has integrated Code Editor, Terminal and Web tabs. It lets you download and chat with open-weight models locally or use frontier model harnesses in terminal tabs, and it has a Git GUI that I’ve been building to replace the standalone Git clients I used before.

Dash itself is built with Electrobun 2.0, Cottontail, Hutch and Warren.

It’s smaller and faster than ever, runs on macOS, Windows and Linux, and it’s free. Launching to everyone soon.
