obsidian-multi-env-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Obsidian Multi-Environment Setup

Obsidian多环境配置

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.
为Obsidian插件开发配置独立的开发、测试和生产vault。涵盖团队入职的vault模板、各环境专属插件设置、同步策略,以及跨环境的
.obsidian/
目录管理。

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
  • 已安装Obsidian桌面应用
  • Node.js 18+以及npm/pnpm用于插件构建
  • Git用于版本控制(推荐)
  • 了解符号链接(symlink)和文件系统操作的基础知识

Instructions

使用说明

Step 1: Create the Environment Structure

步骤1:创建环境结构

Set up three isolated vaults -- dev, test, and prod:
bash
undefined
搭建三个隔离的vault:开发(dev)、测试(test)、生产(prod):
bash
undefined

Base directory for all environments

Base directory for all environments

mkdir -p ~/obsidian-envs/{dev,test,prod}
mkdir -p ~/obsidian-envs/{dev,test,prod}

Dev vault: your working vault with symlinked plugin source

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
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

Test vault: clean environment for QA

mkdir -p ~/obsidian-envs/test/.obsidian/plugins/your-plugin mkdir -p ~/obsidian-envs/test/test-data
mkdir -p ~/obsidian-envs/test/.obsidian/plugins/your-plugin mkdir -p ~/obsidian-envs/test/test-data

Prod vault: mirrors real user setup

Prod vault: mirrors real user setup

mkdir -p ~/obsidian-envs/prod/.obsidian/plugins/your-plugin
undefined
mkdir -p ~/obsidian-envs/prod/.obsidian/plugins/your-plugin
undefined

Step 2: Symlink Plugin Source for Development

步骤2:为开发环境创建插件源码符号链接

In the dev vault, symlink your plugin's build output so changes appear immediately:
bash
undefined
在开发vault中,为插件的构建产物创建符号链接,修改可以立即生效:
bash
undefined

Remove the empty plugin directory in dev

Remove the empty plugin directory in dev

rm -rf ~/obsidian-envs/dev/.obsidian/plugins/your-plugin
rm -rf ~/obsidian-envs/dev/.obsidian/plugins/your-plugin

Symlink to your plugin's repo (contains manifest.json, main.js, styles.css)

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
ln -s /path/to/your-plugin ~/obsidian-envs/dev/.obsidian/plugins/your-plugin

开发过程中如需热重载,可以使用[Hot Reload plugin](https://github.com/pjeby/hot-reload):

```bash

Clone hot-reload into dev vault's plugins

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"]
git clone https://github.com/pjeby/hot-reload.git
~/obsidian-envs/dev/.obsidian/plugins/hot-reload

之后在`.obsidian/community-plugins.json`中启用你的插件和热重载插件:

```json
["your-plugin", "hot-reload"]

Step 3: Environment-Specific Plugin Settings

步骤3:各环境专属插件配置

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<string, boolean>;
}

const ENV_CONFIGS: Record<string, Partial<PluginConfig>> = {
  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)),
    });
  }
}
每个vault都有独立的插件
data.json
配置文件,你可以创建一个配置工厂:
typescript
// config/environments.ts
interface PluginConfig {
  debugMode: boolean;
  logLevel: 'debug' | 'info' | 'warn' | 'error';
  apiEndpoint: string;
  featureFlags: Record<string, boolean>;
}

const ENV_CONFIGS: Record<string, Partial<PluginConfig>> = {
  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] };
}
在插件的
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

步骤4:用于团队入职的vault模板

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
创建一个模板vault,新团队成员可以直接克隆使用:
vault-template/
  .obsidian/
    app.json              # 标准应用设置
    appearance.json       # 主题和字体设置
    hotkeys.json          # 团队统一快捷键
    community-plugins.json  # 审批通过的插件列表
    plugins/              # 预配置的插件data.json文件
      dataview/data.json
      templater-obsidian/data.json
  templates/              # 笔记模板(日报、会议、项目)
    daily.md
    meeting.md
    project-kickoff.md
  README.md               # Vault使用指南
为新团队成员预配置vault的脚本:
bash
#!/bin/bash

provision-vault.sh <username> <role>

provision-vault.sh <username> <role>

USERNAME=$1 ROLE=${2:-editor}
VAULT_DIR=~/obsidian-team-vaults/$USERNAME cp -r vault-template "$VAULT_DIR"
USERNAME=$1 ROLE=${2:-editor}
VAULT_DIR=~/obsidian-team-vaults/$USERNAME cp -r vault-template "$VAULT_DIR"

Inject user-specific settings

Inject user-specific settings

cat > "$VAULT_DIR/.obsidian/plugins/rbac-plugin/data.json" <<EOF { "userEmail": "${USERNAME}@company.com", "role": "${ROLE}" } EOF
echo "Vault provisioned at $VAULT_DIR for $USERNAME ($ROLE)"
undefined
cat > "$VAULT_DIR/.obsidian/plugins/rbac-plugin/data.json" <<EOF { "userEmail": "${USERNAME}@company.com", "role": "${ROLE}" } EOF
echo "Vault provisioned at $VAULT_DIR for $USERNAME ($ROLE)"
undefined

