Files
obsidian-global-config/README.md
Brendan Chen f865b400fb Initial global Obsidian config
Shared config extracted from obsidian-config; vault-specific files (bookmarks.json, daily-notes.json) excluded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_01ASYabtTgxSxJPjxPmBK9PJ
2026-06-24 12:03:59 -04:00

3.9 KiB

Obsidian config — global + per-vault fork model

Two-tier Obsidian configuration:

  • Global configssh://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, 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, daily-notes.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 bookmarks.json and daily-notes.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 upstream to 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.