Decentralized peer-to-peer synchronization for Obsidian vaults using Hyperswarm. No central server required.
- Real-time Sync: Instant file synchronization across all connected devices
- Decentralized: Direct peer-to-peer connections via Hyperswarm DHT
- Conflict Resolution: GitHub-style UI for resolving conflicting changes
- Three-Way Merge: Intelligent conflict detection using common ancestor
- Live Typing Sync: See changes as you type (debounced)
- File Operations: Handles create, modify, delete, and rename operations
- Network Resilience: Automatic reconnection and late peer discovery
- Persistent Identity: Maintains consistent peer ID across sessions
HyperswarmManager (src/hyperswarm-manager.ts)
- Manages P2P connections via Hyperswarm
- Handles peer discovery, connection, and disconnection
- Broadcasts messages to all peers
SyncEngine (src/sync-engine.ts)
- Core synchronization orchestration
- Three-way merge algorithm (local, remote, last-synced)
- Message routing (file_list, file_data, file_request, file_delete, conflict_resolved)
- Deduplication and race condition handling
FileManager (src/file-manager.ts)
- Vault file operations (read, write, delete, rename)
- Content hashing (SHA-256)
- Metadata management (mtime, size)
ConflictManager (src/conflict-manager.ts)
- Conflict detection and storage
- Responsive modal UI for resolution
- Cross-device conflict state synchronization
- Persistent "Resolve conflicts" button in editor
SyncMetadataStore (src/sync-metadata-store.ts)
- Tracks
lastSyncedHashper file per peer - Enables three-way merge conflict detection
- Connection: All devices join the same Hyperswarm topic (derived from vault ID + shared secret)
- Discovery: Peers discover each other via DHT and establish encrypted connections
- Initial Sync: New peer broadcasts file list; peers exchange missing/newer files
- Live Sync: File changes trigger immediate broadcasts to all connected peers
- Conflict Detection: Three-way merge compares
localHash,remoteHash, andlastSyncedHash- If all same → no action
- If local == last-synced → accept remote (remote is newer)
- If remote == last-synced → accept local (local is newer)
- If all differ → conflict (show resolution UI)
- Resolution: User chooses local or remote; choice syncs to all devices
file_list, file_request, file_data, file_delete, conflict_resolved
- Clone to
.obsidian/plugins/hypersync/→npm install→npm run build - Enable plugin in Obsidian settings
- Set the same shared secret on all devices you want to sync
- Devices auto-discover and sync
Both devices must be online simultaneously for sync to work. The current implementation uses direct peer-to-peer connections, meaning if your device is offline, your other device cannot access or sync vault data.
Blind Mirroring: Data will be fragmented and distributed across multiple peers in an encrypted, privacy-preserving manner. This allows you to access your vault even when your primary devices are offline, as fragments are retrieved and reassembled from available peers in the network.
File Structure:
main.ts # Plugin entry, Obsidian integration
src/
hyperswarm-manager.ts # P2P networking
sync-engine.ts # Sync orchestration
file-manager.ts # File I/O operations
conflict-manager.ts # Conflict UI & resolution
sync-metadata-store.ts # Per-peer hash tracking
three-way-merge.ts # Merge algorithm
settings-tab.ts # UI for configuration
types.ts # TypeScript interfaces
Build: npm run build
Dev: npm run dev (watch mode)
SHA-256 hashing, 1.5s editor debounce, message deduplication, race condition handling via pendingResolutions, network change detection, Obsidian Desktop compatible (Electron/Node.js)
If you like the plugin, you can support me here:
BTC: bc1qmer7j8rnvnmnw5dxuf5e7jmql7e62rmmywy6cf
XMR: 421WZpXqLuq6A8yTp8cN6AHd6zT993xeMbks1bNuQ1XcVVvoDvoFReDRdgp2pQdY8u2SSTnFc9Tg5fSFF6xeUdteDNfVg4f
ETH: 0x36f9cf6253a24feedda85d1dacad19d1e9a5c729
SOL: 2t3Vq8hVG77Nufckj7boucx3JeZQWDFf8SRBaPgCum3v