Skip to content

Obsidian Sync folder exclusions

Historical. Obsidian Sync is no longer the Bob vault's sync channel. The vault syncs through git only; see vault-git-sync.md for the live runbook. ob-sync-bob.service is disabled and the Obsidian Sync core plugin is off, so nothing here runs as part of normal operation. This page is kept because the exclusion semantics it records are not documented anywhere else and are easy to get wrong if Sync is ever relinked.

Exactly one sync engine may run against ~/bob. With both git sync and Obsidian Sync live, a delete propagated by one is resurrected by the other, indefinitely. Stop bob-vault-sync.service and the MacBook LaunchAgent before re-enabling Sync for any reason.

This runbook covers removing an already-synced folder from Obsidian Sync while preserving the local copy in the Bob vault.

Key rules

Obsidian Sync exclusions are not remote delete commands. Adding a path to the excluded folders list stops future sync consideration for that path, but it does not remove files that are already present in the remote vault.

For an already-synced folder, push the remote deletions before setting the exclusion. If the exclusion is set first, the sync client filters those paths out and will skip the remote-deletion branch for them.

Exclusions are device-local. The headless client stores them under its obsidian-headless sync config, and desktop Obsidian stores them in the app's own IndexedDB state, outside the vault. Desktop Obsidian never writes a .obsidian/sync.json, so the absence of that file says nothing about a device's exclusions. Configure the same folder exclusion on every device that should keep its local copy before any deletion-drain phase runs.

The ignoreFolders value is prefix-matched and case-sensitive. For the Bob vault's archival library, the value is exactly:

old_lib

Do not write /old_lib, old_lib/, or Old_lib.

Procedure

  1. Confirm that the folder is fully backed up outside Obsidian Sync. For old_lib/, the required durable backup is the vault Git repo; keep a second independent copy during any destructive sync window. Note that the vault Git repo does not cover every path: lit_review/ and xlib/ are gitignored by policy, and paths outside .gitignore's extension allowlist are untracked.
  2. Stop automated sync processes. Today that means bob-vault-sync.service on athena, the com.bbugyi.bob-vault-sync LaunchAgent on the MacBook, the 03:30 bob nightly crontab line, and ob-sync-bob.service if it has been re-enabled. bob nightly no longer gates on ob sync; it runs vault-sync, task archive, a report-only articles check, and vault-sync.
  3. Move the target folder out of the sync client's view without copying bytes, for example by staging it under a dot-prefixed vault directory:
mkdir -p ~/bob/.old_lib_migrating
mv ~/bob/old_lib/* ~/bob/.old_lib_migrating/
rmdir ~/bob/old_lib
  1. Run foreground sync cycles until the remote has no live entries for the original folder. Do not proceed while any remote entry remains live.
  2. Set the device-local exclusion while the folder is still staged and sync automation is still stopped:
ob sync-config --path ~/bob --excluded-folders old_lib

--excluded-folders replaces the whole list. If other exclusions already exist, pass the full comma-separated list. 6. Verify both the CLI output and the raw config before restoring the folder:

ob sync-config --path ~/bob | grep 'Excluded folders'
python3 -c "import json; p='/home/bryan/.config/obsidian-headless/sync/8a259ad922718b6d8400c1f0e3ba8abe/config.json'; print(json.load(open(p)).get('ignoreFolders'))"

The expected value for this migration is ['old_lib']. 7. Restore the local folder, restart automation, and watch several sync cycles for accidental uploads:

mkdir -p ~/bob/old_lib
mv ~/bob/.old_lib_migrating/* ~/bob/old_lib/
rmdir ~/bob/.old_lib_migrating
systemctl --user start ob-sync-bob.service  # only if Sync is the live channel
tail -f ~/.config/obsidian-headless/sync/8a259ad922718b6d8400c1f0e3ba8abe/sync.log | grep -i old_lib

Any Uploading file old_lib/... log line means the exclusion is not active. Stop the service immediately and recheck the stored ignoreFolders value before running another sync cycle.

Verifying a desktop device

Set the exclusion in the GUI under Settings > Sync > Excluded folders. There is no supported CLI for this, and there is no file in the vault to inspect afterwards.

To confirm the saved value without the GUI, read the sync record out of Obsidian's IndexedDB. Desktop Obsidian persists its sync settings with db.put("data", ...), and because that record carries the full local and remote file maps it lands in the IndexedDB blob store rather than inline in LevelDB:

python3 - <<'EOF'
import os
root = os.path.expanduser(
    "~/Library/Application Support/obsidian/IndexedDB"
    "/app_obsidian.md_0.indexeddb.blob"
)
best = None
for dirpath, _, filenames in os.walk(root):
    for name in filenames:
        path = os.path.join(dirpath, name)
        data = open(path, "rb").read()
        if b"dataVer" not in data:
            continue
        if best is None or os.stat(path).st_mtime > best[0]:
            best = (os.stat(path).st_mtime, data)
blob = best[1]
segment = blob[blob.find(b"ignoreF"):blob.find(b"preventSleep")]
index = 0
while index < len(segment):
    if segment[index] == 0x22 and segment[index + 1] < 0x80:
        length = segment[index + 1]
        print(segment[index + 2:index + 2 + length].decode("utf-8", "replace"))
    index += 1
EOF

Each printed line is one entry of that device's ignoreFolders. Grepping the blob for ignoreFolders does not work: the surrounding bytes are Snappy-encoded, so the key itself is usually stored as a back-reference rather than as literal text.

Tested rolling snapshot bob-cli 41afa14 bob-mac-capture 556bb67 bob-plugins af1e691 Built 2026-10-24T22:34:13Z (zensical) build.json