One repository, twenty checkouts
Running several agents at once is easy until two of them edit the same file. Codecast gives each one its own worktree, with the env files, dependencies and a port of its own, in one command.
The shared checkout problem
Three weeks ago on this blog, a Codex agent and a Claude Code agent coordinated a repair by messaging each other, because both were editing one working tree and one of them had to stay out of the other's files. That was the right thing to do in a shared checkout, and it is also a cost: two agents spending turns negotiating who may touch which file. The cheaper answer, when the work allows it, is to not share the checkout at all.
Git has had worktrees for years: extra checkouts of the same repository, each on its own branch, sharing one object store. What stops people using them for agents is everything around the checkout. The ignored files that hold secrets are not copied. Dependencies are not installed. The dev server wants port 3200, which the main checkout already holds. By the time an agent has fixed all that, it has spent its first ten minutes on plumbing. So codecast made the plumbing one command.
Twenty of them
Here is the codecast repository's own list this morning. Every row is a checkout an agent asked for by name, most of them for a feature branch, two for a task by its id:
$ cast ws ls
NAME STATE BRANCH PATH
deprecate-reconcilers ready codecast/deprecate-reconcilers /Users/ashot/src/codecast/.codecast/worktrees/deprecate-reconcilers
browser-watch-pane ready codecast/browser-watch-pane /Users/ashot/src/codecast/.codecast/worktrees/browser-watch-pane
deploy-repo-objects destroying codecast/deploy-repo-objects /Users/ashot/src/codecast/.codecast/worktrees/deploy-repo-objects
linear-token-deploy ready codecast/linear-token-deploy /Users/ashot/src/codecast/.codecast/worktrees/linear-token-deploy
safe-query ready codecast/safe-query /Users/ashot/src/codecast/.codecast/worktrees/safe-query
browser-resident-driver ready codecast/browser-resident-driver /Users/ashot/src/codecast/.codecast/worktrees/browser-resident-driver
ct-49675 ready codecast/ct-49675 /Users/ashot/src/codecast/.codecast/worktrees/ct-49675
grok-fork broken codecast/grok-fork /Users/ashot/src/codecast/.codecast/worktrees/grok-fork
… 11 more rows, all ready …
Nineteen tracked: seventeen ready, one being torn down, one broken. The broken one is the interesting row. A workspace carries a contract, and codecast checks it rather than assuming it. Ask about one and you get the state and every clause of the contract, verified:
$ cast ws status safe-query
safe-query
state: ready
path: /Users/ashot/src/codecast/.codecast/worktrees/safe-query
branch: codecast/safe-query
ports: web=3201
updated: 2026-08-11T22:34:58.491Z
contract: ok
✓ worktree-exists
✓ git-branch
✓ deps-installed
✓ env-vars
✓ port:web
✓ port-free:web
The worktree exists, the branch is right, dependencies are installed, the secret files are present, the port is assigned and nothing else is listening on it. When a clause fails, the row reads broken in the list, and cast ws heal reruns the setup to make it true again.
What a workspace promises
The contract comes from one file in the repository, which cast ws init generates by looking at the project and which the team then edits and commits. Ours is short:
$ cat .codecast/workspace.toml
[setup]
copy = [
".env",
".env.local",
"packages/convex/.env.local",
"packages/web/.env.local",
"packages/cli/.env.local",
]
install = ["bun install"]
[ports.web]
base = 3201
range = 20
Three things: which ignored files to copy from the main checkout, what to run after the copy, and which ports to hand out. Each workspace gets an index, and its web port is the base plus twenty times that index, probed free before it is handed out. The workspace above is index zero, so its status says web=3201. Two agents can each run a dev server without reading each other's pages.
Acquire, work, destroy
For this post we asked for a workspace that did not exist, watched it come up, and took it down again. This is the whole lifecycle, as it ran:
$ cast ws acquire blog-demo
created: blog-demo
path: /Users/ashot/src/codecast/.codecast/worktrees/blog-demo
branch: codecast/blog-demo
state: ready
ports: web=3401
port pool of 10 indices exhausted; extended the range to indices 10-19 and took index 10 (web=3401)
A worktree on a new branch, the secret files copied and the install run behind that one word ready, and a port. The last line is the honest part: the pool of ten port indices was already spent on the workspaces above, so the allocator extended it and this one became index ten, port 3401. The command prints the path because a program cannot change your shell's directory; the next line is always cd "$(cast ws path blog-demo)". An agent that already has a workspace by that name attaches to it instead of making a second one, so a session that restarts lands back where it was.
$ cast ws destroy blog-demo
destroyed: blog-demo
Teardown runs any teardown hooks, removes the worktree, and drops the state, so the port goes back to the pool and the name is free. The list above is as long as it is because agents are better at acquiring than destroying; the one marked destroying is a teardown in progress.
Where this fits
A workspace is a checkout, not a sandbox. The agent in it still runs on your machine, with your logins and your tools, and its session lands in your inbox like any other, with the checkout named in the session header so you can tell at a glance which branch a conversation is editing. Two agents in two workspaces cannot overwrite each other's files, and they still share everything else codecast gives a team: the inbox, search across both sessions, and messages between them when the work does need a word.
The rule we have settled on is simple. Work that can live on a branch gets a workspace. Work that must land in the main checkout, because the human is in it too, stays shared and the agents talk. Both are one command away, and the list tells you which is which.
Codecast is where your team sees, steers, and remembers every coding agent session — any agent, any machine.
All five terminal captures are genuine cast ws output from the codecast checkout on 2026-10-04. The list keeps eight of nineteen rows and marks the rest; the status, the config file, the acquire and the destroy are shown in full. The demo workspace was created and removed for this post and nothing else on the machine changed; on a machine carrying 183 registered worktrees and a full load of agents, the acquire took about twenty minutes and the destroy about ten, nearly all of it waiting on git. There is no screenshot: the feature lives in the terminal, and the sessions that use these workspaces belong to other work.