並行編碼智能體留下 9 類殘留項目及相應清理命令
Parallel Coding Agents Leave 9 Kinds of Junk on Your Disk. The Commands That Clear It
作者整理並行編碼智能體留下的 9 類殘留項目,並為每類列出檢查與清理命令。清單涵蓋工作樹及鎖定記錄、分支與 refs、依賴及忽略檔案、佔用連接埠的開發伺服器和 Git 物件;文中提醒先檢查待刪內容,再執行清理。Hermes IDE 2.2.9 會清理部分任務快照、工作樹和其他資料,但連接埠及 git gc 仍須手動處理。
- Book: AI That Acts
- The series: AI in TypeScript — 5 books, from your first LLM call to agents in production — all five here
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
Codex keeps the 15 most recent worktrees it manages by default, and deletes older ones to stay under that limit or when you archive a chat. Claude Code removes a clean worktree automatically when you exit an unnamed interactive session; a named one asks first. A claude -p --worktree run has no exit prompt, so its worktree stays on disk, still locked until a later session's sweep releases it. Add the worktrees you made by hand for a third agent, and a few weeks of parallel work leaves a lot behind.
Most of it is harmless until it adds up: it eats disk and holds ports, and the refs keep objects alive that git gc would otherwise drop. For each of the nine kinds of leftover below there is a read-only command that finds it and a second one that removes it. Run the deletes after you've looked at what they would delete.
The commands assume your main branch is main and that agent branches use a prefix: hermes/* for Hermes IDE, worktree-* for Claude Code's --worktree sessions (naming). Swap in your own.
Worktrees: folders, records and locks
1. Worktree folders nobody is using. Start with the list. With -v, git worktree also prints why a worktree is locked or prunable.
git worktree list -v
For each folder you're done with, remove it through git so the record goes with it:
git worktree remove ../fix-login
Git only removes clean worktrees: no untracked files and no modified tracked files. An unclean one needs --force, and a locked one needs --force twice (git-worktree). Treat that refusal as the safety catch it is. Open the folder, commit or copy what you want to keep, then decide.
2. Records for folders that are gone, and stale locks. Delete a worktree folder with rm -rf or your file manager and git still keeps its record under $GIT_DIR/worktrees; git worktree list marks it prunable. Dry-run first, then prune:
git worktree prune --dry-run --verbose
git worktree prune --verbose
git gc does this on its own eventually, but with a three-month grace period by default (gc.worktreePruneExpire, git-gc). Locks are the other half. Claude Code locks a worktree while its agent runs and releases the lock when the agent finishes, and a lock left by a killed session waits for a later sweep (Claude Code docs). git worktree list --porcelain shows a locked line for each one. When you're sure nothing is running there, git worktree unlock <path> frees it.

Each tool cleans up part of what it leaves. The rest stays on disk until you remove it.
Branches and refs nobody will merge
3. Task branches that already landed. git branch --merged lists branches whose tips are reachable from the commit you name (git-branch):
git branch --merged main --list 'hermes/*' 'worktree-*'
With main checked out, delete them with -d, which refuses a branch that isn't fully merged. Remove a branch's worktree (item 1) before you delete the branch.
git branch --merged main --list 'hermes/*' 'worktree-*' \
--format='%(refname:short)' | xargs -r -n1 git branch -d
A squash-merged or rebased branch won't show up here. Its changes are on main, but its tip commit isn't reachable from main, so --merged skips it. Those end up in the next item.
4. Branches nobody finished. Sort the unmerged ones by their last commit, oldest first, with git for-each-ref:
git for-each-ref --sort=committerdate \
--no-merged=main \
--format='%(committerdate:short) %(refname:short)' \
refs/heads/
The abandoned experiments sit at the top. git branch -D deletes them, and it is the force delete, so read git log main..<branch> first and make sure nothing there is worth keeping.
5. Refs that git branch never shows. Tools can keep their own data under refs/. Count refs by namespace:
git for-each-ref --format='%(refname:rstrip=-2)' \
| sort | uniq -c
rstrip=-2 keeps the first two path components (git-for-each-ref), so you see refs/heads, refs/tags, refs/remotes and anything else. This matters for disk: git gc keeps every object referenced by your branches, tags, reflogs, the index, "and anything else in the refs/* namespace" (git-gc). A namespace full of snapshot refs can pin a lot of old blobs. Before you delete refs a tool wrote, check that tool's docs, because they may be its undo history. To delete one you've confirmed is safe, use git update-ref -d <ref> (git-update-ref).
The copies: dependencies and ignored files
6. A node_modules in every worktree. A new worktree holds tracked files only, so every worktree where an agent ran an install has its own dependency folder. Size them all:
git worktree list --porcelain \
| awk '/^worktree /{print substr($0, 10)}' \
| while read -r wt; do
du -sh "$wt/node_modules" 2>/dev/null
done
For a worktree you'll come back to later, deleting its node_modules is cheap: reinstall when you return. For one you won't, item 1 removes the whole folder. If you use Claude Code's defaults, du -sh .claude/worktrees/* from the repository root shows the full size of each of its worktrees.
7. Ignored and untracked files: screenshots, logs, scratch notes. Agents and the people driving them leave pasted images, log files and notes inside worktrees. git clean has two dry runs worth knowing:
git clean -nd # untracked files that are not ignored
git clean -ndX # ignored files only
-n only shows what would go. Read the -X list carefully: your .env and node_modules are ignored files too, so a blanket git clean -fdX takes them with it. Delete by path instead.
Processes and the .git directory
8. Dev servers still bound to ports. A dev server started in the background can outlive the agent session that started it, and the next worktree's server finds its port taken. List every listening TCP socket with lsof:
lsof -nP -iTCP -sTCP:LISTEN
-iTCP -sTCP:LISTEN is the man page's own example for listening TCP sockets, and -n and -P skip host and port name lookups. To see which folder a process runs in, and so which worktree started it, ask for its working directory, then stop it once you know it's yours:
lsof -a -p "$PID" -d cwd
kill "$PID"

Leftover dev servers keep their ports long after the agent that started them is gone.
9. A .git directory that only grows. All worktrees share one object store, so every agent's commits land in the same place. Measure it with git count-objects:
git count-objects -vH
size is the space used by loose objects, size-pack by packs, and size-garbage by files that are neither. Then run git gc. After items 3 to 5, gc can drop objects that nothing references any more, but not straight away. By default it prunes only loose objects older than two weeks, and keeps reflog entries for unreachable commits for 30 days (git-gc). So the disk drop from deleting branches can come weeks later. To reclaim the space now:
git reflog expire --expire-unreachable=now --all
git gc --prune=now
That throws away the reflog entries you would use to recover a commit you dropped by mistake. Run it after you've finished the cleanup, not before.
What Hermes 2.2.9 cleans up for you
I build Hermes IDE, so weigh this with that in mind. Hermes starts each task on its own hermes/<name> branch in its own worktree (README), which means it creates several of the leftovers above and should clear them too. Hermes 2.2.9, published October 12, 2026, fixed problems that build up when the app stays open for days or weeks. The cleanup parts:
- Turn history snapshots from tasks that ran in their own worktree are removed from the repository 14 days after the session closes. Before this fix that didn't always happen.
- A worktree that couldn't be removed when its session closed is retried at the next launch, and launch is faster when old leftover worktrees are lying around.
- A worktree you chose to keep when you closed its session is no longer deleted automatically later.
- Pasted screenshots older than a week are cleaned up, along with saved output of sessions closed more than a month ago, undo data for landed tasks after 14 days, and worktree backups after 90 days (with automatic clean-up on).
- Large dependency or build folders inside worktrees no longer slow Hermes down or use up the system's file-watch limit.
At the time of writing, the current release is 2.3.3 (changelog). The 2.2.9 notes don't mention ports or git gc, so I'd still run items 8 and 9 by hand.
Other tools handle their own share well. Claude Code runs a periodic sweep that removes subagent and background-session worktrees older than your cleanupPeriodDays setting, and skips any that still hold work (docs). Codex saves a snapshot of a managed worktree before it deletes it, so you can restore the chat's work later (docs). If you run agents from more than one vendor, each tool cleans up its own worktrees and the checklist above covers the rest.
Hermes is free, source-available under BSL 1.1, and runs on macOS, Windows and Linux. It is not affiliated with Nous Research, Anthropic, OpenAI or any agent vendor. Download it here, and the source is on GitHub.
If this was useful
Every item on this list is a side effect: an agent called a tool that made a folder, a branch or a process, and nothing came back for it. AI That Acts is about that tool layer from the builder's side: tool calling, functions and a first working agent, in TypeScript. If you're writing an agent of your own, that layer is where you decide what it leaves behind.
It is book 3 of AI in TypeScript, a five-book series that runs from your first LLM call to agents in production.
來源:DEV Community · dev.to

