How to Configure OpenWork Profiles for Development: A Complete Guide
OpenWork uses a hierarchy of environment variables—OPENWORK_ELECTRON_USERDATA, OPENWORK_ELECTRON_APP_IDENTIFIER, and OPENWORK_DEV_PROFILE—to isolate Electron user data directories, allowing multiple independent development instances to run without interfering with production data.
OpenWork is an open-source Electron desktop application maintained at different-ai/openwork. During development, you need isolated OpenWork profiles to prevent test data from corrupting your production installation. The application implements a cascading configuration system that determines the profile directory through environment variables resolved at runtime in apps/desktop/electron/main.mjs.
Understanding the OpenWork Profile Hierarchy
The profile resolution logic is implemented in apps/desktop/electron/main.mjs (lines 38–44), where the resolveAppIdentifier function evaluates environment variables in strict precedence order:
OPENWORK_ELECTRON_USERDATA– Directly specifies the exact file system path to the profile directory.OPENWORK_ELECTRON_APP_IDENTIFIER– Provides the base identifier used to construct the profile folder name.OPENWORK_DEV_PROFILE– Available only in unpacked development builds; accepts a short slug (e.g.,auto,feature-x) that gets sanitized into the identifier.- Legacy identifier – Fallback when no environment variables are set.
Configuring Development Profiles
Default Shared Profile
Running pnpm dev with no additional environment variables reuses the existing shared development profile. According to the dev/README.md (lines 86–98), this is the fastest way to start coding but offers no isolation between worktrees.
Isolated Worktree with Auto-Generated Profiles
Use the built-in dev:worktree script defined in package.json (line 7) to automatically configure an isolated profile:
pnpm dev:worktree
This executes OPENWORK_DEV_PROFILE=auto pnpm dev, generating a unique profile directory that prevents conflicts with other development instances.
Named Profiles for Reproducible Testing
For deterministic test environments, assign a specific profile name. The value is sanitized into a valid identifier to ensure a separate userData directory:
OPENWORK_DEV_PROFILE=my-feature pnpm dev
Mock Keychain Configuration
By default, OpenWork development profiles use a mock keychain to avoid macOS system prompts that block the Electron main loop. Control this behavior with OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN (default: 1):
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=0 pnpm dev
Setting this to 0 forces the app to use the real system keychain for authentication testing.
Remote Debugging Configuration
The development server exposes a Chrome DevTools Protocol (CDP) endpoint. Force a specific port or let Electron choose automatically:
OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0 pnpm dev
Upon startup, the application prints a banner like [openwork] dev profile=… cdp=http://127.0.0.1:9223 (as documented in dev/README.md lines 98–100), enabling direct CDP tooling integration.
Headless Web Development Mode
For browser-based testing without Electron overhead, use the headless web launcher:
pnpm dev:headless-web
This creates tmp/headless-server.json and tmp/dev-headless-web.json containing URLs, tokens, and CDP addresses while respecting the same profile isolation logic and mock keychain settings.
Practical Configuration Examples
Run multiple configuration scenarios using these tested command patterns:
# Built-in worktree helper with auto-generated profile
pnpm dev:worktree
# Stable named profile with auto-selected debug port
OPENWORK_DEV_PROFILE=feature-xyz \
OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0 \
pnpm dev
# Real keychain testing with isolated profile
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=0 \
OPENWORK_DEV_PROFILE=auth-test \
pnpm dev
# Headless UI with captured CDP endpoint
pnpm dev:headless-web
Summary
- OpenWork profiles are resolved through a four-level hierarchy in
apps/desktop/electron/main.mjs, withOPENWORK_ELECTRON_USERDATAtaking highest precedence. - Use
pnpm devfor shared profiles orpnpm dev:worktreefor automatic isolation viaOPENWORK_DEV_PROFILE=auto. - Named profiles (
OPENWORK_DEV_PROFILE=my-feature) create deterministic, isolated user data directories. - The mock keychain (
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1) prevents macOS login prompts during development. - Headless web mode (
pnpm dev:headless-web) supports profile isolation without Electron.
Frequently Asked Questions
What is the difference between OPENWORK_DEV_PROFILE and OPENWORK_ELECTRON_USERDATA?
OPENWORK_DEV_PROFILE accepts a short slug that gets sanitized into a profile identifier, useful for quick worktree isolation. OPENWORK_ELECTRON_USERDATA requires an absolute file system path and bypasses all identifier generation logic, offering direct control over the Electron userData directory location.
How do I prevent development builds from accessing my production OpenWork data?
Always set OPENWORK_DEV_PROFILE to a unique value (or use pnpm dev:worktree) before running pnpm dev. According to the source code in apps/desktop/electron/main.mjs, this ensures the app resolves a distinct userData path, completely isolating development state from production installations.
Why does OpenWork use a mock keychain by default in development?
The mock keychain prevents the native macOS "Login" dialog from blocking the Electron main loop during automated testing and rapid iteration. Set OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=0 only when specifically testing system keychain integration, as implemented around lines 100–107 of apps/desktop/electron/main.mjs.
Can I use OpenWork profiles when running the headless web mode?
Yes. The pnpm dev:headless-web command respects the same environment variables including OPENWORK_DEV_PROFILE and OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN, creating isolated temporary JSON files in tmp/ while maintaining profile separation from production data.
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 →