Desktop apps on Bun + WebKit
Build an app before you finish your bun-maska & chai.
A drop-in Electron replacement - the same APIs, none of the Chromium. Tiny downloads, native modules that are just .ts files, and a laptop fan that finally gets a rest.
Alpha - and we'll admit it. macOS + Linux.
No logos of companies we can't name yet. Just the truth: it's open, it's built on Bun + WebKit, and it's early.
The whole thing
~16 MB. Yes, all of it.
Electron asks for 150 MB+ before it's done anything. Bunmaska is the download you won't notice and the app you can't hear running.
Same app. One bundles a whole browser; the other just doesn't.
The part worth paying attention to
A native module is just a .ts file.
It dlopens the OS and gets on
with its life. No node-gyp. No
N-API. No
electron-rebuild. No 40-minute compile that fails on the one
machine that matters.
Nothing to rebuild, because there was never anything to build.
// notify.ts - a native module. No build step. No bindings.gyp. Just Bun.
import { dlopen, FFIType } from "bun:ffi";
const { symbols: libc } = dlopen("libc.so.6", {
getpid: { args: [], returns: FFIType.i32 },
});
export const pid = () => libc.getpid();
The Electron version of this starts with npm install node-gyp and
ends with a Stack Overflow tab. We skipped to the end.
Built on WebKit, not Chromium.
Your apps render on WebKit instead of a bundled browser. No Chromium shipped - ever.
Pure bun:ffi
Zero compiled native code. Zero runtime deps. The whole framework is TypeScript calling the OS.
WebKit, not Chromium
Renders on WebKit - WKWebView on macOS, WebKitGTK on Linux. No browser engine bundled into your app.
Electron-shaped API
app, BrowserWindow, ipcMain, Menu, Tray, dialog… the names you already know. Drop-in shim included.
A real CLI
bunmaska init / dev / run / build. Scaffold, hot-reload, and package to .dmg or .deb.
macOS + Linux
Two platforms that actually work. Windows is on the list, not in the build. We'll be honest about it.
Fast cold start
No Chromium to boot, no V8 snapshot to thaw. Bun + JavaScriptCore, up before your splash screen would've loaded.
When "works on my machine" isn't enough
Pin the WebKit you actually tested.
By default you render on the system's WebKit - that's why the apps are tiny. When you'd rather ship the exact build you tested, pin it. The app resolves that engine from a shared store, downloaded once and shared by every app. Different apps can pin different versions, side by side. No global switch.
import { defineConfig } from "bunmaska/config";
export default defineConfig({
// Pin the exact WebKit you tested. Shared across apps. No global switch.
engine: { webkit: "webkitgtk-6.0-2.52.4-bunmaska1-linux-x64" },
}); This is an opt-in, Linux-first tier today: pinning, the shared store, and the engine CLI work now. Downloadable prebuilt engines and full macOS + Windows support are on the way - Windows brings its own WebKit (WinCairo, never Chromium). Most apps never need it; it's here for when byte-for-byte consistency matters.
Two platforms that work, one we're honest about.
Bunmaska ships on macOS and Linux today - x64 and ARM. Windows isn't here yet, and we're not going to pretend it is: it's not truly cross-platform until Windows actually works.
macOS
Apple Silicon (ARM64) · Intel (x64)
AppKit + WKWebView via objc_msgSend
Linux
x64 · ARM64 - incl. Raspberry Pi
GTK 4 + WebKitGTK 6 (where WebKitGTK is available)
Windows
Not yet - on the roadmap
Planned via WinCairo WebKit. We will not ship Chromium.
Want Windows? So do we - track it on the roadmap.
Developer experience
From zero to a window in about ninety seconds.
bunmaska init →
bunmaska dev → a real window. Then
bunmaska build → one executable you can hand someone. The other
steps are optional, and so is your patience.
import { app, BrowserWindow } from "bunmaska";
app.whenReady().then(() => {
const win = new BrowserWindow({ width: 960, height: 720 });
win.loadURL("https://example.com");
});
What ships is a standalone .app or
.deb - your users double-click it. They never install Bunmaska
or open a terminal. The CLI is your dev tool, not theirs.
One command
The whole loop is bunmaska.
Scaffold, develop, package, and manage engines - one CLI, pure Bun, no Xcode project and no electron-builder. It's your dev tool; it never ships inside your app.
# scaffold · develop · package
bunmaska init my-app # a full starter: main + preload + renderer + config
bunmaska dev # run it, hot-reloading on save
bunmaska build # a standalone .app / .deb your users double-click
bunmaska build --update # ...plus the auto-update feed (update.json + .tar.zst)
# pin & manage the WebKit engine - the "tested == shipped" tier
bunmaska engine list # what's installed, side by side
bunmaska engine which # the engine this project resolves
bunmaska engine install # a local dir, or a signed feed URL
# is everything wired up?
bunmaska doctor # runtime, store, and the resolved engine
Most days you live in init →
dev → build. The rest
is there the day you need it. Full reference in the CLI docs.
Same shape. A tenth of the weight.
| Electron | Bunmaska | |
|---|---|---|
| Download size | 150 MB+ | ~16-23 MB |
| Installed size | ~220 MB | ~60 MB |
| Rendering engine | Bundled Chromium (every app, again) | OS-native WebKit (not bundled) |
| Native modules | node-gyp / N-API / electron-rebuild | a .ts file that dlopens the OS |
| Compile step | Yes, and it'll fail somewhere | None |
| Runtime deps | Several | Zero |
| Runtime | Node + V8 | Bun + JavaScriptCore |
| Platforms | Win / macOS / Linux | macOS + Linux (Windows: not yet) |
| Familiar API | The original | Drop-in, ~70-80% parity |
We left a few rows where Electron still wins. We're allergic to lying in tables too.
It's alpha. We're not going to pretend otherwise.
Things will move. Some things will break. We'll tell you which ones. If it's still 2027 and this still says alpha, open an issue titled "are you OK."
Windows?
macOS and Linux today. Windows is on the list, not in the build - we'd rather ship two platforms that work than three that sort of do. Windows folks: we see you. Hang tight.
Production-ready?
It says alpha for a reason. Use it for the thing you were going to rewrite anyway.
Why no Chromium?
Because it's already on your computer, and shipping a second one is how we got here.
What's the catch?
~70-80% of Electron's surface, and we publish the parity matrix so you can check before you commit.
What's the bigger picture?
Bunmaska is the foundation. We're also building Chai on top of it - an app store and launcher for genuinely small native apps. That's a separate thing for later; the framework comes first.
Same APIs. Hold the Chromium.
Try it in a weekend. Hate it by Monday, or don't.