Cobalt

Cobalt SDK

A declarative Rust API for E Ink UI, asynchronous work, private storage and capability-gated device services.

Applications manage state. The runtime handles layout, refresh planning, hardware access, network credentials and process isolation.

Create an application

Install the CLI, create an application and start the browser simulator:

cargo install --path crates/kobo-cli
kobo new my-app
cd my-app
kobo dev

Implement KoboApp, render the current state and handle named actions:

use kobo_sdk::{action_id, ActionId, Context, KoboApp, ScreenBuilder};

#[derive(Default)]
struct Counter { taps: u32 }

impl KoboApp for Counter {
    fn on_start(&mut self, context: &mut Context) {
        self.show(context);
    }

    fn on_action(&mut self, context: &mut Context, action: ActionId) {
        if action == action_id("tap") {
            self.taps += 1;
        }
        self.show(context);
    }
}

impl Counter {
    fn show(&self, context: &mut Context) {
        context.set_screen(
            ScreenBuilder::new("counter")
                .top_bar("Counter")
                .heading(format!("{} taps", self.taps))
                .primary_button("tap", "Tap")
                .build(),
        );
    }
}

fn main() {
    let _ = kobo_sdk::run("counter", Counter::default());
}
Hardware support. Cobalt has been tested on the Kobo Clara BW N365, device code 391. Other Kobo models can be supported after hardware testing and review of their device profile.

Application callbacks

The runtime delivers events to one KoboApp. Rebuild the screen after state changes. Do not block callbacks or retain renderer objects.

CallbackWhen it runs
on_startThe application session starts. Draw the first screen and request initial data.
on_actionA named button, row, tile, key, navigation item or Back action was activated.
on_text_holdA selectable rich-text word was held, with stable text coordinates.
on_taskAn asynchronous fetch, post, file read or sleep completed, failed or was cancelled.
on_device_resultA device, radio, audio, dictionary, update or app-catalog request answered.
on_storePrivate key-value or shelf storage answered.
on_shell_eventThe runtime-owned terminal opened, produced bytes, closed or was refused.
on_cover_changeThe hall sensor's settled magnet state changed while the app was foregrounded.
on_background / on_foregroundThe reader left for another app and later returned. Work continues while backgrounded.
on_suspend / on_resumeThe device session suspends and resumes.
on_scheduled_wakeA capability-gated background wake is delivered.
on_exitThe application session is ending.

Callbacks have a 250 ms deadline. Hand slow work to Context::spawn and render an activity or skeleton state while it runs.

UI components

ScreenBuilder provides 94 component and configuration methods. The renderer handles physical size, wrapping, grayscale tone, touch geometry and refresh strategy.

Text and documents

heading, hierarchical headings, plain and linked text, styled and selectable rich text, inline formulae, metadata, sections, facts, quotes, bylines, tables and pictures.

Actions and input

Primary, secondary and disabled buttons, fields with clear actions, chips, choices, steppers, text entry and terminal keyboards.

Collections and media

Rows, checklists, trailing values, row menus, paged lists, tiles, app tiles, picture tiles, configurable tile grids, boards and glyph controls.

Navigation and overlays

Top bars, tabs, destination bars, action bars, pinned bottom actions, page turns, reading menus, holds, popovers, overflow menus and modal sheets.

Feedback and states

Banners, progress, activity, cancellation, byte transfers, skeletons, splash screens, confirmations and standard empty, offline, denied and error states.

Adaptive layout

Semantic spacing, dividers, bottom fill and two- or three-slot bands. Bands stack automatically on narrow panels.

Runtime services

