Real-time sync for plaintext files
opbox is an
experimental daemon that
syncs a directory of plain text files between machines in
real time.
It works at the filesystem level (meaning everyone can keep
their own editor) and merges concurrent edits with CRDTs
instead of conflict copies.
Syncs end-to-end encrypted through a shared log on s2.dev, or self-host it with s2-lite.
Use cases
Share an Obsidian or Logseq vault
The opbox raison d'être basically. Our CRM is just folders of markdown docs, edited in some combination of Obsidian & various plain text editors, plus local agents. And git is too slow for this!
Pair on a repo (between commits)
You can keep using git at meaningful checkpoints,
but use opbox to sync edits in between. opbox
supports a .opboxignore file, and seeds
it from .gitignore when already
present.
Design
Inherently local-first
The files on disk are the core data. The opbox
daemon just listens for edits, and maintains shadow
CRDT
documents.
If you go offline, the daemon
can re-sync later when it's able to exchange CRDT
ops with the shared log again.
Text files only
Files with non-UTF-8 bytes are ignored, as there's
not a reasonable way to convert edits on arbitrary
binary docs into CRDT ops.
If you need
to sync images, PDFs, or etc., keep using git or
another tool for those in combination with opbox.
Editor agnostic-ish
opbox works at the filesystem level, meaning you can
edit your text files with any editor you like.
Generally speaking, opbox works best with editors
that are configured to autosave frequently.
Tested via simulation
Deterministic simulation tests drive complicated multi-daemon scenarios, and assert on CRDT invariants (i.e. that ops exhibit idempotency, commutativity, associativity), and that workspaces converge on a single materialization.
Walkthrough
How it works
-
Init or clone an existing opbox workspace into a
directory, and start the sync daemon.
(cd my-sync-dir && ob init && ob start) - When running, the opbox daemon listens for native file events within the workspace.
- When a text file is saved, the daemon diffs it against a shadow CRDT copy and encodes the change as a new CRDT operation, using yrs, the Rust port of Yjs.
- The op is encrypted with the workspace key, then appended to a durable, shared log on S2.
- Every other daemon syncing with the workspace reads the op, updates its CRDT documents, and materializes the new state on disk.
machine A S2 log machine B
───────── ────── ─────────
editor ┌────────────┐ editor
│ │ op · · · │ ↑
│ save │ op · · · │ │
↓ │ op · · · │ daemon
daemon ── append ──▶│ op · · · │──▶ recv ───▶ │
│ op · · · │ ↓
└────────────┘ hello.txt
append-only, durable
opbox is built in Rust, and relies on several open source libraries for core functionality:
- S2 (serverless, or self-hosted) stores the shared append-only log. Daemons append CRDT ops and read ops produced by other daemons.
- Turso (SQLite-compatible) manages local semantic state, including shadow CRDT documents and namespace metadata.
- yrs/Yjs provides the CRDT data structures and update format.
- turmoil powers deterministic simulation tests for multi-daemon sync scenarios.
CRDT ops in real-time
A file is created, edited in vim, and deleted while
ob spy (a debug tool) tails the shared log
directly from the opbox daemon.
FAQ
How is this different from Syncthing or Dropbox?
Those sync files as opaque blobs. When two machines change the same file at once, one version wins and the other becomes a conflict copy. The trick of opbox is to sync CRDT diffs, and model every document transparently in terms of these, meaning files can merge automatically and deterministically when edited concurrently.
How is this different from Google Docs or Live Share?
These own the editor, so they are able to directly interact with a sync scheme. opbox lets you access the magic of multi-player editors but on files that live on your device.
Why not P2P?
Using a shared log greatly simplifies sync. Each daemon just needs to be able to append to and read from a stream. As soon as an append is acknowledged by the log, the daemon can move on knowing the change is fully durable. This is easier than P2P setups, where daemons would need to own consensus themselves.
The log is S2, which can be used in its serverless offering, or you can run s2-lite yourself.
Can the log service read my files?
No. Workspace content in opbox is end-to-end encrypted. When a workspace is created, a cipher is randomly generated, and stored locally within the database. This cipher must be provided out-of-band (in addition to an S2 access-token) to any other participant you want to share an opbox workspace with.
What happens when two people edit the same file at once?
Both edits survive. Text is modeled as a Yjs CRDT document, so concurrent edits merge at character granularity, kinda like a collaborative editor.
What if two people create the same filename concurrently?
In this case, we do have to conflict. One
creator deterministically wins the path, and the
other file is materialized under a conflict name
like
notes/a (Conflict x7f2).txt. Every
daemon converges on the same result.
What about binary files?
Ignored for sync, for now. Bytes that are not UTF-8 text cannot be meaningfully modeled as a text CRDT. But opbox plays well with git, which can be used for sharing such files.
Can I sync an existing git repo?
Yes. Run ob init at the root of
your checkout; teammates run
ob clone --clobber inside their own
checkouts of the same repo. Identical files are
left untouched, files that differ are
overwritten with workspace content (commit or
stash first), and files only they have are
shared into the workspace on the next
ob start.
Does it work offline?
Yes. If the daemon is running, edits are still captured into an outbox in the local database, allowing CRDT documents to be modeled in the same granularity as when online. Changes that occur to the local files while the daemon is totally stopped won't break anything either, they just will be represented as single diffs the next time opbox does resume and discovers the change.
Which editors work best?
I'm mostly using Obsidian and Zed (with autosave at 100ms) with it without issue.
Two settings end up mattering a lot: your edits only sync once they hit disk, so autosave on a short interval makes collaboration feel live; and your editor should auto-reload files that change on disk.
How safe is my data?
Please don't rely on it as your sole backup of anything! This is very much alpha software.
That said, we've invested in a deterministic simulation testing setup to gain confidence in the sync and materialization logic in opbox.
How do I invite someone to a workspace?
ob init prints a clone command you
can send to collaborators, and
ob share new mints more. Share
tokens are scoped to that one workspace — not
your account — and can be listed and revoked
with ob share. The clone command
also carries the workspace
cipher (encryption key), so only
send it to people who should be able to read the
files.
What does it cost?
opbox itself is MIT-licensed and totally free. The only service dependency is S2, which can be used in its serverless offering, or you can run it yourself. S2 is typically very inexpensive for an opbox workload. On the order of single digit cents per month per user for a workspace. (And S2 gives you $10 worth of welcome credits).
One important caveat: the free tier on S2 caps stream retention at 28 days; a default payment method is required to create streams with infinite retention, which you will likely want to do for any non-demo workloads so as not to break cloning.