Local Sync

by Liu Bo
5
4
3
2
1
New Plugin

Description

LAN bidirectional vault sync — CRDT auto-merge, PSK auth, UDP discovery - This plugin has not been manually reviewed by Obsidian staff.

Reviews

No reviews yet.

Stats

stars
downloads
0
forks
0
days
NaN
days
NaN
days
0
total PRs
0
open PRs
0
closed PRs
0
merged PRs
0
total issues
0
open issues
0
closed issues
0
commits

Latest Version

Invalid date

Changelog

README file from

Github

🔄 Local Sync

Zero-cloud · Zero-conflict · Zero‑config — LAN bidirectional sync for Obsidian vaults



✨ Features

🔗 LAN Direct Sync Peer‑to‑peer WebSocket/WSS connection. Zero cloud dependency — your data stays on your network.

🤝 Zero‑Conflict CRDT Yjs CRDT automatically merges concurrent text edits. No manual conflict resolution. Ever.

🔒 TLS Encrypted WSS transport with auto‑generated ECDSA P‑256 certificates. Certificate PIN verification prevents MITM attacks.

📡 Auto Discovery UDP broadcast finds devices on the same LAN. No IP typing needed.

🔐 Security First PSK challenge‑response authentication. Path traversal protection against rogue file writes.

🎯 Selective Sync Exclude folders & file types. Ignore .trash, .tmp, node_modules — your choice.

🖥️ Cross‑Platform macOS (NSFileCoordinator aware) Linux (writeFile + chmod)
Windows (write + lock‑retry)

🔌 Zero Config Install, set IP (or auto‑discover), and go. Certificates auto‑generate on first launch.


🚀 Quick Start

Installation

📁 Plugin ID: local-sync · Folder: your-vault/.obsidian/plugins/local-sync/

  1. Download the latest release from the Releases page
  2. Copy main.js + manifest.json + styles.css to your-vault/.obsidian/plugins/local-sync/
  3. Open Obsidian → ⚙️ SettingsCommunity pluginsEnable Local Sync

Usage

💡 Pro tip: On the same subnet? Enable UDP discovery for zero‑config auto‑connect.
🔒 TLS is on by default with auto‑generated ECDSA P‑256 certificates.


🏗️ Architecture

┌──────────────────────────────────────────────────┐
│              UI Layer                            │
│  SettingTab / ConflictModal / StatusBar          │
│  └─ TLS settings, fingerprint display, reset     │
├──────────────────────────────────────────────────┤
│           Service Layer                          │
│  SyncEngine + CrdtEngine(Yjs) + ConflictDetector │
├──────────────────────────────────────────────────┤
│         Discovery Layer                          │
│  UDP broadcast + QR pairing (desktop↔mobile)     │
├──────────────────────────────────────────────────┤
│          Security Layer                          │
│  TLS encryption + PSK auth + path validation     │
│  └─ CertManager (ECDSA P‑256, auto‑generate)     │
├──────────────────────────────────────────────────┤
│       Network & IO Layer                         │
│  WebSocket(WSS/WS) + chokidar + OsWriter         │
│  └─ http/https dual‑protocol server              │
└──────────────────────────────────────────────────┘

Module Overview

Layer Module Responsibility
🔒 Security cert-manager.ts ECDSA P‑256 certificate lifecycle (generate/load/reset)
🔒 Security auth-handshake.ts PSK challenge‑response authentication
🔒 Security path-validator.ts Path traversal protection
🌐 Network connection-manager.ts WebSocket/WSS server/client/duplex + TLS fallback
🌐 Network protocol.ts Message serialization protocol
🔄 Sync sync-engine.ts Sync orchestration & file state tracking
🔄 Sync crdt-engine.ts Yjs CRDT auto‑merge for text files
🔄 Sync conflict-detector.ts Binary‑only conflict detection
🔄 Sync initial-sync.ts Two‑phase initial sync (manifest → transfer)
📡 Discovery discovery-manager.ts UDP broadcast device discovery
📂 IO file-watcher.ts Chokidar‑based file change detection
📂 IO os-writer.ts Platform‑aware file writing (macOS/Linux/Win)
🖥️ UI setting-tab.ts Settings panel with 6 configuration sections
🖥️ UI sync-status-bar.ts Status bar indicators
🖥️ UI conflict-resolver.ts Binary file conflict resolution dialog

🔄 How It Works

Sync Flow

