Fix dev server port conflicts across worktrees#312
Merged
Conversation
Running multiple worktrees in parallel (Conductor or plain git worktree) caused studios on 5174/5175 to silently proxy to the first worktree's API on :3001, serving stale code from the wrong branch. A root orchestrator (scripts/dev.mjs) now picks a free port and threads PORT + API_PROXY_TARGET into the api/studio children via env vars. The vite proxy reads API_PROXY_TARGET with a :3001 fallback so solo dev and prod builds are unaffected. Port-probe helper adapted from the findFreePort in zig/electron.
- Added support for setting the document title based on the VITE_WORKSPACE_NAME environment variable in main.tsx. - Updated vite-env.d.ts to define the VITE_WORKSPACE_NAME variable for better type safety. - Enhanced dev.mjs to detect and log the workspace name from the conductor environment or current git branch, improving clarity during development.
Collaborator
Author
|
Continuation of #295, which was auto-closed by GitHub when the head branch was renamed from |
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.
Closes #290.
Summary
Fixes dev server port conflicts when running multiple worktrees in parallel (Conductor or plain
git worktree). Before: only the first worktree's API binds:3001; other studios silently proxy to the stale first instance, so endpoints that only exist on the current branch return 404 in what looks like a UI bug. After: each worktree picks its own free API port, and its studio proxy follows.As a bonus for parallel-worktree workflows, the browser tab title now reflects the workspace (Conductor workspace name, or current git branch as a fallback), so tabs are trivially distinguishable at a glance.
ADT StudioADT Studio — Cool workspaceADT Studio — Dev port conflictsHow
scripts/dev.mjs— root dev orchestrator. Finds a free port (sequential scan from3001), then spawns the existingpnpm --paralleldev withPORTandAPI_PROXY_TARGETthreaded in as env vars. Also detects a workspace label (fromCONDUCTOR_WORKSPACE_NAME, falling back to the current git branch's leaf segment) and forwards it asVITE_WORKSPACE_NAME.scripts/find-free-port.mjs— pure-Node port probe. Logic adapted from Zig'sfindFreePortin thezig/electronbranch (apps/electron/src/main/api/port.ts).apps/studio/vite.config.ts— proxy target now readsAPI_PROXY_TARGETwithhttp://localhost:3001fallback.apps/studio/src/main.tsx— whenVITE_WORKSPACE_NAMEis set at dev time, appends it todocument.title. Unset in production builds, so end users see the default title.apps/studio/src/vite-env.d.ts— type declaration for the new env var.package.json— rootdevscript now callsnode scripts/dev.mjs.dev:api/dev:studiounchanged.Approach
We went with a monorepo-level orchestrator because it's self-contained, tool-agnostic (works with plain
git worktree, Conductor, multiple terminals), needs zero per-worktree config, and adds no dependencies. A more robust alternative would be a dedicated tool like Portless, which handles automatic subdomain routing with zero env wiring — at the cost of another dev dependency and per-developer setup.Scope
Web dev only. The electron launch path already picks its own port via its own supervisor logic and is untouched. Production builds are also untouched: the api's
PORTfallback stays3001,vite buildignoresserver.proxy, andVITE_WORKSPACE_NAMEis unset so the tab title is unchanged.Test plan
pnpm devin one worktree →[dev] API port: 3001, studio on 5173pnpm devin a second worktree concurrently →[dev] API port: 3002, studio on 5174,/api/*requests from the second studio hit the second worktree's APIconsole.logon an api route in worktree 2, triggered from worktree 2's studio, appears in worktree 2's terminal (not worktree 1's)ADT Studio — <workspace name>ADT Studio — <branch leaf>(e.g.Dev port conflictsforEliezir/dev-port-conflicts)pnpm dev:studiostill proxies to:3001and shows the plainADT Studiotitle (backwards compatible)pnpm typecheckpasses