Wtdev – deterministic dev-server ports for parallel Git worktrees Wtdev, a deterministic dev-server port manager for parallel Git worktrees, has been released as a single POSIX shell script. It assigns stable ports based on worktree paths to prevent collisions and supports automation hooks for coding agents like Claude Code. The tool also copies gitignored env files and provides a live dashboard of all checkouts. One dev server per git worktree. No port collisions, stable URLs, and a live dashboard of every checkout. If you run coding agents Claude Code, Cursor, etc. in parallel git worktrees, you've hit this: every worktree's dev server wants port 3000, agents kill each other's servers or drift to random ports, and you can never remember which branch is on which port. wtdev fixes it with one rule: the port is a pure function of the worktree's path. - main checkout → 3000 - every linked worktree → a stable port in 3001–3999 , hashed from its path Same worktree, same port, every time — across restarts, across agents, with zero coordination and zero state. In the rare case two worktrees hash to the same port, the later one in git worktree list order simply takes the next free port, so ports stay unique without anything to configure. curl -fsSL https://raw.githubusercontent.com/Dave-56/wtdev/main/wtdev -o /usr/local/bin/wtdev chmod +x /usr/local/bin/wtdev It's a single dependency-free POSIX shell script; you can also just copy it into your repo. wtdev run start the dev server on this checkout's port wtdev run pnpm dev ...with an explicit command {port} is substituted wtdev up start it in the background if not already serving wtdev port print this checkout's port wtdev list every worktree with its branch + port wtdev dashboard generate a live-status HTML dashboard The easiest setup is to route your dev script through it, so agents and humans alike get the right port without thinking: { "scripts": { "dev": "wtdev run next dev -p {port}" } } wtdev run exports PORT which Next.js, Vite via config, CRA, Remix, and most Node servers respect and also substitutes {port} into the command for tools that want a flag. It also copies gitignored env files .env , .env.local by default from the main checkout into fresh worktrees, since those never come along with git worktree add . wtdev up is run for automation: it starts the server in the background logging to .wtdev.log — add it to .gitignore only if the checkout's port isn't already serving, and prints the URL either way. Because it's idempotent, any number of sessions can call it without double-starting servers. Wire it into your agent's session-start hook and every session begins with its checkout's dev URL already in context. For Claude Code, put this in .claude/settings.json at the repo root: { "hooks": { "SessionStart": { "hooks": { "type": "command", "command": " -d node modules || npm install /dev/null 2 &1; wtdev up 2 /dev/null || true", "timeout": 180, "statusMessage": "Starting dev server for this checkout" } } , "PostToolUse": { "matcher": "EnterWorktree", "hooks": { "type": "command", "command": " -d node modules || npm install /dev/null 2 &1; wtdev up 2 /dev/null || true", "timeout": 180, "statusMessage": "Starting dev server for this worktree" } } } } Both hooks matter. SessionStart covers the checkout a session launches in — but a worktree created mid-session Claude Code's EnterWorktree never re-fires it, so without the PostToolUse hook those worktrees silently run without a server until someone notices. The hook runs after the session has switched into the new worktree, so wtdev up picks up that worktree's port. The npm install guard makes fresh worktrees self-sufficient — git worktree add doesn't bring node modules along. If you vendor the script instead of installing it globally, use sh scripts/wtdev up . wtdev dashboard manual regenerate; run/up also regenerate it automatically Every wtdev run / wtdev up rewrites the dashboard after git worktree prune , so deleted worktrees drop off the page as soon as any server starts — no manual upkeep. The page shows live servers by default; idle checkouts collapse behind a "show N idle checkouts" toggle. Writes worktrees.html into public/ if you have one, so your dev server serves it listing every worktree's branch, last commit, and URL, with a green/red live-status dot probed from the page every 5 seconds. Re-run it when you add or remove worktrees. If localias https://github.com/peterldowns/localias is installed and running brew install peterldowns/localias/localias && localias start , wtdev run also registers http://