daily-notes.json is now shared across vaults; vault-specific set is just bookmarks.json. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ASYabtTgxSxJPjxPmBK9PJ
3.9 KiB
Obsidian config — global + per-vault fork model
Two-tier Obsidian configuration:
- Global config —
ssh://git@gitea.bchen.dev:2222/brendan/obsidian-global-config.git— shared settings (plugins, hotkeys, appearance, theme) used by every vault. - Per-vault config (this repo, e.g.
obsidian-config) — a fork of the global repo: the global config plus files specific to one vault that must sync with that vault but never be published globally.
Each vault's .obsidian is a git submodule pointing at that vault's per-vault repo, which
has the global repo configured as its upstream remote.
vault/.obsidian ──submodule──► obsidian-config (per-vault, downstream)
│ remote: upstream
▼
obsidian-global-config (shared, upstream)
Tiers
| Tier | Examples | Lives in |
|---|---|---|
| Global (shared everywhere) | app.json, appearance.json, hotkeys.json, templates.json, daily-notes.json, core-plugins.json, community-plugins.json, types.json, themes/**, plugin code, most plugin data.json |
global upstream → flows to every vault |
| Vault-specific (synced, never published) | bookmarks.json |
per-vault repo only — never pushed upstream |
| Machine-local (not synced) | workspace.json, workspaces.json, workspace-mobile.json, .DS_Store |
gitignored everywhere |
Daily workflow
Run from a vault root (where .obsidian is the submodule).
Change a vault-specific setting (a bookmark, the daily-notes folder) — stays in this vault:
git -C .obsidian add -A
git -C .obsidian commit -m "..."
git -C .obsidian push
git add .obsidian && git commit -m "bump config" && git push # record the pointer
Pull global changes down — conflict-free; never touches your vault-specific files:
git -C .obsidian fetch upstream
git -C .obsidian merge upstream/main
git -C .obsidian push # save merged result to this vault's repo
git add .obsidian && git commit -m "pull global config" && git push
Change a global setting — make it in a clone of the global repo, push there, then run the pull-down above in each vault:
git -C /path/to/obsidian-global-config add -A
git -C /path/to/obsidian-global-config commit -m "..."
git -C /path/to/obsidian-global-config push
Promoting a global change you happened to make inside a vault isn't a plain push (your per-vault history has vault-specific commits in the way) — cherry-pick it onto an
upstream-tracking branch and push that. Editing global settings in the global clone avoids this entirely.
Which files are vault-specific
The current list is just bookmarks.json. To make a plugin's settings
vault-specific, add plugins/<plugin>/data.json to the denylist and remove it from the
global repo. The denylist is enforced by a pre-receive hook on the global repo, which
rejects any push that touches a vault-specific path (so a stray cherry-pick can't publish
private data). See the project notes for the hook script.
Bootstrapping a new vault
-
Only needs the global config → point the submodule straight at the global repo:
git submodule add ssh://git@gitea.bchen.dev:2222/brendan/obsidian-global-config.git .obsidian -
Needs its own private tracked config → create an empty gitea repo for it, seed it from the global repo, add it as the submodule, and set
upstreamto the global repo. (Ask to have this scripted.)
Do this before opening the vault in Obsidian — Obsidian auto-creates a default
.obsidian/on first open, which blocks the submodule add. Delete it first if present. On first open the vault starts in Restricted Mode — click Trust author and enable plugins to load the configured community plugins.