Step 5: Sync Strategies

步骤5:同步策略

Choose based on your team's needs:
Git sync (best for plugin developers):
bash
cd ~/obsidian-envs/prod
git init
cat > .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 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.
根据团队需求选择合适的同步方式:
Git同步(最适合插件开发者):
bash
cd ~/obsidian-envs/prod
git init
cat > .gitignore <<'EOF'
.obsidian/workspace.json
.obsidian/workspace-mobile.json
.obsidian/cache
.trash/
EOF
git add -A && git commit -m "Initial vault state"
搭配Obsidian Git plugin使用,可以实现定时自动提交/推送。
Obsidian Sync(最适合非技术团队):在设置>同步中配置,选择性同步功能允许你在部分设备上排除
.obsidian/plugins/
目录,避免配置冲突。
iCloud/Dropbox同步(最简单但稳定性最差):将vault放在同步文件夹中,避免同时在多台设备上编辑,
.obsidian/
目录很容易出现冲突,请注意备份。

Step 6: Managing .obsidian/ Across Environments

步骤6:跨环境管理
.obsidian/
目录

The
.obsidian/
directory holds all configuration. Key files and their sync behavior:
FileSync across envs?Why
app.json
YesCore settings should be consistent
appearance.json
YesTheme consistency
community-plugins.json
Per-envDev may have debug plugins
hotkeys.json
YesMuscle memory matters
workspace.json
NeverLayout is per-device
plugins/*/data.json
Per-envSettings differ by environment
Script to sync safe configs from prod to other environments:
bash
#!/bin/bash
.obsidian/
目录存储所有配置,关键文件及其同步规则如下:
文件是否跨环境同步?原因
app.json
核心设置应当保持一致
appearance.json
保持主题一致性
community-plugins.json
按环境区分开发环境可能会安装调试用插件
hotkeys.json
符合用户操作习惯
workspace.json
从不布局是设备专属的
plugins/*/data.json
按环境区分不同环境的设置存在差异
将安全配置从生产环境同步到其他环境的脚本:
bash
#!/bin/bash

sync-config.sh -- copy safe configs from prod to dev/test

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
undefined
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
undefined

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
  • 三个隔离的vault(开发/测试/生产),各自拥有独立的插件配置
  • 开发环境vault中的插件源码通过符号链接关联,支持热重载
  • 插件代码中内置环境检测和配置切换逻辑
  • 用于团队入职的vault模板和预配置脚本
  • 已配置的同步策略(Git、Obsidian Sync或云存储)
  • 用于跨环境配置一致性的
    .obsidian/
    管理脚本

Error Handling

错误处理

IssueCauseSolution
Symlink not workingPermission denied on WindowsRun terminal as Administrator, or use
mklink /D
Plugin not appearing in dev vaultSymlink target missing
manifest.json
Run
npm run build
first; ensure
main.js
exists
Wrong config loadedVault path detection failedCheck
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 vaultAdd
workspace.json
to
.gitignore
Test vault has stale dataForgot to refresh after plugin updateCopy latest build artifacts:
manifest.json
,
main.js
,
styles.css
问题原因解决方案
符号链接不生效Windows系统权限不足以管理员身份运行终端,或使用
mklink /D
命令
开发vault中不显示插件符号链接目标缺少
manifest.json
文件
先执行
npm run build
,确保
main.js
文件存在
加载了错误的配置vault路径检测失败检查
basePath
是否符合预期的路径格式
热重载不触发缺少
.hotreload
文件
在插件目录下创建空的
.hotreload
文件
workspace.json
同步冲突
多台设备同时打开同一个vault
workspace.json
添加到
.gitignore
测试vault数据过时插件更新后忘记刷新测试环境复制最新的构建产物:
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.
独立开发者工作流:开发vault通过符号链接关联插件仓库,开启热重载;手动将
npm run build
的产物复制到测试vault进行最终QA;生产vault是你日常使用的库,安装的是从BRAT或社区插件市场发布的正式版本。
团队入职:执行
provision-vault.sh alice editor
命令,从团队模板为Alice创建专属vault,她在Obsidian中打开后,所有已审批的插件和团队标准配置都已经预安装完成。
跨Obsidian版本的CI测试:创建一个安装了你的插件的无头测试vault,使用
obsidian-cli
或Electron自动化工具打开vault,运行插件命令并验证输出,在你支持的所有Obsidian版本中重复该测试流程。

Resources

参考资源

Next Steps

后续步骤

For monitoring and logging across environments, see
obsidian-observability
. For access control on shared vaults, see
obsidian-enterprise-rbac
.
如需实现跨环境的监控和日志功能,请参考
obsidian-observability
;如需为共享vault配置访问控制,请参考
obsidian-enterprise-rbac