Main Process API
Electrobun exposes the same native core to six main-process runtimes:
Cottontail (the default), Bun, Zig, Rust, Go, and Odin. The TypeScript SDK
(electrobun/main) serves Cottontail and Bun; each native language has its
own SDK that loads ElectrobunCore directly. Pick your runtime once — code
snippets across these docs follow your selection.
Cottontail and Bun share the TypeScript SDK today, but they are separate
runtime choices (build.mainProcess: "cottontail" vs "bun") and will
diverge over time — treat the tabs as distinct even where the code currently
matches. See Main Process Runtimes
for choosing, and the per-runtime
Hello World walkthroughs for complete
setup.
Your first window
Section titled “Your first window”// src/bun/index.ts — Cottontail executes TypeScript directly.import { BrowserWindow, ApplicationMenu, Utils } from "electrobun/main";
const win = new BrowserWindow({ title: "My app", url: "views://mainview/index.html",});
ApplicationMenu.setApplicationMenu([ { label: "File", submenu: [{ role: "quit" }] },]);
Utils.showNotification({ title: "Application started" });void win;// src/bun/index.ts — same TypeScript SDK, running on the actual Bun runtime.import { BrowserWindow, ApplicationMenu, Utils } from "electrobun/main";
const win = new BrowserWindow({ title: "My app", url: "views://mainview/index.html",});
ApplicationMenu.setApplicationMenu([ { label: "File", submenu: [{ role: "quit" }] },]);
Utils.showNotification({ title: "Application started" });void win;// src/zig/main.zig — the core is a dynamic library; windows are created// from a worker thread while runMainThread blocks. Full setup in the// Zig hello world.const electrobun = @import("electrobun");
// ...inside the UI thread, after configureWebviewRuntimeFromExecutableDir:const window_id = try core.createWindow(.{ .title = "My app", .frame = .{ .x = 160, .y = 100, .width = 800, .height = 600 },});
_ = try core.createWebview(.{ .window_id = window_id, .url = "views://mainview/index.html", .frame = .{ .x = 0, .y = 0, .width = 800, .height = 600 }, .callbacks = .{ .decide_navigation = electrobun.allowAllNavigation },});// src/main.rs — the project Cargo.toml points `electrobun` at the Rust crate// projected under .hutch/devkit. Full setup is in the Rust hello world.use electrobun::{Core, Rect, WebviewOptions, WindowOptions};
// ...inside the UI thread, after configure_webview_runtime_from_executable_dir:let window_options = WindowOptions::new("My app", Rect::new(160.0, 100.0, 800.0, 600.0));let window_id = core.create_window(window_options)?;
let webview_options = WebviewOptions::new( window_id, "views://mainview/index.html", Rect::new(0.0, 0.0, 800.0, 600.0),);core.create_webview(webview_options)?;// src/go/main.go — import "electrobun" through the project go.mod replacement// to .hutch/devkit/go-sdk. Windows are created from a goroutine while// RunMainThread blocks. Full setup in the Go hello world.import "electrobun"
// ...inside the UI goroutine, after ConfigureWebviewRuntimeFromExecutableDir:windowOptions := electrobun.NewWindowOptions( "My app", electrobun.NewRect(160, 100, 800, 600),)windowID, err := core.CreateWindow(windowOptions)
webviewOptions := electrobun.NewWebviewOptions( windowID, "views://mainview/index.html", electrobun.NewRect(0, 0, 800, 600),)_, err = core.CreateWebview(webviewOptions)// src/odin/main.odin — windows are created from a worker thread while// runMainThread blocks. Full setup in the Odin hello world.import electrobun "electrobun_sdk:electrobun"
// ...inside the UI thread, after configureWebviewRuntimeFromExecutableDir:window_options := electrobun.defaultWindowOptions("My app")window_options.frame = {x = 160, y = 100, width = 800, height = 600}window_id, _ := electrobun.createWindow(core, window_options)
webview_options := electrobun.defaultWebviewOptions(window_id)webview_options.url = "views://mainview/index.html"webview_options.frame = {x = 0, y = 0, width = 800, height = 600}electrobun.createWebview(core, webview_options)The TypeScript SDK (Cottontail and Bun)
Section titled “The TypeScript SDK (Cottontail and Bun)”Named imports are recommended:
import { BrowserWindow, ApplicationMenu, Utils } from "electrobun/main";A default namespace export is also available (import Electrobun from "electrobun/main"). The package root, electrobun, currently resolves to
the same main-process SDK; use electrobun/view inside browser bundles. The
former electrobun/bun namespace remains a deprecated alias for
electrobun/main so imports can migrate incrementally.
Cottontail standard-library APIs
Section titled “Cottontail standard-library APIs”The Electrobun SDK and Cottontail’s standard library are separate surfaces.
For Cottontail apps, Hutch scans the bundled main process and includes optional
standard-library capabilities used by the SDK, your code, and bundled
dependencies. Computed imports or namespace access may need an explicit,
additive build.cottontail.capabilities entry in electrobun.config.ts.
See Cottontail’s modular standard library
for examples and detection limits.
Runtime coverage
Section titled “Runtime coverage”The TypeScript SDK has the broadest high-level surface. The native SDKs mirror the core contract procedurally (ids + callbacks instead of classes). What exists where:
| API area | Cottontail | Bun | Zig | Rust | Go | Odin |
|---|---|---|---|---|---|---|
| Windows & webviews | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| WGPU views (native GPU surfaces) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Application & context menus | ✓ typed | ✓ typed | JSON | JSON | JSON | JSON |
| Tray (create/show/title) | ✓ + events | ✓ + events | ✓ ¹ | ✓ ¹ | ✓ + clicks | ✓ ¹ |
| Dialogs, message box, notifications | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Clipboard, displays, shell open/reveal/trash | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Sessions & cookies | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Global shortcuts | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Paths | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Typed RPC (createRPC) |
✓ | ✓ | raw bridge ² | raw bridge ² | raw bridge ² | raw bridge ² |
| Updater | ✓ | ✓ | — | — | — | — |
Warren UI (main/ui) |
✓ | ✓ | — | — | — | — |
| three.js / Babylon WebGPU adapters | ✓ | ✓ | — | — | — | — |
¹ Zig, Rust, and Odin create and manage tray items, but their wrappers do
not yet surface tray click events; Go’s TrayOptions.Handler does receive
them. Tray menus remain TypeScript-only everywhere.
² Native SDKs exchange raw JSON messages with Electroview in the webview
(the request/response envelope is implemented by hand; the templates show
the full pattern). The webview-side SDK is identical for every runtime.
Pages for TypeScript-only features say so at the top; everything else shows a tab per supported runtime.