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

> Configure multiple dev profiles for parallel Git worktree development in OpenWork. Isolate instances, manage user data, ports, and app IDs automatically.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-15

---

**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`](https://github.com/different-ai/openwork/blob/main/package.json) line 7) automatically configures:

```bash
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:

```bash
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:**

```bash
git worktree add ../_worktrees/feat-a feat/a
git worktree add ../_worktrees/feat-b feat/b

```

2. **Launch first instance with auto-profile:**

```bash
cd ../_worktrees/feat-a
OPENWORK_DEV_PROFILE=auto pnpm dev

```

3. **Launch second instance with custom profile:**

```bash
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`](https://github.com/different-ai/openwork/blob/main/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`](https://github.com/different-ai/openwork/blob/main/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>/`.