SurfaceDeveloper APIPurpose
Displayset_screen, put_picture, put_fontPublish a screen and bounded picture or book-font resources; release them with drop_picture and drop_font.
Async workspawn, spawn_retrying, cancelHTTPS fetch/post, app-private file reads and sleeps without blocking the event loop.
Small statestore().save/load/cache/load_cached/forget/listAtomic app-private keyed state and evictable cache values.
Large stateshelf(), ShelfUpload, ShelfDownloadApp-private books, audio, covers and other large blobs transferred in bounded chunks.
Application handofflaunchAsk the runtime to open an installed catalog application by stable ID.
App catalogapplications()List installed apps, read or refresh the signed catalog, install/update and uninstall. Identity-authorized for launcher and Store apps.
Power and scheduledevice().hold_wifi/release_wifi/keep_awake/allow_sleep/schedule_wake/cancel_wakeRequest bounded power-policy exceptions and scheduled refreshes.
Device readingsread_battery, read_battery_detail, read_cover, read_frontlightRead typed hardware state; every request receives one result or refusal.
Wi-Fi and Bluetoothread/set/scan/join/connect/disconnect/forgetCapability-gated radio control through firmware-owned services.
Audioload/play/pause/seek/stop/set_audio_volume, AudioPlayerPlay app-shelf audio or bounded unauthenticated HTTPS streams through the active output.
Dictionarylookup_wordUse runtime-installed dictionaries offline, with an optional language tag.
Terminalshell(), TerminalKeysSend bytes to a runtime-owned terminal and receive output events; apps never choose a program path.
Platform updatedevice().updateSettings-only replacement from an HTTPS release archive with an exact SHA-256 digest.
Diagnosticslog, build_checked, AppRunnerStructured runtime logs, screen validation and host-side deterministic app tests.

Capabilities

Capabilities use exact manifest names. Device results distinguish undeclared, battery-withheld and unsupported operations.

CapabilityCurrent SDK surface
networkForeground Task::Fetch and Task::Post.
background-networkNetwork tasks during a scheduled background wake; requires scheduled-wake.
hold-wifiBounded Wi-Fi association hold; requires network.
keep-awakeBounded foreground suspend prevention.
scheduled-wakeSchedule and cancel a runtime-coalesced wake.
battery-readBattery summary and detailed optional gauge readings.
frontlight-controlRead and set front-light percentage.
wifi-controlPower, scan, join and disconnect Wi-Fi.
bluetooth-controlPower, scan, pair, connect, disconnect and forget Bluetooth devices.
audioLoad and control playback.
bluetooth-audioBluetooth audio output; requires audio.
cover-sensorInitial hall-sensor read and foreground change events.
shellRuntime-owned terminal. Reserved to the Terminal application by current platform policy.
sleep-screenReserved manifest vocabulary; no public kobo-sdk application call yet.
notificationsReserved manifest vocabulary; no public kobo-sdk application call yet.
shared-filesReserved manifest vocabulary; no public kobo-sdk application call yet. Context::shelf is private, not user-visible.

App launching, catalog management and platform updates are authorized by caller identity rather than by public manifest capabilities.

Application-facing crates

Use kobo-sdk for the application API. Add companion crates for specific data formats and reading surfaces.

CrateUse it whenReference app
kobo-sdkEvery app: lifecycle, UI, tasks, storage and runtime services.All examples and apps
kobo-uiYou need advanced public UI types, pagination helpers or renderer-level layout assertions. Most component types are re-exported by kobo-sdk.Gallery, Sudoku tests
kobo-imageDecode bounded JPEG/PNG bytes, fit/crop them and dither to panel greys before put_picture.Gallery, readers
kobo-jsonParse untrusted JSON or build request objects without Serde.Brief, Chat, RSS
kobo-htmlTurn untrusted HTML fragments into bounded text, or rasterise mathematical formulae with its optional feature.Hacker News, RSS, arXiv
kobo-xmlScan bounded XML/Atom/RSS input without external entities or recursive allocation.RSS, arXiv
kobo-opdsRead OPDS 1.2 Atom and OPDS 2.0 JSON catalogues into one model.Store/catalog clients
kobo-docSniff and parse EPUB, HTML, Markdown or plain-text bytes into structured document blocks.arXiv, book readers
kobo-readPaginate a structured document and manage stable locations, contents, search and annotations.arXiv
kobo-bookviewYou need an end-to-end reading surface with deferred image loading and stable repagination.arXiv
kobo-termTurn VT100 output bytes into rows and a cursor for ScreenBuilder::terminal.Terminal
Internal crates. kobo-protocol, kobo-policy, kobo-net, kobo-text, kobo-hal, kobo-shell, kobod and the install tools implement the runtime. Applications should use SDK re-exports instead.

CLI commands

