macos-cleaner
Diagnoses and safely reclaims macOS disk space. Use when a Mac is low on storage, reports “Caching needs more space,” shows large Apple Content Caching or AssetCacheManagerUtil usage, or needs analysis of caches, logs, application remnants, large or duplicate files, Docker or OrbStack, Chromium code-sign clones, Homebrew, npm, pip, Xcode, and other developer storage. Routes known suspects to targeted read-only diagnosis before broad scans, distinguishes nominal path accounting from physical release, requires an impact-and-recovery plan plus explicit confirmation before state changes, and verifies disk space and co-resident services afterward.
1实现原理 · 为什么它能做到
入口路由机制:按用户信号走最窄路径——具名可疑源(Apple Content Caching/Docker/Chromium code-sign clones/某缓存目录)先专项读参考文档,只有真正来源未知才走通用扫描。
Choose the narrowest path that can answer the request
安全机制核心是『观察与变更分离 + 精确审批门禁』的四相状态机:Observe(只读)→ Plan(停到确认闸)→ Execute(仅批准范围)→ Verify(独立读回);2/3 相不许压缩进一条消息。
Do not compress phases 2 and 3 into one message. A plan printed beside a cleanup command is not a confirmation gate.
只读诊断由一套自研 python 脚本执行(analyze_caches/analyze_dev_env/find_app_remnants/analyze_large_files/analyze_code_sign_clones),配合物理分配核算纪律:du 是路径记账不是物理释放(APFS clone 共享 extent)。
shared extents can be attributed to every path, so actual release remains unknown until deletion and `df` readback
删除路径双轨:优先 Finder Trash(osascript 删除可恢复,但物理空间要等清空 Trash 才释放);legacy safe_delete.py 是带 denylist 与交互确认的永久删除助手,被文档明确降级(不 Trash、不查全部用户数据根、不检测打开文件)。
HIGH_RISK_PATHS = frozenset( _canonical_path(path) for path in [ '/System', '/Library/Apple', '/usr', '/bin', '/sbin', '/etc', '/private/var/db', '~/.ssh', '~/.aws', '~/.gnupg', '~/Library/Keychains', ] )
Docker/OrbStack 纪律:per-object 分析(列出每个 image/container/volume、检查引用与库类内容、稀疏文件实际分配),数据库卷名(mysql/postgres/redis/mongo/mariadb)强制内容检查后才可提议删除;**绝不使用 prune 家族命令**。
**Never use Docker prune-family commands.** This includes image, container, volume, system, builder, and buildx prune.
事后验证纪律:df 前后读数算实际回收(不信删除工具自报)、重查被清理子系统、对关键共驻服务重解析 PID/健康探针、APFS 记账滞后或可能回填时按有界间隔观察;never report 'fixed' when only the exit code is known。
Never report “fixed” when only the command exit code is known. A successful cleanup requires both the intended state and the protected invariants.
2核心能力
3外部依赖
| Kind | Dependency / Endpoint |
|---|---|
| cli | df / du / lsof / pgrep / launchctl / ps(系统状态与分配测量) |
| cli | uv(运行 bundled python 脚本) |
| cli | osascript(Finder Trash 删除) |
| cli | docker(可选:per-object 分析 + 受权后的临时只读检查容器) |
| cli | mo / Mole(可选第三方全盘扫描器 github.com/tw93/Mole,需用户批准其固定宽扫描根) |
| cli | sudo AssetCacheManagerUtil / AssetCache(受权后的服务控制) |
4管控建议与判定依据
- scripts/: 执行本地脚本或命令: scripts/analyze_caches.py / analyze_dev_env.py / find_app_remnants.py / ana
- scripts/ 或 SKILL.md: 声明动态安装外部语言包依赖
- 本地工作目录: 文件读写与工件输出: ~/.macos-cleaner/{before,after}.json(cleanup_report.py 快照)
5第二遍独立确认
- [ok] safe_delete.py denylist 与删除逻辑 — HIGH_RISK_PATHS 含 /System、/usr、/bin、/etc、~/.ssh、~/.aws、~/.gnupg、~/Library/Keychains 等;delete_path 对 is_high_risk_path 直接拒绝;文件 unlink/目录 shutil.rmtree。
- [ok] 『观察/变更分离 + 确认门禁』在源码与文档双重存在 — SKILL.md 10 条 contract + 四相状态机 + 'Do not compress phases 2 and 3 into one message';safe_delete 每次删除前交互 input('[y/N]')。
- [ok] nominal vs physical 纪律有代码/文档支撑 — SKILL.md 明示 du 路径记账 vs df 物理读回;cleanup_report 只做 df 快照不做释放断言;safe_delete 输出 'Measured size removed' 并提示 'Physical release: verify with before/after df -k'。
- [ok] Docker prune 禁令与 per-object 纪律 — SKILL.md 六行明文禁 prune 家族;docker_analysis.md 给 --pull=never --network=none --read-only --cap-drop=ALL 的只读检查容器配方。
- [ok] 无网络/无凭证(安全结论基础) — 全目录扫描零网络调用代码、零凭证读取;Mole/AssetCacheManagerUtil 等外部工具仅在有授权与安装前提下由宿主调用。
- [ok] batch 'all' 可跳过逐项危险模式警告的注意点 — safe_delete.py batch_confirm 支持输入 'all' 直接返回全部 items(不做 danger_patterns 逐项检查,仅 denylist 兜底)——已在 risks 注明;SKILL.md 也限定该助手仅用于精确批准的非用户数据目标。
- [ok] 元数据(commit/license/stars) — 本地 HEAD == pin d5c4678cb5d4fd6acc9c922690df035dbd33d247;GitHub API:MIT、stars 1385(2026-09-09 实采)、pushed_at 2026-09-09T12:33:29Z。
6结论
2e94bb1d20bbcc55…