--- name: obsidian-multi-env-setup description: 'Configure multiple Obsidian environments for development, testing, and production. Use when managing separate vaults, testing plugin versions, or establishing a proper development workflow with isolated environments. Trigger with phrases like "obsidian environments", "obsidian dev vault", "obsidian testing setup", "multiple obsidian vaults". ' allowed-tools: Read, Write, Edit, Bash(mkdir:*), Bash(ln:*) version: 1.0.0 license: MIT author: Jeremy Longshore tags: - saas - obsidian - testing - workflow compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw --- # Obsidian Multi-Environment Setup ## Overview Configure separate development, testing, and production vaults for Obsidian plugin work. Covers vault templates for team onboarding, environment-specific plugin settings, sync strategies, and `.obsidian/` directory management across environments. ## Prerequisites - Obsidian desktop app installed - Node.js 18+ and npm/pnpm for plugin builds - Git for version control (recommended) - Basic understanding of symlinks and file system operations ## Instructions ### Step 1: Create the Environment Structure Set up three isolated vaults -- dev, test, and prod: ```bash # Base directory for all environments mkdir -p ~/obsidian-envs/{dev,test,prod} # Dev vault: your working vault with symlinked plugin source mkdir -p ~/obsidian-envs/dev/.obsidian/plugins/your-plugin mkdir -p ~/obsidian-envs/dev/sandbox # scratch notes for testing # Test vault: clean environment for QA mkdir -p ~/obsidian-envs/test/.obsidian/plugins/your-plugin mkdir -p ~/obsidian-envs/test/test-data # Prod vault: mirrors real user setup mkdir -p ~/obsidian-envs/prod/.obsidian/plugins/your-plugin ``` ### Step 2: Symlink Plugin Source for Development In the dev vault, symlink your plugin's build output so changes appear immediately: ```bash # Remove the empty plugin directory in dev rm -rf ~/obsidian-envs/dev/.obsidian/plugins/your-plugin # Symlink to your plugin's repo (contains manifest.json, main.js, styles.css) ln -s /path/to/your-plugin ~/obsidian-envs/dev/.obsidian/plugins/your-plugin ``` For hot reload during development, use the [Hot Reload plugin](https://github.com/pjeby/hot-reload): ```bash # Clone hot-reload into dev vault's plugins git clone https://github.com/pjeby/hot-reload.git \ ~/obsidian-envs/dev/.obsidian/plugins/hot-reload ``` Then enable both your plugin and hot-reload in `.obsidian/community-plugins.json`: ```json ["your-plugin", "hot-reload"] ``` ### Step 3: Environment-Specific Plugin Settings Each vault gets its own `data.json` for your plugin. Create a config factory: ```typescript // config/environments.ts interface PluginConfig { debugMode: boolean; logLevel: 'debug' | 'info' | 'warn' | 'error'; apiEndpoint: string; featureFlags: Record; } const ENV_CONFIGS: Record> = { dev: { debugMode: true, logLevel: 'debug', apiEndpoint: 'http://localhost:3000', featureFlags: { experimentalEditor: true, betaSync: true }, }, test: { debugMode: true, logLevel: 'info', apiEndpoint: 'https://staging.api.example.com', featureFlags: { experimentalEditor: true, betaSync: false }, }, prod: { debugMode: false, logLevel: 'error', apiEndpoint: 'https://api.example.com', featureFlags: {}, }, }; export function detectEnvironment(vaultPath: string): string { if (vaultPath.includes('obsidian-envs/dev')) return 'dev'; if (vaultPath.includes('obsidian-envs/test')) return 'test'; return 'prod'; } export function getConfig(env: string): PluginConfig { const defaults: PluginConfig = { debugMode: false, logLevel: 'error', apiEndpoint: '', featureFlags: {}, }; return { ...defaults, ...ENV_CONFIGS[env] }; } ``` Use it in your plugin's `onload()`: ```typescript async onload() { const vaultPath = (this.app.vault.adapter as any).basePath; const env = detectEnvironment(vaultPath); const config = getConfig(env); console.log(`[your-plugin] Running in ${env} mode`); if (config.debugMode) { // Register debug commands only in dev/test this.addCommand({ id: 'dump-state', name: 'Dump Plugin State (debug)', callback: () => console.log(JSON.stringify(this.settings, null, 2)), }); } } ``` ### Step 4: Vault Templates for Team Onboarding Create a template vault that new team members clone: ``` vault-template/ .obsidian/ app.json # Standard app settings appearance.json # Theme and font settings hotkeys.json # Team-standard keybindings community-plugins.json # Approved plugin list plugins/ # Pre-configured plugin data.json files dataview/data.json templater-obsidian/data.json templates/ # Note templates (daily, meeting, project) daily.md meeting.md project-kickoff.md README.md # Vault orientation guide ``` Script to provision a new team member's vault: ```bash #!/bin/bash # provision-vault.sh USERNAME=$1 ROLE=${2:-editor} VAULT_DIR=~/obsidian-team-vaults/$USERNAME cp -r vault-template "$VAULT_DIR" # Inject user-specific settings cat > "$VAULT_DIR/.obsidian/plugins/rbac-plugin/data.json" < .gitignore <<'EOF' .obsidian/workspace.json .obsidian/workspace-mobile.json .obsidian/cache .trash/ EOF git add -A && git commit -m "Initial vault state" ``` Pair with the [Obsidian Git plugin](https://github.com/denolehov/obsidian-git) for auto-commit/push on a schedule. **Obsidian Sync** (best for non-technical teams): Configure in Settings > Sync. Selective sync lets you exclude `.obsidian/plugins/` on certain devices to prevent config conflicts. **iCloud/Dropbox** (simplest, most fragile): Place the vault inside the sync folder. Avoid editing on multiple devices simultaneously. `.obsidian/` conflicts are common -- keep a backup. ### Step 6: Managing .obsidian/ Across Environments The `.obsidian/` directory holds all configuration. Key files and their sync behavior: | File | Sync across envs? | Why | |------|--------------------|-----| | `app.json` | Yes | Core settings should be consistent | | `appearance.json` | Yes | Theme consistency | | `community-plugins.json` | Per-env | Dev may have debug plugins | | `hotkeys.json` | Yes | Muscle memory matters | | `workspace.json` | Never | Layout is per-device | | `plugins/*/data.json` | Per-env | Settings differ by environment | Script to sync safe configs from prod to other environments: ```bash #!/bin/bash # sync-config.sh -- copy safe configs from prod to dev/test SAFE_FILES="app.json appearance.json hotkeys.json" SRC=~/obsidian-envs/prod/.obsidian for env in dev test; do DST=~/obsidian-envs/$env/.obsidian for f in $SAFE_FILES; do cp "$SRC/$f" "$DST/$f" 2>/dev/null && echo "Synced $f to $env" done done ``` ## Output - Three isolated vaults (dev/test/prod) with independent plugin configurations - Symlinked plugin source in dev vault with hot reload - Environment detection and config switching in plugin code - Vault template and provisioning script for team onboarding - Sync strategy configured (Git, Obsidian Sync, or cloud) - `.obsidian/` management scripts for consistent cross-env config ## Error Handling | Issue | Cause | Solution | |-------|-------|----------| | Symlink not working | Permission denied on Windows | Run terminal as Administrator, or use `mklink /D` | | Plugin not appearing in dev vault | Symlink target missing `manifest.json` | Run `npm run build` first; ensure `main.js` exists | | Wrong config loaded | Vault path detection failed | Check `basePath` matches expected pattern | | Hot reload not triggering | `.hotreload` file missing | Create empty `.hotreload` in plugin directory | | Sync conflict on `workspace.json` | Multiple devices open same vault | Add `workspace.json` to `.gitignore` | | Test vault has stale data | Forgot to refresh after plugin update | Copy latest build artifacts: `manifest.json`, `main.js`, `styles.css` | ## Examples **Solo developer workflow**: Dev vault symlinked to plugin repo with hot reload. Test vault gets `npm run build` output copied in manually for final QA. Prod vault is your daily-driver vault with the released version from BRAT or community plugins. **Team onboarding**: Run `provision-vault.sh alice editor` to create Alice's vault from the team template. She opens it in Obsidian, and all approved plugins with team-standard settings are pre-configured. **CI testing across Obsidian versions**: Create a headless test vault with your plugin installed. Use `obsidian-cli` or Electron automation to open the vault, run plugin commands, and verify output. Repeat for each Obsidian version in your support matrix. ## Resources - [Obsidian URI Protocol](https://help.obsidian.md/Extending+Obsidian/Obsidian+URI) - [BRAT for Beta Testing](https://github.com/TfTHacker/obsidian42-brat) - [Hot Reload Plugin](https://github.com/pjeby/hot-reload) - [Obsidian Git Plugin](https://github.com/denolehov/obsidian-git) ## Next Steps For monitoring and logging across environments, see `obsidian-observability`. For access control on shared vaults, see `obsidian-enterprise-rbac`.