{"id":51324567,"url":"https://github.com/webdevtodayjason/obsidian-github-sync","last_synced_at":"2026-07-01T17:02:21.843Z","repository":{"id":362620435,"uuid":"1257705064","full_name":"webdevtodayjason/obsidian-github-sync","owner":"webdevtodayjason","description":"Bidirectionally sync an Obsidian vault to a headless host (e.g. an AI-agent Pi) via Git + a private GitHub repo as source of truth.","archived":false,"fork":false,"pushed_at":"2026-06-02T23:52:33.000Z","size":6,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-05T07:18:48.129Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/webdevtodayjason.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-02T23:52:31.000Z","updated_at":"2026-06-02T23:52:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/webdevtodayjason/obsidian-github-sync","commit_stats":null,"previous_names":["webdevtodayjason/obsidian-github-sync"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/webdevtodayjason/obsidian-github-sync","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webdevtodayjason%2Fobsidian-github-sync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webdevtodayjason%2Fobsidian-github-sync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webdevtodayjason%2Fobsidian-github-sync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webdevtodayjason%2Fobsidian-github-sync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/webdevtodayjason","download_url":"https://codeload.github.com/webdevtodayjason/obsidian-github-sync/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/webdevtodayjason%2Fobsidian-github-sync/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35015061,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-01T17:02:20.680Z","updated_at":"2026-07-01T17:02:21.833Z","avatar_url":"https://github.com/webdevtodayjason.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# obsidian-github-sync\n\nBidirectionally sync an [Obsidian](https://obsidian.md) vault to a **headless host** — e.g. a Raspberry Pi running an AI agent — using **Git + a private GitHub repo as the source of truth**. The agent reads and writes the *live* vault; its edits flow back to GitHub and to your other machines.\n\nNo Obsidian GUI required on the headless host. No Obsidian Sync subscription required. You get full **version history** for free.\n\n```\n        your Mac (Obsidian)                 headless host (AI agent, e.g. Pi)\n   ┌───────────────────────────┐        ┌───────────────────────────────────┐\n   │ vault/  ──launchd 5min──┐  │        │  ┌──systemd 3min── vault/ (clone)  │\n   │  (Obsidian + git)       │  │        │  │   agent reads + writes here     │\n   └─────────────────────────┼──┘        └──┼──────────────────────────────────┘\n                             │   pull/push  │   pull/push\n                             ▼              ▼\n                   ┌──────────────────────────────────┐\n                   │  GitHub (PRIVATE repo) = truth    │\n                   │  full version history             │\n                   └──────────────────────────────────┘\n```\n\n## Why not Obsidian Sync or Syncthing?\n- **Obsidian Sync** is great, but it's a paid cloud and the agent can't read those files headlessly.\n- **Syncthing** is live P2P but has *no central source of truth and no history*.\n- **Git/GitHub** gives you a canonical store, version history, free hosting, and plain files any agent can read/write. It also matches a normal dev workflow (repo updated → everyone syncs).\n\n## Security\n- The vault repo **must be PRIVATE** — it's your personal notes.\n- Don't keep raw secrets in notes you push (a private repo still puts them on GitHub and on the agent host). Keep credentials in a manager (1Password, etc.) and reference them.\n- Push auth uses the GitHub CLI (`gh auth setup-git`) — no tokens in scripts.\n\n## Quickstart\n\n**1. Create + seed a PRIVATE vault repo** (from your main machine, in your vault folder):\n```bash\ncd \"/path/to/your/Obsidian Vault\"\nprintf '%s\\n' '.obsidian/workspace.json' '.obsidian/workspace-mobile.json' '.obsidian/cache/' '.trash/' '.DS_Store' \u003e .gitignore\ngit init \u0026\u0026 git add -A \u0026\u0026 git commit -m \"seed vault\" \u0026\u0026 git branch -M main\ngh repo create \u003cowner\u003e/obsidian-vault --private --source=. --remote=origin --push\n```\n\n**2. On the headless host** (Linux + systemd; enable linger so it runs without a login):\n```bash\nloginctl enable-linger \"$USER\"\n./install-host.sh \u003cowner\u003e/obsidian-vault ~/Obsidian 3min ~/.hermes/.env\n```\n`~/.hermes/.env` is optional — pass your agent's env file and the installer wires `OBSIDIAN_VAULT_PATH` for you (Hermes/Evy reads that). For any other agent, just point it at the clone path.\n\n**3. On your Mac** (launchd daemon — or skip this and use the in-app *Obsidian Git* plugin instead; use one, not both):\n```bash\ngit clone https://github.com/\u003cowner\u003e/obsidian-vault.git \"$HOME/Obsidian\"   # if not already a clone\n./install-peer-macos.sh \"$HOME/Obsidian\" 300\n```\n\nThat's it. Each side runs `sync.sh` on an interval: `git pull --rebase --autostash`, then commit + push local changes.\n\n## How it works\n- `sync.sh` — the portable core. Pull-rebase, commit, push. A `mkdir`-based atomic lock (with a stale-lock guard) prevents concurrent runs from racing — works on macOS and Linux without `flock`.\n- `install-host.sh` — clones the vault + installs a `systemd --user` service + timer.\n- `install-peer-macos.sh` — installs a launchd agent.\n- **Conflicts:** `--rebase --autostash` handles the common case; a true conflict is *logged, not auto-resolved* (so nothing is silently lost) — resolve it once in the repo and the daemons resume.\n\n## Notes\n- Commits from each side carry a label (`mac:` / `host:` / `evy:`) so history shows who edited where.\n- Built to give an AI agent (Evy, on a [Hermes](https://hermes-agent.nousresearch.com) Pi) live, writable access to an Obsidian vault — but it works for any Obsidian + headless-host setup.\n\n## License\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebdevtodayjason%2Fobsidian-github-sync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebdevtodayjason%2Fobsidian-github-sync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebdevtodayjason%2Fobsidian-github-sync/lists"}