Architecture
The decisions that span every part of Kiki. They're what make it different from bolting an agent onto a conventional system.
Platform: Fedora bootc
The OS isn't a package-managed distro — it's an OCI image built with Podman and published to a registry. Updates apply with bootc switch <ref>: atomic, with automatic rollback, no half-applied states. Underneath, bootc uses OSTree with implicit A/B partitions.
Content-addressed everything
OSTree isn't just for the base image — it's the versioning and distribution substrate for the whole system:
So an app update is a pull plus a symlink swap; a rollback is pointing a ref at the previous commit; moving an agent between machines is a push and a pull of only the delta. Shared components are deduplicated by hash.
Remote-first, desktop first-class
The cloud backend is infrastructure, not an add-on. A device with no backend works standalone, but the design assumes connectivity as the normal case. Clients — the mobile app, the dashboard, even other agents — connect to a device through the edge.
Real-time sync: Durable Objects + CRDT
A live session's state syncs in real time between the device and any connected client through a Durable Object per session. A Durable Object is stateful at the edge — it holds the session's CRDT, accepts WebSockets from many clients, and relays bidirectionally. A CRDT converges without central coordination even when a client briefly drops offline. This is what makes remote control (not just observation) possible.
On-device IPC
On the device, subsystems talk over typed channels rather than one bus:
| Channel | Transport | Carries |
|---|---|---|
| Tool calls | JSON-RPC 2.0 over a Unix socket | Agent tool invocations |
| Accessibility tree | FlatBuffers over a Unix socket | The live UI state the agent reads |
| Sensor data | Shared memory + notify socket | High-frequency signals |
| Linux ecosystem | DBus | MPRIS, portals, notifications |
Universal components & schemas
A type in any app's public surface must have a published schema — like ATProtocol Lexicons. Define a type once; every app references it, and the OS generates bindings at install. UI components work the same way and are deduplicated across apps.
Next: The agent loop.