# How to Configure OpenWork Profiles for Development: A Complete Guide

> Configure OpenWork profiles for development with this complete guide. Learn how environment variables isolate Electron user data for multiple independent instances. Prevent production data interference.

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

---

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

1. **`OPENWORK_ELECTRON_USERDATA`** – Directly specifies the exact file system path to the profile directory.
2. **`OPENWORK_ELECTRON_APP_IDENTIFIER`** – Provides the base identifier used to construct the profile folder name.
3. **`OPENWORK_DEV_PROFILE`** – Available only in unpacked development builds; accepts a short slug (e.g., `auto`, `feature-x`) that gets sanitized into the identifier.
4. **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`](https://github.com/different-ai/openwork/blob/main/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`](https://github.com/different-ai/openwork/blob/main/package.json) (line 7) to automatically configure an isolated profile:

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

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

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

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

```bash
pnpm dev:headless-web

```

This creates [`tmp/headless-server.json`](https://github.com/different-ai/openwork/blob/main/tmp/headless-server.json) and [`tmp/dev-headless-web.json`](https://github.com/different-ai/openwork/blob/main/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:

```bash

# Built-in worktree helper with auto-generated profile

pnpm dev:worktree

```

```bash

# Stable named profile with auto-selected debug port

OPENWORK_DEV_PROFILE=feature-xyz \
OPENWORK_ELECTRON_REMOTE_DEBUG_PORT=0 \
pnpm dev

```

```bash

# Real keychain testing with isolated profile

OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=0 \
OPENWORK_DEV_PROFILE=auth-test \
pnpm dev

```

```bash

# 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`, with `OPENWORK_ELECTRON_USERDATA` taking highest precedence.
- Use `pnpm dev` for shared profiles or `pnpm dev:worktree` for automatic isolation via `OPENWORK_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.