storage-analyzer
A macOS / Windows read-only storage analysis assistant (automatically detects OS). Scans full disk usage, identifies major space hogs, categorizes every item into three tiers—🟢 Safe to Auto-Clean / 🟡 Requires Human Review / 🔴 Clean with Caution—and provides actionable remediation plans. Generates beautifully formatted, collapsible, interactive HTML reports with one-click command copying, and can launch a local service for one-click deletion (Move to Trash / Permanent Delete) directly from the web page. The scanning phase is strictly read-only. Always use in scenarios where the user asks for: "storage analysis", "disk is full", "C drive/hard drive is full", "not enough space", "clean up space", "clean disk", "taking up space", "what is taking up room", "check my storage", "look at computer storage/space", "free up disk", "out of memory / out of space" (in colloquial speech, "memory" often refers to disk storage), "storage analysis", "disk cleanup", "clear cache", "disk cleanup"; or when the user complains about running out of disk space, wants to know what is consuming hard drive space, or asks for cleanup advice. Note: If the user explicitly refers to operational RAM/memory (e.g., "which process is hogging memory", "high memory usage", looking for Activity Monitor/Task Manager), that is RAM, not storage, and is out of scope for this skill.
1How It Works & Mechanism
Four-step pipeline: read-only scan → agent triage & analysis → interactive HTML report generation → bottom-line-first summary in dialogue; scanning is separated from reporting, with an intermediate JSON artifact.
对 macOS 做一次只读存储分析,产出交互式 HTML 报告。流程:扫描 → 分析分级 → 生成网页 → 打开。
Scanner is completely read-only: only executes df/du/diskutil/stat/ls and os.scandir, never writing to disk; strictly declared both in script docstrings and as an absolute rule in SKILL.md.
STRICTLY READ-ONLY: only sizes/lists/reads metadata. Never creates, moves, or deletes anything.
Scanner automatically detects the operating system (sys.platform) and targets corresponding directory sets: macOS scans home/library/caches/containers/app_support/applications/downloads/dev_caches using du for size calculation; Windows scans user_profile/appdata/temp/downloads/program_files using os.scandir.
- **macOS**:扫 home、library、caches、containers、group_containers、app_support、applications、downloads、dev_caches,用 `du` 算大小。 - **Windows**:扫 user_profile、appdata_local、appdata_roaming、temp、downloads、program_files(_x86)、dev_caches,用 `os.scandir` 算大小;`system.disks` 含所有盘符。
Triage serves as a "cleanup decision list" rather than an exhaustive audit: only items that warrant a decision on whether to act are categorized into the three-light system; normal active apps and system files fall into the blue "System & Others" category.
**三级分类 = 清理决策清单,不是全盘点。** 只把"存在'要不要动它'这个决策"的项放进三灯;日常在用的正常应用、操作系统本身、海量零碎小文件没有清理决策,不进三灯,它们落在磁盘条的蓝色"系统及其他"里。判定标准:
One-click deletion relies on a local server: server.py binds to 127.0.0.1 on a random port with a per-session random token, executing only upon POST /action; static mode (build_report.py) explicitly omits deletion buttons.
- Bound to 127.0.0.1 only; every POST requires the session token; Host header
The security model applies three progressive whitelists from strictest to broadest: rm allows only green trash_paths; trash allows green and yellow trash_paths; open additionally permits yellow path and red app_paths, all subject to realpath verification and strictly confined within $HOME.
**安全模型——三套白名单,权限从严到宽**:`rm` 只允许绿灯 `trash_paths`;`trash` 允许绿灯+橙灯 `trash_paths`(橙灯永远不能 rm);`open`(在文件管理器打开,非破坏性)允许上述全部 + 橙灯真实 `path`。所有请求 realpath 校验 + 必须在 $HOME 内 + token + Host 校验,每次点击浏览器先 confirm。
Deletion invokes system trash APIs rather than direct rm: macOS uses osascript to instruct Finder to delete (falling back to moving to ~/.Trash upon failure); Windows uses SHFileOperationW with FOF_ALLOWUNDO.
script = 'tell application "Finder" to delete (POSIX file %s as alias)' % json.dumps(path)
Yellow-tier items can only be moved to trash (reversible); red-tier items omit deletion buttons entirely, offering only "Open in File Manager"—an explicit classification for items that warrant review but should not be manually deleted.
橙灯只准移废纸篓、可逆,绝不给"直接删除")。App 托管又无安全子路径的(Chrome/微信)只给打开按钮、不给 trash_paths。按钮下方会自动写明注意事项(打开只查看不删、移废纸篓可逆需清空才释放等);如果某项在文件管理器里是 App 内部格式、不方便手动挑选,给它一个 `open_note` 字段做客观说明(会显示在注意事项里)。**口吻要中性、像产品说明**:直接描述"这里是什么结构、为什么不好手动删、想精细操作该去哪",不要写成"我发现/提醒注意/看着像没视频"这种暴露开发者踩坑视角的话。 - 🔴 **谨慎清理(有决策但不建议手删)**:你可能想动、但建议别手删的具体项——重复安装的应用、想卸载的大应用、运行中应用的核心数据等。给"为什么不建议手删" + `indirect_release` 写**具体卸载步骤**(自带卸载器 / 启动台长按 / 右键移废纸篓 / AppCleaner 清残留 / App Store 可重装等,要可照做不是空话)。应用项给 `app_paths`(真实 `.app` 绝对路径数组)→ 网页出现「在文件管理器打开(去卸载)」按钮,定位到 App 让用户自己正规卸载。**红灯不给删除/卸载按钮**
The report follows a structured interactive HTML reading flow: Disk Overview (segmented progress bar) → Top 5 → Actionable Recommendations → Tri-color Collapsible Cards (with one-click command copy) → Long-term Optimization Advice, representing "Status → Diagnosis → Prescription → Action → Prevention".
报告阅读流(固定顺序):磁盘总览卡片(容量 + 进度条 + 三色容量 pills + 系统信息,纯数据)→ 占用排行 Top5 → 执行建议 → 🟢🟡🔴 三级可折叠卡片(命令一键复制)→ 长期优化建议。
Windows support is explicitly noted as not fully tested in practice, requiring initial verification of paths, scandir sizing, and recycle bin deletion; multi-drive support is implemented.
- **Windows**:代码已写(`scan.py` 的 `scan_windows`、`server.py` 的 `_trash_windows` 走 `SHFileOperationW`),但**未在真实 Windows 上实测**。
Zero third-party dependencies: scripts rely solely on Python 3 standard library; macOS includes native python3/du/diskutil/osascript, enabling out-of-the-box execution.
- 全部脚本是 **Python 3 标准库**,零第三方依赖(不用 pip install)。
2Core Capabilities
4Recommended Governance & Evidence
- scripts/: Executes local scripts or commands: scripts/scan.py (read-only scan, calls system commands like du/df/diskutil via subprocess without disk writes)
- 网络端点: Declares external network access: Local loopback only: http://127.0.0.1:<random_port>/ serving the report page and POST /action (Host header must strictly match 127.0.0.1/localhost)
- 本地工作目录: File I/O and artifact output: /tmp/storage_scan.json (scan results), user-specified analysis JSON (written by agent), report HTML (written in static mode)
5Second-Pass Verification
- [ok] 扫描器确实只读 — scan.py 只用 os.scandir/os.listdir/du/df/diskutil 等读取与统计;无 open(...,"w")、无 shutil.rmtree/os.remove、无 mkdir;docstring 明写 STRICTLY READ-ONLY。
- [ok] 服务侧白名单构造与文档一致 — load() 中:green.trash_paths → rm/trash/open 三集合;yellow.trash_paths 只进 trash+open;yellow.path(存在时)只进 open;red.app_paths(存在时)只进 open——与 SKILL.md「三套白名单,权限从严到宽」逐条对应。
- [ok] 删除请求的多重校验 — do_POST 依次校验:Host ∈ {127.0.0.1, localhost}、token 相等、mode ∈ {rm,trash,open}、每个 path realpath 后必须在对应白名单、且必须在 HOME 或 /Applications 之下(删除类白名单不含 /Applications)。
- [ok] 回收站删除的实现 — macOS: osascript `tell application "Finder" to delete (POSIX file ...)`,失败回退 shutil.move 到 ~/.Trash;Windows: ctypes 调 SHFileOperationW,fFlags 含 FOF_ALLOWUNDO(进回收站)。
- [ok] 无公网请求 — 全目录 URL 扫描仅命中 http://127.0.0.1:%d/(服务自述地址);无 CDN、无遥测、无第三方 API。
- [ok] 无凭证读取 — API_KEY/token/secret 扫描:唯一 token 变量是 secrets.token_urlsafe(24) 生成的会话 token,非用户凭证;无 env 读取、无 keychain、无配置文件读取。
- [ok] 静态报告确实没有删除能力 — build_report.py 把 __DELETE_CONFIG__ 替换为 "null";模板里的 fetch(DELETE.endpoint, ...) 只有在服务模式下注入 token/endpoint 才可用(SKILL.md 的排障段落也这么说)。
- [ok] 零第三方依赖 — 三个脚本 import 仅 json/os/secrets/shutil/subprocess/sys/time/webbrowser/http.server/re/ctypes;无 requirements/pip 指令。
6Verdict & Scenarios
b8b3f5bde010e27b…