SuperAPI AI Directory

disk-cleanup

Deployment & operations

View repository

Updated 10-16 01:19

About this skill

Disk Cleanup

Reclaim disk space on a Linux VM. The skill runs a triage — survey every space consumer, split targets into safe vs ask, execute the approved set, then verify the delta.

When to Use

  • User says "disk cleanup", "free up space", "clean up the VM"
  • Disk usage above 80%
  • After large builds, git operations, or Docker image accumulation

Procedure

1. Baseline

df -h

Done: used and available numbers recorded for all mounts for the before/after comparison.

2. Survey

Requires root for apt, journalctl, and /var/log operations. Non-root users can survey but cannot clean system paths.

Build a ranked list of every consumer over ~50M. Survey all mounts, not just /.

# All mounts (not just /)
df -h
df -i                           # inode exhaustion — "No space left on device" with free blocks

# Deleted-but-open files (canonical "df says full, du says empty" case)
lsof +L1 2>/dev/null | head -20

# Hermes data + user caches + tmp (stay on one filesystem, don't cross mounts)
du -xsh ~/.hermes/*/ 2>/dev/null | sort -rh | head -20
du -xsh ~/.hermes/projects/*/ 2>/dev/null | sort -rh | head -20
du -xsh ~/.cache/*/ 2>/dev/null | sort -rh | head -15
du -xsh /tmp/* 2>/dev/null | sort -rh | head -15

# Memory store (if Mnemosyne is installed)
du -xsh ~/.hermes/mnemosyne/data/* 2>/dev/null | sort -rh

# Session checkpoints (if present)
du -xsh ~/.hermes/checkpoints/store/ 2>/dev/null

# Docker
docker system df                # shows build cache separately from images
docker images --format "{{.Size}}\t{{.Repository}}:{{.Tag}}" | sort -rh | head -25
docker ps -a --filter "status=exited" --format "{{.Image}}" | sort -u

# System
du -xsh /var/cache/apt /var/log ~/.cache/pip ~/.cache/uv 2>/dev/null
journalctl --disk-usage
find /var/log \( -name "*.gz" -o -name "*.1" -o -name "*.old" \) 2>/dev/null

# Bloated git repos (orphaned tmp_pack files from interrupted operations)
find ~/.hermes/projects -name ".git" -type d -exec sh -c 'du -sh "$1" 2>/dev/null' _ {} \; | sort -rh | head -10

Done: every consumer over 50M identified with its size. All mounts surveyed. Inode exhaustion and deleted-but-open files checked.

3. Triage

Split every found target into two buckets. Present the table to the user before executing.

Safe — execute without asking:

Target Command Reclaims
uv cache uv cache prune Up to full cache size
pip cache pip cache purge Up to full cache size
apt cache apt autoclean ~100M typical
Journal logs journalctl --vacuum-size=50M Down to 50M
Rotated logs find /var/log \( -name "*.gz" -o -name "*.1" -o -name "*.old" \) -delete ~20M typical
Browser automation caches rm -rf ~/.cache/puppeteer ~/.cache/ms-playwright ~650M; re-downloads if needed
Dangling Docker images docker image prune -f Varies
Docker build cache docker builder prune -f --filter until=168h --reserved-space 10GB Often multi-GB; bounded: skips cache younger than 7 days, always keeps 10GB

Ask first — user must confirm:

Target Risk Command
git gc aggressive Destroys recoverable objects (dropped stashes, orphaned commits after bad reset). Aggressive repack temporarily grows disk use. cd /repo && git gc --aggressive --prune=now
apt autoremove May remove wanted packages. Review the list before confirming. apt autoremove (without -y)
Old DB backups Confirm current DB is healthy first. Use explicit paths, not globs. rm /path/to/specific-backup.bak
Stale /tmp dirs Directory mtime does not track activity inside. List before deleting. find /tmp -maxdepth 1 -mtime +3 -type d -name "*_*" | xargs ls -ld then confirm
Docker images for stopped containers May want to restart later docker rmi <image>
Session checkpoint stores May contain recoverable state —
Large skill references (PDFs, maps, RAG indexes) User data —
Large project uploads User data —
Docker images for running services Disruptive —

Done: table presented with safe-only total and with-ask total. User has approved a set.

4. Execute

Run the commands from the Safe table for each approved target. Capture before/after size for each.

For Docker stopped containers + images (requires two steps):

docker rm $(docker ps -a --filter "status=exited" --filter "ancestor=IMAGE" -q)
docker rmi IMAGE

Done: every approved target cleaned. Before/after size captured for each.

5. Verify

df -h

Compare per-mount against baseline from step 1.

Done: total reclaimed reported per mount. Used/free compared against baseline.

Pitfalls

Problem Cause Fix
df shows free blocks but writes fail with ENOSPC Inode exhaustion — millions of small files. Check df -i. Locate with find <mount> -xdev -type f | head -100000 | wc -l per directory, then clear the offending cache/spool. Disk-size cleanup will not help.
df says full but du shows nothing A process holds a deleted file open. Check lsof +L1. Identify the holding process with lsof +L1, restart it (or truncate via cat /dev/null > /proc/<pid>/fd/<n>). No file deletion reclaims this.
git gc reclaims nothing No orphaned objects — just large history Accept the size or run git repack -ad for marginal compression
tmp_pack files persist after gc Git process still running or lock file fuser .git/objects/pack/*.pack to find the process, retry after it ends
Docker rmi fails "image is in use" Stopped container still references it docker rm the container first, then docker rmi
apt autoremove lists wanted packages Auto-removable deps flagged incorrectly Review the list before confirming; skip with apt-mark manual <pkg>
journalctl --vacuum-size fails Journald service issue systemctl restart systemd-journald then retry
uv cache prune fails uv not in PATH Use python -m uv cache prune