Skip to content

Interface Boundaries

Each running Dokime instance has one runtime owner. In-process calls and native gRPC requests reach the same commands, queries, and subscriptions.

InterfaceAdapter boundary
Desktop RustDepends on dokime-app, dokime-protocol, and dokime-server. Starts an owned local runtime and native gRPC listener, or connects to a supplied native endpoint.
ReactUses generated protobuf RPC facades through the native session and generated Tauri commands for desktop-only operations.
Native gRPCdokime-server::grpc::Server attaches to a runtime handle; it owns the listener and connection I/O, never another runtime.
CLIParses arguments, calls shared runtime assembly, optionally attaches a server, reports results, and flushes before exiting.
PythonEmbeds a native runtime and can expose that same instance through an attached native gRPC listener.

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.

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.

Dokime markDokime · Stokker Technologies