| name | windows-disk-cleanup |
| description | Use when cleaning up disk space on Windows, analyzing WizTree exports, reclaiming space from caches, temp files, Docker, Python venvs, or dev tool bloat. Use when the user mentions disk full, low space, WizTree, cleanup, or wants to free up storage. |
Windows Disk Cleanup with WizTree Analysis
Systematic Windows disk cleanup for developer machines. Two mandatory phases: Discover first, then Execute only after user approval. All deletions must preserve parent folder timestamps.
Mandatory Rules
- NEVER delete anything without running Discover first. Always dry-run before execute.
- ALWAYS preserve timestamps on parent folders when deleting subfolders or their contents. See Timestamp Preservation.
- ALWAYS get explicit user approval between Discover and Execute phases.
Phase 1: Discover (Dry-Run)
This phase is read-only. No files are deleted. Run this first to understand what can be cleaned.
Steps
- Analyze -- If user provides a WizTree screenshot, read it and identify top space consumers using the Space Consumer Reference table below.
- Copy scripts -- Copy the bundled scripts from scripts/ into the user's working directory.
- Run dry-runs -- Execute the scripts without
-Execute to report what would be deleted:
powershell -ExecutionPolicy Bypass -File ./cleanup.ps1
powershell -ExecutionPolicy Bypass -File ./clean_venvs.ps1
powershell -ExecutionPolicy Bypass -File ./clean_venvs.ps1 -Path D:\other\projects
powershell -ExecutionPolicy Bypass -File ./downloads_report.ps1
- Present findings -- Show the user a summary table with per-category sizes and estimated total savings.
- Ask user -- Which categories to clean, which to skip. Do NOT proceed to Phase 2 without explicit approval.
What Discover Reports
| Script | Dry-run output |
|---|
cleanup.ps1 | Per-category size (temp, Docker, npm, uv, Chrome, Windows junk, Android SDK) + Downloads analysis (top 50 files, top 20 file types, up to 15 duplicate groups). Shows Drive C: free space. Color-coded output with elapsed time. |
clean_venvs.ps1 | Every .venv found, its size, whether it has pyvenv.cfg, total across all venvs. Color-coded by size (red >2 GB, yellow >1 GB). Per-venv elapsed time and running total. Terminal output only (no report file). |
downloads_report.ps1 | Top 50 files, top 25 file types, up to 25 duplicate groups (>1 MB same size with waste calculation), .venv summary. Saved to timestamped .txt in script directory. Note: only searches for .venv folders (not venv or numbered variants). |
Phase 2: Execute (Deletions)
Only run this after the user has reviewed Phase 1 output and explicitly approved.
Steps
- Run with
-Execute:
powershell -ExecutionPolicy Bypass -File ./cleanup.ps1 -Execute
powershell -ExecutionPolicy Bypass -File ./cleanup.ps1 -Execute -SkipDocker -SkipAndroid
powershell -ExecutionPolicy Bypass -File ./clean_venvs.ps1 -Execute
powershell -ExecutionPolicy Bypass -File ./clean_venvs.ps1 -Execute -ToRecycleBin
- Review report --
cleanup.ps1 writes cleanup_report_TIMESTAMP.txt (in script directory) logging every item with status (DELETED, LOCKED, WOULD DELETE, EXECUTED). The EXECUTED status is used for native CLI commands like npm cache clean --force and uv cache clean.
- Check Drive C: -- Both
cleanup.ps1 and clean_venvs.ps1 show Drive C: free space before and after execution.
- Verify -- User runs WizTree again to confirm space reclaimed.
- Handle failures -- If
-ToRecycleBin fails on deep paths (>260 chars), re-run those specific folders without -ToRecycleBin for permanent delete.
Timestamp Preservation
MANDATORY for all deletion operations. When deleting a subfolder (venv, cache, temp), the parent folder's LastWriteTime, LastAccessTime, and CreationTime change. This must be prevented.
Pattern: Save and Restore
Every script that deletes subfolders MUST save parent timestamps before deletion and restore them after:
$parentDir = Split-Path $targetPath -Parent
$parentItem = Get-Item $parentDir -Force -ErrorAction SilentlyContinue
$origLastWrite = $parentItem.LastWriteTime
$origLastAccess = $parentItem.LastAccessTime
$origCreation = $parentItem.CreationTime
# --- perform deletion ---
Remove-Item $targetPath -Recurse -Force -ErrorAction Stop
# --- restore timestamps ---
$parentItem = Get-Item $parentDir -Force -ErrorAction SilentlyContinue
if ($parentItem) {
$parentItem.LastWriteTime = $origLastWrite
$parentItem.LastAccessTime = $origLastAccess
$parentItem.CreationTime = $origCreation
}
Where This Applies
clean_venvs.ps1 -- Already implemented. Saves/restores parent timestamps around every venv deletion.
cleanup.ps1 -- Operates on system caches (temp, npm, Docker) where parent timestamp preservation is less critical, but the pattern should be applied if extending to user project directories.
- Any new cleanup scripts you generate -- Always include this pattern.
Why This Matters
Developers rely on folder timestamps to know when a project was last modified. Deleting a .venv inside my-project/ should NOT change my-project/'s LastWriteTime from "2024-06-15" to "today". Without this, WizTree and file explorers show misleading modification dates.
Bundled Scripts
Three ready-to-use PowerShell scripts in scripts/. All use $env: variables for portability -- no hardcoded personal paths. Reports are written to $PSScriptRoot (the script's own directory).
| Script | Purpose | Key Parameters | Default Path |
|---|
| scripts/cleanup.ps1 | Main cleanup: temp, Docker, npm/uv caches, Chrome (multi-profile), Windows junk, Android SDK, Downloads report | -Execute, -SkipDocker, -SkipAndroid | Uses $env: variables per category |
| scripts/clean_venvs.ps1 | Python .venv cleanup with pyvenv.cfg safety, timestamp preservation, Recycle Bin option | -Execute, -ToRecycleBin, -Path <dir> | User's home directory |
| scripts/downloads_report.ps1 | Downloads analysis: top 50 files, file types, duplicates, .venv summary | -Path <dir> | User's Downloads folder |
Script Features
- Native CLI fallback:
cleanup.ps1 prefers native cache commands (npm cache clean --force, uv cache clean) when available, falls back to Remove-Item if CLI not found.
- npm cache path fallback: Checks
$env:LOCALAPPDATA\npm-cache first, then $env:APPDATA\npm-cache.
- Chrome multi-profile: Discovers all Chrome profiles (Default + Profile *) and cleans 5 cache subdirectories per profile.
- Chrome running warning: Warns user if Chrome is running (cached files may be locked).
- Progress tracking: All scripts show elapsed time, per-item progress counters (
X/Y), and running totals during measurement and deletion.
- Color-coded output: Categories color-coded by severity/size; venvs colored red (>2 GB), yellow (>1 GB), white (smaller).
Space Consumer Reference
| Category | Typical Location | Typical Size | Safe to Delete? |
|---|
| Temp files | $env:TEMP, C:\Windows\Temp | 5-30 GB | Yes (skip locked) |
| Docker | AppData\Local\Docker | 10-50 GB | Yes (if not using) |
| npm cache | AppData\Local\npm-cache | 2-10 GB | Yes (rebuilds on demand) |
| uv cache | AppData\Local\uv\cache | 2-10 GB | Yes (rebuilds on demand) |
| pip cache | AppData\Local\pip\cache | 1-5 GB | Yes (rebuilds on demand) |
| Chrome cache | AppData\Local\Google\Chrome\...\Cache | 2-10 GB | Yes (regenerates) |
| Recycle Bin | System | Variable | Yes |
| Windows Update | C:\Windows\SoftwareDistribution\Download | 1-5 GB | Yes |
| Thumbnail cache | AppData\Local\Microsoft\Windows\Explorer | 0.1-1 GB | Yes (regenerates) |
| Android SDK | AppData\Local\Android | 5-15 GB | Ask user |
| Python .venv | Inside project folders | 0.5-3 GB each | Yes (recreate with pip install) |
| Ollama models | ~/.ollama | 5-50 GB | Ask user |
| LM Studio | ~/.lmstudio | 5-30 GB | Ask user |
| node_modules | Inside project folders | 0.2-2 GB each | Yes (recreate with npm install) |
Leave Alone
AppData\Local\Programs -- installed applications
AppData\Local\Microsoft -- OS/app data
ms-playwright -- if actively used for testing
- WSL distributions -- contains Linux filesystems
- CapCut / other creative apps -- user content
Python .venv Safety Checks
- Verify with
pyvenv.cfg: Only delete folders containing pyvenv.cfg at root. Folders named venv without this file are NOT Python venvs.
- Search patterns (
clean_venvs.ps1): .venv, venv, .venv310, .venv39, and regex \.?venv\d+. Deduplicated by FullName -Unique.
- Search patterns (
downloads_report.ps1): Only searches for .venv folders. Does NOT search venv or numbered variants.
- Recycle Bin option:
-ToRecycleBin uses Shell API which fails on paths >260 chars. Always offer permanent delete as fallback.
Quick Reference
| Command | Phase | Purpose |
|---|
.\cleanup.ps1 | Discover | See what would be cleaned |
.\cleanup.ps1 -Execute | Execute | Delete files |
.\cleanup.ps1 -Execute -SkipDocker | Execute | Delete files, skip Docker |
.\clean_venvs.ps1 | Discover | Find all .venv folders (default path) |
.\clean_venvs.ps1 -Path D:\code | Discover | Find .venvs in custom path |
.\clean_venvs.ps1 -Execute | Execute | Permanently delete .venvs |
.\clean_venvs.ps1 -Execute -ToRecycleBin | Execute | Send .venvs to Recycle Bin |
.\downloads_report.ps1 | Discover | Analyze Downloads folder |
.\downloads_report.ps1 -Path D:\data | Discover | Analyze custom directory |
All scripts run from Git Bash as: powershell -ExecutionPolicy Bypass -File ./script.ps1 [flags]
Critical Lessons Learned
- PowerShell 5.1 encoding: Without BOM defaults to ANSI. Never use Unicode chars (box-drawing, em-dashes) in generated scripts. ASCII only.
- NTFS small-file deletion is slow: Tens of thousands of small files (uv cache, venvs) take 10-30+ min. Warn users. This is not a hang.
- Git Bash + PowerShell interop:
$_ gets mangled by bash. Always use -File flag, never -Command with complex expressions.
- Recycle Bin Shell API limit:
Microsoft.VisualBasic.FileIO fails on paths >260 chars with "The system call level is not correct". Offer permanent delete as fallback.
- Recycle Bin caveat for
-ToRecycleBin: When clean_venvs.ps1 -Execute -ToRecycleBin sends venvs to the Recycle Bin, space is only freed when the user empties it. Note: cleanup.ps1 -Execute empties the Recycle Bin automatically via Clear-RecycleBin -Force.
- Docker cleanup order:
docker system prune -a --volumes -f first, stop Docker Desktop, then remove AppData\Local\Docker.
- Cache deletion is safe: npm, uv, Chrome caches all regenerate on demand. Zero functional impact. pip cache is not cleaned by the bundled scripts but is listed in the Space Consumer Reference for manual cleanup if needed.
Common Mistakes
- Deleting without dry-run first -- always run Discover phase.
- Forgetting to preserve parent timestamps -- always save/restore around deletions.
- Writing Unicode in PowerShell scripts -- always ASCII for PS 5.1.
- Deleting non-venv folders named "venv" -- always check for
pyvenv.cfg.
- Promising Recycle Bin for deep paths -- Shell API fails on long paths.
- Not showing progress -- users think the script is hung during slow NTFS deletions.