Loro: a CRDT library for JSON, with version control built in
Make your JSON data collaborative and version-controlled with CRDTs
At a glance
- What is it?
- Loro is a Rust CRDT library with JS and Swift bindings that makes JSON documents collaborative and versioned. It ships rich text, moveable trees and lists, time travel and shallow snapshots, but the sync transport is still yours to build.
- Who is it for?
- Adopt Loro if you are building a local-first editor, a whiteboard, or any app where users edit the same JSON document offline and expect automatic merging, and you are willing to write your own transport layer. Do not adopt it if you want a hosted backend or a drop-in replacement for a CRDT you already run in production; the README documents no server, no auth and no storage layer.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem Loro solves, and who ends up using it
Most applications store shared state in a central database and resolve conflicts by rejecting writes. That model breaks when the network is slow, when two people edit the same paragraph, or when a user wants to undo something from an hour ago. Loro is a CRDT library: each client keeps a full copy of the document, edits it locally, and exchanges binary updates with peers. The merge is automatic, so no server has to decide who wins.
The README states the target plainly: building local-first and collaborative apps. The repository ships bindings for Rust, JS via WASM, and Swift. If you are writing a text editor, a whiteboard, a project tracker, or a note-taking tool where the document is JSON-shaped and users expect offline editing, Loro is aimed at you. If your data is a stream of events or a relational schema with foreign keys, a CRDT is the wrong abstraction and Loro will not help.
Inside the oplog: how Loro merges concurrent edits
A Loro document is a container tree. You get a list, a map, a text field, or a tree by name, and each container holds operations. The README example uses `docA.getList("list")` and then `listA.insert(0, "A")`. Those operations go into an oplog, and `docA.export({ mode: "update" })` returns a `Uint8Array` you can send over any channel. The receiving peer calls `docB.import(bytes)`.
Incremental sync is the part worth understanding. After importing, the example reads `docB.oplogVersion()` and later exports with `docB.export({ mode: "update", from: version })`. That `from` argument means only operations after the recorded version are serialised, so a long-lived session does not resend the whole history on every round trip.
Underneath, the README credits specific algorithms. Text editing uses Fugue, from Matthew Weidner's work. The project adapted the Event Graph Walker from Diamond-types to cut computation and space, and it took columnar encoding ideas from Automerge. It also lists a moveable tree, a moveable list, and a last-write-wins map. Those are the containers you actually program against.
One design point the README highlights but does not fully explain is `ensureMergeable*` / `ensure_mergeable_*`, described as mergeable map-key children for lazy child container creation. The idea is that a map key can hold a container that two peers create independently, and the containers still merge. The README gives the API name and nothing about failure cases, so treat that as a gap to test rather than a guarantee.
Installing Loro and syncing two documents
Loro is distributed as a Rust crate and as an npm package. The README points to the getting-started page at loro.dev/docs/tutorial/get_started and to docs.rs for the Rust API. The npm package name that appears in the README example is `loro-crdt`.
For a JS or TypeScript project, install the package and import the two classes the example uses:
npm install loro-crdtThen create two documents, edit one, and import its update into the other. This mirrors the README test:
import { LoroDoc } from "loro-crdt";
const docA = new LoroDoc();
const listA = docA.getList("list");
listA.insert(0, "A");
listA.insert(1, "B");
const bytes = docA.export({ mode: "update" });
const docB = new LoroDoc();
docB.import(bytes);
console.log(docB.toJSON()); // { list: ["A", "B"] }After the import, `docB.toJSON()` should show the same list. If it does not, the export or the import call is the place to look first, not the container code.
For a Rust project, add the crate and build the workspace as the repository does:
cargo add loro
cargo buildTo inspect a document's state and history without writing your own viewer, the README names the Loro Inspector at inspector.loro.dev. It is a browser tool, and the README shows it being used on a document rather than describing a CLI.
The sync layer is yours to write
Loro exports bytes and imports bytes. It does not tell you how those bytes travel. The README lists P2P synchronization as a CRDT-provided feature, but the repository contains no server component, no WebSocket endpoint, no authentication, and no persistence backend. There is no port number to configure because there is no service.
That is the sharpest limitation. If you expected to run a Loro collaboration server the way you might run a Yjs provider, you will be writing it. You need a relay or a peer discovery mechanism, a way to persist snapshots, and a policy for who is allowed to write. None of that is in the README.
The second limitation is version skew. The repository publishes `loro-crdt` and `loro.js` as separate npm packages, and the recent releases show different version numbers for each. The `release-wasm` script in package.json runs a version sync step before building, which suggests the project treats the two as coupled even though they version independently. If you depend on both, pin them together and check the lockfile.
The third is the size of the surface. Moveable trees, rich text, shallow snapshots and time travel are each documented on their own pages, and the README links out rather than explaining them. A team adopting Loro for a simple list will find the API small. A team adopting it for a rich text editor with undo across a tree will be reading the blog posts.
Loro compared with Automerge and Yjs
The README itself names Automerge and Yjs as influences, so the comparison is fair. Automerge is a CRDT library with a JSON document model, and Loro credits it for columnar encoding, which is how both projects compress operation history. The difference is in the container set. Loro ships a moveable tree and a moveable list as first-class containers, and documents a rich text CRDT and a shallow snapshot mode that the README compares to a Git shallow clone. If your data is a nested outline or a file tree that users reorder, that container set is the reason to pick Loro over a plain map-and-list CRDT.
Yjs is the older, more widely deployed option for collaborative text, and Loro's README says it incorporated a similar algorithm for merging operations. Yjs has a larger ecosystem of editor bindings and providers. Loro's advantage, as the README frames it, is version control alongside real-time collaboration: time travel through history and shallow snapshots that let you load a document without the full operation log. If you need to show a user the state of the document at a past timestamp, that is a Loro feature, not a Yjs one.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-09-21. Releases are frequent: `[email protected]` and `[email protected]` both landed on 2026-09-21, with `[email protected]` earlier the same day. The changeset directory and the release scripts in package.json indicate a structured release process rather than ad-hoc tagging.
The licence is MIT. That is permissive: you can use Loro in closed-source products, and you carry no copyleft obligation. It also means there is no patent grant clause and no warranty, which is standard for MIT and worth knowing if your legal team asks. Nothing here is legal advice.
The upgrade cost is concentrated in the WASM boundary. The `release-wasm` script runs a version sync step, and the changelog lives in a changeset directory rather than in the README. If you pin `loro-crdt` and later bump it, read the changeset entries for the version range rather than assuming the wire format is stable across minor releases. The repository does not document a compatibility policy for the binary update format.
Editorial conclusion
Adopt Loro if you are building a local-first editor, a whiteboard, or any app where users edit the same JSON document offline and expect automatic merging, and you are willing to write your own transport layer. Do not adopt it if you want a hosted backend or a drop-in replacement for a CRDT you already run in production; the README documents no server, no auth and no storage layer. Before committing, verify two things yourself: that the Fugue text algorithm and the moveable tree behave correctly under your own conflict patterns, and that the loro-crdt version you pin matches the loro.js version in the same lockfile, since the repository maintains them as separate packages.
Frequently asked questions
What is Loro?
Loro is a CRDT library that makes JSON data collaborative and version-controlled, usable from Rust, JS via WASM, and Swift. It provides automatic merging, P2P synchronization and delta updates so clients can edit offline and reconcile later.
How do I install Loro in a JavaScript project?
The README example imports from the `loro-crdt` package, so you install it with npm and then import `LoroDoc` and the container classes you need. For Rust, the crate is published on crates.io and documented at docs.rs/loro.
How does Loro differ from Yjs?
The README credits Yjs for a similar merge algorithm and lists it as an influence. Loro's own emphasis is version control alongside real-time collaboration, including time travel through history and shallow snapshots that work like a Git shallow clone.
Does Loro include a server?
No. Loro exports updates as bytes and imports them on the other side, but the README describes no server component, authentication, or persistence layer. You choose the transport and storage.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/loro-dev-loro)