bunmaska build compiles your app with bun build --compile, bundles it next to the Bun runtime, and emits native distributables. There’s no Chromium to ship, so the outputs are small and the build is fast - no Xcode project, no electron-builder.
Build your app
From your project root:
bunmaska build
The entry comes from your bunmaska.config.ts (pass it explicitly - bunmaska build src/main.ts - if you prefer). By default this targets the operating system you run it on; --target macos|linux|windows cross-builds from another host (a macOS .app still needs a macOS host for codesign). A build is “your compiled code + the Bun runtime” - on macOS and Linux there is no engine to ship at all.
macOS
bunmaska build # > MyApp.app
bunmaska build --dmg # > MyApp.app + MyApp.dmg
You get:
.appbundle - with a.icnsicon converted from your PNG..dmg- the drag-to-Applications disk image.- Code signing & notarization (optional but recommended for distribution):
# Sign with your Developer ID, then notarize with Apple
APPLE_ID="[email protected]" \
TEAM_ID="XXXXXXXXXX" \
BUNMASKA_NOTARIZE_PASSWORD="app-specific-password" \
bunmaska build --sign "Developer ID Application: Your Name (TEAMID)" --notarize
A signed + notarized app passes macOS Gatekeeper without a warning. (Requires an Apple Developer account - $99/yr, one account, unlimited apps.)
Architectures
Build on the architecture you’re targeting: an Apple Silicon Mac produces arm64, an Intel Mac produces x64. To target the other arch, build on a machine (or CI runner) of that arch.
Linux
bunmaska build # > AppDir (.tar.gz) + MyApp.deb
You get:
- AppDir
.tar.gz- a relocatable directory bundle. .deb- for Debian/Ubuntu and derivatives (theararchive is assembled in pure JS - nodpkgtoolchain required to produce it).
The generated
.debdeclareslibwebkitgtk-6.0as a dependency, so a user’sapt installpulls the engine in automatically - you don’t ship it, and they don’t hunt for it. Bunmaska never bundles a browser.
Architectures
Build on the target architecture: an x64 box produces x64, an ARM64 box (including a Raspberry Pi) produces arm64. The same command, no cross-compile gymnastics.
Windows
bunmaska build --target windows compiles a self-contained .exe and packages it as a .zip (x64). Because Windows ships no system WebKit, the app needs a WinCairo WebKit2.dll - today you build that from WebKit source and embed it (--embed-engine, or point BUNMASKA_WEBKIT_PATH at a build). A hosted prebuilt engine - so you don’t have to build it yourself - is the next step. See Platform Support and the roadmap.
Auto-updates
Add --update to also emit the update feed your app’s autoUpdater consumes:
bunmaska build --update --channel stable
This writes a content-hashed <name>-<channel>-<os>-<arch>.tar.zst plus an update.json manifest alongside your build. Because there’s no 150 MB engine inside, update payloads are tiny - users download your code, not a browser. Wire it up in your app:
import { autoUpdater } from "bunmaska";
autoUpdater.setFeedURL({ url: "https://downloads.example.com" });
autoUpdater.on("update-downloaded", () => autoUpdater.quitAndInstall());
autoUpdater.checkForUpdates();
quitAndInstall’s final atomic swap-and-relaunch is still experimental in alpha - the check / download / verify / stage engine is solid.
A note on signing & trust
For a distribution users will trust on first launch:
- macOS: Developer ID signing + notarization (above).
- Linux: ship the
.debfrom a repo or a signed release; users get the engine from their package manager.