┌─────────────────────────────────────────────────────────────────────┐
│                        Initial Sync                                │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Device A ── FILE_LIST_BATCH (manifest, 100 files/batch) ──→ Device B │
│                ←── FILE_LIST_ACK (missing + different) ──────────┤  │
│                ── FILE_RESPONSE (missing files, 10 concurrent) ──→   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────────┐
│                     Incremental Sync                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  File change detected                                                │
│      ├── TEXT (.md/.txt/.canvas) → CRDT incremental update          │
│      └── BINARY (.png/.pdf/.zip) → Full file transfer               │
│                                                                     │
│  Both paths: protected by recentlyPushed(2s) + originDeviceId       │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

TLS Handshake

Client (WSS)                  Server (WSS)
     │                            │
     │──── wss://connect ──────→│  TLS 1.2/1.3 handshake
     │←── TLS established ─────│  Transport encrypted
     │                            │
     │── cert-fingerprint ────→│  Exchange SHA‑256 fingerprints
     │←── cert-fingerprint-ack─│  PIN verification
     │                            │
     │── PSK challenge ───────→│  Inside encrypted channel
     │←── authenticated ──────│
     │                            │
     │── sync data (encrypted) →│  All traffic protected

Conflict Resolution

File Type Strategy
📝 .md / .txt / .canvas Yjs CRDT auto‑merge — no user intervention needed
🖼️ .png / .pdf / .zip Detected → User prompted to keep local / remote / both

Synchronization Safeguards

Mechanism Purpose
recentlyPushed (2s TTL) Prevents sync loop
originDeviceId Ignores changes originated from self
Debounce (500ms) Avoids redundant sync on rapid saves
UUID dedup Prevents duplicate message processing
Heartbeat (120s ping/pong) Detects dead connections
Exponential backoff (1s→60s) Smart reconnection
Version tracking Discards stale file versions
Pending queue Buffers changes when offline, flushes on reconnect

🔒 TLS Encryption (v1.1.0)

Feature Description
Protocol WSS (WebSocket Secure) — TLS 1.2/1.3
Certificate ECDSA P‑256 self‑signed, auto‑generated on first launch
Storage ~/.obsidian-sync/certs/cert.pem + key.pem
Validation SHA‑256 fingerprint exchange + PIN code verification
Fallback Automatic downgrade to plain WS (configurable)
Dependencies Zero — all Node.js built‑ins (crypto, tls, http, https)

No CA needed. No OpenSSL setup. No external dependencies. Just works — with or without TLS.


📊 Project Stats

Metric Value
📁 Source Files 20 .ts files, ~7,800 lines
🧪 Tests 148 passing (unit + integration + E2E)
⏱️ Test Duration ~1 second
📦 Build Output Single main.js (~552KB)
🔗 External Deps ws · chokidar · yjs (all bundled)
🖥️ Platforms macOS ✅ · Linux ✅ · Windows ✅
🔒 TLS Deps Zero (all Node.js built‑in)
🏷️ Latest v1.1.0 — TLS encryption

🛠️ Development

# Clone & build
git clone https://github.com/liuboacean/obsidian-local-sync-plugin.git
cd obsidian-local-sync-plugin
npm install
npm run build     # Production build (main.js)
npm run dev       # Watch mode (for Hot Reload plugin)
npm test          # Run all 148 tests

# Quick local test with two vaults:
cp main.js manifest.json styles.css /path/to/vault-a/.obsidian/plugins/local-sync/
cp main.js manifest.json styles.css /path/to/vault-b/.obsidian/plugins/local-sync/
# Open both vaults in Obsidian, enable plugin, connect

📋 Changelog

Version Date Highlights
1.1.0 Jul 2, 2026 ✅ TLS encryption (WSS), ECDSA P‑256 certs, 148 tests
1.0.9 Jul 2, 2026 Obsidian community review fixes
1.0.8 Jul 2, 2026 Release format fix
1.0.7 Jul 2, 2026 Initial release, 131 tests

🗺️ Roadmap

  • Yjs CRDT auto‑merge
  • PSK auth + path security
  • UDP auto‑discovery
  • Cross‑platform file writer
  • TLS encryption (WSS) ← v1.1.0
  • Mobile client support (P2)
  • Sync history viewer (P2)
  • Diff preview before sync (P2)

🤝 Contributing

PRs are welcome! Check the issues for areas to contribute.

📄 License

MIT © 2026 Obsidian Local Sync Team


Made with ❤️ for the Obsidian community