Plugin Overview
Live Cursor is an advanced, offline-first, zero-cloud collaborative sync engine designed specifically for private Obsidian vaults. By leveraging Yjs conflict-free replicated data types (CRDTs) and local background daemons, it lets you edit vaults simultaneously with team members without exporting your data to third-party databases.
Why Zero-Cloud?
Standard real-time collaborative editors require a cloud registry to sequence and resolve keystrokes. Live Cursor routes sync traffic directly between your connected clients and your own local background SQLite database daemon, maintaining absolute privacy for your intellectual property.
Key Capabilities
Never deal with Git line conflicts or overwriting other authors again. CRDTs merge changes deterministically at the character level.
Dynamically propagates workspace configurations, pane positions, and custom styles across connected devices.
Work fully offline; changes buffer locally in SQLite and cleanly merge upon reconnecting to the team node.
No data ever leaves your own network. Use wss:// for encrypted transport over your local LAN or VPN tunnel.
Technology Stack
| Layer | Technology | Purpose |
|---|---|---|
| Sync | Yjs + y-websocket |
CRDT document state & real-time broadcast |
| Editor | y-codemirror.next |
Collaborative cursors & selections in CodeMirror 6 |
| Storage | better-sqlite3 |
Persistent document state snapshots |
| Runtime | Node.js 20 / Docker Alpine |
Headless daemon process |
| Network | WebSocket / Tailscale | Local LAN or encrypted overlay VPN |
Manual Installation
While Live Cursor is available via the Obsidian Community Plugins marketplace, you can also install it manually by following these lightweight packaging steps.
1. Grab Compiled Releases
Download the latest compiled release bundle from GitHub. The plugin directory requires three fundamental assets:
main.js— The compiled execution logic.manifest.json— Metadata containing configuration permissions.styles.css— Custom rendering styling for peer cursors and flags.
2. Place Assets in Vault
Move these assets to your target vault's hidden plugin directory:
# Create the target directory inside your Obsidian vault plugins folder
mkdir -p .obsidian/plugins/live-cursor
# Copy your downloaded release files into the directory
cp main.js manifest.json styles.css .obsidian/plugins/live-cursor/
3. Reload Plugins
Navigate to Obsidian Settings > Community Plugins, click Check for updates, and toggle Live Cursor to enabled.
Community Marketplace Alternative
Search for "Live Cursor" directly in Obsidian's Community Plugins browser. No manual file copying required — Obsidian handles asset management automatically.
Plugin Settings Reference
| Setting | Default | Description |
|---|---|---|
serverUrl |
ws://localhost:1234/sync |
WebSocket endpoint of the sync daemon |
username |
— | Collaborator login username |
passwordHash |
— | Auth credential for daemon access |
nickname |
— | Display name shown on peer cursors |
cursorColor |
#6366f1 |
Hex color for your cursor and selections |
workspaceName |
default-workspace |
Namespace for config sync isolation |
autoSyncOnLoad |
false |
Auto-trigger config sync when Obsidian starts |
debugLogging |
false |
Print verbose telemetry to developer console |
Vault Quickstart
To synchronize vaults, a background sync database must be running. We provide an embedded sync server inside the plugin settings or a detached Docker container for remote execution.
Bootstrap local server in 15 seconds
- Open Obsidian Settings > Live Cursor.
- Click the Launch Setup Wizard button inside the control panel.
- Under Step 1: background server, click the switch to boot the secure local daemon process.
- Under Step 2: Profile setup, type your display name and pick your cursor color banner.
- You are now ready to collaborate! Share your local network address (e.g.,
ws://192.168.1.100:1234/sync) with teammates.
Wizard Generator
For advanced custom configurations, use our interactive Guided Setup Wizard to instantly compile Docker Compose or environment manifests.
Connecting Remote Teammates
Once your daemon is running, teammates connect by entering your server's WebSocket URL into their plugin settings. There are three network topology options:
Fastest option. All devices must be on the same Wi-Fi or ethernet segment. Use your machine's LAN IP address.
ws://192.168.x.x:1234/sync
Best for remote teams. Tailscale creates a secure encrypted mesh between devices anywhere on the internet.
ws://100.x.x.x:1234/sync
Deploy on a VPS, NAS, or home server using Docker. Expose via reverse proxy with HTTPS/WSS.
wss://sync.yourdomain.com/sync
Daemon Infrastructure
The Live Cursor daemon process is structured in TypeScript, utilizing a low-overhead SQLite storage mechanism and a WebSocket listener to relay operations.
Docker Container Deployment
If you prefer a headless server running on a NAS, server, or cloud node, deploy the precompiled Alpine Docker container.
# Deploy the Docker container on port 1234
docker run -d \
--name live-cursor-daemon \
-p 1234:1234 \
-v /volume1/obsidian/data:/app/data \
-v /volume1/obsidian/backups:/app/backups \
-e PORT=1234 \
-e DB_PATH=/app/data/live-cursor.db \
live-cursor/daemon:latest
Docker Compose (Recommended)
For persistent, auto-restarting deployments, use the official Compose manifest:
version: '3.8'
services:
live-cursor:
image: ghcr.io/live-cursor/sync-server:latest
container_name: live-cursor-server
restart: unless-stopped
ports:
- "1234:1234"
volumes:
- ./data:/app/data
- ./backups:/app/backups
environment:
- PORT=1234
- ADMIN_USER=admin
- ADMIN_PASS=yourpassword
Environment Parameters
The daemon respects standard environmental variables for easy tailoring:
| Variable | Default | Description |
|---|---|---|
PORT |
1234 |
WebSocket listener port |
DB_PATH |
/app/data/live-cursor.db |
Absolute path to SQLite state file |
BACKUP_DIR |
/app/backups |
Directory for Markdown flush backups |
ADMIN_USER |
admin |
Admin account username |
ADMIN_PASS |
— | Admin account password (required) |
Security Notice
Never expose port 1234 directly to the public internet without placing it behind a reverse proxy (e.g., Caddy or Nginx) with TLS termination. Use Tailscale for zero-config encrypted remote access instead.
Network Protocol
Communication between Obsidian clients and the local sync daemon occurs over binary WebSockets utilizing custom packaging structures derived from the Yjs protocols.
Operational Packets
Packets are framed with a single-byte prefix indicating message type. The payload consists of standard Uint8Array binary frames.
{
"message_types": {
"0": "SyncStep1 (Client sends their local state vector)",
"1": "SyncStep2 (Daemon replies with missing updates)",
"2": "SyncUpdate (Real-time delta keystrokes and selections)",
"3": "AuthRequest (Daemon challenges client validation signature)"
}
}
Connection Lifecycle
| Phase | Direction | Description |
|---|---|---|
| Handshake | Client → Daemon | WebSocket upgrade with user & pass URL params |
| SyncStep1 | Client → Daemon | Client sends its current Yjs state vector |
| SyncStep2 | Daemon → Client | Daemon replies with all missing document updates |
| Live Sync | Bidirectional | Real-time delta keystrokes and awareness states |
| Reconnect | Client | Auto-reconnects on mobile wake, network resume, window focus |
Lazy Flush Interval
To maintain standard vault format compatibility, the daemon doesn't just store edits in SQLite. Every 15 seconds of idle inactivity, it flushes the parsed, compiled Markdown buffer directly back to a human-readable .md file in your backups directory.
CRDT Merge Logic
Conflict-free Replicated Data Types (CRDTs) form the mathematical foundation of Live Cursor's concurrent editing capability.
Why git diffs fail real-time edit resolution
Git utilizes line-based three-way merges. If two authors edit different portions of the exact same line at the same time, Git is unable to resolve order, prompting a merge conflict.
Yjs manages text as a doubly linked list of character chunks. Each chunk contains:
- ID: A unique key containing the author's client code and an incremental sequence number.
- Origin Left / Origin Right: Pointers targeting the adjacent characters at the time the keystroke was pressed.
This guarantees that even if 10 people type concurrently inside the same paragraph, all keystrokes are merged in exactly the same deterministic order across every single peer.
Awareness Protocol
Alongside document sync, Live Cursor propagates real-time awareness state — lightweight JSON objects broadcasting each peer's cursor position, selection range, and collaborator name. Awareness updates are never persisted to SQLite; they are ephemeral and discarded when a client disconnects.
// Live Cursor sets collaborator awareness on each file sync
provider.awareness.setLocalStateField('user', {
name: settings.nickname || settings.username || 'Collaborator',
color: settings.cursorColor || '#6366f1',
colorLight: (settings.cursorColor || '#6366f1') + '33'
});
Performance Characteristic
Yjs CRDT updates are binary-encoded using lib0 encoding, keeping delta sizes extremely small — typically under 50 bytes per keystroke even in complex collaborative sessions.
Tailscale Setup
Tailscale is the recommended networking solution for sharing your Live Cursor daemon with remote teammates. It creates an encrypted peer-to-peer mesh network (using WireGuard® under the hood) where every device gets a stable private IP address — no port forwarding, no firewall rules, no dynamic DNS needed.
Zero-Config Encrypted Networking
Tailscale handles NAT traversal, encryption, and authentication automatically. Once installed, every device on your tailnet can reach your Live Cursor daemon as if it were on the same local network.
Step 1 — Install Tailscale on the Host Machine
The host machine is the device running the Live Cursor daemon (local background process or Docker container). Install Tailscale on this machine first.
# Install Tailscale on Debian/Ubuntu
curl -fsSL https://tailscale.com/install.sh | sh
# Authenticate and connect to your tailnet
sudo tailscale up
# Confirm your Tailscale IP (100.x.x.x range)
tailscale ip -4
# Install via Homebrew
brew install tailscale
# Start and authenticate
sudo tailscaled &
tailscale up
# Or download the App from the Mac App Store (recommended)
# https://apps.apple.com/app/tailscale/id1475387142
# Download installer from https://tailscale.com/download/windows
# Or install via winget:
winget install tailscale.tailscale
# After installation, sign in from the system tray icon
# Confirm your Tailscale IP
tailscale ip -4
# docker-compose.yml — Live Cursor + Tailscale sidecar
version: '3.8'
services:
tailscale:
image: tailscale/tailscale:latest
hostname: live-cursor-node
environment:
- TS_AUTHKEY=${TS_AUTHKEY}
- TS_STATE_DIR=/var/lib/tailscale
volumes:
- tailscale-state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
cap_add:
- NET_ADMIN
restart: unless-stopped
live-cursor:
image: ghcr.io/live-cursor/sync-server:latest
network_mode: "service:tailscale"
volumes:
- ./data:/app/data
- ./backups:/app/backups
environment:
- PORT=1234
- ADMIN_USER=admin
- ADMIN_PASS=yourpassword
restart: unless-stopped
depends_on:
- tailscale
volumes:
tailscale-state:
Step 2 — Install Tailscale on Teammate Devices
Each collaborator installs Tailscale on their device and joins your tailnet (Tailscale network). You can invite them via email from the Tailscale admin console.
- Download from tailscale.com/download for all platforms including iOS and Android.
- Once connected, every device sees others via stable
100.x.x.xIPs — these never change. - For Obsidian mobile users, Tailscale runs in the background and maintains the VPN tunnel automatically.
Step 3 — Configure Live Cursor to Use Tailscale IP
Once Tailscale is running on all devices, update the Live Cursor server URL to point to the host machine's Tailscale IP instead of its local LAN address:
# In Obsidian → Settings → Live Cursor → Server URL
# Replace with the host machine's Tailscale IP:
ws://100.x.x.x:1234/sync
# Example with a specific IP:
ws://100.64.0.12:1234/sync
# To find the host's Tailscale IP, run on the host machine:
tailscale ip -4
Step 4 — Using MagicDNS (Optional but Recommended)
Tailscale's MagicDNS feature assigns human-readable hostnames to every device on your tailnet, so you never need to remember IP addresses.
# Enable MagicDNS in the Tailscale Admin Console:
# https://login.tailscale.com/admin/dns
# Then use the hostname instead of IP in Live Cursor:
ws://my-desktop.tail12345.ts.net:1234/sync
# Or if you set a custom domain:
ws://live-cursor-node:1234/sync
Network Topology with Tailscale
100.64.0.1
100.64.0.2
100.64.0.3
100.64.0.4
Tailscale ACL — Restricting Access
For organizations, you can restrict which Tailscale devices can reach your Live Cursor daemon using Access Control Lists (ACLs) in the admin panel.
{
"acls": [
{
"action": "accept",
"src": ["tag:obsidian-collab"],
"dst": ["tag:live-cursor-server:1234"]
}
],
"tagOwners": {
"tag:obsidian-collab": ["autogroup:member"],
"tag:live-cursor-server": ["autogroup:admin"]
}
}
Tailscale Free Tier
Tailscale's free personal plan supports up to 3 users and 100 devices — more than enough for most small collaboration teams. Larger organizations can upgrade to a team plan at tailscale.com.
Troubleshooting Tailscale Connectivity
| Symptom | Likely Cause | Fix |
|---|---|---|
Cannot connect to ws://100.x.x.x:1234 |
Tailscale not running on host | Run sudo tailscale up on the host machine |
| Connection timeout after a few minutes | Host machine sleep/hibernate | Disable sleep on the host or use a Docker server on a NAS |
| Mobile Obsidian disconnects frequently | iOS/Android background process limits | Enable "Always-on VPN" in Tailscale mobile settings |
| MagicDNS hostname not resolving | MagicDNS not enabled in admin console | Enable at login.tailscale.com/admin/dns |
| High latency despite short distances | Using DERP relay instead of direct connection | Ensure UDP port 41641 is open; Tailscale prefers direct P2P |
Frequently Asked Questions
Is my vault data completely encrypted?
Yes. Direct connections between Obsidian and local sync daemons can be established using secure WebSockets (wss://). Data never transits through public routers, remaining locked within your own sandboxed network perimeter. When using Tailscale, traffic is additionally encrypted with WireGuard®-grade encryption at the network layer.
What happens if I edit offline?
Live Cursor queues operational transactions locally within your device memory. The moment a client regains connectivity to your sync server, the vectors are exchanged and overlapping edits are resolved effortlessly using CRDT merge semantics — no manual conflict resolution required.
Does this increase the size of my Markdown files?
No. The operational histories and cursor tags are recorded in a separate SQLite database file. Your Markdown vault notes remain fully standard, clean, and free of any bloating tracking markers.
Can I use Live Cursor on mobile (iOS / Android)?
Yes! The plugin is fully supported on Obsidian mobile. Live Cursor automatically reconnects whenever the app becomes visible or the network comes back online. For remote access on mobile, pair it with the Tailscale mobile app for reliable encrypted connectivity from anywhere.
How many users can collaborate simultaneously?
There is no hard user limit built into Live Cursor. Practical limits depend on the host machine's resources. The SQLite daemon is single-threaded but uses async I/O, comfortably handling 10–20 concurrent editors on modest hardware. The Docker deployment on a NAS or small VPS handles even more.
Do I need Tailscale, or can I use my own VPN?
Tailscale is recommended for its zero-config simplicity, but any VPN solution that provides IP-level routing between devices works. This includes WireGuard, OpenVPN, ZeroTier, or a traditional site-to-site VPN. As long as the WebSocket URL is reachable, Live Cursor will connect.