Perform a read-only storage analysis on macOS and produce an interactive HTML report. Flow: scan → analyze and classify → generate web page → open.
Iron rules
- Read-only throughout. Only scan/statistics/list directories/read metadata (df, du, diskutil, stat, ls) may be run. Absolutely forbidden: rm, mv, rmdir, emptying the trash, changing permissions, or any other write operation.
- Delete commands are only displayed, not executed. The cleanup commands given in the report are for the user to run in the terminal after confirming themselves. Even if the user says "help me delete" in the conversation, stop and confirm first (hits the global red line: deleting files must be asked about first), do not run it on their behalf.
- Estimates are clearly labeled. Anything involving "reclaimable space" must be stated as an estimate.
- Paths and commands are kept in their original form and not translated.
Execution flow
Step 1 Scan (read-only)
python3 scripts/scan.py > /tmp/storage_scan.json
scan.py Auto-detect the system (sys.platform):
- macOS: scan home, library, caches, containers, group_containers, app_support, applications, downloads, dev_caches, use
duto calculate sizes. - Windows: scan user_profile, appdata_local, appdata_roaming, temp, downloads, program_files(_x86), dev_caches, use
os.scandirto calculate sizes;system.disksincludes all drive letters.
Output JSON:system(system/disk info, including disk_name main drive name + disks all drives) + groups(size of each group's subdirectories, already sorted descending, filtering out anything under 50MB). Scanning is slow, wait patiently. Directories that cannot be read are marked denied, and must be listed in the report with a note about the omitted volume.
Step 2 Analysis and classification
First look at system.os to determine the system, and read the corresponding data layout reference: for macOS read references/macos.md, for Windows read references/windows.md(explains where that system stores things, how to identify them, and which level they belong to). Then read /tmp/storage_scan.json to do these things:
- Pick the Top 5 space hogs, determine their type (system assets/application itself/application data/application cache/development cache/user files/media content/downloaded content/virtual machine images/trash/other).
- Identify "mysterious large directories": UUID-named Containers, unknown hidden directories — trace which App they belong to and what is stored in them (for example, a certain 97GB UUID Container is actually Bilibili offline video cache). If necessary,
ls/dugo one level deeper to see clearly, but still read-only. - Three-level classification = cleanup decision list, not a full inventory. Only put items that involve a "should I touch it or not" decision into the three lights; normal applications in daily use, the operating system itself, and massive numbers of tiny scattered files have no cleanup decision, so they do not go into the three lights — they fall into the blue "System and Other" part of the disk bar. Criteria:
- 🟢 Can be cleaned automatically: pure caches, temporary files, leftover installers, clearly regenerable and not affecting functionality, not losing user data (pip/uv/npm/Xcode DerivedData and other development caches, browser caches).
- 🟡 Requires manual judgment: Contains user data or has a judgment cost (offline videos, documents, project code node_modules, chat history, design files). Provide a content profile + at least 3 sentences on handling paths (in-app cleanup / system tools / manual review in file manager, choose the most appropriate of the three) + risk warnings.All orange-light items automatically have an "Open in Finder/File Explorer" button in service mode(skip it and review/delete it yourself); if the item has a verified safe subpath that can be deleted without breaking the App (such as Bilibili offline videos'
.Downloadsdirectory, old backup directories), give ittrash_paths→ a "Move to Trash" button appears on the webpage (orange light only allows moving to Trash, which is reversible; never give "direct delete"). For App-managed items with no safe subpath (Chrome/WeChat), only give the open button, not trash_paths. Below the button, notes will automatically be written (opening only views, does not delete; moving to Trash is reversible and requires emptying to free space, etc.); if an item is in an App-internal format in the file manager and inconvenient to select manually, give it aopen_notefield for an objective explanation (it will be shown in the notes).The tone should be neutral, like product documentation: directly describe "what structure is here, why it is hard to delete manually, and where to go for fine-grained operations"; do not write things like "I found / note that / looks like there are no videos" that expose the developer's troubleshooting perspective. - 🔴 Clean with caution (there is a decision but manual deletion is not recommended): specific items you may want to touch but are advised not to delete manually—duplicate installed apps, large apps you want to uninstall, core data of running apps, etc. Provide "why manual deletion is not recommended" +
indirect_releasewritespecific uninstall steps(built-in uninstaller / long-press in Launchpad / right-click Move to Trash / AppCleaner to clean leftovers / reinstallable from App Store, etc.; must be actionable, not empty talk). For app items, giveapp_paths(real.appabsolute path array) → an "Open in file manager (go uninstall)" button appears on the webpage, locating the App so the user can uninstall it properly themselves.Red light does not give delete/uninstall buttons(the app is in a system directory, may require an administrator password, may have a built-in uninstaller and leftovers, and background deletion on its behalf is not reliable).Pure system files and APFS snapshots should not be listed as separate red cards(there is no cleanup decision), just classify them as blue; system-level space-freeing tips (restart to release swap, Time Machine snapshot policy, automatic reclamation of purgeable space) should be written intosummary.long_termlong-term recommendations.
Each 🟢 item must include: estimated space freed, processes to close before cleanup, and a one-click copyable cleanup command (using a safe method such as moving to Trash or the App's own cleanup entry; use rmcautiously; if using rm , it must be a clear cache subdirectory).
Write the size field cleanly:size / size_estimate Use "about 14 GB" or "about 8.6 GB in total"—"about" already indicates an estimate, so do not add "(estimated)"; it is repetitive and unprofessional (the template will also automatically remove this kind of redundant parenthesis). The regenerable attribute is already covered by the tier heading and button description, so do not stuff it into the size field.
Step 3 Generate interactive report
Write the analysis results as analysis JSON (see the schema in the comments at the top of scripts/build_report.py ).
🟢 items must include trash_paths(a specific array of deletable absolute paths, distinct from the human-readable path Display fields) — this is the prerequisite for the web page delete button; if it's missing, the button won't appear.
By default, open the report in one-click delete mode (server.py), because the core value of this skill is being able to clean up directly on the web page:
python3 scripts/server.py /tmp/storage_analysis.json # 自动开浏览器,Ctrl+C 停
server.py starts on 127.0.0.1 + random port + random token. 🟢 items get "Move to Trash" (reversible) + "Delete directly" (frees space immediately, irreversible); 🟡 items get "Open in Finder" + (when there is a safe subpath) "Move to Trash".Security model — three whitelists, permissions from strict to broad:rm only allows green-light trash_paths;trash allows green-light + orange-light trash_paths(orange-light can never be rm'd);open(opening in the file manager, non-destructive) allows all of the above + real orange-light path. All requests are realpath-validated + must be within $HOME + token + Host validation, and each browser click requires confirm first. osascript/SHFileOperationW moves to Trash; on macOS, just click Allow on the first Finder automation authorization prompt.
Only when the user explicitly wants only a shareable/archivable read-only file, use static mode (no delete buttons, because the page opened by file:// cannot reach the filesystem):
python3 scripts/build_report.py /tmp/storage_analysis.json ~/Desktop/storage-report.html && open ~/Desktop/storage-report.html
Troubleshooting: no delete/move-to-Trash buttons on the web page = either a static report was opened (switch to server.py), or the 🟢 items are missing trash_paths(add it and restart the service).
Report reading flow (fixed order): disk overview card (capacity + progress bar + three-color capacity pills + system info, pure data) → top 5 usage ranking → execution recommendations → 🟢🟡🔴 three-level collapsible cards (one-click command copy) → long-term optimization suggestions. That is, "current state → diagnosis → prescription → action → prevention".
Note: summary.overview should be written as a one-sentence insight (directly state what the largest usage is and how much can be freed), and do not repeat the total/used/available numbers — those are already displayed as the large numbers in the card. overview is rendered at the beginning of the "Execution Recommendations" section as a lead-in (plain text), immediately followed by the summary.priority priority list.
The disk progress bar splits "used" into segments: green (can be cleaned automatically) + orange (requires manual action) + red (identified items not recommended to touch) + blue (system and others, automatically takes the remainder of used − green − orange − red), with the rest being available (gray background).summary.tier_stats The three values green / yellow / red must each start with a parseable GB number (e.g. "about 27.8 GB"); the script extracts numbers from them to compute the segments; the blue segment and the "system and others" pill are automatically calculated as the remainder by the template.
pills only render the parsed pure numbers (e.g. "about 5.5 GB") and do not display annotations from the data, so just write clean numbers for the three tier_stats values, and don't add apologetic explanations like "identified items only / system not counted" — system files naturally fall under the blue segment anyway, and red only holds the 🔴 items you can quantify (duplicate apps, uninstallable large apps, etc.); system files/snapshots that cannot be measured accurately naturally fall under blue.
Give a summary in the conversation at Step 4
After the report is generated, give a conclusion-first summary in the conversation in one paragraph: total estimated reclaimable space, the 2-3 items that should be cleaned first, and the highest-risk item. Let the user see the details on the web page.
Dependencies and runtime prerequisites
- All scripts are Python 3 standard library, with zero third-party dependencies (no pip install needed).
- macOS comes with python3,
du、diskutil、osascript, ready to use out of the box. - Windows does not have Python installed by default — you need to install Python 3 first, and commands are mostly
pythonorpy -3(notpython3). This skill's command example is written aspython3, and on Windows it automatically switches topython/py -3。 - This skill is agent-driven: after scanning the data, the agent (Claude) performs tiered analysis; it is not a standalone double-click-to-use app.
Platform status
- macOS: fully implemented and tested (scan / report / one-click delete all verified).
- Windows: code is written (
scan.py'sscan_windows、server.py's_trash_windowsusesSHFileOperationW), butnot tested on real Windows. When running on Windows for the first time, verify: the target directory path,os.scandirsize, and whether recycle bin deletion works properly. Multiple drives are now supported (segmented bar for the main drive + list for other drives).
Long-term optimization suggestion material (written into report summary.long_term)
- Regular cleanup:
brew cleanup, Xcode DerivedData, browser cache - Visualization tools: DaisyDisk, GrandPerspective, OmniDiskSweeper
- Archive large files to an external drive / iCloud / NAS; the optimization options in macOS "System Settings > General > Storage"