Parallel Development with Git Worktrees

How automated port management and environment configuration enable zero-friction parallel AI coding sessions.

The pain of context switching

You are deep in a feature branch. Three files open, a mental model of the data flow loaded into your head, tests half-written. Then a critical bug report comes in. Something is broken in production.

The traditional workflow: stash your changes, switch branches, lose your mental context, fix the bug, commit, switch back, pop your stash, and hope that the stash applies cleanly and your mental model reassembles itself. More often than not, you spend twenty minutes getting back to where you were before the interruption.

Git worktrees solve this at the primitive level. Instead of switching branches in a single directory, you create a second working directory that points to a different branch of the same repository. Two branches, two directories, zero stashing. Your feature work stays exactly where you left it.

The problem is that worktrees are easy to create and painful to configure — especially in a monorepo.

Why worktrees are hard in monorepos

A Turborepo monorepo with pnpm workspaces adds layers of complexity that a simple git worktree add does not handle:

  • Shared packages need building. The product app depends on compiled output from shared packages (@nextsaasai/ui, @nextsaasai/utils, @nextsaasai/blog). A fresh worktree has no dist/ directories — nothing compiles until you run the build pipeline.
  • Multiple environment files. The monorepo requires .env.local files at three levels: repository root, apps/boilerplate/, and apps/marketing/. Missing any one of them means missing environment variables at runtime.
  • Port conflicts. Two Next.js dev servers cannot bind to the same port. Every worktree needs its own port configuration — but Next.js does not read PORT from .env.local. The Commander.js CLI parser runs before @next/env loads environment variables.
  • Dev script patching. The only reliable way to set the port is the --port CLI flag, which means every worktree needs its package.json dev scripts patched with the correct port number.
  • Cleanup complexity. git worktree remove does not clean up untracked files like .turbo/daemon/ that Turborepo creates. Leftover directories cause errors when creating future worktrees with the same name.

Any one of these issues is solvable in five minutes. All of them together, every time you want a parallel workspace, add up to thirty minutes of manual configuration that defeats the purpose of worktrees entirely.

The automation we built

The nextsaas.ai worktree command handles the complete lifecycle — creation, configuration, and cleanup — in a single step:

  1. Branch detection. Automatically identifies the parent branch for the worktree, defaulting to the current branch or allowing explicit specification.
  2. Directory creation. Creates the worktree in a predictable location relative to the main repository, with a naming convention that makes finding worktrees easy.
  3. Port assignment. Calculates unique ports based on the worktree's position (base port + offset), then patches apps/boilerplate/package.json and apps/marketing/package.json with the correct --port flags.
  4. Environment setup. Copies all .env.local files from the main repository to the worktree, adjusting port references in each file.
  5. Dependency installation. Runs pnpm install in the worktree to ensure the lockfile is respected.
  6. Package building. Runs pnpm build for shared packages so that application imports resolve immediately.
  7. Git cleanup flags. Marks the patched package.json files with --skip-worktree so they do not appear as modified in git status.

Removal is equally automated. The cleanup command runs git worktree remove, then follows with rm -rf on the directory to eliminate untracked files that Git's worktree removal intentionally leaves behind.

AI coding in parallel

The real motivation behind this automation was not traditional developer workflow — it was AI-assisted development.

Running multiple AI coding sessions against the same working directory creates a fundamental problem: write conflicts. Two sessions editing overlapping files will corrupt each other's work. This is not a theoretical risk — it happens the moment both sessions touch a shared utility, a config file, or a test suite. The more sessions you run in parallel, the worse the conflicts get.

Worktrees eliminate this entirely. Each AI coding session gets its own directory, its own dev server, its own Git state. There is no possibility of write conflicts because each session operates on a physically separate copy of the codebase. A refactor in the shared UI package can run in one worktree while a new API endpoint develops in another — same repository, same Git history, complete isolation.

The workflow benefit compounds from there. You spin up a second workspace in under a minute, and the feature session continues undisturbed while the hotfix session operates independently. When the fix ships, you remove the worktree and resume exactly where you left it. As a bonus, each session's accumulated context — the files it has read, the patterns it has learned, the approaches already tried — stays intact rather than being lost to a branch switch or stash cycle.

Transferable patterns

The specific automation we built is tailored to our Turborepo + pnpm monorepo. But the patterns transfer to any monorepo setup:

Worktree automation must handle everything a fresh clone would handle — environment files, port configuration, dependency installation, and package builds. If you would not hand someone a bare git worktree add directory and tell them "just run npm start," then your worktree tooling has gaps.

The --skip-worktree trick for patched files is universally useful. Any file that needs per-worktree modifications (port configs, environment overrides) should be invisible to git status so developers and CI tools see a clean working tree.