The CLI creates and tests applications, manages developer devices, and builds Store artifacts. Commands accepting --device also accept -s.

Build and exercise applications

CommandPurpose
new <name>Create a Rust SDK application. Aliases: init, create.
dev [--builtin] [address]Run the current SDK app in the browser simulator. Aliases: sim, simulator.
run --sim [--app NAME]Run the SDK transport, daemon and one application together on the host.
drive --script PATHDrive a running simulator with taps, typing, expectations, scenarios and PNG screenshots.
shot [--device HOST]Save a PNG of the simulated or real panel. Device capture is read-only.
build [--device]Build the host workspace or the ARM safe doctor, disabled runtime and sample app.
package [--out PATH] [--folder PATH]Build the KoboRoot.tgz an owner installs over USB.
inspect <package>List a package and verify that no entry can write outside Cobalt's install folder.
verify <arm-binary>Verify static ARMv7 hard-float binary format.
versionPrint the CLI version.

Work with a developer device

CommandPurpose
setup [--volume PATH] [--undo] [--enable-ssh] [--no-key]Prepare or undo a reader over USB. Root SSH is an explicit development opt-in.
deploy --device IP [--package PATH]Install over Wi-Fi without rebooting. Alias: install.
devices [--subnet A.B.C]Find readers on the local network and report hardware, firmware and Cobalt versions.
doctor [--device IP]Run read-only host or device diagnostics.
present <app> --device IP [--seconds N]Run one installed application on the real panel for a bounded presentation.
stop --device IPStop the Cobalt session and hand the panel back to the stock reader.
session --device IP [--hold [minutes]]Keep a development device reachable, awake and associated with Wi-Fi.
wait --device IPBlock until a device answers again. Alias: wait-for-device.
logs --device IP [--follow] [--lines N]Read or follow the runtime trace. Alias: logcat.
shell --device IP [command ...]Run one developer command on the reader, or open an interactive SSH session.
record --device IP [--seconds N] [--fps F] [--out DIR]Capture a read-only sequence of panel frames.
touch-probe --device IP [--seconds N]Watch touch input read-only to verify the hardware profile's coordinate transform.
guard-test --device IP --confirm ...Attended proof that the session guardian restores the previous screen.

Credentials, trust and Store releases

CommandPurpose
secret set/list/removeInstall, name or remove runtime-held application credentials without printing their values.
trust set/list/removeManage owner TLS roots for private HTTPS services.
app-key --seed PATHPrint the Ed25519 public key for a Store release seed.
app-bundle ...Build one signed, pathless .cobalt-app package.
app-catalog ...Build and sign the public application catalog.
app-list --registry PATHList validated Store registry entries as JSON.
app-check --registry PATH ...Build and verify registered Store applications.
app-release --registry PATH ...Build and sign the complete registered application release.
Device-write feature. Build kobo-cli with --features device-write to enable tap --device IP X,Y [MS:X,Y ...] and smoke-display --device IP --confirm .... These commands write to the device input or display.

Testing and shipping

# Browser simulator from an app directory
kobo dev

# Host runtime
cargo run -p kobo-cli -- run --sim --app my-app

# Drive taps, typing, expectations and screenshots
cargo run -p kobo-cli -- drive --script tour.kobo --shots target/shots

# Targeted application tests
cargo test -p kobo-my-app

# Package a device build
cargo run -p kobo-cli -- package

The simulator uses the production layout, renderer, hit testing and refresh planner. Failure scenarios cover offline, timeout, low battery, denied capability, missing credentials, storage pressure and image-cache pressure.

Platform constraints

Callback duration

Callbacks must return quickly. Network, files, sleeps and device operations use asynchronous requests.

Brokered access

Applications do not open sockets, device nodes, shared paths or processes. Runtime requests return a result or refusal.

Bounded data

Rows, cells, choices, pictures, tasks, keys and wire strings have explicit limits. Diagnostics report truncation and overflow.

Pagination

Long prose, rows and tiles are measured into pages. The SDK does not provide continuous scrolling.

Credentials

Requests name runtime-held credentials. Values do not enter application memory or follow redirects.

Hardware profiles

Device support requires an exact profile. Unknown models are refused.