
Disk Hygiene
- 246 installs
- 62 repo stars
- Updated August 3, 2026
- terrylica/cc-skills
disk-hygiene is a Claude Code maintenance skill that audits and cleans development-machine disk usage—caches, build artifacts, and stale project folders—so developers recover free space without breaking active workspaces
About
disk-hygiene is a cc-skills utility for developers whose local disks fill up from node_modules, Docker layers, Xcode derived data, package caches, and abandoned clones. The skill guides safe inspection of large directories, identifies reclaimable artifacts, and applies conservative cleanup steps that preserve active repositories and running environments. Use disk-hygiene when installs fail for lack of space, IDEs lag from bloated caches, or a machine needs routine maintenance between sprints. It fits terminal-first workflows on macOS and Linux dev boxes where manual du/find cleanup is error-prone.
- disk-hygiene
Disk Hygiene by the numbers
- 246 all-time installs (skills.sh)
- +2 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,568 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/terrylica/cc-skills --skill disk-hygieneAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 246 |
|---|---|
| repo stars | ★ 62 |
| Last updated | August 3, 2026 |
| Repository | terrylica/cc-skills ↗ |
How do you free disk space on a dev machine?
Use disk-hygiene for development tasks
Who is it for?
Developers hitting disk-full errors from package managers, containers, or multi-repo workspaces who want guided, low-risk cleanup.
Skip if: Production server capacity planning or cloud storage lifecycle policies that require infrastructure-as-code changes.
When should I use this skill?
A developer reports low disk space, bloated caches, or wants routine local workstation hygiene before major installs.
What you get
Disk usage report, reclaimed gigabytes, and a list of removed caches or archived folders.
Files
Disk Hygiene
Audit disk usage, clean developer caches, find forgotten large files, and triage Downloads on macOS.
Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.
When to Use This Skill
Use this skill when:
- User asks about disk space, storage, or cleanup
- System is running low on free space
- User wants to find old/forgotten large files
- User wants to clean developer caches (brew, uv, pip, npm, cargo)
- User wants to triage their Downloads folder
- User asks about disk analysis tools (dust, dua, gdu, ncdu)
TodoWrite Task Templates
Template A - Full Disk Audit
1. Run disk overview (df -h / and major directories)
2. Audit developer caches (uv, brew, pip, npm, cargo, rustup, Docker)
3. Scan for forgotten large files (>50MB, not accessed in 180+ days)
4. Present findings with AskUserQuestion for cleanup choices
5. Execute selected cleanups
6. Report space reclaimedTemplate B - Cache Cleanup Only
1. Measure current cache sizes
2. Run safe cache cleanups (brew, uv, pip, npm)
3. Report space reclaimedTemplate C - Downloads Triage
1. List Downloads contents with dates and sizes
2. Categorize into groups (media, dev artifacts, personal docs, misc)
3. Present AskUserQuestion multi-select for deletion/move
4. Execute selected actionsTemplate D - Forgotten File Hunt
1. Scan home directory for large files not accessed in 180+ days
2. Group by location and type (media, ISOs, dev artifacts, documents)
3. Present findings sorted by size
4. Offer cleanup options via AskUserQuestion---
Phase 1 - Disk Overview
Get the lay of the land before diving into specifics.
/usr/bin/env bash << 'OVERVIEW_EOF'
echo "=== Disk Overview ==="
df -h /
echo ""
echo "=== Major Directories ==="
du -sh ~/Library/Caches ~/Library/Logs ~/Library/Application\ Support \
~/.Trash ~/Downloads ~/Documents ~/Desktop ~/Movies ~/Music ~/Pictures \
2>/dev/null | sort -rh
echo ""
echo "=== Developer Tool Caches ==="
du -sh ~/.docker ~/.npm ~/.cargo ~/.rustup ~/.local ~/.cache \
~/.conda ~/.pyenv ~/.local/share/mise 2>/dev/null | sort -rh
OVERVIEW_EOFPhase 2 - Cache Audit & Cleanup
Cache Size Reference
| Cache | Location | Typical Size | Clean Command |
|---|---|---|---|
| uv | ~/Library/Caches/uv/ | 5-15 GB | uv cache clean |
| Homebrew | ~/Library/Caches/Homebrew/ | 3-10 GB | brew cleanup --prune=all |
| pip | ~/Library/Caches/pip/ | 0.5-2 GB | pip cache purge |
| npm | ~/.npm/_cacache/ | 0.5-2 GB | npm cache clean --force |
| cargo | ~/.cargo/registry/cache/ | 1-5 GB | cargo cache -a (needs cargo-cache) |
| rustup | ~/.rustup/toolchains/ | 2-10 GB | rustup toolchain uninstall <name> (list with rustup toolchain list) |
| mise | ~/.local/share/mise/installs/<tool>/<version>/ | 0.2-2 GB each | mise uninstall <tool>@<version> (list with mise ls) |
| Docker | Docker.app | 5-30 GB | docker system prune -a |
| Playwright | ~/Library/Caches/ms-playwright/ | 0.5-2 GB | npx playwright uninstall |
| sccache | ~/Library/Caches/Mozilla.sccache/ | 1-3 GB | rm -rf ~/Library/Caches/Mozilla.sccache |
| go-build | ~/Library/Caches/go-build/ | 5-25 GB | go clean -cache (or rm -rf if go not on PATH) |
| huggingface | ~/.cache/huggingface/ | 1-10 GB | rm -rf ~/.cache/huggingface/hub/<model> |
Safe Cleanup Commands (Always Re-downloadable)
/usr/bin/env bash << 'CACHE_CLEAN_EOF'
set -euo pipefail
echo "=== Measuring current cache sizes ==="
echo "uv: $(du -sh ~/Library/Caches/uv/ 2>/dev/null | cut -f1 || echo 'N/A')"
echo "Homebrew: $(du -sh ~/Library/Caches/Homebrew/ 2>/dev/null | cut -f1 || echo 'N/A')"
echo "pip: $(du -sh ~/Library/Caches/pip/ 2>/dev/null | cut -f1 || echo 'N/A')"
echo "npm: $(du -sh ~/.npm/_cacache/ 2>/dev/null | cut -f1 || echo 'N/A')"
echo ""
echo "=== Cleaning ==="
brew cleanup --prune=all 2>&1 | tail -3
uv cache clean --force 2>&1
pip cache purge 2>&1
npm cache clean --force 2>&1
CACHE_CLEAN_EOFTroubleshooting Cache Cleanup
| Issue | Cause | Solution |
|---|---|---|
uv cache lock held | Another uv process running | Use uv cache clean --force |
brew cleanup skips formulae | Linked but not latest | Safe to ignore, or brew reinstall <pkg> |
pip cache purge permission denied | System pip vs user pip | Use python -m pip cache purge |
| Docker not running | Docker Desktop not started | Start Docker.app first, or skip |
Phase 3 - Forgotten File Detection
Find large files that have not been accessed in 180+ days.
/usr/bin/env bash << 'STALE_EOF'
echo "=== Large forgotten files (>50MB, untouched 180+ days) ==="
echo ""
# Scan home directory (excluding Library, node_modules, .git, hidden dirs)
find "$HOME" -maxdepth 4 \
-not -path '*/\.*' \
-not -path '*/Library/*' \
-not -path '*/node_modules/*' \
-not -path '*/.git/*' \
-type f -atime +180 -size +50M 2>/dev/null | \
while read -r f; do
mod_date=$(stat -f '%Sm' -t '%Y-%m-%d' "$f" 2>/dev/null)
size=$(du -sh "$f" 2>/dev/null | cut -f1)
echo "${mod_date} ${size} ${f}"
done | sort
echo ""
echo "=== Documents & Desktop (>10MB, untouched 180+ days) ==="
find "$HOME/Documents" "$HOME/Desktop" \
-type f -atime +180 -size +10M 2>/dev/null | \
while read -r f; do
mod_date=$(stat -f '%Sm' -t '%Y-%m-%d' "$f" 2>/dev/null)
size=$(du -sh "$f" 2>/dev/null | cut -f1)
echo "${mod_date} ${size} ${f}"
done | sort
STALE_EOFCommon Forgotten File Types
| Type | Typical Location | Example |
|---|---|---|
| Windows/Linux ISOs | Documents, Downloads | .iso files from VM setup |
| CapCut/iMovie exports | Movies/ | Large .mp4 renders |
| Phone video transfers | Pictures/, DCIM/ | .MOV files from iPhone |
| Old Zoom recordings | Documents/ | .aac, .mp4 from meetings |
| Orphaned downloads | Documents/ | CFNetworkDownload_*.mp4 |
| Screen recordings | Documents/, Desktop/ | Capto/QuickTime .mov |
| TTS debug WAV | ~/.local/share/tts-debug-wav/, ~/.local/share/kokoro-debug*/ | Debug-mode TTS audio captures — can grow 1-2 GB/day if debug mode left on. Look for a tts-prune mise task in your repos or set tighter retention in the pruner script |
Phase 4 - Downloads Triage
Use AskUserQuestion with multi-select to let the user choose what to clean.
Workflow
1. List all files in ~/Downloads with dates and sizes 2. Categorize into logical groups 3. Present AskUserQuestion with categories as multi-select options 4. Offer personal/sensitive PDFs separately (keep, move to Documents, or delete) 5. Execute selected actions
Categorization Pattern
/usr/bin/env bash << 'DL_LIST_EOF'
echo "=== Downloads by date and size ==="
find "$HOME/Downloads" -maxdepth 1 \( -type f -o -type d \) ! -path "$HOME/Downloads" | \
while read -r f; do
mod_date=$(stat -f '%Sm' -t '%Y-%m-%d' "$f" 2>/dev/null)
size=$(du -sh "$f" 2>/dev/null | cut -f1)
echo "${mod_date} ${size} $(basename "$f")"
done | sort
DL_LIST_EOFAskUserQuestion Template
When presenting Downloads cleanup options, use this pattern:
- Question 1 (multiSelect: true) - "Which items in ~/Downloads do you want to delete?"
- Group by type: movie files (with total size), old PDFs/docs, dev artifacts, app exports
- Question 2 (multiSelect: false) - "What about personal/sensitive PDFs?"
- Options: Keep all, Move to Documents, Delete (already have copies)
- Question 3 (multiSelect: false) - "Ongoing cleanup tool preference?"
- Options: dust + dua-cli, Hazel automation, custom launchd script
Disk Analysis Tools Reference
Comparison (Benchmarked on ~632GB home directory, Apple Silicon)
| Tool | Wall Time | CPU Usage | Interactive Delete | Install |
|---|---|---|---|---|
| dust | 20.4s | 637% (parallel) | No (view only) | brew install dust |
| gdu-go | 28.8s | 845% (very parallel) | Yes (TUI) | brew install gdu |
| dua-cli | 37.1s | 237% (moderate) | Yes (staged safe delete) | brew install dua-cli |
| ncdu | 96.6s | 43% (single-thread) | Yes (TUI) | brew install ncdu |
Recommended Combo
- `dust` for quick "where is my space going?" - fastest scanner, tree output
- `dua i` or `gdu-go` for interactive exploration with deletion
Quick Usage
# dust - instant tree overview
dust -d 2 ~ # depth 2
dust -r ~/Library # reverse sort (smallest first)
# dua - interactive TUI with safe deletion
dua i ~ # navigate, mark, delete with confirmation
# gdu-go - ncdu-like TUI, fast on SSDs
gdu-go ~ # full TUI with delete support
gdu-go -n ~ # non-interactive (for scripting/benchmarks)Install All Tools
brew install dust dua-cli gduNote: gdu installs as gdu-go to avoid conflict with coreutils.
Quick Wins Summary
Ordered by typical space reclaimed (highest first):
| Action | Typical Savings | Risk | Command |
|---|---|---|---|
go clean -cache | 5-25 GB | None (re-downloads) | go clean -cache |
uv cache clean | 5-15 GB | None (re-downloads) | uv cache clean --force |
brew cleanup --prune=all | 3-10 GB | None (re-downloads) | brew cleanup --prune=all |
| Delete movie files in Downloads | 2-10 GB | Check first | Manual after AskUserQuestion |
| Prune old rustup toolchains | 2-5 GB | Keep current | rustup toolchain list then rustup toolchain uninstall <name> |
| Prune stale mise toolchains | 0.5-3 GB | Cross-check .mise.toml pins first | mise ls, then mise uninstall <tool>@<version> |
npm cache clean --force | 0.5-2 GB | None (re-downloads) | npm cache clean --force |
pip cache purge | 0.5-2 GB | None (re-downloads) | pip cache purge |
| Docker system prune | 5-30 GB | Removes stopped containers | docker system prune -a |
| Empty Trash | Variable | Irreversible | rm -rf ~/.Trash/* |
Post-Change Checklist
After modifying this skill:
1. [ ] Cache commands tested on macOS (Apple Silicon) 2. [ ] Benchmark data still current (re-run if tools updated) 3. [ ] AskUserQuestion patterns match current tool API 4. [ ] All bash blocks use /usr/bin/env bash << 'EOF' wrapper 5. [ ] No hardcoded user paths (use $HOME) 6. [ ] Append changes to evolution-log.md
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
uv cache clean hangs | Lock held by running uv | Use --force flag |
brew cleanup frees 0 bytes | Already clean or formulae linked | Run brew cleanup --prune=all |
find reports permission denied | System Integrity Protection | Add 2>/dev/null to suppress |
gdu command not found | Installed as gdu-go | Use gdu-go (coreutils conflict) |
dust shows different size than df | Counting method differs | Normal - df includes filesystem overhead |
| Stale file scan is slow | Deep directory tree | Limit -maxdepth or exclude more paths |
| Docker not accessible | Desktop app not running | Start Docker.app or skip Docker cleanup |
parse error near TASK_ID=$(pueue add ...) from heredoc with spaced paths | A user shell hook (e.g. pueue submission) re-parses the command string and breaks on ${var}/Path With Spaces/* globs inside heredocs | Write multi-line scripts to /tmp/<name>.sh first via Write tool, then invoke as bash /tmp/<name>.sh — bypasses the inline heredoc → hook re-quote path entirely |
| Removing a mise toolchain triggers immediate auto-reinstall | A project's .mise.toml pins the version you just removed; mise restores it on next invocation from that project | Before mise uninstall <tool>@<version>, grep all reachable .mise.toml and mise.toml files for the version. If pinned, leave it alone or update the pin first. Same applies to rustup toolchains vs. rust-toolchain.toml files in projects. |
Hook-safe multi-line scripts
If the user's shell environment has bash hooks that intercept tool calls (pueue, asciinema, etc.) and the heredoc pattern fails with cryptic parse errors, write the script to a temp file and invoke it:
# Instead of: bash << 'EOF' ... EOF
# Use: Write tool → /tmp/<task>.sh, then:
bash /tmp/<task>.shSingle-line bash invocations like du -sh "$HOME/Library/Application Support"/Google/* 2>/dev/null | sort -rh | head work fine even with hooks installed — only multi-line heredocs containing spaced-path globs are problematic.
Post-Execution Reflection
After this skill completes, reflect before closing the task:
0. Locate yourself. — Find this SKILL.md's canonical path before editing. 1. What failed? — Fix the instruction that caused it. 2. What worked better than expected? — Promote to recommended practice. 3. What drifted? — Fix any script, reference, or dependency that no longer matches reality. 4. Log it. — Evolution-log entry with trigger, fix, and evidence.
Do NOT defer. The next invocation inherits whatever you leave behind.
Evolution Log
Reverse chronological - newest on top.
2026-05-15 — Three new high-impact cache vectors discovered
Trigger: Second disk audit on terryli's MBP found 21GB in ~/Library/Caches/go-build plus multi-toolchain accumulation in rustup (8.8GB, 6 versions) and mise installs (7GB) — none of which were in the skill's cache reference table. Skill incorrectly listed cargo cache -a as the rustup cleanup; the actual command is rustup toolchain uninstall <name>. Mise toolchain pruning wasn't documented at all.
Root cause: The skill's cache table predates heavy Go and multi-version-Rust usage. It also confuses cargo registry caching with rustup toolchain installs (they're distinct concerns at different paths).
Fix: Added 3 rows to the Cache Size Reference table:
go-buildat~/Library/Caches/go-build/— typical 5-25GB on active dev machines; clean withgo clean -cache(orrm -rfas fallback ifgonot on PATH)rustup toolchainsat~/.rustup/toolchains/— typical 1-2GB per installed version; list withrustup toolchain list, remove withrustup toolchain uninstall <name>(NOTrustup toolchain remove— that's wrong syntax)mise installsat~/.local/share/mise/installs/<tool>/<version>/— typical 200MB-2GB per version; list withmise ls, remove withmise uninstall <tool>@<version>
Evidence: 2026-05-15 audit. Round 2 reclaim breakdown: go-build 21GB, std cache regrowth 8GB (Homebrew 3.8G + uv 2.5G + sccache 1.6G + npm/pre-commit 0.4G), rustup 1.94 + 1.94.1 = 2.7GB, mise python/3.11 + node/20 = 0.6GB. Total 32GB physical reclaim in one pass.
Two operational learnings worth surfacing:
1. `mise uninstall <tool>@<version>` is the correct command, NOT mise toolchain uninstall or any other variant. Verified on mise 2024+. 2. Always cross-check stale-toolchain candidates against project `.mise.toml` pins before removal. Example: removing node@22.21.1 would have triggered an auto-reinstall on next mise invocation from ~/.claude/ because ~/.claude/.mise.toml pins node = "22". Skipped that removal mid-cleanup based on this check.
Bonus finding: ~/.local/share/tts-debug-wav accumulated to 11GB in 7 days from Kokoro TTS debug captures (~1.4GB/day generation rate). The pruner was working — retention was just generous. Worth surfacing as a separate non-cache "debug-output growth" vector in future audits.
Action taken: Updated Cache Size Reference table (3 new rows + corrected rustup row), updated Quick Wins Summary to include go-build, added the project-pin cross-check note to Troubleshooting.
2026-05-09 — pueue hook conflict with heredocs containing spaced paths
Trigger: Drilldown bash blocks for ~/Library/Application Support/... failed with parse error near TASK_ID=$(pueue add ... and (eval):X: unmatched ' after the pueue interception hook tried to wrap them.
Root cause: When a Bash tool call is intercepted by a pueue submission hook, the hook re-parses the command string. Heredocs that contain ${var}/Path With Spaces/* or backslash-escaped spaces inside variable expansions break the hook's quoting layer, even though the bash itself is well-formed.
Fix: For multi-line drilldowns, write the script to /tmp/<name>.sh with the Write tool, then invoke as bash /tmp/<name>.sh. This bypasses the inline heredoc → hook re-quote path entirely. Single-line du -sh "$VAR"/path/* style commands still work fine.
Evidence: 2026-05-09 disk audit on terryli's MBP — Chrome / Claude / MacWhisper drilldowns failed twice via heredoc, succeeded immediately when scripted via /tmp/disk-hygiene-scan.sh. Reclaim totals were unaffected; 40GB freed across both passes (caches 19GB + selected items 20GB physical).
Action taken: Added "pueue hook + heredoc with spaced paths" row to Troubleshooting table in SKILL.md, plus a "Hook-safe multi-line scripts" note in Phase 2.
2026-02-08 - Initial creation
- Created skill from real disk audit session
- Benchmarked dust (20.4s), gdu (28.8s), dua-cli (37.1s), ncdu (96.6s) on ~632GB home dir
- Documented cache cleanup workflow: uv (10.8GB), brew (9.4GB), pip (837MB), npm (1.1GB) = ~22GB reclaimed
- Added forgotten file detection patterns (ISOs, video exports, old recordings)
- Added Downloads triage workflow with AskUserQuestion multi-select pattern
- Covers 10 cache types: uv, brew, pip, npm, cargo, rustup, Docker, Playwright, sccache, huggingface
#!/usr/bin/env bash
# cache-audit.sh - Measure all developer cache sizes on macOS
# Usage: bash scripts/cache-audit.sh
set -euo pipefail
echo "=== Developer Cache Audit ==="
echo "Date: $(date '+%Y-%m-%d %H:%M')"
echo ""
declare -a names=(
"uv"
"Homebrew"
"pip"
"npm"
"cargo registry"
"rustup"
"sccache"
"Playwright"
"huggingface"
"Docker"
)
declare -a paths=(
"$HOME/Library/Caches/uv"
"$HOME/Library/Caches/Homebrew"
"$HOME/Library/Caches/pip"
"$HOME/.npm/_cacache"
"$HOME/.cargo/registry/cache"
"$HOME/.rustup/toolchains"
"$HOME/Library/Caches/Mozilla.sccache"
"$HOME/Library/Caches/ms-playwright"
"$HOME/.cache/huggingface"
"$HOME/Library/Containers/com.docker.docker/Data"
)
total_kb=0
for i in "${!names[@]}"; do
name="${names[$i]}"
path="${paths[$i]}"
if [ -d "$path" ]; then
size_human=$(du -sh "$path" 2>/dev/null | cut -f1)
size_kb=$(du -sk "$path" 2>/dev/null | cut -f1)
total_kb=$((total_kb + size_kb))
printf "%-20s %8s %s\n" "$name" "$size_human" "$path"
fi
done
echo ""
total_gb=$(echo "scale=1; $total_kb / 1048576" | bc 2>/dev/null || echo "N/A")
echo "Total: ${total_gb} GB"
Related skills
FAQ
What does disk-hygiene clean on a dev machine?
disk-hygiene focuses on development caches, build artifacts, and stale project folders that consume local disk. The skill prioritizes safe, inspect-first cleanup so active repositories and running environments stay intact.
When should developers run disk-hygiene?
disk-hygiene helps when installs fail from low disk space, IDEs slow down from bloated caches, or routine maintenance is overdue. Developers invoke it before large Xcode, Docker, or package-manager updates.