Agent Tile BlogRunning a fleet of AI coding agents, well.

Port and database collisions when parallel AI agents run your app

· Claude Code, workflow, parallel development

Git worktrees stop parallel agents from editing the same files. They do not stop them from sharing everything outside the repository: the port the dev server listens on, the local database, a cache directory in your home folder.

That is where a second, quieter kind of collision happens. One session starts the app and gets the port. Another session starts the app, sees "address already in use", and either gives up or picks a new port without telling you. Or two sessions run integration tests at the same time and one wipes the database the other is reading. The result is a test that fails for a reason that has nothing to do with the code the agent just wrote — and an agent that will happily try to "fix" it.

The three things agents usually share by accident

  1. Ports. Dev servers, API mocks, Storybook, a local queue — anything that listens on a fixed number.
  2. Databases. A local Postgres or SQLite file that tests reset, migrate or seed.
  3. Caches and temp folders. Build caches, downloaded fixtures, a tmp/ path hard-coded outside the repo.

Files inside a worktree are separate by design. These three are separate only if you make them so.

Give each session its own slot

The simplest pattern is a slot number per session, and everything else derived from it.

  • Port: session 1 uses 3001, session 2 uses 3002, and so on. Many dev servers read a PORT environment variable or accept a --port flag; check what yours supports.
  • Database: one database name or file per slot, e.g. app_test_1, app_test_2, or test-1.sqlite.
  • Cache / temp: keep them inside the worktree (and in .gitignore) instead of a shared path in your home directory.

Put the values in a small, git-ignored env file at the root of each worktree, so the setting travels with the folder rather than living in someone's memory:

# .env.local in the worktree for session 2
PORT=3002
DATABASE_URL=postgres://localhost/app_test_2

Then tell the agent once, in its brief: "Use the port and database in .env.local. Never kill a process you didn't start."

Two lines worth adding to every brief

  • "If a port is in use, stop and report it." Without this, an agent may kill whatever is holding the port — which can be another agent's server — or silently switch ports and then test against the wrong process.
  • "Only reset the database named in .env.local." Destructive test setup is fine when it is scoped. It is a problem when it reaches the shared default database.

These fit naturally into the "forbidden area" part of a four-part brief.

Finding out who holds a port

When something is already listening, check before killing it. On macOS:

lsof -nP -iTCP:3002 -sTCP:LISTEN

The output shows the process ID and command. If it belongs to another session's worktree, the fix is a different slot, not kill.

Where Agent Tile fits

Slots only work if you can tell which session is which. Agent Tile is a one-time $10 macOS app that shows each Claude Code session as a tile with its project and folder visible, so "session 2 = the worktree with port 3002" is something you can see rather than remember. After a restart it relaunches each session with --resume in its original directory, so each one comes back next to its own .env.local. It does not assign ports for you — that part is the env file.

Takeaway

Worktrees separate files; you still have to separate ports, databases and caches. Give each session a slot number, store the values in a git-ignored env file in the worktree, and tell agents to report a busy port instead of killing it.

Agent Tile
Practical guides for running many Claude Code sessions in parallel on macOS — orchestration, review workflows, and staying sane with a fleet of AI coding agents.
Get Agent Tile — full source, $10 once →
Also from TechAthletes
  • IT-QA — Technical Q&A with AI-assisted answers and point bounties — for the questions that come up while you're running a fleet.