Interface Boundaries
Each running Dokime instance has one runtime owner. In-process calls and native gRPC requests reach the same commands, queries, and subscriptions.
| Interface | Adapter boundary |
|---|---|
| Desktop Rust | Depends on dokime-app, dokime-protocol, and dokime-server. Starts an owned local runtime and native gRPC listener, or connects to a supplied native endpoint. |
| React | Uses generated protobuf RPC facades through the native session and generated Tauri commands for desktop-only operations. |
| Native gRPC | dokime-server::grpc::Server attaches to a runtime handle; it owns the listener and connection I/O, never another runtime. |
| CLI | Parses arguments, calls shared runtime assembly, optionally attaches a server, reports results, and flushes before exiting. |
| Python | Embeds a native runtime and can expose that same instance through an attached native gRPC listener. |
Ownership and shutdown
Section titled “Ownership and shutdown”dokime-api owns the contracts every party compiles; dokime is the plugin SDK
kit layered on them and re-exports each one under its original path;
dokime-app owns the folded state those contracts are committed into, and the
transactions that change it. dokime-app::app owns the entry verbs
that stand the application up, and dokime-app::config owns the settings
they take, the trusted builtins they seed, and brand resolution.
Hosts choose their configuration and install the process’s tracing
subscriber; the application crates only emit. The CLI is a
peer interface; no other interface imports its implementation.
A server’s shutdown drains its connections and releases its runtime handles. The host can continue native operations after that. At final shutdown the host stops its servers, releases external handles, then awaits runtime shutdown and its durable flush. A server startup failure must also release its handles.
At startup, desktop either owns a local runtime and loopback native gRPC listener
or attaches to the endpoint supplied with --endpoint. Attachment does not
start or shut down the remote runtime. The standalone CLI defaults to a loopback
listener on port 8765; use its --host and --port flags to choose another
address. Native endpoints use an http:// URI for loopback and https:// with
TLS for remote listeners.
A different process cannot obtain an in-memory runtime handle. Scripts that control an existing desktop or headless instance use its native gRPC endpoint and generated protobuf client instead of opening its active storage directory. GUI reloads and client reconnections do not restart runtime execution.
Interface contracts
Section titled “Interface contracts”Protobuf service messages and wire types are defined in
proto/dokime/v1/. The native server implements those typed services, while the
GUI consumes generated Protobuf-ES messages and RPC facades through explicit
Tauri adapters.
The desktop shell owns a second, smaller IPC surface that never crosses gRPC:
native desktop operations, backend connections, startup status, account login,
and updates. crates/dokime-gui/src-tauri/src/bindings/mod.rs declares those
commands once; the adapters and Tauri’s invocation registry expand from that
declaration, and each wire type is defined beside the command that uses it.
Its TypeScript side is hand-written in crates/dokime-gui/src/lib/desktop/,
one module per Rust module, with commands.ts mirroring the declaration list.
Nothing generates either side, so a change to one is a change to the other in
the same commit.
The protobuf definitions are the canonical schema. The gRPC reference documents the generated services and workflows.
Run mise run bindings:generate after changing the protobuf schema. Committed
bindings make changes reviewable; mise run bindings:check compares generated
output without rewriting source and is part of mise run check. Generation
runs without opening a window, booting a runtime, or accessing devices. It is an
explicit build-workflow step, not a side effect of build.rs or app startup.
Both tasks run one step, node tools/node/gui/generate-rpc.mjs [--check], which exports the canonical protobuf descriptor and writes the
generated native RPC facades — no runtime, server, storage, Tauri, native
resources, or application compilation. dokime-app::config owns the shared
paths and preferences, saved through the existing durable filesystem
implementation in native hosts.
A generated standalone report carries its payload as serde JSON embedded in the
HTML rather than as protobuf. crates/dokime-gui/src/report/document-contracts.ts
is the hand-maintained TypeScript shape of that payload and mirrors
dokime::document and dokime_app::report::materialization; change it in the
same commit as the Rust types it mirrors.
WatchRuntime is a latest-state invalidation stream, not event replay. Records,
telemetry, and artifacts retain their native persistence semantics; receiving a
stream frame is not a durable flush acknowledgment.