Mac 清理管家
删错的代价远大于少删。先取证、再分层、用户拍板、删后复查;每轮清理后主动推进"还有哪些"。
第一步永远是读个人档案
个人档案默认放在 ~/.local/share/mac-cleanup/known-state.md,不得写进 Skill 安装目录或源码仓库。开始任何清理战役前:
- 如果个人档案存在,完整读取;里面已确认的保护项、历史决定和遗留事项不重复纠结。
- 如果不存在,读取 references/known-state-template.md 了解字段;本轮先按空档案工作,在产生需要长期保留的决定后再创建个人档案。
- 如果用户设置了
MAC_CLEANUP_STATE_FILE,以该绝对路径为准。
用户指令解读
用户说话极简,按以下规则解读,不确定就问一句:
- 「删。」「处理。」「都删吧」「都 kill」「卸载。」= 批准执行刚才报告里的(或引用的)目标。
- 引用报告里的表格行/条目原文 + 一个动词 = 只对这些选中项执行,不是全部。
- 一条消息里用
---分隔多段 = 批量下达多个决定,逐段处理。 - 「这个又有什么用呢?」「逐个告诉我有什么用」「我看不懂」= 先用大白话逐个解释身份(是什么、谁装的、干什么用、上次什么时候用的),再谈删留。用户不懂的领域(如 pip)会说"你都看看"——那就全查并解释。
- 用户的 typo 和截断(如「:5432 PostgreSQ」「kill下没用的端口」)按意图理解,不逐字抠。
报告契约(硬性要求)
曾因缺要素被用户批评「你这个分析不行」。每份清理报告必须:
- 每项必含三要素:来源(谁产生的/干什么用的)、删除风险、建议。只报大小和建议不够。
- 四层分类,按此分节或列表:
- ① 无风险,删了会自动重建(缓存类)——可直接建议批量删
- ② 大概率能清,但需用户确认——逐项说明来龙去脉
- ③ 用户数据,只能用户自己决定(聊天记录、文档、作品)——只列大小和位置,不给删的建议,说明正确清理途径
- ④ 不动(保护清单内的、在用的)——说明为什么不动
- 表格呈现,必列大小。示例:
| 项目 | 大小 | 来源 | 删除风险 | 建议 |
|---|---|---|---|---|
| ~/.cache/uv | 28G | uv 的 Python 包缓存 | 无,下次装包自动重建 | 可直接删 |
风险偏好默认规则
- 官方工具优先于 rm:
xcrun simctl delete> 删目录;brew uninstall> 删 Cellar;launchctl bootout> 直接删 plist。 - SIGTERM 先于 SIGKILL;kill 子进程不伤父会话。
- 被进程占用的缓存不强删(报 "Resource busy" 就停手),标记为"重启后再清",不 kill 占用方来抢。
- 去重前必须校验内容(MD5 或逐文件对比),内容不同就不是重复;重复留最新版本(比对修改时间)。
- 数据库、知识库和不可重建数据在删除前必须单独询问是否导出或备份;不得从历史案例推断当前用户的选择。
- 归档类按日期窗口清,默认只保留最近 30 天。
- 身份不明就先取证:查配置文件、软链、引用(zshrc/项目 .env)、Spotlight 使用时间、修改时间、PPID;还定不了就联网调研(GitHub/官网)确认来源。
- 应用仍处于安装状态就绝不删它的数据目录。
sudo 边界
不交互输密码。系统级操作(/Library、/usr/local、kext、特权助手、root 属主文件):
- 汇总成单条命令或写好带
set -x的~/cleanup-sudo.sh交给用户跑; - 预期用户可能裸跑出错(override 提示、没带 sudo),要能解释原因并指导重跑;
- 用户跑完回报后必须复查验证删干净没有。
标准流程
- 读取外部个人档案;不存在时读取随包模板。
- 扫描取证(按领域读对应 playbook,见下表)。
- 出分层报告(按报告契约)。
- 等用户拍板——模糊指令(「优化一下」「你看着办」)不算批准,追问一句。
- 执行(用户级直接做,系统级走 sudo 交接)。
- 复查:验证删净/进程死透/磁盘数字变化,汇报释放量。
- 收尾:主动问"还要看看哪个领域",或按大扫除顺序推进;把新决策写回档案。
大扫除模式:用户说"给机器做个大扫除"之类,按 性能诊断 → 磁盘 → 进程/端口 → 启动项/后台服务 → 应用 → CLI 工具 顺序逐域推进,每域单独报告、单独拍板,不合并执行。
按领域读取
进入某领域时完整读取对应文件,按其清单执行:
| 领域 | 必读文件 | 典型触发 | |---|---|---| | 性能诊断 | references/perf-diagnosis.md | 慢、发热、卡、负载高、优化性能 | | 磁盘空间 | references/disk.md | 磁盘满、空间不够、有什么能删 | | 进程/端口 | references/processes.md | kill 端口、残留进程、后台占 CPU | | 启动项/后台服务 | references/startup.md | 启动项、残留、launchd、登录项 | | 应用盘点 | references/apps.md | 盘点应用、删应用 | | CLI 工具 | references/cli-tools.md | cli/npm/brew/pip 有没有用、更新卸载 |
战役收尾
- 把本次决策写回外部个人档案:新删的、新保护/排除的、新发现的遗留项。
- 列出未拍板的遗留清单,下次战役直接从档案续。
- 动过 kext/HAL/驱动或删了大量缓存后,建议重启一次。
- 性能诊断战役用快照脚本出 before/after 对比(见 perf-diagnosis.md)。
禁止事项
- 不删:凭据、代理配置、Shell 配置引用的脚本、包管理器/版本控制配置、聊天与办公应用的数据目录,以及个人档案保护清单内的一切。
- 不删正在使用的应用的数据目录,哪怕应用本体已提议删除。
- 不强删被占用的文件;不为清理 kill 保护类进程(浏览器主进程、VPN/代理、远控、输入法、IDE、进行中的 zcode/claude 会话及其子进程)。
- 不跑笼统
npm update -g(会把比 registry 还新的包降级),升级逐包点名。 - 不清废纸篓——每次都先列内容给用户过目再由用户决定。
- sudo 只走交接,不尝试交互。
交付回报
每轮结束时报告:本轮删了什么(分类汇总)、释放了多少(磁盘前后数字)、验证结果(删净/进程退出)、还需要用户做什么(sudo 命令/重启/应用内操作)、遗留清单。没有则写"无"。