How to Configure OpenWork Environment Variables and Dev Profiles: A Complete Guide
Set OPENWORK_DEV_MODE=1 and use OPENWORK_DEV_PROFILE to isolate Electron user data, CDP ports, and credentials across worktrees.
OpenWork uses a purpose-built environment variable system to manage local development workflows, particularly when running multiple Git worktrees or isolating sensitive credentials. This article explains every variable, how the dev profile system works under the hood, and the exact commands for common scenarios based on the different-ai/openwork source code.
Core Environment Variables
OpenWork recognizes six primary environment variables that control development behavior. These are defined across .env.dev, package.json scripts, and the Electron main process.
| Variable | Purpose | Default | Defined In |
|---|---|---|---|
OPENWORK_DEV_MODE |
Enables built-in dev mode with profile logic | 1 |
.env.dev |
OPENWORK_DEV_PROFILE |
Selects the dev profile (auto, custom name, or unset) |
unset (legacy fallback) | [package.json](https://github.com/different-ai/openwork/blob/dev/package.json#L7) |
OPENWORK_ELECTRON_REMOTE_DEBUG_PORT |
CDP port for Chrome DevTools Protocol | 0 (auto-select) |
[package.json](https://github.com/different-ai/openwork/blob/dev/package.json#L7) |
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN |
Uses isolated mock keychain instead of OS keychain | 1 (dev worktrees) |
[package.json](https://github.com/different-ai/openwork/blob/dev/package.json#L7) |
OPENWORK_ELECTRON_DISABLE_PROTOCOL_REGISTRATION |
Prevents custom URL protocol registration | 1 (tests) |
dev-profile.test.mjs |
OPENWORK_ELECTRON_USERDATA |
Direct override for Electron user-data directory | unset | dev-profile.test.mjs |
In apps/desktop/electron/main.mjs, the Electron main process reads process.env.OPENWORK_DEV_PROFILE and logs the resolved profile path at startup. The OPENWORK_ELECTRON_USERDATA variable takes precedence over profile-based paths when explicitly set.
How the Dev Profile System Works
When you launch pnpm dev, OpenWork prints a diagnostic banner:
[openwork] dev profile=/Users/you/.openwork/dev-<hash> cdp=http://127.0.0.1:9223
The profile directory stores isolated Chromium data: cookies, localStorage, IndexedDB, and credential caches. This isolation prevents collisions between developers or branches.
The CDP endpoint (9223 in the example) exposes Chrome DevTools Protocol for remote debugging, automated browser testing, or external tooling like browser_navigate and browser_snapshot.
Profile Naming Modes
auto: Hashes the current Git worktree path to generate a stable, unique directory per checkout. Ideal for parallel worktree development.- Custom name (e.g.,
my-feature): Creates a deterministic, reusable profile. Useful for CI pipelines or persistent debugging sessions. - Unset: Falls back to a legacy identifier derived from the project name. Not recommended for multi-worktree setups.
The mock keychain (OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1) prevents macOS keychain authorization prompts during development. Disable it only when testing real OAuth flows that require OS credential storage.
Common Development Workflows
Single Checkout Development
Run the standard dev server with shared profile state:
pnpm dev
No additional environment configuration required. Uses legacy profile fallback.
Parallel Worktree Development
Run multiple worktrees simultaneously with fully isolated profiles and auto-assigned ports:
pnpm dev:worktree
This script in package.json automatically sets:
OPENWORK_DEV_PROFILE=auto
OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1
Named Profile with Custom Settings
Create a deterministic profile for reproducible paths or CI:
OPENWORK_DEV_PROFILE=feature-x \
OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0 \
PORT=0 \
pnpm dev
Setting PORT=0 allows Vite to select a free port, preventing collisions with other instances.
Real System Keychain for OAuth Testing
When authenticating against live providers that require OS-level credential storage:
OPENWORK_DEV_PROFILE=auth-test \
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=0 \
pnpm dev
Capturing the CDP Endpoint Programmatically
Extract the Chrome DevTools URL for external tooling:
# Start dev server and capture CDP URL
export CDP_URL=$(pnpm run -s print-cdp 2>/dev/null || echo "http://127.0.0.1:9223")
# Use in Node.js script
node -e "
const CDP = require('chrome-remote-interface');
CDP({ target: '$CDP_URL' })
.then(client => {
const { Network, Page } = client;
return Page.navigate({ url: 'https://example.com' });
})
.catch(console.error);
"
Key Source Files
| File | Role |
|---|---|
.env.dev |
Base environment values including OPENWORK_DEV_MODE and placeholder secrets |
[package.json](https://github.com/different-ai/openwork/blob/dev/package.json#L7) |
dev:worktree script definition with auto-profile environment setup |
apps/desktop/electron/main.mjs |
Profile resolution and startup logging |
apps/desktop/electron/dev-profile.test.mjs |
Test suite validating profile selection, mock keychain, and protocol registration flags |
[scripts/dev-web-local.sh](https://github.com/different-ai/openwork/blob/dev/scripts/dev-web-local.sh) |
Web-only dev server with environment propagation to Vite |
Summary
- Set
OPENWORK_DEV_MODE=1to enable the development profile system (typically pre-configured in.env.dev). - Use
OPENWORK_DEV_PROFILE=autofor automatic isolation across Git worktrees, or assign custom names for reproducible environments. - The mock keychain (
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1) prevents OS prompts but must be disabled for real OAuth flows. - Override
OPENWORK_ELECTRON_USERDATAdirectly when you need complete control over the Electron data directory. - Reference
apps/desktop/electron/main.mjsfor the runtime implementation anddev-profile.test.mjsfor expected behavior.
Frequently Asked Questions
What happens if I don't set OPENWORK_DEV_PROFILE?
OpenWork falls back to a legacy identifier derived from the project name. This works for single-checkout development but causes state collisions when running multiple worktrees simultaneously. As implemented in different-ai/openwork, the fallback is intentionally simple to maintain backward compatibility.
Why does pnpm dev:worktree set CDP port to 0?
Setting OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0 instructs Electron to bind to any free port, preventing conflicts when multiple dev servers run concurrently. The actual port is logged in the startup banner and can be captured via the print-cdp helper or parsed from stdout.
Can I use the real macOS keychain in development?
Yes. Set OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=0 before starting the dev server. This is necessary for testing OAuth flows that require OS-level credential persistence, but expect authorization prompts and potential state sharing between profiles.
How do I completely override the profile directory?
Set OPENWORK_ELECTRON_USERDATA to an absolute path. This bypasses all OPENWORK_DEV_PROFILE logic and directs Electron to use your specified directory for all user data. According to dev-profile.test.mjs, this is primarily used in test suites for temporary directory injection.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →