A while after I started running multiple Antigravity 2.0 agents in parallel, a low-disk warning woke me up. The culprit was neither the app nor model caches. It was the debris my agents had left behind: eleven verification worktrees, thousands of browser screenshots and recordings, more than eighty merged-but-undeleted temp branches.
Parallelism speeds up task completion — and it speeds up debris accumulation by exactly the same factor. The deferred tidying that never mattered with one agent becomes an operational problem the moment you raise the degree of parallelism. That was my lesson.
Deleting is scary; hoarding is unsustainable. What follows is the design I settled on to walk that line: defined lifespans per artifact type, and automated cleanup wrapped in paranoid guards. Run logs are a different animal with different retention needs, covered separately in Keeping Unattended Agent Run Logs Long Enough to Debug — Without Filling the Disk. This article is about everything else — the by-products of work.
Start with an inventory, not a delete script
Cleanup design goes faster when you begin by cataloguing, not coding. In my environment, parallel agents produce six artifact types:
| Artifact | Produced by | Lifespan | Deletion condition |
|---|---|---|---|
| Verification worktrees | Isolated parallel task execution | 7 days | Branch merged and no uncommitted changes |
| Temp branches | Agent trial and error | 14 days | Merged, or 14 days since last commit and unreferenced |
| Screenshots and recordings | Browser verification, visual regression | 3 days | Associated run finished successfully |
| Build outputs | Verification builds | 2 days | Unconditional (regenerable) |
| Downloaded reference material | Research tasks | 30 days | 30 days since last access |
| Residue of failed runs | Abnormally terminated tasks | 14 days | Postmortem record closed |
What matters in that table is not the specific numbers but the fact that only two axes ever appear in the deletion column: can it be regenerated, and is anything still referencing it. Regenerable artifacts get short lives; anything entangled with human judgment gets conditions. Tune the numbers to your own environment freely.
Safety guards — make "safe to delete" a suspicious question
Lose work to automated deletion once and the cleanup system itself loses trust — you will be back to manual tidying forever. So the guards should feel excessive. I run three.
First, never touch a worktree with uncommitted changes:
is_dirty() {
local wt="$1"
# dirty if any uncommitted changes, untracked files, or stashes exist
[ -n "$(git -C "$wt" status --porcelain 2>/dev/null)" ] && return 0
[ -n "$(git -C "$wt" stash list 2>/dev/null)" ] && return 0
return 1
}Second, exclude directories in use by a running agent. Each run writes its working path to a lock file at start and removes it on exit; the cleaner only checks lock existence:
is_in_use() {
local path="$1"
grep -qsF "$path" "$HOME/.agent-runs/active/"*.lock 2>/dev/null
}Third, deletion is always two-phase. Phase one moves the target into a quarantine directory; the real deletion happens on the next run, seven days later. It is insurance against "deleted yesterday, needed today" — and it has paid out twice for me.
quarantine() {
local target="$1"
local dest="$HOME/.agent-trash/$(date +%Y-%m-%d)"
mkdir -p "$dest"
mv "$target" "$dest/" && echo "quarantined: $target"
}
# hard-delete only quarantine folders older than 7 days
find "$HOME/.agent-trash" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +