Run three AI coding agents on one machine, each in its own git worktree, and the code stays separate. Everything around the code does not.

Two dev servers try to bind port 3000, and one of them fails. Two tasks write to the same database, so one agent's test rows appear in the other agent's run. Three builds start at the same moment and the machine freezes. Finished task folders stay on disk, while package caches, browser downloads and temp files fill the drive.

Git keeps the files apart. It does not keep ports, databases, processes or disk space apart. You can fix most of this with no tool at all. Here is the manual version first.

Step 1: one worktree per task

git worktree add -b feature-login ../myapp-feature-login main cd ../myapp-feature-login 

-b creates a new branch from main. Each task gets its own folder and branch. Your main checkout stays as it is.

Step 2: one env file per task, with its own port

Create .env.local in each worktree:

PORT=3101 DATABASE_URL=postgres://localhost/myapp_feature_login 

The next task gets PORT=3102. Check how your dev server reads its port. Some frameworks read .env.local. Others take a flag.

Step 3: one database per task, inside one Postgres server

createdb myapp_feature_login 

Or, in psql: CREATE DATABASE myapp_feature_login;. Run the migrations against that database. One server holds all the tasks. You do not start a second Postgres instance for each agent.

Step 4: run heavy commands one at a time

On macOS, Linux or Git Bash, a directory lock works. mkdir either creates the folder or fails, so only one shell wins:

until mkdir /tmp/build.lock 2>/dev/null; do sleep 2; done npm run build rmdir /tmp/build.lock 

If the build crashes or you close the terminal, rmdir never runs. Delete /tmp/build.lock by hand before the next build.

What gets hard by hand

Steps 1 to 4 hold up while the task count stays small. As it grows, four chores pile up:

  • Cleanup. git worktree remove refuses while a shell or an editor sits in the folder. On Windows, the folder stays locked until you find the program that holds it.
  • Port bookkeeping. You keep a list of which port belongs to which task. A forgotten dev server keeps its port after its task ends.
  • Killing the right process. On Windows, netstat -ano | findstr :3101 shows the PID. Then run taskkill /PID <pid> /F. Check the PID first. A wrong PID stops someone else's work.
  • Dependencies. Each worktree holds its own node_modules, .venv or target folder. The disk use adds up for every task.

The same steps in agentgc

agentgc is a garbage collector for the disk junk that CLI coding agents and dev tools leave behind: package caches, browser downloads, agent sessions and temp files. It also builds task environments: one worktree, free ports, one database name per task and an env file. The task commands create all of that in one step. The run command queues heavy work, and up starts the services of a task.

Download an archive for Windows, Linux or macOS (Apple Silicon) from the latest release. Or build it from a clone of the repo with Rust: cargo install --path .

Put the task settings in agentgc.task.toml in the repo root. A short version:

[worktree] dir = "worktrees" base = "main" [copy] files = [".env.local"] [ports] names = ["web"] range = [3100, 3999] [db] name = "{repo}_{name}" create = "createdb {db}" drop = "dropdb {db}" [env.dynamic] DATABASE_URL = "postgres://localhost/{db}" [setup] commands = ["npm install"] 

dir = "worktrees" puts the worktrees in a folder inside the repo, so add that folder to .gitignore. agentgc prints a hint when the folder is not ignored. It never edits .gitignore itself.

The commands:

agentgc scan # read every path before any clean agentgc task new feature-login # dry run: prints the plan agentgc task new feature-login --yes --run-setup # worktree, ports, database, setup agentgc task list # ports, database and status per task agentgc ps # processes per task, with RAM agentgc ps --stop # dry run: idle dev servers, tests, builds agentgc run -- npm test # queued: heavy commands take turns agentgc clean --dry-run # junk from scan, item by item agentgc task done feature-login # dry run: blockers and processes agentgc task done feature-login --yes # removes worktree, task files, merged branch 

task new without --yes only prints the plan. The file .agentgc/task.env holds PORT_WEB and DATABASE_URL, so your dev server must read that file.

Safety model

Only two commands delete: task done --yes and clean.

  • Dry run first. task new, task done and ps --stop print a plan and change nothing until you add --yes.
  • Blockers stop task done. It refuses while the worktree holds uncommitted files or commits that are neither merged nor pushed. --force overrides both checks and prints what would be lost.
  • Item by item. clean asks about each item. A safe item needs a y. A risky item needs you to type its ID. Risky items go to the Recycle Bin, not to permanent delete.
  • Guards. clean refuses paths that hold a .git entry, and paths named Documents, Downloads or User Data, among others.
  • Idle only. ps --stop touches only idle dev servers, language servers, tests and builds. Agents, databases and other processes keep running.
  • Config runs commands. create, drop and setup.commands run as you, without a shell. Read agentgc.task.toml like a Makefile before you use --run-setup or task done --yes.

Honest limits

  • Built and covered by automated tests on Windows, Linux and macOS in GitHub Actions. Windows is the only system where the full flow was run end to end. The release binaries are not code signed.
  • agentgc up starts the services listed for a task. It is opt-in and installs no system service. Nothing starts at boot or login.
  • agentgc never starts containers, never runs Docker and never talks to a database server.
  • On Windows, ps --stop --yes stops nothing without --force, because agentgc has no graceful stop on Windows.
  • run is not fair. Whoever finds a free slot first gets it.

Proof

After one cleanup session on 2026-11-04, free space on my Windows machine went from about 6 GB to about 180 GB. This is my own statement. It is not a measurement by agentgc.

Credit

The queue idea behind run comes from heavy by mokevnin, a counting semaphore for macOS and Linux. agentgc's run is separate code. It adds Windows support and named resources, such as one phone or one browser profile.

Next step

If you run agents in parallel and want fewer collisions, star the repo: https://github.com/JohnWayneeee/agentgc

Telegram channel https://t.me/+pWGhdQdw5DZmYzYy