How to Configure Multiple Dev Profiles for Parallel Git Worktree Development in OpenWork

OpenWork supports isolated development instances by pairing each git worktree with its own dev profile, automatically managing Electron user-data directories, ports, and app identifiers.

The OpenWork desktop application enables sophisticated parallel development workflows through environment-driven dev profiles. Each profile isolates Electron's user-data storage, Vite dev-server ports, and CDP debug endpoints—allowing multiple worktrees to run simultaneously without conflicts. This article explains how to configure these profiles using the OPENWORK_DEV_PROFILE environment variable and the built-in auto-detection system.

Understanding Dev Profiles in OpenWork

A dev profile determines three critical isolation boundaries:

  • User-data directory: Where Electron stores cookies, keychain entries, and caches
  • Vite development server port: PORT environment variable
  • Chrome DevTools Protocol port: OPENWORK_ELECTRON_REMOTE_DEBUG_PORT

According to the OpenWork source code, profiles are resolved in apps/desktop/electron/dev-profile.mjs through the resolveUserDataPath function (line 41), which constructs the path as ${appDataPath}/${appIdentifier}.

Automatic Profile Detection with auto Mode

When you run pnpm dev:worktree, the script (defined in package.json line 7) automatically configures:

OPENWORK_DEV_MODE=1
OPENWORK_DEV_PROFILE=auto          # derives stable profile from worktree path

OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1
OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0   # dynamic CDP port selection

PORT=0                                 # dynamic Vite port selection

The auto mode uses deriveAutoDevProfileName (line 18 of dev-profile.mjs) to hash the absolute worktree path, producing a deterministic name in the format <hint>-<hash>. The resolveAppIdentifier function (line 31) then builds the final app identifier from this value.

Manual Profile Configuration

For explicit control, supply a custom profile name:

OPENWORK_DEV_PROFILE=my-feature pnpm dev

This bypasses auto-detection and uses your chosen identifier directly. The profile name propagates through:

  1. process.env.OPENWORK_DEV_PROFILE — read in main.mjs (line 134) as devProfile
  2. resolveAppIdentifier — constructs APP_IDENTIFIER as ${BASE_APP_IDENTIFIER}.dev.${profileName}
  3. Electron app initialization — applies the identifier to window titles, dock icons, and user-data paths

Step-by-Step: Running Parallel Worktrees

Follow this workflow to develop multiple features simultaneously:

  1. Create worktrees from your repository:
git worktree add ../_worktrees/feat-a feat/a
git worktree add ../_worktrees/feat-b feat/b
  1. Launch first instance with auto-profile:
cd ../_worktrees/feat-a
OPENWORK_DEV_PROFILE=auto pnpm dev
  1. Launch second instance with custom profile:
cd ../_worktrees/feat-b
OPENWORK_DEV_PROFILE=feat-b pnpm dev

Each instance starts with isolated state. The console banner (printed near line 202 of main.mjs) confirms the active profile:


[openwork] dev profile=feat-b cdp=http://127.0.0.1:9223

Technical Implementation Details

Component Source Location Function
Environment setup package.json line 7 dev:worktree script sets base variables
Profile derivation apps/desktop/electron/dev-profile.mjs deriveAutoDevProfileName, resolveAppIdentifier
App initialization apps/desktop/electron/main.mjs line 134 Reads devProfile, configures mock keychain
Port allocation main.mjs lines 261-263 Dynamic port selection with use-mock-keychain
Worktree exclusion .gitignore lines 22-24 Excludes _worktrees/ and .worktrees/ directories

Key Security and Isolation Features

Mock keychain enforcement: OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1 prevents macOS credential dialogs by substituting an in-memory keychain implementation—critical for automated testing and parallel instances.

Deterministic auto-naming: The hash-based profile generation ensures the same worktree path always receives the same profile, preserving cookies and cache across restarts while remaining distinct from other worktrees.

Dynamic port binding: Both PORT=0 and OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0 trigger automatic free-port selection, eliminating manual port management.

Summary

  • Environment variable: OPENWORK_DEV_PROFILE controls profile selection—use auto for path-based hashing or any custom string
  • Auto-detection: Hashes absolute worktree path to produce stable, unique profile names via deriveAutoDevProfileName
  • Isolation guarantees: Separate user-data directories, ports, and app identifiers prevent cross-contamination between instances
  • Mock keychain: Automatically enabled in dev mode to avoid system credential prompts
  • Source files: Configuration flows through package.json → dev-profile.mjs → main.mjs

Frequently Asked Questions

What happens if I don't set OPENWORK_DEV_PROFILE?

The application may use a default profile that shares user-data with other instances, causing session conflicts and port collisions. Always use auto or an explicit name when running parallel worktrees.

Can I use the same profile name across different worktrees?

Avoid this—identical profile names result in shared Electron user-data directories (${appDataPath}/${appIdentifier}), which causes cookie leakage and state corruption between your development contexts.

How does OpenWork handle keychain access on macOS?

In dev mode, OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1 enables a mock keychain via Electron's use-mock-keychain command-line switch (implemented in main.mjs lines 261-263). This prevents system security dialogs while maintaining credential storage functionality.

Where is profile data stored on my system?

resolveUserDataPath in dev-profile.mjs (line 41) constructs the path as ${appDataPath}/${appIdentifier}, where appIdentifier incorporates your profile name. On macOS this typically resolves to ~/Library/Application Support/openwork.dev.<profile>/.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →