An Obsidian plugin for synchronizing notes across devices using Seafile, an open-source, self-hosted file sync and share solution.
seafile-ignore.txt, shared with official Seafile clients instead of using plugin-specific ignore configuration.The initial synchronization downloads the remote library. If the local vault is not empty, its existing files are merged and may be uploaded; start with an empty vault unless that merge is intentional.
After onboarding, the individual server, account, repository, and sync controls remain available in the plugin settings. Manual-token login asks for your account name so synchronized changes have the correct attribution. Account tokens, repository tokens, and remembered encrypted-library passwords are stored with Obsidian SecretStorage and are removed from the plugin's data.json during migration.
Obsidian-aware settings separately control main configuration, appearance and snippets, hotkeys, core-plugin configuration, the active community-plugin list, community-plugin installation files, standard data.json settings, and additional plugin data. These library-wide selections are stored in the versioned .obsidian-seafile-sync.json file at the vault root so every Seafile Sync device follows the same content policy. Existing installations seed that shared policy from their current settings when the library does not yet have one; devices joining an existing library adopt its policy. Per-plugin overrides can select standard, all, or ignore behavior where a plugin stores important user content or disposable runtime data outside data.json.
Smart conflict handling is enabled by default and remains a device-local preference. It performs bounded three-way merges using the last synchronized Seafile object as the common ancestor: Markdown and ordinary text merge by independent line edits, settings JSON merges recursively by key, Canvas arrays merge by stable object IDs, and Bases views merge by stable names. Concurrent changes to the same value, unparseable data, unavailable merge bases, binary files, and oversized files fall back to conflict copies. Users who prefer manual review can select Always create conflict copies.
You can optionally edit seafile-ignore.txt from the plugin settings or directly in the library root. It uses Seafile's standard ignore syntax and is shared with standard Seafile clients. Newly generated files contain a clearly marked managed-defaults block followed by a user-owned section; category changes update only the managed block. Fine-grained plugin allowlists cannot be fully represented by Seafile's exclusion-only pattern language, so the plugin's policy layer remains authoritative for those choices.
To trigger a sync immediately, click "Sync now" in the settings, or run "Seafile: Sync now" from the command palette (assign it a hotkey if you use it often).
Realtime sync is enabled by default. It connects to <server>/notification; a different notification-server URL can be entered in settings. The status row shows whether the WebSocket is connected or periodic synchronization is currently providing the fallback. The Seafile server must have its notification service enabled and exposed through the reverse proxy.
Per-file sync status and transfer progress are shown next to file names in the explorer. The text next to the sidebar sync button can be shown always, only during active synchronization (the default), or never; its complete hover tooltip is always retained. Development mode logs phase timings, transferred bytes, prepared-block reuse, and aggregate throughput to the developer console.
Open Seafile history from the ribbon, plugin settings, or command palette. Its remote-history sections include:
A/M/D file list that can be progressively revealed or shown completely. Clicking a text file lazily loads exact +/− line counts and an inline diff, including additions against an empty file and deletions to an empty file. Markdown is compared up to 16 MiB; JSON and Canvas files up to 2 MiB are parsed and normalized so formatting and object-key order do not create noise. Common text formats such as iCalendar are recognized directly, while unknown extensions use bounded UTF-8 and control-byte detection. Large line counts use a scalable patience-style diff instead of hiding the comparison. Restoring separately compares the selected commit with the current remote HEAD, reports files that will be modified, restored, or removed, and requires the library name as confirmation. The plugin synchronizes first, verifies that the remote HEAD did not change during review, and records the previous HEAD as an undo point. It uses Seafile's atomic library-revert API when permitted; read/write collaborators, encrypted libraries whose server-side password is unavailable, and older servers fall back to reconstructing the snapshot as a new plugin commit.Use the sidebar's File versions tab to select the active file, enter a vault-relative path, or follow a file path from Activity without leaving the history view. Open Seafile version history in a file's context menu opens the same timeline in a larger modal. Markdown and other supported text versions show changes from the previous retained version by default; Current file switches the comparison to the file now in the vault. JSON and Canvas use the same normalized structured comparison as snapshots. Images show a preview, and other files show revision metadata. Restoring writes through Obsidian's adapter, preserves the historical modification time, and then enters the normal synchronization pipeline.
Seafile only creates server versions when a commit reaches the server. To retain work while offline, enable Local offline checkpoints in plugin settings. The plugin periodically stores content-addressed checkpoints for Markdown and Canvas files inside its protected, device-specific plugin data. Interval, retention, and storage limit are configurable, identical content is deduplicated, and local history can be cleared independently. The checkpoint index removes stale entries if an underlying local object is no longer available. These checkpoints are not vault files and do not sync through Seafile.
A local checkpoint can be restored without publication, or restored and published explicitly. Publication is allowed only when the remote HEAD still matches the checkpoint's recorded base; if another device changed the library, the plugin refuses direct publication and asks you to restore locally so ordinary synchronization and conflict handling remain in control. This gives offline recovery points without manufacturing misleading server history while disconnected.
History availability is governed by the Seafile server's file-history and trash retention settings. Expired server versions cannot be reconstructed by the plugin. Local checkpoints complement that retention but remain available only on the device that created them.
The same sidebar also contains Sync issues, a device-local record of conflicts, safety stops, interrupted-download recovery, and recurring errors. Repeated identical errors are grouped, paths can be opened directly, and handled entries can be marked resolved and cleared. File conflicts can be reviewed in place: safe text and JSON files show the current library version against the preserved local copy, then let the user keep the current version, restore the preserved local version, or retain both. Resolution verifies that neither reviewed file changed before applying the choice. If the shared policy file is malformed or uses an unsupported version, synchronization stops safely and the issue offers a validated JSON editor or an explicit reset to this device's current policy selections.
Before changing files, the plugin calculates the complete synchronization plan. By default, it requests explicit confirmation if a sync would delete at least 500 files, or at least 20 files representing 25% of the previously synchronized files. This applies independently to deletion from the local device and the remote library; the absolute threshold is editable and protection can be disabled in settings.
The same preflight rejects filenames that are not portable to Windows, detects case-colliding sibling paths, and prevents uploads or remote deletions when the selected library has become read-only. Read-only libraries can still download remote changes until a local change requires write access.
Use Verify vault to compare the current vault, local sync index, and remote metadata without changing files. Diagnostics report provides inspectable support JSON containing versions, platform, feature and connection states, policy values, and issue counts while excluding credentials, server and repository identifiers, file paths, issue messages, and commit IDs. If the index is damaged or stale, Rebuild sync index removes only the device-local baseline and performs a fresh merge. Existing vault files are preserved, and differing local and remote files enter normal conflict-copy handling. Use destructive Clear vault only when you intentionally want to remove local synchronized files.
Sync issues retains conflicts, safety and preflight stops, recovery actions, repository loss, and generic failures only after automatic retries are exhausted. Self-healing races such as a file changing during upload or another device replacing Seafile HEAD remain visible in logs and temporary sync status but are not kept as user-facing issues.
seafile-ignore.txt is created automatically when absent. Its managed section covers common project state, device-specific workspace layouts, disabled configuration categories that Seafile patterns can express, and this plugin's private operational state. Its rules prevent new matching local files from being uploaded; files already present on the server may still be downloaded by standard Seafile clients. The plugin's Obsidian-aware policy can additionally retain an excluded remote entry without downloading it, and safely downloads it if that category is enabled later. The plugin installation and its device-specific synchronization database are always protected internally.
Downloads are written to a temporary file and verified before replacing an existing local file. If local and remote edits overlap or cannot be merged safely, the local version is preserved as an SFConflict copy and synchronized alongside the remote version.
After a commit is published, changed local sync records are persisted with one batched journal append and one coalesced explorer refresh. Large journals are then compacted into the main sync database.
If the configured repository is deleted or access is revoked, synchronization and realtime notifications stop immediately. Local files are preserved while the user restores access or chooses another repository.
.obsidian. Full sync traversal still discovers them, so these changes are synchronized by the next periodic, manual, or startup sync rather than necessarily triggering an immediate sync themselves.Open an issue in this repository's tracker for bugs, feature requests, or questions.
The test suite exercises the current Seafile HTTP contract through a real local HTTP boundary without credentials. Maintainers can additionally run the read-only smoke test against a deployment with SEAFILE_URL, SEAFILE_TOKEN, SEAFILE_REPO_ID, and SEAFILE_REPO_TOKEN set: npm run test:seafile-smoke.
Original plugin by @conql. This continuation is maintained by @ryanravn, with additional contributions from @tionis.