Sync a vault across devices through a cloud storage service.
Sync a vault across devices through a cloud storage service.
Seamsync is an Obsidian plugin that keeps one person's vault the same on all of their devices, desktop and mobile. This release syncs through Dropbox.
Apps/<app folder name> in Dropbox. Each synced vault (a Remote) is a
subfolder there, chosen or created when you connect. It asks for the
files.metadata.read, files.content.read, files.content.write and
account_info.read scopes and nothing else..seamsync
folder there; do not modify it.<<<<<<<, =======, >>>>>>>) that you resolve in the
editor: keep one side, keep both, or edit.Name (conflict <device name> YYYY-MM-DD HHmm).ext..gitignore syntax, the
extensions treated as text, the size limit and how to handle names
Dropbox cannot store apply to every device.Dot-files and dot-folders such as .git and .trash never sync, except
the configuration folder categories you turn on.
Seamsync is not in the Obsidian community plugin list. To install it,
download main.js, manifest.json and styles.css from a release of
this repository and copy them into <vault>/.obsidian/plugins/seamsync/,
then enable Seamsync in Settings → Community plugins. A build
from source (see Development) connects to Dropbox only
when it is built with SEAMSYNC_DROPBOX_APP_KEY set.
It needs Obsidian 1.11.4 or later.
Repeat on every other device, choosing the same folder.
The refresh token is kept in Obsidian's secret storage on the device. It is
not written to the vault, to the plugin's data.json or to Dropbox.
Disconnect revokes it.
| Command | What it does |
|---|---|
| Sync now | Syncs right away. Also lifts a deletion guard pause. |
| Full reconcile | Syncs by listing the whole Remote instead of reading the change feed. |
| Open sync window | Opens the sync window. |
| Show conflicts / Show skipped files / Show activity / Show help | Opens the sync window on that tab. |
| Next conflict / Previous conflict | Moves between conflict blocks in the open note. |
| Restore local configuration | Restores this device's version of a configuration file replaced in a conflict. |
| Reconnect to Dropbox | Offered only when Dropbox asks for a new login. |
On desktop the status bar shows the sync state; on mobile a ribbon icon does. Selecting it opens the sync window.
This device only:
| Setting | Default | Range |
|---|---|---|
| Post-edit pause (seconds) | 2 | 1 to 60 |
| Polling interval (seconds) | 60 | 10 to 3600 |
| Per-request limit (MiB) | 16 | 1 to 19 |
| Deletion guard: files | 100 | 1 to 100000 |
| Deletion guard: percent | 50 | 1 to 100 |
| Sync settings and hotkeys / Sync themes and snippets / Sync plugins | off |
All devices, stored on the Remote and saved with Apply to all devices:
| Setting | Default |
|---|---|
| Names Dropbox cannot store | Skip and list them |
| Text files | md, txt |
| Ignore list | empty |
| Size limit (MiB) | 100 |
The design is recorded in docs/adr/ and the terms in GLOSSARY.md:
main.js and
styles.css.Tools: Node.js, pnpm, lefthook, gitleaks, typos, shellcheck and shfmt, at the versions pinned in mise.toml. With mise:
mise install
pnpm install --frozen-lockfile
lefthook install
mise run setup-dev does all three.
A dev container is provided in .devcontainer/.
The build bundles a Dropbox app key, which is never committed. Set
SEAMSYNC_DROPBOX_APP_KEY in the environment or in a git-ignored .env
file. A build without it succeeds with a warning, but cannot connect to
Dropbox: its connect window says so. The app must have App Folder access.
| Command | What it does |
|---|---|
pnpm build |
Type-checks, then bundles the plugin into dist/, minified. |
pnpm dev |
Rebuilds dist/ on every change, with inline source maps. |
pnpm typecheck |
Type-checks. |
pnpm lint |
Lints with eslint-plugin-obsidianmd; any warning fails. |
pnpm lint:md |
Lints the tracked Markdown files. |
pnpm lint:sh |
Lints the shell scripts and checks their format. |
pnpm spell |
Spell-checks with typos. |
pnpm knip |
Finds unused files, exports and dependencies. |
pnpm format |
Formats the tracked files with Prettier. |
pnpm format:check |
Checks the format, changing nothing. |
pnpm test |
Runs the unit and plugin tests. |
pnpm test:coverage |
Runs the tests; fails below the coverage thresholds. |
mise run check runs every check that changes nothing.
The git hooks (lefthook.yml) check:
pnpm audit, and
a secret scan of the commits being pushed.Releases are built by the GitHub Actions workflow
.github/workflows/release.yml, started
by pushing a tag equal to the version in manifest.json and
package.json (X.Y.Z, no v prefix). It takes the key from the
repository's Actions secret SEAMSYNC_DROPBOX_APP_KEY, which the
maintainer creates in the repository's settings, and stops when that
secret is unset or empty, attests main.js and styles.css, and
creates a draft release, which the maintainer publishes by hand.
pnpm test runs the unit tests and the tests of the whole plugin on a
fake vault and a fake Dropbox: no network, no Obsidian. The pre-commit
hook runs it.pnpm test:e2e:desktop, pnpm test:e2e:android and
pnpm test:e2e:pair drive a real Obsidian on the desktop and on an
Android emulator. They run on Linux only and need a setup done once:
see test/e2e/README.md.