Why the 460 GB drive keeps hitting the 20 GB floor despite five cleanup rounds, what was measured on 2026-09-28, and the structural change. For Fede and Gera.
2026-09-28 · Measured by session 004 at Fede's ask ("look urgently… stopping cloud sessions") · Local fix, no repo change (pnpm ask withdrawn)
The cleanups never stuck because they reaped finished work, and the space is held by unfinished work plus two hiding places no reaper can see. Result tonight: 17 → 64 GB free, without touching anything a process was using. The durable fix is one shared package store (pnpm), a cap on live checkouts, and checkouts only where the reapers look.
du -xd1 /System/Volumes/Data, 2026-09-28 after the first strip)| Area | GB | What it is |
|---|---|---|
| Home folder | 267 | 175 checkouts of propflowai across ~/.claude (140), ~/agents (17), ~/repos (14), ~/worktrees (4); transcripts 16; Library 40 (14 Application Support, 5.7 iPhone symbols, 3.7 Messages); Downloads 9 |
/private | 67 | 46 in session scratchpads (one session: 11 full clones of the repo, 40 GB, 1.75M files); 18 in per-user temp (node compile cache 7.2, tsx cache 6.6) |
| Applications + System + Library + opt | 45 | fixed |
Folder sizes lie here. npm installs on APFS are clones that share blocks: 66 worktrees' node_modules reported 137 GB and freed 29 GB when removed (~0.45 GB unique each). Only a whole-volume scan compared with df is trustworthy for attribution; every earlier audit used per-folder sizes.
removed=0 stripped=0 every run./private/tmp/claude-501/…/scratchpad (not on the main checkout's worktree list) and the per-user temp caches.| Action | Freed |
|---|---|
Stripped node_modules/.next from 66 checkouts idle 12 h with no process inside (they reinstall on use) | 29 GB |
| Stripped 3 finished scratch clones (#13166 closed, #13357 and #13333 merged), no process inside | ~7 GB |
| Deleted node compile cache + tsx cache (rebuild on use) | ~14 GB |
Spotlight exclusions for ~/.claude, ~/agents, /private/tmp/claude-501 (Fede ran it); load 38 → 6 | — |
Hooks: scratch-clone-guard.sh (no clone / worktree add into /tmp or scratchpad); grep-scope-guard.sh (no whole-home transcript greps) | — |
Fede: "I want a solution with our current setup." We stay on npm. macOS (APFS) already shares identical package files between checkouts, so a checkout really costs about 0.45 GB, not 2.9 GB; the pnpm recommendation is withdrawn. What is now running on the Mac:
node_modules and build output from any checkout nobody has touched for 6 hours when free space is under 60 GB (24 hours otherwise). The work stays; deps come back with one install from the kept npm cache. Nothing with a live process inside is ever touched.~/agents, ~/repos, ~/worktrees, ~/.claude and every session scratch folder under /private/tmp/claude-501. Those get the same strip rule; they are never deleted (they may hold unpushed work).~/agents as registered worktrees. A hook refuses new repo copies in temp or scratch space.Result 2026-09-28: 17 GB free at 18:00 → 154 GB at 21:40; registered worktrees 109 → 24. Fede at 21:25: "just clean up the idle worktrees." Every worktree idle 24 h with no process inside was parked, then removed: 36 pushed to GitHub as wip/<name>-20260928 branches (no CI runs on those), 47 archived as git bundles in ~/.claude/worktree-parked/ (8 MB total, covered by the S3 backup; restore with git fetch <bundle> HEAD) because the pre-push check refuses branches far behind main and that check is never bypassed. 22 fresh and 4 in-use worktrees untouched. Ledger: ~/.claude/logs/worktree-park-2026-09-28.tsv. Spotlight: exclusions for the five code folders applied by Fede (needed the mdutil off/on toggle to take), indexing itself stays on. A 5-minute machine sampler (machine-watch.sh, launchd) and 4-hourly reviews run for 24 h from 21:30. Still Fede's call (uncommitted or unpushed work, or personal files): 83 checkouts with uncommitted changes and 20 with unpushed commits, transcripts kept 60 days locally (~8 GB if cut to 30; S3 keeps them), Downloads 8.8 GB, iOS symbol cache 5.7 GB, Messages 3.7 GB, Whisper model cache 3.4 GB.
Verdict: the Mac was not a bottleneck for agentic work, except for one self-inflicted stretch. From 21:30 to about 08:00 Spotlight (the Mac's search indexer) rebuilt its index after it was switched off and on, and it ate 2 to 3 cores in bursts. That pushed load past 20 many times and the load hook refused some builders' tests. After 08:11 it was quiet. The only bigger load spike (152 at 13:31) was two full test suites running at once, which is real work. Memory, swap and CPU throttling were never a problem. Disk was fine all day, but it fell fast after the window closed (see below).
| Measure | Result (288 samples, every 5 min) |
|---|---|
| Load (12 cores) | median 10.5, 95th percentile 30.5, max 152 (13:31) |
| Samples with load over 20 | 78 of 288. Search indexing led 41 of them, real work (node, git, tsgo) led 37. Before 09:00 nearly all were Spotlight-led; the biggest were 13:26 to 13:36 (110, 152, 133) and 22:30 on Sep 28 (61, a git burst). |
| Free disk | low 110 GB (21:07 to 21:22 Sep 29), high 189 GB (about noon) |
| Largest one-hour disk drop | 23 GB (15:17 to 15:57, new lane checkouts and installs) |
| Swap used, memory under 20% free, CPU limit set | none; memory free never below 77% |
| Non-agentic program on top at over 50% CPU | 84 samples: Spotlight 70, photo analysis 10, Zoom 3, malware scan 1 |
| Of those, lasting 2+ samples in a row | Yes: 15 stretches. Longest 13 samples (23:35 to 00:35), then 8 (04:11 to 04:46) and 6 (three times). All Spotlight, except photo analysis 08:36 to 08:56 (5). |
Free space fell from 189 GB (Sep 29, noon) to 19 GB (Oct 1, 08:53), about 115 GB a day, with every cleanup step switched on. Three of those steps had been quietly doing nothing for days. Their code comments said they worked; their logs said otherwise. All three are fixed today, and free space is back to 41 GB. The target is to stay above 100 GB.
| What we tried | Did it work? | What happened |
|---|---|---|
| Manual cleanups (Sep 12, 18, 28) | Once | Each freed 60–150 GB, then filled back up within days. |
| Nightly cleanup | Barely | Frees at most 10 GB a night. We lose up to 115 GB a day. |
| Weekly cleanup | Never ran | It couldn't find the GitHub tool. Fixed today. |
| Cleanup every 15 minutes | Partly | Skipped 1,933 finished copies because it thought they had unsaved work. Fixed today; first run freed 15 GB. |
| Removing copies idle 1–2 days | Barely | Its own check kept resetting the idle timer. Fixed today; 30 removed since. |
| Clearing code caches | Never | It waited 2 days; the caches were never that old. Now 12 hours; freed 7 GB. |
| Sharing installed packages | Yes, for speed | Made new copies fast. Saved little disk; the copies were already sharing space. |
| Slack alert | Too late | Fired at 38 GB. Now fires under 100 GB. |
gh. Every one looked right in its code and was wrong in its log.du counts APFS clones at full size, and the logs record free space but not bytes freed per action. So savings were overestimated, and the source of the 9/29–9/30 fall was never pinned.git --no-optional-locks, so they no longer reset the idle clock.npm ci or npm install inside a worktree and points to worktree-node-modules.mjs link. Bypass with PF_ALLOW_PRIVATE_INSTALL=1.~/agents/006/disk-watch-2026-10.tsv.lambda/*/dist), more than half of which is source maps. That build output is 11.6 GB across the fleet, and no cleanup step touched it until today; it is now stripped from idle copies. Packages added only 14 GB, and the temp folders added 23 GB. For Gera: could local Lambda builds skip source maps, or write them outside the worktree?gera-propflow/local-bin. Does it run on this Mac? If it does, we have two reapers with different rules, and we should keep one.Sources: ~/.claude/logs/ (worktree-reap-fast, worktree-park.tsv, disk-janitor, worktree-reap), repo PRs #12019, #12062, #12120, #13739 and #14115, and ADR-0037 (agentflow-relay). Measured 2026-10-01 by session 006.