kuilt
kuilt stitches peers together and keeps their shared data in sync — across WebSocket, LAN, Bluetooth, and WebRTC — without changing your app code when you swap connection paths.
It is a Kotlin Multiplatform library (JVM, Android, iOS, macOS, wasmJs).
Building blocks — pick what you need
Network Fabric — one API for devices to find each other and exchange messages. kuilt calls this the network fabric (
Loom/Seam). Swap WebSocket for LAN discovery or Bluetooth without touching your app logic.Replicated Data — shared data stays in sync, even when devices edit offline or at the same time. Under the hood this uses CRDT data types such as
LWWMap,ORSet,Rga, andJsonCrdtfromkuilt-crdt. AddQuilterto propagate changes live over aSeam. For large sessions, aGossipSeamkeeps the cost flat as peers grow.Consensus — when every peer must agree on one order of decisions (turns in a game, locks, durable steps), this keeps one leader and everyone aligned. Under the hood this is
kuilt-raft.TurnSequencer(fromkuilt-game) wraps it for turn-based games.Observability — see what your app is doing on real devices, even ones that were offline. It records three kinds of note — traces (how long something took), metrics (running counts and levels), and logs (text lines) — saves them on the device first, and delivers them with no duplicates once the network returns. Under the hood this is
kuilt-otel.
Pick by the guarantee you need
Connect and send bytes → add a fabric only.
Shared state that survives offline edits and concurrent updates → add Replicated Data.
Strict turn order or globally-agreed decisions → add Consensus on top.
Observability is orthogonal to those three — turn it on whenever you want to see what your app is doing on real devices, at any guarantee level.
Start with the weakest guarantee that keeps your product correct. Add stronger guarantees only where needed.
How it fits together
Think of a quilt: a loom creates sessions, a seam is one peer's view of a live session, and a swatch is one frame of bytes. Every fabric — WebSocket, TCP, Network.framework on Apple devices, Nearby on Android, WebRTC in the browser — implements these three types. Your app code never deals with socket APIs, Bluetooth internals, or peer-connection objects directly.
Every peer in a session uses the same Seam interface — there is no client/server split at this layer. The same app code runs with two peers or twenty, and over relay or direct links.
Modules at a glance
Module | What it gives you |
|---|---|
| The contract ( |
| Replication data structures ( |
| Live replication over a |
| Raft consensus — leader election, log replication, snapshots, dynamic membership, linearizable reads, leadership transfer |
| Turn-based game facade: |
| Ktor WebSocket fabric ( |
| Offline-first telemetry: record logs, metrics, and traces on any device; they sync up when the network returns, with no duplicates |
→ All modules — the wider list, including the other fabrics (mDNS, Network.framework, Nearby, WebRTC), gossip, dealing, clustering, liveness, and sessions.
Beyond the core: the Observability page walks the whole telemetry path — record on any device, survive being offline, and deliver to your dashboard with no duplicates — and the Warp page covers an experimental way to spread work across a roomful of devices.
What kuilt is not
kuilt moves bytes between peers. It does not assign roles, manage membership lifecycles, or interpret your payload bytes. Those responsibilities belong to your app — or to kuilt-session when you need a Room with admit/leave semantics.