by Wes

Automerge provides fast, mergeable CRDT data structures for building local-first collaborative applications, with implementations in Rust, WebAssembly, JavaScript, and C. Supports offline editing, automatic conflict-free merging, and efficient sync protocols.
This block is the core Rust implementation of Automerge, a family of CRDTs with a compact binary format and a network sync protocol. It targets Rust developers building local-first applications who need conflict-free collaborative data structures, efficient serialization, and peer-to-peer sync without a central server. The typical buyer integrates this crate directly into a Rust backend, CLI tool, or compiles it to WebAssembly for use in a browser.
src/ - Full Rust source for the Automerge library (documents, transactions, sync, storage, patches, iterators, and more)src/automerge.rs - Core Automerge document struct and its primary read/write implementationsrc/autocommit.rs - AutoCommit wrapper that auto-commits each operation without explicit transaction managementsrc/transaction.rs / src/transaction/ - Explicit transaction API for batching multiple mutations atomicallysrc/sync.rs / src/sync/ - Bloom-filter-based sync protocol state machine for peer-to-peer replicationsrc/storage.rs / src/storage/ - Binary encoding/decoding of document state (the Automerge binary format)src/patches.rs / src/patches/ - Patch log for computing diffs between document statessrc/op_set2.rs / src/op_set2/ - Internal operation set, the core data structure tracking all CRDT opssrc/columnar/ - Columnar encoding primitives (RLE, delta, boolean, value columns)src/iter.rs / src/iter/ - Zero-copy iterators over document valuessrc/hydrate.rs / src/hydrate/ - Materializing document state into concrete Rust valuessrc/marks.rs - Rich-text mark support (bold, italic, comments, etc.)src/types.rs - Shared type definitions (ObjId, OpId, ScalarValue, Prop, etc.)src/value.rs - Value and ScalarValue enums for Automerge-typed datasrc/error.rs - Unified error typessrc/exid.rs - External object ID (ExId) used in the public APISpin up an isolated sandbox and run it server-side — no local setup.
Tetrees AI Review of this version
This Rust library / package completed archive review. Structure, dependency manifests, documentation, functional source, and common risk patterns were checked by the Tetrees verification pipeline; runtime phases are stated separately.
Deterministic AVCP artifact review
Pipeline avcp-2026-08-04.1 · SHA-256 e1a4acba9ee775fc…
This version-scoped review deterministically inspects the submitted archive for structure, dependencies, documentation, functional source, and common malicious or high-risk signals. Build and test phases are reported as passed only after an isolated sandbox audition. It is not a guarantee of perfect security.
Reviewed Aug 4, 2026
Push this product straight into your AI IDE, web builder or cloud IDE.
Connect Tetrees to a compatible AI IDE, list products you own, and request the verified ZIP without exposing seller upload controls.
No reviews yet.
Sign in to join the discussion
Loading discussion…
src/cursor.rssrc/read.rs - ReadDoc trait that every readable document implementssrc/change.rs / src/change_graph.rs - Change and causal graph structuressrc/clock.rs - Vector-clock (state vector) for causality trackingsrc/text_diff.rs / src/text_value.rs - UTF-8 text diffing and Text type supportbenches/ - Criterion benchmarks (load/save, map operations, range queries, sync)examples/ - quickstart.rs and watch.rs showing basic usage patternsfuzz/ - Libfuzzer fuzz targets for the binary format loaderCargo.toml - Crate manifest with feature flagsThis is a pure Rust crate. There are no npm packages to install. Add it to your Cargo.toml:
# No npm install needed. Add to Cargo.toml instead:
# automerge = "0.5" # check crates.io for the latest version
cargo add automerge
If you are compiling to WebAssembly (via automerge-wasm), you also need:
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli wasm-opt
No iOS pod install, Android linking, or Expo prebuild steps are required for pure Rust targets.
Clone or copy the source/ directory (which maps to rust/automerge) into your workspace, e.g. vendor/automerge.
In your workspace Cargo.toml, add a path dependency:
[dependencies]
automerge = { path = "vendor/automerge" }
Alternatively, use the published crate directly and treat source/ as a reference:
[dependencies]
automerge = "0.5"
Enable optional features as needed in Cargo.toml:
automerge = { version = "0.5", features = ["serde"] }
No environment variables or tsconfig changes are required. This is a native Rust crate with no Node.js surface until you layer automerge-wasm on top.
Run tests to verify the vendored source is intact:
cd vendor/automerge
cargo test
The file listing exposes several primary surfaces. Because no source excerpts were provided, the symbols below are derived from the canonical module names, the README, and the examples directory.
Automergeuse automerge::{Automerge, ReadDoc, ROOT};
let mut doc: Automerge = Automerge::new();
The main document type. Holds the full CRDT state including the operation set, change graph, and actor ID. Use this when you need explicit control over when changes are committed (pair with a Transaction). Load an existing document with Automerge::load(&bytes).
AutoCommituse automerge::{AutoCommit, ObjType, ReadDoc, ROOT};
let mut doc = AutoCommit::new();
let map = doc.put_object(ROOT, "config", ObjType::Map)?;
doc.put(&map, "version", 1u64)?;
A convenience wrapper around Automerge that commits after every operation. Use this when you do not need to batch multiple writes into a single atomic change. Ideal for simple CLI tools and scripts.
ReadDoc (trait)use automerge::{ReadDoc, ROOT};
// Implemented by both Automerge and AutoCommit
let val = doc.get(ROOT, "version")?;
The unified read interface. Any type that implements ReadDoc supports get, keys, values, length, text, marks, and cursor-based access. Code your read-only helpers against &impl ReadDoc so they work with both Automerge and AutoCommit.
sync::State and sync::Messageuse automerge::sync::{Message, State, SyncDoc};
let mut sync_state = State::new();
let msg: Option<Message> = doc.generate_sync_message(&mut sync_state);
The sync protocol state machine. One State instance per remote peer tracks what that peer has seen. Call generate_sync_message to produce a message to send, and receive_sync_message to apply an incoming one. No transport is prescribed; wrap messages in whatever framing your network layer uses.
A local-first settings store where two "users" independently edit and then merge.
// This is a Rust snippet — paste into src/main.rs
use automerge::{AutoCommit, ObjType, ReadDoc, ROOT};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Actor A creates a document
let mut doc_a = AutoCommit::new();
let settings = doc_a.put_object(ROOT, "settings", ObjType::Map)?;
doc_a.put(&settings, "theme", "dark")?;
doc_a.put(&settings, "fontSize", 14u64)?;
// Save and hand to actor B
let bytes = doc_a.save();
let mut doc_b = AutoCommit::load(&bytes)?;
// B makes an independent change
let settings_b = doc_b.get(ROOT, "settings")?
.and_then(|(_, id)| id.into_object())
.unwrap();
doc_b.put(&settings_b, "theme", "light")?;
// A merges B's changes
doc_a.merge(&mut doc_b)?;
// Both actors now converge — last-write-wins on "theme"
let (val, _) = doc_a.get(&settings, "theme")?.unwrap();
println!("theme = {:?}", val);
Ok(())
}
A rich-text document where one peer bolds a range and another inserts text; both changes are merged.
use automerge::{AutoCommit, ObjType, ReadDoc, ROOT, marks::Mark};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut doc = AutoCommit::new();
let text = doc.put_object(ROOT, "body", ObjType::Text)?;
doc.splice_text(&text, 0, 0, "Hello world")?;
// Bold "world" (characters 6..11)
doc.mark(
&text,
automerge::marks::MarkSet::from([(
"bold",
automerge::ScalarValue::Boolean(true),
)]),
6..11,
automerge::marks::ExpandMark::None,
)?;
let content = doc.text(&text)?;
println!("text = {}", content);
let active_marks = doc.marks(&text)?;
println!("marks = {:?}", active_marks);
Ok(())
}
Two in-process peers exchanging sync messages until quiescent.
use automerge::{AutoCommit, ObjType, ROOT};
use automerge::sync::{Message, State, SyncDoc};
fn sync_until_quiescent(a: &mut AutoCommit, b: &mut AutoCommit) {
let mut state_a = State::new(); // A's view of B
let mut state_b = State::new(); // B's view of A
loop {
let msg_from_a = a.generate_sync_message(&mut state_a);
if let Some(m) = msg_from_a {
b.receive_sync_message(&mut state_b, m).unwrap();
}
let msg_from_b = b.generate_sync_message(&mut state_b);
if let Some(m) = msg_from_b {
a.receive_sync_message(&mut state_a, m).unwrap();
}
if a.generate_sync_message(&mut state_a).is_none()
&& b.generate_sync_message(&mut state_b).is_none()
{
break;
}
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut peer_a = AutoCommit::new();
let counter = peer_a.put_object(ROOT, "counter", ObjType::Map)?;
peer_a.put(&counter, "value", 0u64)?;
let mut peer_b = AutoCommit::load(&peer_a.save())?;
peer_a.put(&counter, "value", 42u64)?;
sync_until_quiescent(&mut peer_a, &mut peer_b);
println!("peers converged");
Ok(())
}
benches/ - Criterion benchmark suite covering load/save round-trips, map write throughput, range iteration, and sync message generation. Run with cargo bench.examples/ - quickstart.rs is the canonical first-use example; watch.rs shows change observation patterns.fuzz/ - Libfuzzer harness targeting Automerge::load. Run with cargo fuzz run load.src/automerge.rs - The Automerge struct: actor ID management, applying changes, forking, merging, and saving.src/autocommit.rs - AutoCommit thin wrapper; delegates to Automerge with an implicit per-operation commit.src/transaction.rs / src/transaction/ - Transaction type for grouping multiple mutations; committed or rolled back as a unit.src/sync.rs / src/sync/ - Bloom-filter peer-state tracking and message (de)serialization for the sync protocol.src/storage.rs / src/storage/ - Automerge binary format encoder and decoder (the .automerge file format).src/op_set2.rs / src/op_set2/ - The internal operation set: indexed, columnar storage of every CRDT operation.src/columnar/ - Low-level columnar encoding (RLE, delta, boolean, key, value columns) used by storage and op set.src/patches.rs / src/patches/ - PatchLog for computing incremental diffs; used for UI binding and testing.src/iter.rs / src/iter/ - Lazy iterators over keys, values, spans, marks, and list elements.src/hydrate.rs / src/hydrate/ - Converts internal op-set state into materialized Value trees.src/marks.rs - Rich-text Mark, MarkSet, and ExpandMark types for annotating text ranges.src/types.rs - Core type aliases and structs: ObjId, OpId, Prop, Clock, ActorId.src/value.rs - Value<'_> and ScalarValue enums wrapping all Automerge-typed data.src/error.rs - AutomergeError and related error variants.src/exid.rs - ExId (external object ID): the stable, serializable handle to any object in the document.src/cursor.rs - Cursor for stable text/list positions that survive concurrent insertions.src/read.rs - ReadDoc trait definition; implemented by Automerge, AutoCommit, Transaction.src/change.rs / src/change_graph.rs - Change struct and ChangeGraph for causal dependency tracking.src/clock.rs - Clock (state vector) used to determine causal ordering between changes.src/text_diff.rs / src/text_value.rs - Myers-diff-based text diffing and the TextValue abstraction.src/autoserde.rs - Optional serde serialize/deserialize implementations for Automerge types.src/convert.rs - Conversion utilities between internal types and public-facing types.src/legacy/ - Compatibility layer for older Automerge binary formats.src/query/ - Internal query engine for looking up values, parents, and list positions in the op set.src/sequence_tree.rs - B-tree backing sequence (list/text) operations.src/indexed_cache.rs - Interning cache mapping actor IDs and strings to compact integer indices.src/change_queue.rs - Queue of out-of-order changes awaiting causal dependencies.src/validation.rs - Change validation logic applied before insertion into the op set.Cargo.toml - Crate manifest; declares features (serde, wasm), dependencies, and bench targets.README.md - Project overview, status, build instructions, and community links.rustup toolchain is stable 1.65 or later (rustup update stable).wasm32 target missing: compiling for WASM fails with "can't find crate for std"; fix with rustup target add wasm32-unknown-unknown.AutoCommit::new() documents in the same process may share the same random actor ID in some configurations; set distinct actors with AutoCommit::new().with_actor(ActorId::random()).ExId not Send across threads: ExId borrows the document's actor cache; clone the document or use Automerge::fork to work across threads rather than sharing a raw ExId.AutomergeError::InvalidChange; pin the crate version across all binaries in a system.usize range to mark() panics rather than returning an error; always validate text length with doc.length(&text_obj) before computing ranges.I have the Automerge Rust core library vendored at `vendor/automerge/` in my
project. I also have `USAGE.md` at the repo root describing its API and file
layout.
Please help me integrate Automerge into my existing Rust project step by step:
1. Read `USAGE.md` fully before generating any code.
2. Add the path dependency to my `Cargo.toml` (at `Cargo.toml` in the repo
root, NOT inside `vendor/`).
3. Create a `src/collab.rs` module that exposes:
- A `CollabDoc` struct wrapping `AutoCommit`.
- A `new()` constructor.
- A `apply_patch(key: &str, value: &str)` method that writes into a root
map and returns the updated bytes via `save()`.
- A `load(bytes: &[u8]) -> Result<CollabDoc, AutomergeError>` constructor.
4. Wire `collab::CollabDoc` into my existing `main.rs`.
5. Add a sync helper that takes two `&mut CollabDoc` and calls
`generate_sync_message` / `receive_sync_message` in a loop until
quiescent, using the `sync::State` + `SyncDoc` API shown in `USAGE.md`.
6. Use only symbols documented in `USAGE.md`; do not invent new Automerge API.
7. Add inline comments explaining the CRDT semantics at each step.
My project structure: [DESCRIBE YOUR STRUCTURE HERE]
My Rust edition: [2021 or 2018]
Automerge is released under the MIT License. See source/LICENSE if present, or the upstream repository for the full license text. This AVCP block packages the Rust core library from the automerge crate maintained by Ink & Switch. Upstream documentation is available at docs.rs/automerge.
This product’s unique contribution is clean room implementation of valuable code block into AVCP compatible standard.
The full install guide and integration prompts unlock after purchase.
PHP, Laravel & Business Scripts
Free