Core library for darn - CRDT-backed filesystem management.
darn_core provides the foundational types and logic for managing files as Automerge CRDT documents. It handles:
| Feature | Description |
|---|---|
| Workspace management | .darn marker file and centralized storage |
| File-to-document mapping | Converting files to/from Automerge documents |
| Manifest tracking | Mapping file paths to Sedimentree IDs |
| Change detection | BLAKE3 content hashing for efficient diffing |
| Ignore patterns | Gitignore-style patterns stored in .darn config |
| Directory tree sync | Patchwork-style directory structure as Automerge docs |
| Staged batch writes | Two-phase commit for atomic workspace updates |
| Module | Purpose |
|---|---|
darn.rs |
Workspace management + sync methods |
file.rs |
File ↔ Automerge conversion |
directory.rs |
Directory tree (Patchwork-style) |
manifest.rs |
Tracked, ContentHash, FileState |
dotfile.rs |
.darn config file (JSON) |
ignore.rs |
Ignore pattern matching |
staged_update.rs |
Two-phase batch file writes |
refresh.rs |
Change detection & incremental sync |
peer.rs |
Peer config (JSON) |
signer.rs |
Ed25519 key management |
config.rs |
Global config (~/.config/darn/) |
watcher.rs |
Filesystem watcher for auto-sync |
Workspace management and sync orchestration:
use darn_core::darn::Darn;
// Initialize new workspace
let ws = Darn::init(Path::new("my-project"))?;
// Open existing
let darn = Darn::open(Path::new("my-project")).await?;
// Access components
let manifest = darn.load_manifest()?;
let subduction = darn.subduction();Patchwork-compatible file representation:
use darn_core::file::{File, content::Content};
// Create from file
let doc = File::from_path("example.txt")?;
// Or construct directly
let doc = File::text("notes.txt", "Hello, world!");
// Convert to Automerge
let mut am_doc = doc.to_automerge()?;
let bytes = am_doc.save();Track files with change detection:
use darn_core::manifest::tracked::{Tracked, FileState};
// Check file state
match entry.state(workspace_root) {
FileState::Clean => println!("unchanged"),
FileState::Modified => println!("changed on disk"),
FileState::Missing => println!("deleted"),
}Patchwork-inspired schema:
| Field | Type | Description |
|---|---|---|
name |
Name |
Validated filename (no path seps) |
content |
Text or Bytes |
File content |
metadata |
Metadata |
Permissions (u32, rwx display) |
Content encoding:
- Text files →
Textobject (character-level CRDT merging) - Binary files →
Bytesscalar (last-writer-wins)
| Data | Format | Notes |
|---|---|---|
| File documents | Automerge | Direct API (put, get), not serde |
| Manifest | JSON | Via serde_json, base58 for 32-byte types |
| Peer config | JSON | One file per peer in ~/.config/darn/peers/ |
| Sedimentree data | CBOR | Via minicbor, managed by Subduction |
File documents use Automerge's direct API rather than serde integration. This gives explicit control over CRDT types (e.g., ObjType::Text for character-level merging vs ScalarValue::Bytes for LWW semantics).
| Crate | Purpose |
|---|---|
automerge |
CRDT document storage |
sedimentree_core |
Content-addressed partitioning |
sedimentree_fs |
Filesystem storage backend |
subduction_core |
Sync protocol |
blake3 |
Content hashing |
serde / serde_json |
JSON serialization |
Apache-2.0 OR MIT