Shangeeth Sivan156 downloadsSync your vault across devices through a self-hosted Syncidian server, with optional GitHub backup and MCP for AI tools.
Your data stays with you. Sync your knowledge. Back it up. Connect your AI.
Obsidian plugin: install Syncidian from Community plugins (or BRAT / sideload). Point it at your Syncidian server with a sk_sync_… token. This plugin does not use Obsidian Sync.
Syncidian is an open-source, self-hostable Obsidian synchronization and AI bridge.
It runs as an Obsidian plugin on your devices and connects to a lightweight Syncidian server that coordinates synchronization between them.
Each signed-in user can connect one private GitHub repository. GitHub is the durable, versioned source of truth for that user's vault. The public site is a one-page story: join the waitlist and sign in with GitHub on Syncidian.com, or sign in with email on a self-hosted host. GitHub sign-in is hidden on the hosted landing (tap the app name six times to reveal it) and limited to SYNCIDIAN_GITHUB_ALLOWED_EMAILS until public launch. Operators use a private hostname (SYNCIDIAN_ADMIN_HOST, for example admin.syncidian.com on Tailscale) or an unlisted path (SYNCIDIAN_ADMIN_PATH, default /admin) — neither is linked from the landing page. Admins manage users and an optional instance GitHub App, and never see vault or GitHub data.
Syncidian also includes a built-in MCP server, allowing compatible AI tools and agents to securely interact with your Obsidian knowledge base.
The server is designed to be written in Go and deployed with a simple Dockerfile, making self-hosting as easy as:
docker build -t syncidian .
docker run -d \
--name syncidian \
-p 8080:8080 \
syncidian
Self-host Syncidian for free. A managed service is planned at $1/month; it is not available yet.
One click deploys this repo on Railway. Attach a volume at /data before you create the admin so users survive redeploys. Details: Deploy on Railway.
Buy me a coffee if Syncidian is useful.
This repository is ready to run. Clone it, start the server, install the Obsidian plugin, and sync.
With Docker (recommended):
git clone https://github.com/shangeethsivan/Syncidian.git
cd Syncidian
docker compose up --build -d
Self-host operators open /admin. You can skip Tailscale — leave SYNCIDIAN_ADMIN_HOST unset, or set SYNCIDIAN_ADMIN_PRIVATE=0. Optional mesh lock-down: Hide admin.syncidian.com on Tailscale.
Open http://localhost:8080. The public page explains Syncidian and, on a self-hosted instance, lets people sign up with email — a GitHub App is not required to create an account. On Syncidian.com people use Continue with GitHub (hidden until you tap the app name six times). Operators open /admin (or SYNCIDIAN_ADMIN_PATH), or a private hostname (SYNCIDIAN_ADMIN_HOST, see Hide admin.syncidian.com on Tailscale) once to create the first admin — that surface is not advertised on the landing page. Persist /data so that admin and later users survive deploys. Follow Set up the GitHub App only if you want GitHub sign-in or per-user backup. A Help button on the operator page and the signed-in dashboard walks through the rest. After sign-in, a regular user can connect one GitHub repository, then creates an access token (sk_sync_…). Admins can also mint a one-time token for a vault user from Users (they still cannot sync as admin). Copy the token once — it is not shown again.
Without Docker (Go 1.22+):
go run ./cmd/syncidian serve
Data is stored in ./data by default (SYNCIDIAN_DATA to change it). Docker Compose persists it at /data via a named volume (not a Dockerfile VOLUME, which Railway and some builders reject). Without that volume, a new deploy starts with an empty database — no users, no GitHub App, empty vaults.
Users, GitHub App credentials, and vault files live in SQLite on disk. Railway’s container filesystem is empty on every deploy unless you attach a volume.
Dockerfile from railway.json./data. Do this before creating the admin or registering the GitHub App. railway.json sets requiredMountPath to /data so a deploy without a volume fails instead of silently resetting the instance, and overlapSeconds to 0 so two replicas do not share SQLite during a rollout.PORT and uses RAILWAY_PUBLIC_DOMAIN for the dashboard URL unless you set SYNCIDIAN_PUBLIC_URL.SYNCIDIAN_BOOTSTRAP_USER, SYNCIDIAN_BOOTSTRAP_PASSWORD. To keep the GitHub App if the volume is missing, also set SYNCIDIAN_GITHUB_APP_* (see Set up the GitHub App). Set SYNCIDIAN_DATA_KEY (32-byte hex) so GitHub App secrets stay encrypted even if syncidian.db is copied off the volume. Until public GitHub sign-in, set SYNCIDIAN_GITHUB_ALLOWED_EMAILS to the GitHub emails that may complete OAuth (JSON array, commas, or one per line). Hosted should include [email protected]. Joining the waitlist does not grant access — add each person to this variable, then redeploy./admin. People can then sign up with email on /. Register the GitHub App (walkthrough) only if you want GitHub sign-in or backup. /admin warns if the data directory is still ephemeral. On the hosted landing, tap Syncidian six times to reveal GitHub sign-in. Point the plugin at that URL with that user's token.Health check: GET /health. Agents can also fetch /robots.txt, /auth.md, /.well-known/mcp/server-card.json, and markdown for GET / (Accept: text/markdown). /robots.txt disallows the operator path (/admin by default) and operator APIs; that HTML also sends X-Robots-Tag: noindex so search engines should not list it. The operator page is not in /sitemap.xml and is not linked from /. If a CDN (Cloudflare AI Crawl Control) injects its own robots.txt, turn that off so the origin file is what crawlers see.
You still run a Syncidian server (step 1). The plugin is only the Obsidian client.
From Community plugins:
sk_sync_… value from the dashboardMacBook ProIf Browse does not show Syncidian yet, install BRAT, then add shangeethsivan/Syncidian. BRAT needs a GitHub Release whose tag matches manifest.json version and whose Assets list includes main.js, manifest.json, and styles.css (not only the automatic source zip). See Publishing.
Sideload from a running Syncidian server (no git clone) or from this repo:
Syncidian is a mobile-capable community plugin (isDesktopOnly: false). It does not use Node.js, Electron, or a local Git binary — that is why Obsidian Git and similar plugins never run on Android or iOS, and why this one can.
# from a deployed instance — downloads only the three plugin files
./scripts/install-plugin.sh "/path/to/YourVault" "https://your-syncidian.example"
# or open https://your-syncidian.example/assets/obsidian.zip
# from this repository
chmod +x scripts/install-plugin.sh
./scripts/install-plugin.sh "/path/to/YourVault"
On a Mac this is often something like:
./scripts/install-plugin.sh "$HOME/Documents/Obsidian/MyVault"
Or copy these files by hand into {Vault}/.obsidian/plugins/syncidian/:
plugin/manifest.jsonplugin/main.jsplugin/styles.cssThen Settings → Community plugins → turn Restricted mode off → enable Syncidian → Connect as above.
Repeat the token (and install, if you sideloaded) on each device (Windows, Mac, Android, iOS). Create one token per person; the same user can register many devices.
Step-by-step (Restricted mode, Community plugins / BRAT / copying files, then Connect): Enable on Android and iOS.
On a phone, leave Syncidian.com selected or choose Custom Domain with a public https:// address. http://localhost:8080 is the phone itself, not your computer. iOS often blocks plain http://.
Create one GitHub App for this instance before people sign in with GitHub. Step-by-step: Set up the GitHub App.
Short version: create the first admin at /admin. Self-hosted users sign in with email. The GitHub App is optional — open /admin → Create GitHub App, or set SYNCIDIAN_GITHUB_APP_*, if you want GitHub sign-in or backup. After identity, a user can install the app on one repository. Syncidian always uses the main branch — other branches are not supported. Personal access tokens and deploy keys are not used. That repository is bound to that user only. Admins do not connect a vault repo and cannot see another user's repo or GitHub App credentials. The plugin never needs GitHub credentials. Until that user connects GitHub, their devices still sync through the server.
Dashboard → Overview and MCP / AI list connected MCP clients, how often they call tools (last 24 hours, 7 days, and all time), and per-tool counts. MCP / AI also sets tool permissions (search/read on by default). Point an MCP client at:
POST http://localhost:8080/mcp
Authorization: Bearer sk_sync_…
Create a token on the Tokens page, or exchange a password for one:
POST http://localhost:8080/api/v1/mcp/login
{"username":"you","password":"…"}
Dashboard session cookies also work on /mcp. MCP does not save notes on the Syncidian server. Create/update/delete write to your connected GitHub repository on main and notify live Obsidian clients. Connect GitHub before using write tools. Tools cover search, graph/backlinks, create/update/append, moving any vault file type (including images), and bulk organize when permissions allow.
There are two places plugin metadata lives. Neither is a tests/ folder (a test only checks the root files exist).
manifest.json and versions.json at the repository root, kept identical to plugin/manifest.json and plugin/versions.json with make plugin-manifest. Obsidian reads these at HEAD of the default branch.version (0.1.0, not v0.1.0):main.jsmanifest.jsonstyles.css“Assets” here means that downloadable list on the release page. Creating a tag or clicking Create release in the GitHub UI does not attach those files by itself. .github/workflows/release.yml builds the plugin and uploads them.
If a previous run left a release with no plugin files (for example attestation failed on a private repo before upload), merge this workflow, then Actions → Release Obsidian plugin → Run workflow and enter the existing tag. That uploads or overwrites the three files. You can also attach plugin/main.js, plugin/manifest.json, and plugin/styles.css by hand on the release page.
Publish:
Edit the plugin under plugin/. Bump plugin/manifest.json version in the same change (required before merging plugin updates to main). Then copy metadata to the root:
make plugin-manifest
Push an annotated tag matching plugin/manifest.json version:
git tag -a 0.1.0 -m "0.1.0"
git push origin 0.1.0
The workflow skips GitHub attestations on private repositories (that feature is not available there) so the three files still upload.
Submit (or update) the listing at community.obsidian.md: sign in with your Obsidian account, link GitHub, and add this repository (shangeethsivan/Syncidian). The directory uses the root manifest.json on the default branch; the id is syncidian.
Address automated review feedback, then bump the version and tag again. After approval, people install from Community plugins → Browse → Syncidian.
You can also install with BRAT pointed at this GitHub repo after the three files are on the Release, or with scripts/install-plugin.sh. Keep isDesktopOnly false so Android and iOS can install it. Mobile install: docs/install-mobile.md. Packaging notes: docs/community-plugin.md.
Rebuilding the plugin after TypeScript changes:
cd plugin && npm install && npm run build
plugin/main.js is the compiled artifact Obsidian loads. Commit it so people can sideload without Node.js.
Syncidian brings three capabilities together:
The goal is simple:
Your Obsidian vault should belong to you, be backed up by you, and be accessible to the AI tools you choose.
Syncidian isn't just another file synchronization tool.
The long-term goal is to make synchronization almost invisible.
flowchart TB
AI["AI tools<br/>Claude · Gemini · agents"] -->|"MCP"| Server
Win["Obsidian Windows"] <--> Server
Mac["Obsidian macOS"] <--> Server
And["Obsidian Android"] <--> Server
iOS["Obsidian iOS"] <--> Server
Server["Syncidian server<br/>Sync + Git + MCP + Auth + Dashboard"] --> GH["Per-user private GitHub repo<br/>optional source of truth"]
Eventually, Syncidian should be able to detect a conflict, have a small LLM resolve it automatically, validate the result, commit it to GitHub, and propagate the resolution to every device.
Let AI handle the boring conflicts. Let humans handle the important ones.
The public site is a one-pager. Hosted visitors join a waitlist and sign in with GitHub (hidden until the app name is tapped six times, allowlisted via SYNCIDIAN_GITHUB_ALLOWED_EMAILS until public launch). Self-hosted visitors sign in with email. Operators use a private hostname (SYNCIDIAN_ADMIN_HOST) or an unlisted path (SYNCIDIAN_ADMIN_PATH, default /admin) to create the first admin.
flowchart TD
Open["Open dashboard URL"] --> Land["Public landing: what Syncidian is"]
Land --> Wait["Hosted: join the waitlist"]
Land --> Email["Self-host: email signup or login"]
Land --> GHSign["Hosted: GitHub sign-in hidden until app name tapped 6 times"]
Ops["Private operator host or unlisted path"] --> First{"Any users yet?"}
First -->|no| Admin["Create first admin"]
First -->|yes| AdminLogin["Admin sign in"]
Admin --> Ready["Optional: register GitHub App"]
AdminLogin --> Ready
Ready --> Users["Optional: create vault users"]
Email --> Role{"Who signed in?"}
GHSign --> Role{"Who signed in?"}
Role -->|admin| AdminHome["Operator dashboard — no vault"]
Role -->|user| UserHome["User dashboard"]
UserHome --> Repo["Optional: install GitHub App<br/>one repo for this user · main"]
UserHome --> Tok["Create sk_sync_ token"]
Tok --> Plug["Install plugin<br/>Community plugins · desktop · Android · iOS"]
Plug --> Sync["Devices sync through the server"]
Repo --> Backup["Server commits/pushes that user's vault"]
When this workflow changes, update this diagram, docs/architecture.md, and follow AGENT.md.
Syncidian separates the system into four major components. GitHub renders the chart below; full sync, auth, MCP, and data-model diagrams live in docs/architecture.md.
flowchart TB
Plugin["Obsidian plugin<br/>desktop + Android + iOS"] -->|"requestUrl HTTPS / WS or poll"| SyncSrv
subgraph SyncSrv [Syncidian server]
Sync[Sync engine]
Auth[Authentication]
Devices[Device management]
Git[Git integration]
MCP[MCP server]
Conflicts[Conflict resolution]
Dash[Web dashboard]
end
SyncSrv --> GitHub["Per-user GitHub repo<br/>after login"]
SyncSrv -.->|"planned"| LLM["Small LLM<br/>conflict resolver"]
Syncidian lives inside Obsidian as a plugin.
There is no separate sync application that the user needs to manually operate.
The plugin handles:
The user configures the plugin once.
After that, Syncidian works automatically in the background.
Syncidian is designed to work wherever Obsidian plugins are supported.
The plugin is not desktop-only. It uses the Obsidian Vault API and requestUrl so it loads on phones; Git community plugins that depend on Node or a local git binary cannot. On Android and iOS, leave Syncidian.com selected or point Custom Domain at a public HTTPS server (not localhost). Enable steps: docs/install-mobile.md.
The goal is to maintain one consistent synchronization experience across all supported platforms.
Syncidian is designed around a server-first configuration model.
The Obsidian plugin should require as little configuration as possible.
Run Syncidian on your own infrastructure.
The simplest deployment is Docker Compose from this repository:
docker compose up --build -d
Equivalent one-container flow:
docker build -t syncidian .
docker run -d \
--name syncidian \
-p 8080:8080 \
-v syncidian-data:/data \
syncidian
That container is the complete Syncidian server:
No separate services are required for a basic deployment.
GitHub identity lives on the public site. GitHub backup is still per user, not a shared vault.
Self-hosting? Use the full walkthrough: Set up the GitHub App. That page is the operator README for creating the app, filling GitHub’s callback / setup / webhook URLs, and wiring credentials.
The public landing never asks for a repository name. It sends people through GitHub OAuth, then the GitHub App setup URL. The Obsidian plugin does not need GitHub credentials. Admin login at /admin registers the instance App and does not connect a vault repo.
You need one App per Syncidian instance, not per vault user.
{base} is the URL you will keep (https://syncidian.example.com or http://localhost:8080).{base}/admin and create the first admin./admin with the app Registered./admin and GET /api/v1/github/app/urls)..pem).SYNCIDIAN_GITHUB_APP_ID, SYNCIDIAN_GITHUB_APP_SLUG, SYNCIDIAN_GITHUB_CLIENT_ID, SYNCIDIAN_GITHUB_CLIENT_SECRET, and SYNCIDIAN_GITHUB_APP_PRIVATE_KEY, then restart. Put literal \n in the PEM env value for newlines.Then each vault user signs in from / and installs the app on one repository (main only). Details, localhost notes, and a failure checklist are in docs/github-app.md.
When you create the GitHub App (from /admin → Create GitHub App, or by hand), GitHub asks for these. Open this instance at its public hostname and copy them from the admin page, or from GET /api/v1/github/app/urls.
Replace {base} with your public URL, for example https://syncidian.example.com:
| GitHub field | URL | Why |
|---|---|---|
| Callback URL / User authorization callback URL / redirect URI | {base}/api/v1/auth/github/callback |
GitHub sends people here after Sign in with GitHub, and after Install & Authorize when OAuth during installation is enabled. Syncidian binds installation_id here in that case. |
| Setup URL | {base}/api/v1/github/app/setup |
Used when OAuth during installation is off. GitHub sends people here after they install the app so Syncidian can bind that installation. |
| Webhook URL | {base}/api/v1/github/app/webhook |
GitHub requires a webhook URL so it can ping the app when you create or update it. Syncidian answers that ping with HTTP 200 even if you do not subscribe to extra events. |
Optional env vars if you prefer not to use the in-dashboard manifest flow: SYNCIDIAN_GITHUB_APP_ID, SYNCIDIAN_GITHUB_APP_SLUG, SYNCIDIAN_GITHUB_CLIENT_ID, SYNCIDIAN_GITHUB_CLIENT_SECRET, SYNCIDIAN_GITHUB_APP_PRIVATE_KEY. See docs/github-app.md for exact GitHub UI fields and Docker examples.
Rules:
SYNCIDIAN_ADMIN_HOST (Tailscale) or SYNCIDIAN_ADMIN_PATH (default /admin). Self-hosted vault users sign in with email from /. The GitHub App is optional. On hosted Syncidian.com, GitHub sign-in is hidden until the app name is tapped six times and limited by SYNCIDIAN_GITHUB_ALLOWED_EMAILS.github_config is keyed by user_id.main.flowchart LR
Land["Public landing"] --> OAuth["GitHub OAuth callback"]
OAuth --> User["store.User"]
Admin["/admin"] --> Manifest["Create GitHub App"]
Manifest --> URLs["callback · setup · webhook"]
User --> Install["Install and Authorize"]
Install --> Callback["Callback with installation_id"]
Install --> Setup["Setup URL when no OAuth-on-install"]
Callback --> Map["Store installation_id + repo for that user_id"]
Setup --> Map
Map --> Git["Server git commit / push on main"]
Git --> Repo["That user's private repo"]
Syncidian Server
├── Admin — manage users only
├── User A — one GitHub repo
└── User B — one GitHub repo
This keeps GitHub credentials on the server and scoped to the account that entered them.
The Syncidian server can support multiple users.
Each user can have:
Example:
Syncidian Server
User A
├── Windows
├── macOS
└── Android
User B
├── Windows
└── iOS
User C
└── macOS
Users are isolated from one another.
Once a vault user exists, the server generates an access token.
sk_sync_********************************
The token is used by the Obsidian plugin to authenticate with the Syncidian server.
Create one from the user’s Tokens page, or as an admin via Users → Create Obsidian token (shown once). Admins cannot use tokens themselves.
The token should provide access only to the user's configured resources.
Future authentication options may include:
Install Syncidian from Community plugins (or BRAT / sideload), then open Settings → Syncidian.
The plugin configuration should remain intentionally small:
Syncidian
────────────────────────────────
Server
Syncidian.com Custom Domain
Custom domain
https://sync.example.com (enabled when Custom Domain is selected)
Access Token
••••••••••••••••••
Device Name
MacBook Pro
Connect
Status: ● Connected
The client does not require:
Once the plugin authenticates successfully:
Repeat the process on other devices.
The Syncidian server is the coordination layer.
GitHub is the primary source of truth.
flowchart TB
GH["GitHub — source of truth"]
Srv["Syncidian server"]
GH <-->|"Git"| Srv
Srv --> Win["Windows Obsidian"]
Srv --> Mac["macOS Obsidian"]
Srv --> And["Android Obsidian"]
Srv --> iOS["iOS Obsidian"]
The server coordinates changes between clients and synchronizes the durable state with GitHub.
When a user edits a note:
flowchart TD
Edit[Edit note] --> Plugin[Obsidian plugin]
Plugin -->|Detect change| Srv[Syncidian server]
Srv --> Other["Other devices<br/>WS or manifest poll"]
Srv --> GH[GitHub]
GH --> SoT[Source of truth]
The user does not need to manually:
The plugin handles this automatically. Edits are queued until typing stops, then pushed after a 3 second idle. Simple replacements merge on their own; large conflicts still open a resolver. Deleting or moving a folder (or file) is synced as a Git delete or rename so a later sync does not restore the old path.
Whenever Obsidian starts:
Open Obsidian
│
▼
Syncidian Plugin Starts
│
▼
Authenticate
│
▼
Connect to Syncidian
│
▼
Check GitHub
│
▼
Compare Local State
│
▼
Fetch / Merge / Sync
│
▼
Vault Ready
Coming back to an already-open vault (switching apps, focusing the window, or bringing the phone app to the foreground) also polls the server and pulls any notes that arrived while Obsidian was in the background.
The goal is:
Open Obsidian and start working.
Synchronization should happen automatically in the background.
Conflicts happen when the same file is modified on multiple devices before synchronization completes.
Syncidian should never silently overwrite user data.
The first version can provide an Obsidian-native conflict UI.
┌─────────────────────────────────────────┐
│ ⚠️ Sync Conflict │
│ │
│ "Project Ideas.md" was modified on │
│ another device. │
│ │
│ Local version Remote version │
│ ───────────── ───────────── │
│ Modified 10:32 Modified 10:34 │
│ │
│ Keep Local Keep Remote │
│ │
│ Merge │
└─────────────────────────────────────────┘
Users can:
A major future goal is to make merge conflicts almost invisible.
Instead of requiring the user to manually resolve every conflict, Syncidian can use a small LLM running alongside the Syncidian server.
Device A
│
│ Change
▼
Syncidian Server
│
│ Conflict detected
▼
┌──────────────────────┐
│ Conflict Resolver │
│ │
│ Small LLM │
└──────────┬───────────┘
│
▼
┌────────────────────────┐
│ Local Version │
│ Remote Version │
│ Git History │
└───────────┬────────────┘
│
▼
Resolved File
│
▼
Validation
│
▼
GitHub Commit
│
▼
Other Devices
When a conflict occurs:
AI should not blindly overwrite important information.
Conflict
│
▼
Small LLM
Resolver
│
┌───────┴───────┐
│ │
High confidence Ambiguous
│ │
▼ ▼
Auto-resolve User review
│ │
▼ ▼
GitHub Obsidian UI
The goal is:
Let AI handle the boring conflicts. Let humans handle the important ones.
Syncidian includes a built-in Model Context Protocol (MCP) server.
This provides a controlled interface between your Obsidian knowledge base and AI tools (Cursor, Claude, and other MCP clients).
flowchart TB
Tools["AI tools<br/>Cursor · Claude · agents"] -->|"Bearer token or login"| MCP["Syncidian MCP server"]
MCP --> Vault["Obsidian vault"]
MCP --> Graph["Wikilink graph"]
Authenticate with a dashboard access token (Authorization: Bearer sk_sync_…), a dashboard session cookie, or POST /api/v1/mcp/login with username/password to mint a token.
Capabilities:
suggest_note_path) and find related notesPermissions default to search + read. Enable create/modify in Dashboard → MCP / AI.
An Obsidian vault can contain years of:
Syncidian makes that knowledge available to AI through MCP.
Instead of permanently moving your knowledge into an AI platform, Syncidian provides a bridge between your local knowledge and the AI tools you choose.
Your knowledge stays yours. AI comes to your knowledge.
AI access should be independently controllable.
Example:
MCP Permissions
☑ Search notes
☑ Read notes
☐ Create notes
☐ Modify notes
Future controls can include:
The default configuration should follow least privilege.
Syncidian includes a lightweight web dashboard.
The dashboard answers:
What is happening with my devices?
Example:
┌─────────────────────────────────────────────┐
│ Syncidian │
│ │
│ DEVICES │
│ │
│ ● MacBook Pro macOS Active │
│ ● Pixel 10 Android Active │
│ ● Windows Desktop Windows Active │
│ ○ iPhone iOS Offline │
│ │
├─────────────────────────────────────────────┤
│ │
│ SYNC ACTIVITY │
│ │
│ Total Syncs 1,248 │
│ Files Synced 6,482 │
│ Last Sync 2 min ago │
│ Active Clients 3 │
│ │
└─────────────────────────────────────────────┘
The dashboard should provide:
The dashboard is for monitoring and management, not editing the vault.
A single Syncidian server can support multiple users.
Syncidian Server
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
User A User B User C
│ │ │
┌───┼───┐ ┌───┼───┐ ┌───┼───┐
│ │ │ │ │ │ │ │ │
Win Mac Android Win Mac iOS Mac Linux Android
Each user is isolated.
A user can only see their own:
A user can connect multiple Obsidian installations.
Example:
My Devices
● MacBook Pro macOS Active
● Windows Desktop Windows Active
● Pixel Android Active
○ iPhone iOS Offline
The server tracks:
Syncidian uses access tokens to authenticate Obsidian clients.
Server:
Syncidian.com (default)
or Custom Domain:
https://sync.example.com
Access Token:
sk_sync_********************************
Tokens should be:
Future authentication options:
Syncidian is designed around several principles.
Client-to-server communication should use encrypted channels.
Obsidian clients never need direct GitHub credentials. Each user connects at most one GitHub App installation and repository. Those values are never returned to admins.
Multiple users can safely share a Syncidian server. Admin APIs list public account fields only (id, username, is_admin, created_at). Vault files, tokens, activity, devices, MCP permissions, and GitHub config are always loaded by the authenticated user_id.
Clients and AI tools should only receive required access.
Self-hosted users control their Syncidian server.
GitHub provides durable versioned storage.
The synchronization layer should avoid becoming a permanent storage location for vault data.
Security is still under active development. Do not use early builds for highly sensitive or critical vaults until the implementation and security model have been reviewed.
The initial architecture is intentionally simple.
Go
Go is a good fit for:
Obsidian Plugin
The client integrates directly with the Obsidian vault and lifecycle.
Git + GitHub
Private repositories provide durable, versioned vault storage.
MCP + Small LLM
MCP provides the interface to AI tools.
A small LLM can eventually provide automated conflict resolution.
Docker
The server should ideally be deployed as a single container.
The repository should contain a simple Dockerfile.
Example:
FROM golang:alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build \
-o syncidian ./cmd/syncidian
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/syncidian /app/syncidian
EXPOSE 8080
ENTRYPOINT ["/app/syncidian"]
The exact build configuration may evolve.
The important goal is:
Clone → Build → Run.
Syncidian is completely free to self-host.
A basic installation can provide the entire system:
┌─────────────────────────┐
│ Syncidian Server │
│ │
│ Sync Engine │
│ GitHub Integration │
│ MCP Server │
│ Web Dashboard │
│ Authentication │
│ Device Management │
│ Conflict Resolver │
└─────────────────────────┘
$0 for the Syncidian software.
You only pay for your own infrastructure.
This could be:
GitHub sign-in and backup need a GitHub App for this instance. Operators follow Set up the GitHub App after /admin first-boot.
Don't want to manage your own server?
A managed Syncidian service is in development. It is not for sale yet.
Starting at $1/month
The hosted service will provide:
The self-hosted version will remain free and open source.
Build the fundamental synchronization experience.
Obsidian
↕
Syncidian Server
↕
Obsidian
Add Git-backed persistence, version history, recovery, and conflict handling.
Allow one Syncidian server to securely serve multiple users and devices.
Introduce device monitoring and synchronization statistics.
Connect Obsidian knowledge to AI tools through MCP.
Provide a managed experience starting at $1/month.
Use small LLMs to automatically resolve safe conflicts and fall back to human review when necessary.
| Syncidian | Obsidian Sync | |
|---|---|---|
| Open source | ✅ | ❌ |
| Self-hosted | ✅ | ❌ |
| GitHub backup | ✅ | ❌ |
| Git version history | ✅ | ❌ |
| Server-side Git configuration | ✅ | — |
| Multi-user server | ✅ | — |
| Device dashboard | ✅ | — |
| Built-in MCP | ✅ | ❌ |
| AI knowledge bridge | ✅ | — |
| AI-assisted conflict resolution | 🚧 Planned | — |
| Hosted service | Planned | ✅ |
| Self-hosted cost | Free | — |
| Hosted Syncidian | From $1/month | — |
Syncidian isn't trying to reproduce every feature of Obsidian Sync.
It takes a different approach:
The plugin is the client. Syncidian is the coordination layer. GitHub is the source of truth. MCP connects your knowledge to AI.
Syncidian is built around four principles.
The sync server coordinates devices instead of becoming another permanent copy of your vault.
Git provides transparent version history, recovery, and change tracking.
Your knowledge base shouldn't need to be permanently copied into every AI platform.
Running your own Syncidian instance should be simple enough for anyone comfortable with Docker.
Syncidian is currently under active development.
The architecture, synchronization protocol, plugin implementation, Git integration, dashboard, and MCP interface may change significantly before the first stable release.
The initial milestone is a reliable self-hosted synchronization experience with:
AI/MCP capabilities will be developed alongside the core synchronization system.
AI-assisted conflict resolution is a longer-term goal.
Do not use early builds for critical or highly sensitive vaults.
Syncidian is open source and contributions are welcome.
You can contribute through:
Contribution guidelines will be added as the project matures.
If Syncidian is useful, you can buy me a coffee. The repo also lists that link on GitHub’s Sponsor button.
Syncidian is licensed under the MIT License.
You are free to use, modify, distribute, and self-host Syncidian, including for commercial purposes, subject to the terms of the MIT License.
See LICENSE for the full license text.
Syncidian
Your data stays with you.