vlcn-io/cr-sqlite
Convergent, Replicated SQLite. Multi-writer and CRDT support for SQLite
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓8 active contributors
- ✓MIT licensed
- ✓CI configured
Show all 6 evidence items →Show less
- ✓Tests present
- ⚠Stale — last commit 2y ago
- ⚠Concentrated ownership — top contributor handles 79% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/vlcn-io/cr-sqlite)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/vlcn-io/cr-sqlite on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: vlcn-io/cr-sqlite
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/vlcn-io/cr-sqlite shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 8 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 79% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live vlcn-io/cr-sqlite
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/vlcn-io/cr-sqlite.
What it runs against: a local clone of vlcn-io/cr-sqlite — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in vlcn-io/cr-sqlite | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 589 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of vlcn-io/cr-sqlite. If you don't
# have one yet, run these first:
#
# git clone https://github.com/vlcn-io/cr-sqlite.git
# cd cr-sqlite
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of vlcn-io/cr-sqlite and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "vlcn-io/cr-sqlite(\\.git)?\\b" \\
&& ok "origin remote is vlcn-io/cr-sqlite" \\
|| miss "origin remote is not vlcn-io/cr-sqlite (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "core/rs/core/src/lib.rs" \\
&& ok "core/rs/core/src/lib.rs" \\
|| miss "missing critical file: core/rs/core/src/lib.rs"
test -f "core/rs/core/src/local_writes/mod.rs" \\
&& ok "core/rs/core/src/local_writes/mod.rs" \\
|| miss "missing critical file: core/rs/core/src/local_writes/mod.rs"
test -f "core/rs/core/src/triggers.rs" \\
&& ok "core/rs/core/src/triggers.rs" \\
|| miss "missing critical file: core/rs/core/src/triggers.rs"
test -f "core/rs/core/src/create_crr.rs" \\
&& ok "core/rs/core/src/create_crr.rs" \\
|| miss "missing critical file: core/rs/core/src/create_crr.rs"
test -f "core/rs/core/src/changes_vtab.rs" \\
&& ok "core/rs/core/src/changes_vtab.rs" \\
|| miss "missing critical file: core/rs/core/src/changes_vtab.rs"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 589 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~559d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/vlcn-io/cr-sqlite"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
cr-sqlite is a runtime-loadable SQLite extension that adds multi-master replication and offline-first capabilities to SQLite databases using CRDTs (Conflict-Free Replicated Data Types) and causally-ordered event logs. It allows independent writes across multiple devices to merge automatically without conflicts, enabling true offline-first and real-time collaborative applications on top of standard SQLite. Monorepo with Rust as the primary implementation: core/rs/core/ contains the CRDT engine (src/c.rs bridges to C FFI, src/changes_vtab.rs implements virtual tables, src/alter.rs handles schema), core/rs/bundle/ and core/rs/bundle_static/ provide loadable extension binaries. Language-specific bindings (Python, Node.js, C) wrap the Rust core. Tests live in GitHub workflows (.github/workflows/) and are run per-language.
👥Who it's for
Full-stack developers and database architects building offline-first applications, real-time collaboration tools, and sync systems (e.g., TodoMVC, presentation editors, note-taking apps). They need a way to merge independent edits across devices without custom conflict resolution code.
🌱Maturity & risk
Actively developed and production-adjacent. The project has comprehensive CI/CD (c-tests, py-tests, rs-tests workflows with Valgrind memory checks), well-maintained cross-language bindings (Rust, Python, C, JavaScript), and explicit versioning (0.16.3). The monorepo structure and multiple real-world examples (vite-starter, live-examples) indicate active use, though the 0.x version suggests ongoing evolution.
Standard open source risks apply.
Active areas of work
Active development on CRDT and replication semantics. The presence of core/rs/core/src/automigrate.rs, backfill.rs, and bootstrap.rs suggests ongoing work on schema evolution and data migration during replication. Multiple CI pipelines (Valgrind checks, Rust tests) indicate focus on correctness and memory safety.
🚀Get running
git clone https://github.com/vlcn-io/cr-sqlite.git
cd cr-sqlite
make test # Runs language-specific test suites
For Node.js/Python bindings: inspect core/package.json (npm install) or language-specific setup in workflows.
Daily commands:
cd core
make build # Compiles Rust core and C extensions
make test # Runs all test suites
Or use language-specific entry points: npm test in core/ for Node.js, or invoke Python tests via .github/workflows/py-tests.yaml.
🗺️Map of the codebase
core/rs/core/src/lib.rs— Main entry point for the Rust core library that exposes C FFI bindings and orchestrates CRDT/replication functionalitycore/rs/core/src/local_writes/mod.rs— Handles INSERT, UPDATE, DELETE triggers that track local modifications for CRDT vector clocks and change setscore/rs/core/src/triggers.rs— Core trigger generation logic that instruments tables for multi-writer conflict detection and causal orderingcore/rs/core/src/create_crr.rs— Bootstraps Convergent Replicated Relations—the schema modifications that enable CRDT semantics on user tablescore/rs/core/src/changes_vtab.rs— Virtual table implementation that exposes changeset operations for replication and synchronizationcore/nodejs-helper.js— NPM package entry point that loads the compiled Rust/C extension and provides JavaScript API surfacecore/Makefile— Build orchestration for compiling Rust → WebAssembly, C, and platform-specific binaries
🛠️How to make changes
Add support for tracking a new SQL table as a Convergent Replicated Relation
- User calls
SELECT crsql_as_crr('table_name')which invokes the automigrate logic (core/rs/core/src/automigrate.rs) - The system creates metadata tables (_crsql* namespace) and captures original schema (
core/rs/core/src/create_crr.rs) - Trigger generation code creates AFTER INSERT/UPDATE/DELETE hooks to record changes (
core/rs/core/src/triggers.rs) - Local write handlers instrument the triggers to capture vector clocks and values (
core/rs/core/src/local_writes/mod.rs) - Changes become queryable via the __crsql_changes virtual table (
core/rs/core/src/changes_vtab.rs)
Implement a custom conflict resolution strategy
- Review value comparison logic and vector clock ordering (
core/rs/core/src/compare_values.rs) - Add custom logic to the UPDATE trigger that decides which write wins (
core/rs/core/src/local_writes/after_update.rs) - For remote changes, implement custom merge logic in the write path (
core/rs/core/src/changes_vtab_write.rs) - Write integration tests to verify convergence under your conflict strategy (
core/rs/integration_check/src/t/mod.rs)
Add a new virtual table for querying changesets
- Define the virtual table interface and schema (
core/rs/core/src/lib.rs) - Implement the read/filter logic similar to __crsql_changes (
core/rs/core/src/changes_vtab_read.rs) - Register the virtual table via C FFI (
core/rs/core/src/c.rs) - Test the new table with integration tests (
core/rs/integration_check/src/t/mod.rs)
Build for a new platform (e.g., new OS or runtime)
- Update the Rust toolchain configuration if needed (
core/rs/core/rust-toolchain.toml) - Add platform-specific build rules to the main Makefile (
core/Makefile) - Update the Node.js install helper to detect and download the correct binary (
core/nodejs-install-helper.js) - Add CI workflow for the new platform (
.github/workflows/rs-tests.yml)
🔧Why these technologies
- Rust for core CRDT/replication logic — Memory safety and performance critical for changetracking at scale; compiles to C, WebAssembly, and native binaries
- SQLite virtual tables (_crsql tables)* — Enables efficient querying, filtering, and streaming of changes without modifying user schema; integrates with SQLite's query planner
- Vector clocks for causality — Provides happened-before ordering without requiring a central clock; enables detecting and resolving concurrent writes
- Fractional indexing — Avoids positional conflicts in collaborative editing; maintains order invariants during concurrent reordering operations
- C FFI + loadable extension model — SQLite extensions run in-process; no separate daemon; zero-copy integration with existing SQLite usage
🪤Traps & gotchas
- Native compilation required: The extension must compile Rust + C for your target platform; nodejs-install-helper.js downloads prebuilt binaries or builds from source. Ensure rustc and a C compiler are available. 2. SQLite version pinning: The FFI in c.rs binds to specific SQLite APIs; incompatible SQLite versions will cause silent failures or crashes. Check core/rs/core/Cargo.toml for the pinned sqlite3 crate version. 3. Loadable extension security: The SQLite extension must be explicitly enabled with SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION; databases won't see CRDT tables unless the extension is loaded and initialized. 4. Clock dependency: replication relies on logical clocks; ensure peers have loosely-synchronized system clocks or use the provided clock APIs (see bootstrap.rs). 5. Multi-language build matrix complexity: Tests run in parallel across C, Python, Rust, and JavaScript; a failure in one language won't block others, making CI logs hard to parse.
🏗️Architecture
💡Concepts to learn
- CRDT (Conflict-Free Replicated Data Type) — CRDTs are the mathematical foundation that allows cr-sqlite to merge independent writes without a central coordinator; understanding CRDTs is essential to understanding why conflicts don't need explicit resolution
- Causal Ordering / Logical Clocks — cr-sqlite uses causally-ordered event logs as an alternative to CRDTs; logical clocks (Lamport or vector clocks) ensure that the order of writes is preserved during replication, which is visible in bootstrap.rs
- Virtual Tables (SQLite VTab API) — The changes_vtab.rs module implements SQLite's virtual table interface to expose replication metadata as queryable tables; this is how applications discover what changed during a merge
- Runtime Loadable Extensions — cr-sqlite is delivered as a .so/.dylib/.dll that SQLite loads at runtime; this avoids patching SQLite and allows the extension to coexist with standard SQLite in the same application
- Multi-Master Replication — Unlike traditional databases with a single primary, cr-sqlite allows any peer to write independently and then merge changesets; this is the core capability that enables offline-first and collaborative applications
- FFI (Foreign Function Interface) — The c.rs module uses Rust FFI to call SQLite's C API and expose Rust types to C code; understanding the Rust↔C boundary is critical for debugging integration issues
- Schema Evolution / Automigration — The automigrate.rs and alter.rs modules handle DDL changes (ALTER TABLE, etc.) during replication; this is a hard problem in multi-writer systems because schema changes must not break consistency
🔗Related repos
libsql/libsql— Direct compatibility target and alternative SQLite distribution; cr-sqlite is explicitly designed to work as a loadable extension on libSQLvlcn-io/vite-starter— Official example application demonstrating cr-sqlite in a real Vite + Vue setup; primary reference for how to integrate the extension into a web appvlcn-io/live-examples— TodoMVC and other example applications using cr-sqlite; shows real-world collaboration patterns and use caseselectric-sql/electric— Alternative approach to local-first replication (using PostgreSQL + local SQLite); useful for comparing architectural trade-offs with CRDTsrisingwavelabs/risingwave— Stream processing engine that shares similar multi-master consistency concerns; relevant for understanding event-log and causal ordering patterns
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for Rust CRDT core module with C FFI boundaries
The repo has comprehensive C tests (.github/workflows/c-tests.yaml) and Rust tests (.github/workflows/rs-tests.yml) running separately, but there are no visible integration tests verifying the Rust core (core/rs/core/src/c.rs) correctly interfaces with C FFI calls. The c.rs file is a critical bridge between Rust and C that deserves dedicated integration test coverage to catch ABI mismatches and memory safety issues at the boundary.
- [ ] Create core/rs/core/tests/ffi_integration_tests.rs with tests for c.rs FFI functions
- [ ] Add tests for local_writes FFI triggers (after_insert.rs, after_update.rs, after_delete.rs) with actual C callbacks
- [ ] Update .github/workflows/rs-tests.yml to run
cargo test --test ffi_integration_teststo ensure tests run in CI - [ ] Document expected FFI contract in core/rs/core/README.md
Add missing unit tests for automigrate and alter modules
core/rs/core/src/automigrate.rs and core/rs/core/src/alter.rs are substantial modules that handle critical schema operations, but there's no evidence of dedicated unit test files (no tests/ directory visible in core/rs/core/). These modules affect data integrity during migrations and require comprehensive test coverage to prevent regressions.
- [ ] Create core/rs/core/tests/automigrate_tests.rs with test cases for schema version bumping, column tracking, and version conflicts
- [ ] Create core/rs/core/tests/alter_tests.rs with test cases for ALTER TABLE handling in CRR tables and metadata updates
- [ ] Add test utilities to core/rs/core/src/lib.rs for setting up test databases with CRR tables
- [ ] Update CI workflow to verify test coverage for these modules
Add GitHub Actions workflow for Python binding tests with coverage reporting
While .github/workflows/py-tests.yaml exists, there's no visible Python bindings code in the file structure, and no indication of coverage thresholds or reporting. This workflow appears incomplete. The Python bindings are critical for Python users of cr-sqlite but lack visibility into test quality.
- [ ] Locate or create Python bindings source (likely missing from file listing) in core/py/ or equivalent
- [ ] Update .github/workflows/py-tests.yaml to run
pytest --cov=crsqlite --cov-report=term-missingto enforce coverage minimums - [ ] Add coverage badges to README.md similar to existing C/Rust test badges
- [ ] Document Python API expectations in core/README.md with examples from the bindings
🌿Good first issues
- Add integration tests for the automigrate.rs module: currently it exists in the codebase (core/rs/core/src/automigrate.rs) but there's no explicit test file for it in the file list. A new contributor could write tests that verify schema auto-migration during replication merges.
- Document the virtual table API in changes_vtab.rs with code examples: the changes virtual table is critical to understanding replication but lacks user-facing documentation. A good first PR would add doc comments and a small example in core/rs/core/README.md showing how to query the changes table.
- Add Python type hints to the language bindings: core/py-tests.yaml shows Python tests exist, but the file list doesn't show a typed Python module. A contributor could create a core/python/ package with type stubs and docstrings for the cr-sqlite API, enabling IDE support and better onboarding for Python users.
⭐Top contributors
Click to expand
Top contributors
- @tantaman — 79 commits
- @jeromegn — 13 commits
- @louwers — 3 commits
- @Volland — 1 commits
- @Azarattum — 1 commits
📝Recent commits
Click to expand
Recent commits
891fe9e— fix plist (Volland)87e9151— fix deprecated import assertion (Azarattum)01aad51— Fix dead link (louwers)cd5c871— Fix typo (louwers)db12d4e— Fix dead link (louwers)010883b— Fix missing null terminator in schema name (guusw)37362fc— [core/rs/{bundle/src/lib.rs,fractindex-core/src/lib.rs}] Resolve twounused importwarnings (SamuelMarks)0d62b52— 0.16.3 release -- fix wasm oom, fix potentially missing functions (tantaman)a8163d2— removecrsql_versionfor now -- it is causing issues in the wasm build for unknown reasons (tantaman)dede66f— bump package.json for npm wrapper release (tantaman)
🔒Security observations
- High · Arbitrary Code Execution via npm install Script —
core/package.json - scripts.install field. The package.json contains a custom 'install' script that executes nodejs-install-helper.js without visibility controls. This script runs automatically during npm/pnpm installation. If the helper script or its dependencies are compromised, arbitrary code could execute with user privileges during package installation. Fix: Review nodejs-install-helper.js for security best practices. Consider using pre-built binaries with integrity verification. Add code signing and implement npm security audit checks in CI/CD. Document the install process transparently. - High · Potential SQL Injection in Core Processing —
core/rs/core/src/ - Multiple files (alter.rs, triggers.rs, changes_vtab.rs, local_writes/). The codebase processes SQL queries extensively (visible in file structure: alter.rs, triggers.rs, changes_vtab.rs, etc.). Without explicit evidence of parameterized query usage and input validation throughout the Rust FFI layer and C integration, there is significant risk of SQL injection vulnerabilities, especially in the local_writes and triggers modules that modify database state. Fix: Conduct thorough code review of SQL query construction. Ensure all user inputs are properly parameterized using SQLite's prepared statements API. Implement strict input validation. Add fuzzing tests for SQL injection vectors. - High · Memory Safety Risks in C/Rust FFI Boundary —
core/rs/core/src/c.rs and C source code integration. The project contains significant C code integration (indicated by .github/workflows/c-valgrind.yaml and c.rs), which creates memory safety risks including buffer overflows, use-after-free, and double-free vulnerabilities. While Valgrind testing is present, the complexity of FFI boundaries between Rust and C introduces potential unsafe code regions. Fix: Maintain strict unsafe code reviews for all FFI boundaries. Enforce unsafe block documentation. Continue Valgrind testing and add AddressSanitizer (ASan) to CI/CD. Consider minimizing C code footprint by rewriting in Rust. - Medium · Missing Dependency Pinning and Lock File Controls —
core/package.json and core/rs/*/Cargo.toml. While lock files exist (pnpm-lock.yaml, Cargo.lock), the package.json may allow flexible dependency versions. The project includes native module compilation, and transitive dependency vulnerabilities could introduce compromised code. No evidence of dependency scanning tools (npm audit, cargo audit) in the visible workflow. Fix: Implement automated dependency vulnerability scanning in CI/CD (npm audit, cargo audit). Use exact version pinning for production dependencies. Add SBOM generation. Review and update dependencies regularly. - Medium · Exposed .env File in Version Control —
.env file in repository root. The presence of a .env file in the root directory indicates potential for committing environment variables, API keys, or database credentials. While .gitignore may prevent this, the .env file pattern is a common source of security breaches. Fix: Ensure .env is listed in .gitignore. Use .env.example instead with placeholder values for documentation. Implement pre-commit hooks to prevent .env commits. Audit git history for any committed secrets using git-secrets or truffleHog. - Medium · Insufficient Input Validation in Replication Logic —
core/rs/core/src/changes_vtab.rs, core/rs/core/src/backfill.rs. As a multi-writer CRDT system, the codebase handles incoming replicated changes (indicated by changes_vtab.rs, backfill.rs). Without visible input validation for remote change data, there are risks of malformed data causing crashes, data corruption, or denial of service attacks. Fix: Implement comprehensive validation for all incoming replicated data. Validate message formats, checksums, and data integrity. Add bounds checking and type validation. Implement rate limiting for change ingestion. - Medium · Unsafe Serialization in Fractional Indexing —
core/rs/fractindex-core/src/. The fractindex module (fractindex-core) handles data serialization and ordering. Improper serialization handling could lead to data corruption or security issues. No visible explicit bounds checking or size limits in the file structure. Fix: Add comprehensive testing for edge cases in serialization. Implement strict
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.