Roamium
Roamium is the Chromium browser engine binary for TermSurf. It wraps
libtermsurf_chromium (a C shared library built from the Chromium
fork) in a small Rust binary (~400 lines) that handles Unix socket IPC,
protobuf message dispatch, and process lifecycle.
How it works
The GUI (Ghostboard) spawns one Roamium
process per browser profile. Each process serves exactly one profile — one set
of cookies, storage, and cache — a hard constraint of Chromium’s
BrowserContext. The GUI passes the IPC socket, the profile’s
user-data directory, and the engine’s own listen socket on launch; Roamium
enters Chromium’s message loop, creates the profile’s context, registers with
the GUI, and then creates tabs and streams GPU layers on demand. For the wire
format and topology, see Architecture; for the
message types, see the
protocol message reference.
Architecture
Roamium follows a two-layer pattern designed to be reusable across browser engines:
libtermsurf_chromium— a C shared library that wraps Chromium’s embedding API. Exports thets_*functions below for lifecycle, profiles, tabs, navigation, input, and state. Built from the Chromium fork.Roamium — a Rust binary that links the C library, connects to the GUI socket, dispatches incoming protobuf messages to
ts_*calls, and relays Chromium callbacks back out as protobuf messages.
Source layout
| File | Purpose |
|---|---|
main.rs | Entry point, arg parsing, callback registration, Chromium message loop |
dispatch.rs | Message dispatch — routes protobuf messages to FFI calls, relays callbacks |
ipc.rs | Unix socket connection, length-prefixed protobuf framing, reader loop |
ffi.rs | FFI bindings to the libtermsurf_chromium C functions |
proto.rs | Generated protobuf types (prost) |
C API
The ts_* functions exported by
libtermsurf_chromium:
Lifecycle
| Function | Purpose |
|---|---|
ts_content_main | Enter Chromium’s message loop (blocks) |
ts_set_on_initialized | Register the initialization callback |
ts_post_task | Post a task to the UI thread |
ts_quit | Shut down Chromium |
Profiles (browser contexts)
| Function | Purpose |
|---|---|
ts_create_browser_context | Create a profile (BrowserContext) |
ts_create_incognito_browser_context | Create an ephemeral incognito profile |
ts_destroy_browser_context | Destroy a profile |
Tabs
| Function | Purpose |
|---|---|
ts_create_web_contents | Create a browser tab |
ts_create_devtools_web_contents | Create a DevTools tab |
ts_destroy_web_contents | Close a tab |
Navigation and input
| Function | Purpose |
|---|---|
ts_load_url | Navigate to a URL |
ts_forward_mouse_event | Forward a mouse click |
ts_forward_mouse_move | Forward mouse movement |
ts_forward_scroll_event | Forward a scroll |
ts_forward_key_event | Forward keyboard input |
State
| Function | Purpose |
|---|---|
ts_set_focus | Set focus state (browse vs. control) |
ts_set_color_scheme | Set dark/light mode |
ts_set_view_size | Resize the viewport |
ts_set_gui_active | Set whether the GUI is active/foreground |
Dialog and auth replies
| Function | Purpose |
|---|---|
ts_reply_javascript_dialog | Answer a JavaScript dialog (accept/cancel + prompt text) |
ts_reply_http_auth | Answer an HTTP authentication challenge (credentials) |
Callbacks
Chromium fires callbacks on the UI thread (registered with the
ts_set_on_* functions). Roamium converts each to a protobuf
message and sends it to the GUI:
| Callback | Protobuf message | Purpose |
|---|---|---|
on_tab_ready | TabReady | Tab created, tab_id assigned |
on_ca_context_id | CaContext | GPU layer ready for compositing |
on_url_changed | UrlChanged | Page navigated |
on_loading_state | LoadingState | Loading started/finished |
on_title_changed | TitleChanged | Page title updated |
on_cursor_changed | CursorChanged | Cursor type changed (pointer, text, …) |
on_target_url_changed | TargetUrlChanged | Link hover target |
on_console_message | ConsoleMessage | Console log entry from the page |
on_renderer_crashed | RendererCrashed | Renderer process crashed (recovery) |
on_http_auth_request | HttpAuthRequest | Server requested HTTP authentication |
on_javascript_dialog_request | JavaScriptDialogRequest | Page opened a JavaScript dialog |
The auth and dialog callbacks are request/reply round trips: the
*_request callback notifies the GUI and the
web TUI, which collects the
answer and replies via ts_reply_http_auth /
ts_reply_javascript_dialog.
Multi-engine pattern
Roamium is the first engine binary, but the architecture is built for several.
Each engine pairs a C shared library wrapping the engine’s embedding API (the
ts_* functions) with the reusable ~400-line Rust binary — only the
C library changes per engine. Planned engines: Surfari (WebKit), Waterwolf
(Gecko), Girlbat (Ladybird) — see the roadmap.
Installation
Homebrew installs Roamium to
/opt/homebrew/opt/termsurf-roamium/. That root holds the
roamium binary, the Chromium dylibs, .pak resources,
ICU data, V8 snapshots, and generated resources under gen/. The
GUI resolves the installed engine at
/opt/homebrew/opt/termsurf-roamium/roamium. See
Getting Started to install.
scripts/build.sh roamium —release
sudo scripts/install.sh roamium