Running Claude Code and Codex in Parallel Without Wasting Tokens
Mike Codeur
Watch the video: how to isolate coding agents working in parallel
Launching more agents is the easy part
I run dozens of Claude Code and Codex agents around the clock. Starting them in parallel is easy. Keeping them from interfering with one another is the hard part.
A Git worktree gives each agent a separate directory and branch. That is necessary, but it does not isolate the full runtime. The agents may still share a database, port, environment variables, development server, migrations, test records, or E2E browser target.
I learned this through an expensive failure: one full 24-hour loop burned 12 million tokens and produced nothing useful. The agents kept writing code, running tests, reading errors, and attempting fixes. Some of those errors came from shared infrastructure rather than the code they were changing.
That distinction matters. An agent can spend hours repairing valid code when it observes a real failure caused by another story’s environment.
Why Git worktrees are not enough
A worktree isolates files tracked by Git. It does not automatically isolate application state or running processes.
| Resource | Possible collision | Effect on the agent |
|---|---|---|
| Git branch | Changes from different tasks are mixed | Commits become difficult to review or merge |
| Worktree | Temporary files or paths point elsewhere | The agent reads or changes the wrong workspace |
| Port | Multiple servers bind to the same address | Startup fails or tests hit the wrong build |
| Database | Schemas and records are shared | Tests become unstable or data disappears |
| Environment variables | Agents inherit common settings | Code connects to the wrong service or database |
| Migrations | Stories expect different schemas | One story breaks another story’s runtime |
| Test data | Fixtures are reused | Results depend on execution order |
| E2E browser | Sessions or target URLs are shared | A test validates a different branch |
The Git state can look clean while the runtime is contaminated.
Why these failures fool agents
A collision rarely reports itself as another agent changing a shared resource. It looks like a normal application bug: a missing constraint, an unknown user, an unavailable server, an expired session, an already-applied migration, or an element that never appears.
The agent sees the symptom, inspects its branch, and writes a local fix. When the cause lives outside that branch, each attempted fix can take it further away from the answer.
Build one complete sandbox per user story
The correct isolation boundary is the user story, not the agent process.
Every story gets its own:
- branch;
- worktree;
- reserved port;
- database;
- environment file;
- application server;
- E2E target;
- migrations and test data scoped to that sandbox.
Put the story number in every resource name. It becomes the key that humans, scripts, and agents can use to connect the pieces and verify their scope.
Example branch, worktree, port, database, and E2E convention
The exact syntax can change with your stack. The important part is using one story identifier across the full chain.
| Item | Convention |
|---|---|
| Story | STORY-<number> |
| Branch | story/<number>-<topic> |
| Worktree | ../worktrees/story-<number> |
| Port | PORT_<number> assigned by the sandbox manager |
| Database | app_story_<number> |
| Environment file | .env.story-<number> |
| Server | server-story-<number> |
| E2E project | e2e-story-<number> |
| E2E URL | http://127.0.0.1:${PORT_<number>} |
A complete sandbox descriptor could look like this:
story = STORY-<number>
branch = story/<number>-<topic>
worktree = ../worktrees/story-<number>
port = PORT_<number>
database = app_story_<number>
env = .env.story-<number>
server = server-story-<number>
e2e_project = e2e-story-<number>
e2e_baseUrl = http://127.0.0.1:${PORT_<number>}The agent should not invent any of these values. A sandbox manager creates or reserves them, writes the configuration, and gives the agent a coherent execution context.
The lifecycle of an isolated story
Provision before delegation
Before starting Claude Code or Codex, create the branch and worktree, reserve a port, provision the database, and generate the environment file. Run migrations against the story database rather than a shared default database.
Provisioning should stop immediately when a requested resource is already in use. A clear failure before the agent starts is cheaper than an agent investigating an infrastructure collision throughout its loop.
Start the server from the correct worktree
Launch the application server from the story worktree and pass its environment file explicitly. Do not rely only on the current directory. The process logs should identify the story, port, and database so that the runtime can be audited.
Run a health check against the reserved URL before starting E2E tests. Otherwise, the browser may connect to an older server that still occupies the expected address.
Point E2E tests at an explicit target
Give each E2E project a story-specific baseURL. Isolate browser sessions, temporary output, and test records too when the test framework keeps them between runs.
The agent should always be able to answer three questions:
- Which commit is under test?
- Which server is running that commit?
- Which database contains the state observed by the test?
If any answer is missing, the E2E result is not reliable evidence.
Tear down only that story
After a story is merged or abandoned, stop its server, release its port, remove its database, and delete its worktree. Cleanup commands should target complete names derived from the story number. Broad cleanup commands can erase another agent’s active environment.
Guardrails for autonomous agents
Technical isolation works best when the agent also receives explicit rules:
- never use a default port or database;
- never run a migration without printing its target;
- reject an E2E run when its
baseURLdoes not match the story; - log the branch, commit, port, and database;
- confirm server health before opening the browser;
- treat an occupied resource as a configuration error, not an application bug;
- restrict each agent to its story’s worktree and services.
These rules help humans as well. When a test fails, the logs identify the exact version, server, and data that produced the result.
What isolation changes
A dedicated sandbox does not guarantee good code. Agents can still misunderstand a requirement, introduce a regression, or write a weak test. Isolation does not replace review, specifications, or test design.
It removes a class of misleading failures created by shared state. The agent can modify, restart, migrate, seed, and reset its environment without changing another story’s environment. Its observations become reproducible: the migration belongs to the story, the test data belongs to the story, and the browser points to the server built from that story’s worktree.
This also creates a cleaner failure boundary. If the story fails inside a complete sandbox, the investigation can focus on that story instead of first untangling every neighboring agent’s activity.
Conclusion
Running Claude Code and Codex in parallel requires more than separate branches. Everything the code touches at runtime needs a story-level boundary: the worktree, port, database, environment, migrations, test data, server, and E2E browser.
Use the story number in every resource name, prepare the sandbox before launching the agent, verify the target before testing, and remove only that sandbox when the work ends. This keeps an agent from spending its loop fixing side effects created by another one.
Watch the complete isolation workflow
Join The Agentic Dev newsletter for more field-tested agent workflows