Low Nam Lee545 downloadsDeterministic desktop and mobile vault sync through GitHub with automatic recovery snapshots.
Oppsyncer is a small Obsidian plugin that synchronizes a vault through a private GitHub repository on desktop and mobile without requiring a local Git binary.
It is designed for one person who edits one device at a time but wants protection from delayed polling, offline edits, or an accidentally stale second device.
Public beta: Oppsyncer is under active development. Test with a disposable vault and repository before trusting it with primary notes.
The first device that successfully advances the remote main branch wins.
Oppsyncer never force-pushes main and does not create merge commits.
If two devices start from commit A, mobile pushes B, and desktop has an
unpublished edit C, desktop performs this sequence:
C.obsyncer-recovery/desktop/2026-08-18T13-30-00Z-deadbeef.B and make the local vault match it.C can be recovered.If both devices race to push, GitHub accepts only the first normal fast-forward update. The rejected candidate automatically becomes the losing device's recovery branch.
.obsidian synchronization is opt-in. Oppsyncer's credential/state file,
workspaces, caches, file-recovery state, Obsidian Sync configuration, legacy
sync metadata, SQLite sidecars, .git/**, Git control files, and .trash/**
are never synchronized.Common small edits use GitHub's atomic commit mutation: the expected remote head, file changes, commit, and branch update are handled in one request. A stale device is rejected before the branch moves and follows the same verified recovery path. Large batches retain the Git Database fallback. Unchanged remote polls use ETags, and unchanged local files reuse their size, modification time, and verified Git blob hash.
Enable Sync Obsidian configuration to synchronize safe files under the
vault's configuration folder, normally .obsidian. This includes application
settings, hotkeys, themes, snippets, community-plugin code and settings, and
stable plugin data such as LearnKit's committed SQLite database files.
Hidden configuration changes are discovered by startup/foreground scans and a periodic full inventory. Some settings and newly downloaded plugins require an Obsidian restart before the app uses them.
The following remain device-local regardless of user exclusions:
.obsidian/plugins/obsyncer/data.json* (GitHub token and sync baseline).obsidian/workspace*.json, caches, and file-recovery state.obsidian/sync.json and legacy Git sync metadata/logs-wal, -shm, and -journal sidecarsOther community plugins may store their own credentials in data.json. Add
those paths under Additional exclusions before enabling configuration sync.
Oppsyncer requires a private GitHub repository and a fine-grained GitHub token limited to that repository with Contents: Read and write.
The local vault name is only a display name. For example, a desktop vault named
Obsidian Vault and a mobile vault named Testing can safely use the same
repository. Oppsyncer pairs them using a repository identity stored at
.obsyncer/vault.json; it does not require folder or vault names to match.
The first setup must have one empty side:
Do not run Oppsyncer together with Obsidian Git, GitHub Gitless Sync, Obsidian Sync, Syncthing, or another tool that writes the same vault.
api.github.com for only the repository configured in its
settings. The recovery command can open the configured repository on
github.com.pnpm install
pnpm run check
Maintainers can run pnpm test:github-live while authenticated with GitHub CLI.
It creates a uniquely named private repository, verifies the sibling-commit race
and recovery-ref behavior against GitHub, and deletes the repository afterward.
The production build produces main.js. For manual installation, copy
main.js, manifest.json, and styles.css into:
<vault>/.obsidian/plugins/obsyncer/
Oppsyncer is a fork of GitHub Gitless Sync by Silvano Cerza. It remains licensed under AGPL-3.0-only; see LICENSE.