feat(desktop): isolate dev profiles per worktree so several can run at once - #3124
Merged
Conversation
Every dev Electron instance shared one profile directory, so app.requestSingleInstanceLock() failed for the second worktree. Chromium had already opened the CDP port by then, so the process lingered answering /json/version without ever creating a window or logging anything - it looked exactly like a hang. Add OPENWORK_DEV_PROFILE (dev-only, inert when packaged): unset keeps today's shared profile so existing profiles are untouched, 'auto' derives a stable name from the worktree path, and any other value names a profile explicitly. OPENWORK_ELECTRON_USERDATA still wins. On lock contention the second dev instance now explains which profile directory is held and how to isolate, then exits for real so the CDP port is released. Dev startup prints the resolved profile directory and CDP address. Add pnpm dev:worktree for the common case: auto profile plus free CDP and Vite ports, so several worktrees run side by side.
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Contributors keep many git worktrees of this repo. Every dev Electron instance shares one profile directory (
com.differentai.openwork.dev), soapp.requestSingleInstanceLock()fails for the second worktree. The failure mode is the bad part: Chromium has already opened the CDP port by then, so the process lingers answering/json/versionwhile never creating a window and never logging anything. It looks exactly like a hang, with no hint and no easy way to run two worktrees side by side.The primitive
OPENWORK_DEV_PROFILE— dev-only, completely inert when packaged:autoPrecedence (documented in the code):
OPENWORK_ELECTRON_USERDATA→OPENWORK_ELECTRON_APP_IDENTIFIER→OPENWORK_DEV_PROFILE→ today's default.Unset is unchanged on purpose. Nobody's existing dev profile (sessions, auth, providers) moves or disappears. There is no migration.
Fail loud instead of hanging. On lock contention a dev instance now names the locked profile directory, says another instance holds it, gives the exact remedy, and exits for real (
app.exit+process.exit) so the CDP port is released and no zombie remains.second-instancefocus behavior is untouched, and production still uses plainapp.quit().Dev boot banner so you can tell instances apart:
pnpm dev:worktree—OPENWORK_DEV_PROFILE=autoplus free CDP and Vite ports.pnpm devkeeps its pinned9823unchanged, becauseevals/runnerdefault-probes9825then9823and moving it would break eval discovery.It also defaults
OPENWORK_ELECTRON_USE_MOCK_KEYCHAIN=1, which I only found by testing: a brand-new profile has no stored credentials, so on macOS the real keychain prompts as soon as Chromium persists an authenticated cookie — andmain.mjsalready documents that this modal "blocks the entire Electron main loop". Without this default, the new script would reproduce the very hang it exists to remove. Override with=0.Verification
New
apps/desktop/electron/dev-profile.test.mjscovers: unset → legacy identifier unchanged;autostable for the same path and different for another; named value sanitized;OPENWORK_ELECTRON_USERDATAbeatingOPENWORK_DEV_PROFILE; packaged mode ignoring the var.Observed live from a second worktree:
…/com.differentai.openwork.dev.cap-dev-profile-wt2-156b2b1bc8[electron-dev] Vite dev server will use free port 59148pnpm devscript verified byte-identical to beforeWhat I could NOT verify, honestly
I could not observe two dev windows side by side on this machine, because dev Electron currently opens no window on this macOS host at all — I reproduced 0 CDP page targets from the unmodified main checkout with an isolated profile and a mock keychain, so it is pre-existing and unrelated to this change. The same commit does open a window in a clean Linux sandbox.
I also want to correct something I claimed earlier on a related PR: I attributed that local no-window hang to the single-instance lock. That was wrong — this testing disproved it. The lock collision is real and worth fixing (this PR), but it is not the cause of the local no-window symptom, which remains an open macOS-host issue I have not root-caused.
So: the profile/port collision and the silent-hang-on-lock-contention are fixed and unit-tested; the "two windows at once" end state is verified only in the sense that both instances get distinct profiles and ports.