obsidian-git-livesync
v0.1.0
Published
Bridge git pushes to Obsidian via CouchDB + Self-hosted LiveSync plugin
Maintainers
Readme
obsidian-git-livesync
Bridge git pushes to Obsidian via CouchDB and the Self-hosted LiveSync plugin.
Problem
Obsidian's Self-hosted LiveSync plugin syncs notes between devices via CouchDB replication. But it only works when Obsidian is running. If you edit markdown files in a headless environment (CI, server, scripts, git hooks), there is no way to push those changes into the LiveSync network. Your phone and other devices never see the update.
There is no CLI bridge between git and LiveSync. This tool fills that gap.
Solution
obsidian-git-livesync writes markdown files directly to CouchDB in LiveSync's document format, so all connected LiveSync clients replicate the changes instantly -- no Obsidian desktop needed.
Architecture
git push --> post-receive hook
--> obsidian-git-livesync sync
--> reads changed .md files from disk
--> writes to CouchDB (LiveSync document format)
--> all LiveSync clients replicate via CouchDB
<-- phone sees changes in secondsQuick Start
1. Start CouchDB
Clone this repo and start CouchDB using the included Docker Compose file:
git clone https://github.com/ecstatic-pirate/obsidian-git-livesync
cd obsidian-git-livesync
docker compose up -d
bash scripts/setup-couchdb.shThe Docker defaults are admin / password. Edit docker-compose.yml before running if you want different credentials.
2. Init and configure
npx obsidian-git-livesync init
# Edit .obsidian-git-livesync.json — fill in couchdbUser and couchdbPassword
# Docker defaults: admin / password3. Validate the connection
npx obsidian-git-livesync validate
# Should print: [OK] Connected to http://localhost:5984/obsidian-livesync4. Sync
# Sync all markdown files in the current directory
npx obsidian-git-livesync sync --all
# Sync files changed in the last git commit
npx obsidian-git-livesync sync --git
# Watch for changes in real time
npx obsidian-git-livesync watch .CLI Reference
Global Options
| Flag | Description |
|------|-------------|
| --version | Show version number |
| --config <path> | Path to config file (default: .obsidian-git-livesync.json) |
| --verbose | Log each file as it syncs |
| --dry-run | Show what would be synced without writing to CouchDB |
Commands
| Command | Description |
|---------|-------------|
| sync [files...] | Sync specific files to CouchDB |
| sync --git | Sync files changed in the last git commit |
| sync --all | Sync all files in the vault directory |
| watch [dir] | Watch a directory and sync changes in real time |
| validate | Test connection to CouchDB |
| init | Create a template config file |
Sync Options
| Flag | Description | Default |
|------|-------------|---------|
| --git | Sync files from last git commit | - |
| --all | Sync entire vault directory | - |
| --delete | Delete files from CouchDB that no longer exist on disk | false |
| --extensions <exts> | Comma-separated file extensions | .md |
| --debounce <ms> | Debounce interval in milliseconds | 200 |
Watch Options
| Flag | Description | Default |
|------|-------------|---------|
| --extensions <exts> | Comma-separated file extensions to watch | .md |
| --debounce <ms> | Debounce interval in milliseconds | 200 |
Git Hook Setup
A post-receive hook is included for bare git repos. When you push to the repo, it automatically syncs changed markdown files to CouchDB.
Installation
# If you cloned this repo:
cp hooks/post-receive.sh /path/to/repo.git/hooks/post-receive
# Or if installed via npm (npx or local install):
cp node_modules/obsidian-git-livesync/hooks/post-receive.sh /path/to/repo.git/hooks/post-receive
chmod +x /path/to/repo.git/hooks/post-receiveThe hook:
- Only triggers on pushes to
mainormaster - Detects changed
.mdfiles between the old and new revisions - Calls
npx obsidian-git-livesync syncwith those files - Handles initial pushes (empty repo) correctly
To sync additional file types, edit the EXTENSIONS variable at the top of the hook script.
Docker Compose
The included docker-compose.yml runs CouchDB 3 locally:
services:
couchdb:
image: couchdb:3
ports:
- "5984:5984"
environment:
COUCHDB_USER: admin
COUCHDB_PASSWORD: password
volumes:
- couchdb_data:/opt/couchdb/dataAfter starting the container, run bash scripts/setup-couchdb.sh to:
- Configure single-node cluster mode
- Create the
obsidian-livesyncdatabase - Enable CORS for Obsidian
- Set request and document size limits
- Require authenticated access
Configuration
Configuration is loaded in this priority order: environment variables > config file > defaults.
Config File
Created by obsidian-git-livesync init at .obsidian-git-livesync.json:
{
"couchdbUrl": "http://localhost:5984",
"couchdbUser": "admin",
"couchdbPassword": "password",
"couchdbDatabase": "obsidian-livesync",
"vaultRoot": ".",
"extensions": [".md"],
"debounce": 200
}Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| COUCHDB_URL | CouchDB server URL | http://localhost:5984 |
| COUCHDB_USER | CouchDB username | (required) |
| COUCHDB_PASSWORD | CouchDB password | (required) |
| COUCHDB_DATABASE | Database name | obsidian-livesync |
| VAULT_ROOT | Root directory for vault files | current directory |
| PASSPHRASE | Encryption passphrase (if LiveSync uses one) | (none) |
Environment variables override values in the config file.
How It Works
Obsidian's Self-hosted LiveSync plugin stores files in CouchDB using a specific document format:
Metadata document (
_id= file path, e.g.notes/hello.md)type:"plain"children: array of chunk IDsctime,mtime,size: file timestamps and size
Leaf (chunk) document (
_id=h:+ SHA-256 hash)type:"leaf"data: file content (plain text for text files)
This tool writes files in that exact format. When a file is synced:
- Content is hashed to produce a chunk ID (content-addressable)
- A leaf document is created (or reused if the same content already exists)
- A metadata document is created or updated with the leaf reference
Once written to CouchDB, all LiveSync clients connected to the same database replicate the change automatically via CouchDB's replication protocol.
Note on livesync-commonlib: The official DirectFileManipulator API lives in vrtmrz/livesync-commonlib but is Deno-first and not installable via npm. This project uses a direct CouchDB REST API client that speaks the same document format. See src/couchdb-client.ts.
Limitations
- Text files only. Binary files (images, PDFs, etc.) are not synced. Only text-based extensions are supported (
.md,.txt,.canvas,.csv,.svg,.html,.css,.js,.xml). - Requires CouchDB + LiveSync plugin. You need a running CouchDB instance and Obsidian's Self-hosted LiveSync plugin configured to use it.
- Schema coupling. The document format is reverse-engineered from LiveSync's internal storage. If LiveSync changes its format in a future update, this tool may need corresponding updates.
- No conflict resolution. If the same file is edited both via this tool and via Obsidian simultaneously, CouchDB will create a conflict. LiveSync's conflict resolution in Obsidian will handle it, but the behavior depends on your LiveSync settings.
- Single-chunk storage. Currently stores each file as a single chunk. Very large files (>1MB) may benefit from multi-chunk splitting in the future, matching LiveSync's chunking behavior.
