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());
}
Application callbacks
The runtime delivers events to one KoboApp. Rebuild the screen after state changes. Do not block callbacks or retain renderer objects.
| Callback | When it runs |
|---|---|
on_start | The application session starts. Draw the first screen and request initial data. |
on_action | A named button, row, tile, key, navigation item or Back action was activated. |
on_text_hold | A selectable rich-text word was held, with stable text coordinates. |
on_task | An asynchronous fetch, post, file read or sleep completed, failed or was cancelled. |
on_device_result | A device, radio, audio, dictionary, update or app-catalog request answered. |
on_store | Private key-value or shelf storage answered. |
on_shell_event | The runtime-owned terminal opened, produced bytes, closed or was refused. |
on_cover_change | The hall sensor's settled magnet state changed while the app was foregrounded. |
on_background / on_foreground | The reader left for another app and later returned. Work continues while backgrounded. |
on_suspend / on_resume | The device session suspends and resumes. |
on_scheduled_wake | A capability-gated background wake is delivered. |
on_exit | The 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
| Surface | Developer API | Purpose |
|---|---|---|
| Display | set_screen, put_picture, put_font | Publish a screen and bounded picture or book-font resources; release them with drop_picture and drop_font. |
| Async work | spawn, spawn_retrying, cancel | HTTPS fetch/post, app-private file reads and sleeps without blocking the event loop. |
| Small state | store().save/load/cache/load_cached/forget/list | Atomic app-private keyed state and evictable cache values. |
| Large state | shelf(), ShelfUpload, ShelfDownload | App-private books, audio, covers and other large blobs transferred in bounded chunks. |
| Application handoff | launch | Ask the runtime to open an installed catalog application by stable ID. |
| App catalog | applications() | List installed apps, read or refresh the signed catalog, install/update and uninstall. Identity-authorized for launcher and Store apps. |
| Power and schedule | device().hold_wifi/release_wifi/keep_awake/allow_sleep/schedule_wake/cancel_wake | Request bounded power-policy exceptions and scheduled refreshes. |
| Device readings | read_battery, read_battery_detail, read_cover, read_frontlight | Read typed hardware state; every request receives one result or refusal. |
| Wi-Fi and Bluetooth | read/set/scan/join/connect/disconnect/forget | Capability-gated radio control through firmware-owned services. |
| Audio | load/play/pause/seek/stop/set_audio_volume, AudioPlayer | Play app-shelf audio or bounded unauthenticated HTTPS streams through the active output. |
| Dictionary | lookup_word | Use runtime-installed dictionaries offline, with an optional language tag. |
| Terminal | shell(), TerminalKeys | Send bytes to a runtime-owned terminal and receive output events; apps never choose a program path. |
| Platform update | device().update | Settings-only replacement from an HTTPS release archive with an exact SHA-256 digest. |
| Diagnostics | log, build_checked, AppRunner | Structured 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.
| Capability | Current SDK surface |
|---|---|
network | Foreground Task::Fetch and Task::Post. |
background-network | Network tasks during a scheduled background wake; requires scheduled-wake. |
hold-wifi | Bounded Wi-Fi association hold; requires network. |
keep-awake | Bounded foreground suspend prevention. |
scheduled-wake | Schedule and cancel a runtime-coalesced wake. |
battery-read | Battery summary and detailed optional gauge readings. |
frontlight-control | Read and set front-light percentage. |
wifi-control | Power, scan, join and disconnect Wi-Fi. |
bluetooth-control | Power, scan, pair, connect, disconnect and forget Bluetooth devices. |
audio | Load and control playback. |
bluetooth-audio | Bluetooth audio output; requires audio. |
cover-sensor | Initial hall-sensor read and foreground change events. |
shell | Runtime-owned terminal. Reserved to the Terminal application by current platform policy. |
sleep-screen | Reserved manifest vocabulary; no public kobo-sdk application call yet. |
notifications | Reserved manifest vocabulary; no public kobo-sdk application call yet. |
shared-files | Reserved 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.
| Crate | Use it when | Reference app |
|---|---|---|
kobo-sdk | Every app: lifecycle, UI, tasks, storage and runtime services. | All examples and apps |
kobo-ui | You 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-image | Decode bounded JPEG/PNG bytes, fit/crop them and dither to panel greys before put_picture. | Gallery, readers |
kobo-json | Parse untrusted JSON or build request objects without Serde. | Brief, Chat, RSS |
kobo-html | Turn untrusted HTML fragments into bounded text, or rasterise mathematical formulae with its optional feature. | Hacker News, RSS, arXiv |
kobo-xml | Scan bounded XML/Atom/RSS input without external entities or recursive allocation. | RSS, arXiv |
kobo-opds | Read OPDS 1.2 Atom and OPDS 2.0 JSON catalogues into one model. | Store/catalog clients |
kobo-doc | Sniff and parse EPUB, HTML, Markdown or plain-text bytes into structured document blocks. | arXiv, book readers |
kobo-read | Paginate a structured document and manage stable locations, contents, search and annotations. | arXiv |
kobo-bookview | You need an end-to-end reading surface with deferred image loading and stable repagination. | arXiv |
kobo-term | Turn VT100 output bytes into rows and a cursor for ScreenBuilder::terminal. | Terminal |
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
| Command | Purpose |
|---|---|
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 PATH | Drive 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. |
version | Print the CLI version. |
Work with a developer device
| Command | Purpose |
|---|---|
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 IP | Stop 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 IP | Block 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
| Command | Purpose |
|---|---|
secret set/list/remove | Install, name or remove runtime-held application credentials without printing their values. |
trust set/list/remove | Manage owner TLS roots for private HTTPS services. |
app-key --seed PATH | Print 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 PATH | List 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. |
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.