A broker-less CRDT mesh for Quilt cells. Two devices, no server, no internet, no account β they sync.
When they come back online, they reconcile. When they go offline, they keep working. The mesh is the network.
β Try it live in your browser β two browser tabs sync cells in real time via BroadcastChannel.
use quilt_mesh::{QuiltMesh, CellEvent};
let alice = QuiltMesh::new("alice");
let bob = QuiltMesh::new("bob");
// Alice updates a cell.
alice.set("counter", 1);
alice.set("counter", 2);
// Gossip. Peer-to-peer. No server.
alice.gossip_with(&bob);
// Bob now has the latest.
let state = bob.get("counter");
assert_eq!(state, Some(2));That's the whole thing. set, gossip_with, automatic reconciliation. No broker. No central state. No single point of failure.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β quilt-mesh β
β β
β ββββββββββββ β
β β Alice β β
β β β β
β β counter: β β
β β 2 β β
β β β β
β β clock: 2 β β
β β peer: {} β β
β ββββββ¬ββββββ β
β β β
β β gossip_with β
β β (events: [(counter, 1, t=1), β
β β (counter, 2, t=2)]) β
β βΌ β
β ββββββββββββ β
β β Bob β β
β β β β
β β counter: β β
β β 2 β (after gossip) β
β β β β
β β clock: 2 β β
β β peer: β β
β β {alice:β β
β β (ctr,β β
β β 2, 2)β β
β β } β β
β ββββββββββββ β
β β
β No server. No router. No internet. Just two nodes. β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- CRDT-based state β eventually consistent, conflict-free
- Lamport clocks β total ordering across peers
- Per-peer version vectors β "I've seen what alice saw up to t=N"
- Offline-first β work locally, sync when you meet
- Broker-less β no central server, no internet required
- ~250 lines of Rust, 0 external dependencies for the core
- 3 unit tests, 0 failures β verified for the basic patterns
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β QuiltMesh β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ β
β β RoomState β β Lamport β β Peer Registry β β
β β β β β β β β
β β cells: β β clock: 5 β β { β β
β β {ctr: 2} β β tick() β β alice: v[1] β β
β β β β observe() β β bob: v[0] β β
β β β β β β } β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ β
β β β β β
β ββββββββββββββββββββΌβββββββββββββββββββββ β
β βΌ β
β ββββββββββββββββββββ β
β β CellEvent β gossip payload β
β β cid, value, t β β
β ββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Three structures, one protocol:
- RoomState β the merged state across all peers
- Lamport clock β the causal ordering
- Peer registry β what each peer has seen
The CellEvent is the gossip payload. Sent, received, applied, merged. The whole protocol.
Alice has: Bob has:
βββββββββββββββββββ βββββββββββββββββββ
β counter = 2 β β counter = 5 β
β t = 2 β β t = 1 β
β β β β
β version_vector: β β version_vector: β
β {alice: 2, β β {alice: 1, β
β bob: 0} β β bob: 1} β
βββββββββββββββββββ βββββββββββββββββββ
1. Alice sends her version_vector to Bob.
2. Bob sees he's behind on alice. He requests events.
3. Alice sends (counter, 2, t=2).
4. Bob applies: his counter was t=1, alice's is t=2, take alice's.
5. Bob updates his version_vector: {alice: 2, bob: 1}.
After: After:
Alice: counter = 2 Bob: counter = 2
{alice: 2, bob: 0} {alice: 2, bob: 1}
Bidirectional sync is symmetric: Bob also sends his events back.
| Use case | What you build |
|---|---|
| Phone β laptop sync | No server. Direct WiFi, Bluetooth, USB. |
| Team offline collaboration | "The bus broke down, but our sheets still work." |
| Family calendar | Mom's phone, dad's phone, kids' tablets. They all stay in sync. |
| IoT mesh | 50 sensors, no cloud. They gossip. |
| Censorship-resistant apps | No central server to take down. |
| Disaster response | Cell towers down, but the mesh still works via LoRa. |
git clone https://github.com/SuperInstance/quilt-mesh
cd quilt-mesh
cargo test3 tests, 0 failures. The basic patterns: two peers sync, duplicate events ignored, offline-then-sync.
pub struct QuiltMesh {
pub id: PeerId,
pub room: RoomState,
}
impl QuiltMesh {
pub fn new(id: impl Into<PeerId>) -> Self;
pub fn set(&mut self, cid: impl Into<CellId>, value: Value);
pub fn get(&self, cid: &str) -> Option<Value>;
pub fn tick(&mut self) -> LamportTime;
pub fn observe(&mut self, t: LamportTime);
pub fn gossip_with(&mut self, peer: &mut QuiltMesh);
pub fn pending_events_for(&self, peer: &QuiltMesh) -> Vec<CellEvent>;
pub fn apply(&mut self, event: CellEvent);
pub fn version_vector(&self) -> &VersionVector;
}
pub struct CellEvent {
pub cid: CellId,
pub value: Value,
pub t: LamportTime,
pub author: PeerId,
}- Multi-hop gossip β relay through intermediate peers
- Merkle DAG sync β efficient diff over millions of cells
- Authenticated gossip β sign every event with a private key
- Conflict resolution policies β LWW, max-value, custom
- Compression β gzip the gossip payload
- WebRTC transport β browser-to-browser directly, no server
- LoRa transport β for the IoT mesh case
- Quilt (TypeScript) β the canonical reactive runtime
- Quilt (Rust) β the desktop runtime
- Quilt Time β time travel (combine with mesh for "rewind to before disconnect")
- Quilt Vault β encryption (mesh + vault = encrypted peer-to-peer)
- Quilt Live β single-file browser runtime
- Quilt 5-year roadmap
MIT.