# Repository Guidelines
## Project Snapshot
Loro is a Rust CRDT workspace with JS/WASM packaging and a MoonBit codec.
- `crates/loro`: public Rust API; avoid breaking downstream users.
- `crates/loro-internal`: core CRDT logic. Read its
[AGENTS.md](crates/loro-internal/AGENTS.md) before changing import/export,
encoding, state, diff, checkout, or replay behavior.
- `crates/loro-wasm`: `loro-crdt` WASM/TypeScript package. Read its
[AGENTS.md](crates/loro-wasm/AGENTS.md) before changing bindings, exports,
wrappers, or build scripts.
- `crates/delta`, `crates/rle`, `crates/kv-store`, `crates/fractional_index`,
`crates/loro-common`, and `packages/fractional-index`: shared primitives and
packages.
- `moon/`: MoonBit Loro binary codec; use [skills/moonbit/SKILL.md](skills/moonbit/SKILL.md).
## Context Index
- Encoding/import/export modes, current vs outdated formats, shallow snapshots:
[context/internal-encoding.md](context/internal-encoding.md).
- Mergeable container model, marker/cid rules, tests, and common pitfalls:
[context/mergeable-containers.md](context/mergeable-containers.md).
- `import_batch` force-detach, batch-wide rollback scope, and the never-exit-detached
invariant: [context/import-batch-atomicity.md](context/import-batch-atomicity.md).
- Shallow-snapshot dead-style redaction (null-only, both-expand exclusion,
root-whitelisted latest state):
[context/shallow-snapshot-style-redaction.md](context/shallow-snapshot-style-redaction.md).
- User-facing Loro usage, sync, editor integration, and performance guidance:
[skills/loro/SKILL.md](skills/loro/SKILL.md).
- Pure TypeScript runtime indexes, complexity contracts, benchmarks, and remaining gaps:
[context/loro-js-performance.md](context/loro-js-performance.md).
- WASM panic/OOM reporting channels, `__wbindgen_start` glue invariant, and
trap-testing recipes:
[context/wasm-error-reporting.md](context/wasm-error-reporting.md).
- Context backlog: [context/CONTEXT-GAPS.md](context/CONTEXT-GAPS.md).
## Commands
- JS deps: `pnpm install --frozen-lockfile`.
- Rust build/check/format/lint: `cargo build`, `cargo check -p loro-internal`,
`cargo fmt --all`, `pnpm check`.
- Rust tests: `pnpm test`; internal doctests: `cargo test -p loro-internal --doc`.
- Loom: `pnpm test-loom`.
- WASM: `pnpm release-wasm`, or `pnpm -C crates/loro-wasm build-dev`.
- Bundlers after WASM packaging changes: `pnpm test-bundlers`; browser runtime:
`pnpm --dir examples/bundler-smoke-tests run test:browser`.
- Fractional-index TS: `pnpm test-fractional-index`.
- Fuzz smoke: `pnpm run-fuzz-corpus`.
- MoonBit codec, when `moon` is available: from `moon/`, run `moon check`,
`moon test`, `moon fmt`.
Use narrow checks first. Ask before broad fuzzing or long browser matrices.
## Working Rules
- Start with `git status --short --branch`; treat uncommitted changes as user
work unless you made them.
- Before editing, read every `AGENTS.md` from root to target directory. Keep
`CLAUDE.md` as a symlink to the nearest `AGENTS.md`.
- Use `rg` / `rg --files` for search.
- Public API changes in `loro` or `loro-crdt` should be backward-compatible when
possible. Prefer new `try_*` APIs over breaking signatures.
- Internal corruption should fail fast; invalid external input should return
`Err`. Returning wrong state is worse than panicking on an impossible internal
invariant.
- Add regression tests near behavior: `crates/loro/tests`,
`crates/loro-internal/tests`, module tests, `crates/loro-wasm/tests`, or
`moon/loro_codec/*_test.mbt`.
- Add a changeset for publishing behavior or package output changes.
- Do not hand-edit generated WASM package output; regenerate it with package
scripts.
## Self-Maintained Agent Context
- Treat "why was that hard to find?" as a context bug. Add a nearby
`AGENTS.md` pointer or a `context/` article, or append a line to
[context/CONTEXT-GAPS.md](context/CONTEXT-GAPS.md).
- Keep root context short. If an `AGENTS.md` grows past about 4000 characters, move
detail into a linked `context/` article.
- Header context articles with `Verified against code YYYY-MM-DD`, anchor claims
to files/symbols, and link them from root plus the nearest per-directory
`AGENTS.md`.
- If code changes make an `AGENTS.md` or context article stale, update the docs
in the same change.
- When a commit needs non-obvious rationale, land that rationale in the nearest
context file and keep the commit message as a pointer.
## Commit And PR Notes
History uses short imperative commits, often prefixed by `fix:`, `test:`,
`chore:`, or `refactor:`. PRs should include summary, rationale, validation, and
linked issues or traces when relevant.
# Encoding Guidelines
This module owns Loro import/export formats. Read
[../../../../context/internal-encoding.md](../../../../context/internal-encoding.md)
for the verified map of supported modes, outdated modes, shallow snapshots, JSON
schema, and validation entry points.
## Local Entry Points
- `../encoding.rs`: `ExportMode`, `EncodeMode`, 22-byte `loro` header, checksum
validation, top-level dispatch, and `decode_import_blob_meta`.
- `fast_snapshot.rs`: current `FastSnapshot` and `FastUpdates` body layouts.
- `shallow_snapshot.rs`: `ShallowSnapshot`, `StateOnly`, and `SnapshotAt`.
Shallow exports null dead rich-text style values before the state KV is
exported; read
[../../../../context/shallow-snapshot-style-redaction.md](../../../../context/shallow-snapshot-style-redaction.md)
before changing that pass or the surrounding branch structure.
- `json_schema.rs`: JSON updates, peer compression, validation, import/export,
and redaction.
- `outdated_encode_reordered.rs`: legacy-named op/value columnar helpers still
used by current fast paths; do not confuse this with unsupported top-level
outdated blob modes.
- `value.rs`, `value_register.rs`, `arena.rs`: op/value encoding support.
## Rules
- Current binary modes are `FastSnapshot = 3` and `FastUpdates = 4`.
- Top-level `OutdatedRle = 1` and `OutdatedSnapshot = 2` are compatibility
detections, not formats to extend.
- Malformed bytes or JSON schema should return `Err`, not partially import.
- Snapshot import/export must preserve rollback and attached/detached state
invariants.
- Unknown container types must block shallow/state snapshot export rather than
producing a blob that cannot be decoded correctly.
## Validation
- `cargo test -p loro-internal import_atomicity`
- `cargo test -p loro-internal decode_updates_rejects_truncated_block`
- `cargo test -p loro-internal --test mergeable_container` when snapshot changes
can affect mergeable child retention.
- Root `pnpm test` for shared import/export semantic changes.
---
name: loro
description: "Practical guide for helping app developers evaluate, adopt, and use Loro for local-first collaboration. Use when Codex needs to answer questions or write examples for `loro-crdt`, `loro`, `loro-prosemirror`, `loro-codemirror`, `loro-mirror`, language bindings such as Swift/Python/C#/Go/React Native, or Loro-powered apps about: (1) Deciding whether Loro fits a product, (2) Getting started in JavaScript/TypeScript, Rust, or another supported binding, (3) Choosing CRDT containers and document structure, (4) Designing sync, persistence, snapshots, versioning, undo, presence, or time travel, (5) Integrating rich-text editors and stable selections, (6) Mirroring app state with React, or (7) Understanding performance and tradeoffs."
---
# Loro
Use this skill to help users build applications with Loro. Start from the user's product goal, then choose the narrowest chapter that answers it. Load a second chapter only when the task crosses domains.
## Select A Chapter
- Read [references/topic-map.md](references/topic-map.md) if the task is broad and you need to route it.
- Read [references/fit-and-architecture.md](references/fit-and-architecture.md) for product fit, installation, language/package choices, first examples, and core mental models.
- Read [references/containers-and-encoding.md](references/containers-and-encoding.md) for choosing containers, shaping documents, exporting updates, snapshots, persistence, shallow snapshots, and redaction.
- Read [references/sync-versioning-and-events.md](references/sync-versioning-and-events.md) for realtime/offline sync, version vectors, frontiers, checkout, undo, presence, timestamps, events, and Inspector.
- Read [references/richtext-and-editors.md](references/richtext-and-editors.md) for `LoroText`, cursors, `applyDelta`, `updateByLine`, `loro-prosemirror`, Tiptap, and CodeMirror.
- Read [references/mirror-and-react.md](references/mirror-and-react.md) for `loro-mirror`, `$cid`, `idSelector`, validation, selectors, and React integration.
- Read [references/performance-and-tradeoffs.md](references/performance-and-tradeoffs.md) for scaling, document/update size, loading speed, and workload tradeoffs.
## Route Common Tasks
- “I am new to Loro / should I use it / show me a first example”
- Start with `fit-and-architecture.md`
- “Which language package or binding should I use?”
- Start with `fit-and-architecture.md`
- “Build a collaborative document model / choose data types / persist history”
- Start with `containers-and-encoding.md`
- Add `sync-versioning-and-events.md` if version/history behavior matters
- “Sync devices, store data, use snapshots, time travel, undo, or presence”
- Start with `sync-versioning-and-events.md`
- “Integrate ProseMirror, Tiptap, CodeMirror, or custom rich text”
- Start with `richtext-and-editors.md`
- Add `sync-versioning-and-events.md` if undo/version/event behavior matters
- “Model app state with loro-mirror or loro-mirror-react”
- Start with `mirror-and-react.md`
- Add `containers-and-encoding.md` if schema semantics depend on container choice
- “Explain performance, large documents, loading, update size, or tradeoffs”
- Start with `performance-and-tradeoffs.md`
- “Decide whether Loro is the right tool”
- Start with `fit-and-architecture.md`
- Add `performance-and-tradeoffs.md` if workload scale matters
## Execute The Task
1. Classify the task before reading everything.
2. Load one primary chapter.
3. Load at most one secondary chapter for cross-domain work.
4. Keep solutions grounded in Loro semantics:
- choose data types by merge behavior,
- distinguish state version from history version,
- keep ephemeral state out of persisted CRDT data,
- use stable cursors for collaborative selections,
- design sync around updates and snapshots rather than a central locking protocol.
## Keep Guardrails
- Do not assume CRDTs are the right fit for hard invariants, exclusivity, or authorization-at-write-time problems.
- Do not model editable text as plain strings when user intent requires merged edits.
- Do not reuse peer IDs across concurrent sessions.
- Do not confuse detached documents with detached containers.
- Do not persist cursor presence, hover state, or connection state inside the main document; use ephemeral state.