mac-optimize
Fast triage + fix skill for macOS resource pressure on this workstation. Keep CC responsive, keep parallel agents/worktrees from thrashing swap.
When to run
- Load avg > 4 (Apple Silicon: sustained, not spikes)
sysctl vm.swapusageshows >70% of swap used- CC replies feel slow / tools time out
- Before starting a parallel-agents session or >2 worktrees
- Session-start (via hook)
Triage: one-shot diagnose
bash ~/.claude/skills/mac-optimize/diagnose.sh
Boost: one-shot apply (reversible)
bash ~/.claude/skills/mac-optimize/boost.sh # kills zombies, renices competitors, sets NODE_OPTIONS
bash ~/.claude/skills/mac-optimize/boost.sh --purge # also runs sudo purge (prompts)
Reports: load avg, swap %, top 10 CPU procs, top 10 RSS procs, zombie claude sessions (>6h old), Node version + NODE_OPTIONS, Spotlight worker count.
Common fixes (ranked by impact)
1. Kill zombie claude processes (biggest quick win)
Stale CC sessions hold 400–700MB each. Find + kill anything older than 6 hours:
ps -axo pid,etime,rss,comm | awk '$4=="claude" && $2 ~ /-/ {print $1, $2, $3}'
# Review output, then:
kill <PID> # not -9; let it flush
Restart via claude --resume if that terminal tab is still open.
2. Free compressed/purgeable memory
sudo purge # needs password; reclaims cached/purgeable pages
Use when swap >70%. Takes 2–5s. Safe — only drops reclaimable caches.
3. Tune Node heap for CC
Default V8 old-space is ~4GB. On a 24GB Mac running 2+ CC sessions, cap each:
# Add to ~/.zshrc (or ~/.config/zsh/env.zsh)
export NODE_OPTIONS="--max-old-space-size=6144"
Prevents one CC process from ballooning past 6GB when parsing huge tool outputs.
4. Audit launch agents
ls -1 ~/Library/LaunchAgents
launchctl list | grep -v "^-" | sort -k2 -rn | head -15 # sort by PID (running)
Disable unused ones:
launchctl unload -w ~/Library/LaunchAgents/<plist>
5. Spotlight pruning (CC source dirs)
Developer directories don't need Spotlight indexing — saves mdworker CPU:
sudo mdutil -i off /Volumes/External\ HD/Desenvolvimento
sudo mdutil -E /Volumes/External\ HD/Desenvolvimento # erase existing index
6. Close known high-idle-CPU offenders
Check diagnose output. Usual suspects on this box:
- Bitwarden (20–30% idle CPU — known Electron bug) — quit when not unlocking
- UTM / Virtualization.framework VM —
osascript -e 'tell application "UTM" to quit'thenkill <VM-XPC-pid>if orphaned (parent=1). Frees 3–4 GB RAM. - OpenClaw (no longer used on this machine):
launchctl unload -w ~/Library/LaunchAgents/ai.openclaw.*.plist+pkill -f openclaw. - Spotify / Discord / WhatsApp — quit during heavy CC sessions
- Brave tabs — each renderer ≈ 200–300MB, 49 procs ≈ 6.6GB total on this box.
7. Brave Memory Saver (applied 2026-04-15)
Prefs patched at ~/Library/Application Support/BraveSoftware/Brave-Browser/Default/Preferences:
performance_tuning.high_efficiency_mode.state = 2(always on)tab_discarding.enabled = true
Requires a Brave restart to take effect. After restart, inactive tabs auto-suspend (~60–80% RAM reclaim on idle tabs without losing session).
To reapply after profile reset: re-run the python snippet in boost.sh or:
python3 -c "import json; p='$HOME/Library/Application Support/BraveSoftware/Brave-Browser/Default/Preferences'; d=json.load(open(p)); d.setdefault('performance_tuning',{}).setdefault('high_efficiency_mode',{})['state']=2; d.setdefault('tab_discarding',{})['enabled']=True; json.dump(d,open(p,'w'),separators=(',',':'))"
Preflight before parallel agents / worktrees
Before dispatch-parallel-agents or spawning >2 worktrees, run diagnose. Abort if:
- Free memory < 1GB AND swap > 85%
- Load avg > 6
First run fix #1 (zombies) + #2 (purge), recheck, then proceed.
Integration
- Session-start hook:
~/.claude/hooks/session-start-mac-check.shruns diagnose and warns if thresholds breached. - Codex mirror:
~/.codex/scripts/mac-optimize.sh(symlink or copy of diagnose.sh).
Don't do
- Don't
kill -9claude — it leaves orphaned MCP server processes that eat RAM. - Don't disable Spotlight system-wide (breaks Raycast, Alfred).
- Don't
sudo purgein a tight loop — once per hour max. - Don't set
--max-old-space-sizeabove 8192 on a 24GB Mac with VMs running.
Disk-pressure playbook (internal <20GB free)
diagnose.sh flags boot disk <20GB (warn) and <5GB (crit). When triggered, run:
bash ~/.claude/skills/mac-optimize/disk-clean.sh # Tier A autonomous (~35GB on 460GB Mac)
bash ~/.claude/skills/mac-optimize/disk-clean.sh --full # + prompt for Tier B/C moves
Tier A — safe, regenerable (~35G)
All cache; all regenerates on demand. No confirmation needed.
npm cache clean --force→ up to 20G on dev box (biggest single win)rm -rf ~/.cache/uv→ up to 12G (uv is faster thanuv cache clean)rm -rf ~/.cache/{opencode,huggingface,pre-commit,chroma}→ 2-3Grm -rf ~/.bun/install/cache→ up to 3.8Grm -rf ~/Library/Developer/CoreSimulator/Caches→ 1-2Grm -rf ~/Library/Caches/BraveSoftware/Brave-Browser/Default/{Cache,Code\ Cache}→ 1G- Electron runtime cache:
rm -rf ~/Library/Caches/electron/*/electron-v*.zip
Verify before clearing: df -g / baseline → cleanup → df -g / again.
Tier B — move user files to External HD (~18G, reversible)
Confirm target is mounted: df "/Volumes/<external-drive>". Then move (don't copy+delete):
mv ~/Downloads/{*.iso,*.mkv,Archives,Games} "/Volumes/<external-drive>/Downloads-archive/"
Delete re-downloadable installer DMGs/zips outright:
rm -f ~/Downloads/*.dmg ~/Downloads/*.zip ~/Downloads/*.tbz2
Tier C — dev relocation (~37G on this box, needs explicit OK)
Use external-dev-relocation skill. Before moving:
- Audit git status of each ~/Desenvolvimento/ for uncommitted work.
- Compare against canonical copy at
/Volumes/<external-drive>/Desenvolvimento/<repo>. - Never delete a tree with uncommitted changes without pushing first.
Known-ambiguous, don't auto-clean
~/Library/Application Support/Claude/vm_bundles/claudevm.bundle(~10G) — Claude Desktop sandbox VM, redownloads ~10min. Only clear if user confirms.~/Library/Developer/CoreSimulator/Devices— keep if iOS dev active.