tarek.kharsa

home / lessons / t3 code · lesson 6

Dev setupT3 Code · lesson 6 of 82 min read

A dev setup built for ten agents on one laptop

Ports, databases, processes and URLs: everything shared becomes a collision once agents run in parallel.

Problem

Run several agents on one laptop and everything shared collides: ports, databases, processes, URLs.

Idea

Derive ports and state from each worktree, keep one origin, and never kill processes by pattern.

Run five AI agents in five git worktrees on one machine and everything that's normally shared starts colliding: ports, databases, processes, even the URLs you send to your phone. This repo's dev tooling assumes that's the normal case.

Try it: fixed ports vs hashed ports

add worktrees, then restart everything

With a fixed dev port, the second worktree can't start its server. Deriving the port from a hash of the worktree path gives every worktree its own port, and the same one after every restart.

Ports from a hash of the worktree path

The dev runner derives ports from a hash of the worktree path, so the result depends on where a worktree lives, not on who started first. Two details show how carefully it was built:

  • It skips every port on the Fetch spec's blocked list, the ones curl accepts but browsers refuse to connect to.
  • It probes only loopback when checking whether a port is free. Probing wildcard addresses made it move away from a free port whenever tailscale serve held the same number on another interface.

Everything else is per worktree too

State

Each worktree gets its own gitignored data directory, and it deliberately takes priority over any ambient HOME-style variable, so you can't land on shared state by accident.

Setup

A script runs when a worktree is created: it links the shared .env and warms the dependency cache.

Origin

Dev is single-origin: Vite proxies /api and /ws. Baking localhost into the bundle "silently breaks every remote browser."

Sharing

vp run dev --share publishes the dev server on the tailnet and prints a pairing URL for your phone. The mapping goes away when the process exits.

Vendored reference repos

A .repos/ folder holds read-only source of key libraries, skipped by CI's sparse checkout. Agents read real library code instead of guessing from training data. The rules: never edit them, never import from them, re-sync when you bump the dependency.

CI that doesn't wait in line

  • Lint, typecheck, build and tests run as parallel jobs behind one aggregate "Check" gate.
  • System packages install in the background while JS dependencies install.
  • A new push to a PR cancels its superseded runs.

And the one rule that makes all of this safe to automate, never killing processes by pattern, is in lesson 8.

Steal this

Design dev tooling as if a dozen strangers share your laptop, because with agents that's roughly true. Derive ports and state from the worktree path, keep one origin, and make a new worktree ready in one step.

Use it in your code

A prompt for your coding agent

Run it from the root of your repo. It checks whether the idea fits before it changes anything.

Make this project's local dev setup safe for several agents working in parallel, each in its own git worktree or checkout.

The idea: anything shared on one machine becomes a collision when agents run in parallel: ports, databases, caches, background processes, URLs. Derive them from the worktree instead of hard-coding them.

1. Find everything the dev setup shares: fixed ports, a single local database or data directory, global caches, PID files, and scripts that kill processes by name or pattern.
2. Propose a scheme where each worktree gets its own values, for example ports derived from a hash of the worktree path and a gitignored data directory inside the worktree. The same worktree should get the same values on every run.
3. Replace any "kill by pattern" with stopping only the processes this worktree started.
4. Implement it in the dev scripts, print the chosen ports on startup, and document it in the README.

Check that two copies of the repo can run the dev server at the same time. Keep the change small.

Read the source

Where this comes from

T3 Code (pingdotgg/t3code), the open-source GUI for coding agents. The files behind this lesson: