← All projects
Distributed systems · PrivacyIn development

Soki

双記 — "twin record"

Peer-to-peer encrypted notes. Two or more devices, one shared record, and nothing in between that is able to read it.

Platforms
Linux · macOS · Windows · Android
Accounts
None — pairing is a QR code
Started
July 2026
Server
Optional relay, zero knowledge

01Overview

Every notes app that syncs asks you to trust a server with the notes. Soki does not have one. There is no account, no login, no cloud database and no platform sign-in — devices are identified by public key and dial each other directly, hole-punching through NAT where the network allows it and falling back to a public relay where it does not. That relay forwards opaque encrypted packets; it cannot read a note and it never stores one.

The trade-off is deliberate and stated up front: both devices have to be online at the same moment to sync. That single constraint is what removes the need for server-side durability, account recovery, and an operator who could be compelled to hand anything over. Offline the app is completely usable — sync is an enhancement, never a dependency.

Merging is conflict-free rather than last-write-wins. Each note is a CRDT document, so a paragraph edited on a laptop on a train and on a phone in a kitchen keeps both edits, merged character by character, without either device having seen the other. Deletions travel as tombstones carrying generation counters, so a stale copy that resurfaces months after its tombstone expired is re-deleted instead of resurrecting the note.

What a keystroke passes through on its way to your other device
LoroDoc
CRDT note
redb
encrypted at rest
soki/1
framed streams
iroh
QUIC, hole-punched
peer
merged + verified

02Usage

Pairing is the only setup, and it happens once per pair of devices.

01

Pair two devices

One device shows a pairing ticket as a QR code, the other scans it with its camera — or you paste the string, if the camera is not to hand. Both sides derive the same 32-byte storage key from that exchange. First pairing wins: a later pairing never silently re-keys a store it would make unreadable.

02

Write, offline or not

Notes are a title and a body with attachments. Everything is written to the local encrypted database first and is fully usable with no network at all. Whether a peer happens to be reachable changes nothing about the app you are using.

03

Sync happens on its own

Each paired device holds one persistent channel to each other device. An edit pushes immediately; heartbeats every 25 seconds keep the channel honest, and a dead one reconnects with backoff. A periodic sweep catches any peer that was offline when the edit happened.

04

Attachments arrive when asked for

The note carries only a reference — name, type, size and hash. The bytes live in a content-addressed store and are fetched from the peer on demand, verified against their hash before anything is written, and refused if they do not match.

05

Read the status bar

It tells you what is actually happening: your endpoint id, each peer’s channel state, whether the current connection is direct or relayed, when the last sync ran, and whether storage is encrypted — including, on Android, whether the hardware keystore is doing the wrapping.

03Technologies

iroh
Rust · transport

QUIC between devices addressed by public key. Discovery runs over the Mainline DHT via pkarr and over n0’s DNS; connections hole-punch directly where NAT permits and fall back to a public relay where it does not, end-to-end encrypted either way. Soki uses iroh for transport only — not iroh-docs, not iroh-blobs, not gossip — and pins the version exactly.

Loro
Rust · CRDT

Each note is a document with a text container running the Fugue algorithm, so concurrent edits merge character-wise without interleaving into nonsense, plus maps for metadata and attachment references. Updates are idempotent and order-independent, which makes re-running a sync free. Chosen over iroh-docs specifically because that is last-write-wins per key and would discard a concurrent edit wholesale.

redb + AES-256-GCM-SIV
Rust · storage

An embedded key-value store holding note snapshots, tombstones, permanent generation records, the device secret key and content-addressed attachment blobs. Every value is encrypted under a key derived at pairing with HKDF-SHA256 — held in the OS keyring on desktop, wrapped by a hardware-backed Android Keystore key over JNI on mobile — and the fallback path on either platform is loud but never fatal.

soki/1
Rust · sync protocol

A small custom protocol over raw QUIC bi-streams: a one-byte kind tag, then length-prefixed frames. Kind 0 exchanges manifests, kind 1 syncs one note by version vector, kind 2 is a long-lived channel that pushes edits the instant they happen, and kind 3 fetches attachment blobs on demand, verified against their BLAKE3 hash before anything is written. Decoders are strict: malformed input from a peer returns an error, never a panic.

Live sync + watchdog
Rust · resilience

One persistent channel per paired device, with the dial side chosen deterministically so exactly one forms per pair. Repeated reconnect failures escalate — first nudging iroh’s network-change detection, then rebinding the endpoint from scratch under the same identity — which is the fix for an endpoint that wedges silently after an overnight suspend.

Tauri v2
Rust + vanilla JS · application shell

One core crate and one shell across four platforms; desktop and Android build from the same source. The frontend is hand-written HTML, CSS and JavaScript — no framework, no bundler, no build step — talking to Rust through invoke.

Soki is pre-release. Its own landing page and signed downloads for each platform will be linked here when the first build ships.