Livan Kumar49 downloadsSync your vault across all devices using your own GitHub account. Free forever.
Sync your Obsidian vault across every device using your own free private GitHub repo.
No subscription. No cloud fees. Works on desktop (Windows / macOS / Linux) and mobile (iOS / Android).
Your GitHub Account
│
├── obsidian-personal-notes ← Vault 1 (all your devices sync here)
├── obsidian-work-notes ← Vault 2 (separate repo, same account)
└── obsidian-research ← Vault 3 (separate repo, same account)
Desktop ──┐
Mobile ──┼──▶ obsidian-personal-notes (same private GitHub repo)
Laptop ──┘
| Tool | Version | Install |
|---|---|---|
| Node.js | 18+ | https://nodejs.org |
| npm | 9+ | Bundled with Node.js |
| Git | any | https://git-scm.com |
git clone https://github.com/livan116/github-valut-sync.git
cd github-valut-sync
npm install
This installs:
isomorphic-git — pure-JS git engine (works on mobile, no native binaries)esbuild — fast bundlertypescript — type checkerobsidian — type definitions only (not bundled)You need to register a free OAuth App so users can log in with their GitHub account.
This is done once — the client_id is then baked into the plugin code.
Click OAuth Apps → New OAuth App
Fill in the form:
| Field | Value |
|---|---|
| Application name | GitHub Vault Sync |
| Homepage URL | https://github.com/livan116/github-valut-sync |
| Authorization callback URL | https://obsidian.md (placeholder — Device Flow doesn't use this) |
Click Register application
Copy the Client ID (looks like Ov23li...)
Copy .env.example to .env and set your Client ID:
CLIENT_ID=Ov23liYOUR_ACTUAL_ID
Do not generate a Client Secret — Device Flow doesn't need it and secrets must never be embedded in plugin code.
# Development build (watch mode — rebuilds on every save)
npm run dev
# Production build (minified, no source maps)
npm run build
Both commands output a single main.js file in the project root.
Watch mode (npm run dev) keeps running and rebuilds automatically as you edit source files. Leave it running while you test in Obsidian.
github-valut-sync/
├── src/
│ ├── main.ts # Plugin entry point — wires everything together
│ ├── types.ts # All TypeScript interfaces & types
│ ├── constants.ts # App-wide constants (CLIENT_ID injected here at build)
│ ├── auth/
│ │ └── github-device.ts # GitHub OAuth Device Flow (no server needed)
│ ├── github/
│ │ └── api.ts # GitHub REST API wrapper (create repo, get user)
│ ├── sync/
│ │ ├── fs-adapter.ts # Bridges Obsidian DataAdapter → isomorphic-git fs
│ │ ├── git-sync.ts # Core git operations: init / clone / pull / push
│ │ ├── queue.ts # Debounced sync queue with mutex (no race conditions)
│ │ └── conflict.ts # Conflict diff summary helper
│ └── ui/
│ ├── settings-tab.ts # Plugin settings page
│ ├── conflict-modal.ts # Side-by-side conflict resolution modal
│ └── status-bar.ts # Live sync indicator in the status bar
├── .env # Local secrets — git-ignored, never committed
├── .env.example # Template — copy to .env and fill in CLIENT_ID
├── manifest.json # Obsidian plugin manifest
├── package.json
├── tsconfig.json
├── esbuild.config.mjs
└── main.js # Built output (git-ignored, generated by build)
After running npm run build:
YourVault/.obsidian/plugins/github-vault-sync/
main.js
manifest.json
Tip for development: You can symlink the project directory directly into your vault's plugins folder so the built main.js is picked up automatically after each build:
# Windows (run as Administrator)
mklink /D "C:\path\to\vault\.obsidian\plugins\github-vault-sync" "C:\path\to\github-valut-sync"
# macOS / Linux
ln -s /path/to/github-valut-sync /path/to/vault/.obsidian/plugins/github-vault-sync
https://github.com/livan116/github-valut-syncDo this on every device where you want sync. Use the same GitHub account each time.
Go to Settings → GitHub Vault Sync (scroll down in the left sidebar under Community Plugins).
You will see a screen like this:
┌─────────────────────────────────────────┐
│ Open this URL in your browser: │
│ https://github.com/login/device │
│ │
│ AB12-CD34 │
│ │
│ Waiting for approval in browser… │
└─────────────────────────────────────────┘
Your browser will open automatically. If it doesn't, copy the URL manually.
AB12-CD34)Back in Obsidian you'll see:
Connected as @your-github-username. Vault syncing started!
The plugin will:
obsidian-<your-vault-name> and push all your files.Once connected, the plugin runs silently in the background:
| Event | What happens |
|---|---|
| You save / edit a file | Changes are committed and pushed after 3 seconds of inactivity |
| You open Obsidian | Latest changes are pulled from GitHub |
| You close Obsidian | Any pending changes are flushed and pushed |
| Two devices edit same file | Conflict modal appears next time you open Obsidian |
The bottom-right corner shows the current sync state:
| Indicator | Meaning |
|---|---|
✓ MultiSync |
All good, fully synced |
↓ Syncing… |
Pulling from GitHub |
↑ Syncing… |
Pushing to GitHub |
⚠ Conflict |
Two devices edited the same file — action needed |
✗ Sync Error |
Network or auth issue — hover for detail |
Click the status bar item to trigger an immediate manual sync at any time.
Ctrl/Cmd + P) → search "MultiSync: Sync vault now"A conflict happens when the same file is edited on two devices before either has synced.
When the plugin detects a conflict, a modal appears automatically:
┌──────────────────────────────────────────────────┐
│ Sync Conflict (1 / 2) │
│ File: notes/daily/2025-06-01.md │
│ │
│ Changed lines: │
│ Line 4: │
│ - meeting at 3pm │
│ + meeting at 4pm │
│ │
│ YOUR VERSION │ REMOTE VERSION │
│ ────────────────── │ ───────────────── │
│ # June 1 │ # June 1 │
│ meeting at 3pm │ meeting at 4pm │
│ │
│ [Keep Mine] [Keep Theirs] [Open in Editor] │
└──────────────────────────────────────────────────┘
| Button | Action |
|---|---|
| Keep Mine | Use the version from this device, discard remote changes |
| Keep Theirs | Use the remote version, discard local changes |
| Open in Editor | Close modal, open the file — edit it manually, then sync again |
After resolving, the file is immediately committed and pushed.
Each vault gets its own separate repo automatically. There's nothing extra to configure.
Vault: "Personal Notes" → github.com/you/obsidian-personal-notes
Vault: "Work" → github.com/you/obsidian-work
Vault: "Research" → github.com/you/obsidian-research
On each device:
| Setting | Default | Description |
|---|---|---|
| Auto-sync | On | Automatically sync on file changes |
| Sync debounce | 3000 ms | How long to wait after your last keystroke before syncing |
| Excluded patterns | See below | Files/folders that will never be synced |
.obsidian/workspace
.obsidian/workspace.json
.obsidian/plugins/*/data.json
These are excluded because they change frequently, are device-specific, and don't need to be shared.
To add more exclusions, open Settings → GitHub Vault Sync → Excluded patterns and add one pattern per line. Wildcards (*) are supported.
Example — exclude all files in a Private folder:
Private/*
The 8-character code has a 15-minute expiry. Click Connect GitHub again to get a fresh code.
You clicked Cancel on the GitHub authorization page. Click Connect GitHub to try again.
✗ Sync Error✓ MultiSync.Ctrl/Cmd + P → "Sync vault now")..git folder visible in vaultThe .git folder is hidden in Obsidian by default. If you see it, go to
Settings → Files & Links → Excluded files and add .git.
Run npm install to install devDependencies. The obsidian package provides types only.
Copy .env.example to .env and fill in your GitHub OAuth App Client ID.
Run npm install — a dependency may have been added. Then re-run npm run build.
Q: Is my data private?
A: Yes. The plugin creates a private GitHub repo. Only your GitHub account can access it.
Q: Does the plugin developer see my notes?
A: No. The plugin runs entirely on your device and connects directly to your own GitHub account. There is no intermediate server.
Q: What happens if I edit the same file on two offline devices?
A: When both devices come online, the plugin detects the conflict and shows you the resolution modal.
Q: Can I use this with an existing vault that already has files?
A: Yes. On first connection, the plugin pushes all your existing files to the new GitHub repo.
Q: Does this work with Obsidian's built-in sync?
A: It's designed to replace, not complement, Obsidian Sync. Using both at once is not recommended as they may conflict.
Q: What is the storage limit?
A: GitHub repos have a soft limit of 1 GB per repo. A typical Obsidian vault of markdown files is well under 100 MB.
Q: Can I view my notes on GitHub directly?
A: Yes — GitHub renders Markdown files beautifully. Browse your private repo at github.com/your-github-username/obsidian-<vaultname>.
Q: Why does the plugin need the repo OAuth scope?
A: The repo scope is the minimum required to create and push to private repositories. Without it GitHub only allows access to public repos.
.obsidian/plugins/github-vault-sync/data.json) on each device. It never leaves your device except to communicate directly with GitHub's API.repo scope — the minimum required to create and access private repositories.| Concern | Solution | Why |
|---|---|---|
| Auth | GitHub OAuth Device Flow | No server or callback URL needed |
| Storage | User's own private GitHub repo | Free, private, version-controlled |
| Sync engine | isomorphic-git (pure JS) | Works on iOS/Android — no native binaries |
| File system | Custom adapter wrapping DataAdapter | Obsidian's API works on all platforms |
| HTTP | Obsidian's requestUrl API |
Bypasses CORS, works on mobile |
Key constraints:
require('fs') — always use the fs-adapter so mobile works.git-sync.ts::sync().requestUrl from obsidian for HTTP — never fetch or axios.this.saveData().Pull requests welcome!
# 1. Fork and clone
git clone https://github.com/livan116/github-valut-sync.git
cd github-valut-sync
# 2. Install deps
npm install
# 3. Copy .env.example to .env and set your CLIENT_ID
cp .env.example .env
# 4. Start watch mode
npm run dev
# 5. Symlink into your test vault (see Part 2 above)
# 6. Make your changes — Obsidian hot-reloads the plugin automatically
# 7. Run a type check before submitting
npx tsc --noEmit
For bugs and feature requests, open an issue.
MIT © 2025 Livan Kumar