#!/usr/bin/env python3 """Render the global Obsidian desktop config (~/.config/obsidian/obsidian.json). Enables the official CLI and registers every mounted vault so the official `obsidian` CLI can target them with `vault=`. Vaults are read from the environment: * ``OBSIDIAN_VAULTS`` (preferred, multi-vault): - JSON object: {"work": "/vaults/work", "personal": "/vaults/personal"} - or pairs: work=/vaults/work,personal=/vaults/personal * ``OBSIDIAN_VAULT_PATH`` (single-vault fallback): /vault The first registered vault becomes the default (highest ``ts``), which is the vault used when a CLI command omits ``vault=``. """ from __future__ import annotations import json import os import sys from pathlib import Path def _parse_vaults() -> "list[tuple[str, str]]": raw = os.environ.get("OBSIDIAN_VAULTS", "").strip() pairs: list[tuple[str, str]] = [] if raw: # Try JSON object first. try: data = json.loads(raw) if isinstance(data, dict): return [(str(name), str(path)) for name, path in data.items()] except json.JSONDecodeError: pass # Fall back to comma/newline separated name=path pairs. for chunk in raw.replace("\n", ",").split(","): chunk = chunk.strip() if not chunk: continue if "=" not in chunk: print(f"WARNING: ignoring malformed OBSIDIAN_VAULTS entry: {chunk!r}", file=sys.stderr) continue name, path = chunk.split("=", 1) pairs.append((name.strip(), path.strip())) if not pairs: single = os.environ.get("OBSIDIAN_VAULT_PATH", "/vault").strip() or "/vault" name = Path(single).name or "vault" pairs.append((name, single)) return pairs def main() -> int: pairs = _parse_vaults() vaults: dict[str, dict] = {} # Descending timestamps so the first declared vault sorts as most-recent # (the desktop app treats the highest ts as the active/default vault). base_ts = 1893456000000 for index, (name, path) in enumerate(pairs): vaults[name] = { "path": path, "ts": base_ts - index, "open": True, } config = {"cli": True, "vaults": vaults} config_path = Path(os.environ.get("OBSIDIAN_CONFIG_PATH", "/root/.config/obsidian/obsidian.json")) config_path.parent.mkdir(parents=True, exist_ok=True) config_path.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8") names = ", ".join(f"{name} -> {data['path']}" for name, data in vaults.items()) print(f"Registered {len(vaults)} vault(s): {names}") # First declared vault is the default for commands without vault=. print(pairs[0][1]) # default vault path, consumed by the entrypoint return 0 if __name__ == "__main__": raise SystemExit(main())