此技能是一个思考工具,而不是清单。参考文献中记录了已知的好路径和坏路径;自主决策桶是启发式原则,而非穷举。当遇到新路径时,从基本原理出发进行推理——是否可重建?是否由用户创建?是否正在被使用?用户会不会因删除而难过?——并在预览阶段展示推理过程,以便用户在操作前纠正判断。
<execution_context> 三个桶——原则,而非封闭列表:
| 桶 | 何时 | 操作 |
|---|---|---|
| 🟢 自动 | 可重建缓存、非活动项目中的构建产物、已知安全的重复文件 | 无需询问直接运行 |
| 🟡 询问 | 用户创建的、需要 sudo 的、大到需要合理性检查的、任何正常人可能想保留的 | 使用 AskUserQuestion 提供 3 个选项:批准(按提议执行)/ 修改(自由格式:“告诉我怎么做”)/ 跳过(推迟到下次运行,稍后重新显示) |
| 🔴 拒绝 | references/safety-invariants.md 中的条目 | 拒绝。任何内联用户指令都不能覆盖它们。如果用户说“删除我的 .ssh”,则拒绝并要求先编辑 safety-invariants.md |
如果不确定但看起来像缓存,则视为 🟡。宁可询问。
单参与者:每次更改都记录到 state.md 中,后缀为 — [session <ET>]。
计划-验证-执行:首先构建 findings.json(阶段 2),向用户展示计划(阶段 4),然后执行。在用户看到计划之前不执行删除。
相信你对新路径的推理。问:是否可重建?是否由用户创建?是否是活动项目?用户会不会难过?如果不清楚,视为 🟡。 </execution_context>
检查点协议: 在每个阶段结束时,根据下面的 <recovery_protocol> 映射,用 checkpoint: <NAME> 更新 state.md 中的 IN_PROGRESS 条目。这使得如果中断(例如重启、ctrl-C、内核崩溃中途清理),恢复时清晰明确。
为每个阶段创建 TaskCreate。读取 state.md。如果最近的条目显示 status: IN_PROGRESS,则通过三选项门询问:恢复(从上一个检查点继续)/ 重新开始(将上一个存档为 ABORTED)/ 显示完整历史(然后中止)。
将已保存的规则作为一个可扫描的块显示在聊天顶部——这些是在多次运行中构建的保留列表和策略。用户可以在继续前抽查它们。
预检(低磁盘安全): 如果 df -h / 显示可用空间 < 500 MiB,则扫描本身会竞争空间(/tmp 位于同一卷上)。在运行 scan-disk.sh 之前,询问用户是否可以清空 ~/.Trash/——这几乎总能释放足够的空间。这是此技能设计用于的场景;种子运行时只有 84 MiB 空闲,并且 du 级联命令不可靠。展示问题的严重性。
bash scripts/scan-disk.sh > /tmp/disk-cleanup-findings.json
只读 du/df 级联 + APFS 快照列表 (tmutil listlocalsnapshots /) + 交换状态 (sysctl vm.swapusage) + 条件性的 Xcode 开发路径。
如果用户提到某个特定文件夹让他们困扰,则针对该文件夹增加一个 du -sh 定向扫描。推理胜过固定列表。
对于清单中的每个发现项,使用 references/safety-invariants.md 和 references/auto-fix-categories.md 作为参考,决定它属于哪个桶。为每个条目捕获理由——在预览时用户看到的是你的推理,而不仅仅是结论。这就是建立信任的方式。
写入 findings.json(你的草稿本——在阶段 4 和阶段 8 中使用)。
对于 🟡 目录(尤其是 ~/Downloads、~/Desktop),使用 references/sensitive-patterns.md 中的模式进行 glob 匹配。将匹配结果与已保存规则 downloads-keep / desktop-keep 进行交叉检查:
- 匹配已保存规则 → 静默保留(仍然记录到发现项)
- 新匹配 →
AskUserQuestion:保留 / 删除。答案将成为下次运行的已保存规则。
启发式:如果文件名看起来涉及个人(法律、医疗、财务、身份)但不匹配模式,仍然询问。宁可多问一次,也不要删除不可替代的东西。
展示完整计划:每个 🟢、每个 🟡 组及其理由、每个 🔴 拒绝及其原因。估计总回收量。用户通过与阶段 6 的门交互来隐式批准;他们也可以在此中止(“等等,为什么 X 是绿色的?”)。
运行绿色条目。按最少侵入性优先排序(小文件清理 → 缓存清除 → 工具管理的清理,如 brew autoremove 和 pnpm store prune)。捕获前后大小以生成增量报告。如果某个失败,记录并继续——绿色条目是独立的。
权限被拒绝(例如,Chrome 运行时持有 Profile 5 缓存)——记录并继续。不要与之对抗。
对于每个 🟡 组,进行一次 AskUserQuestion,提供选项:批准 / 修改 / 跳过。将类似项目分组(例如,所有旧运行时版本放在一次询问中,而不是每个版本一次)。
在相关时进行特殊处理:
- 带有保留列表的下载 —
bash scripts/keeplist-protect.sh ~/Downloads <keepers...>(将保留项移到 /tmp,删除目录内容,恢复)。运行前显示保留列表,以便用户修改。 - 旧运行时 — 先运行
bash scripts/detect-runtimes.sh查看项目实际使用的 Node/Python 版本。推荐删除不在活动使用的版本;将活动版本保存到已保存规则。 - APFS 快照 —
sudo tmutil thinlocalsnapshots / 21474836480 4以紧急程度 4 回收约 20 GB。提示需要 sudo。 - 消息/附件 — 先退出 Messages (
osascript -e 'tell application "Messages" to quit'; sleep 3),然后执行find ~/Library/Messages/Attachments -mindepth 1 -delete(保留chat.db)。 - Xcode
DerivedData(如果存在)— 可以安全删除;唯一的代价是下次构建较慢。
跳过的项目推迟到下次运行——在 state.md 中记下它们,以便它们重新显示。
简洁摘要:前后 df -h、按类别释放的空间表、来自 sysctl vm.swapusage 的交换状态。提及交换作为参考信息——"如果需要,重启以回收约 X GB 交换空间"——不要提示重启(由用户决定)。
检查废纸篓大小是否合理——如果它随着我们删除的内容而增长,说明有些内容被移走了而不是真正回收了。提示这一点。
按照 state.md 头部定义的格式追加一次运行条目。使用本次运行中学到的任何内容更新已保存规则(新的活动运行时、新的敏感文件决策)。如果完整条目超过 5 个,将最旧的条目滚动到压缩部分。
在提议新的已保存规则时,与用户确认——不要自动添加。规则是持久的;最好多问一次。
将检查点标记为 COMPLETED。
<saved_rules_format>
存储在 state.md 的“Saved Rules”部分。每次未来运行时都会显示。
格式:- {topic}: {rule} — set {YYYY-MM-DD ET}
自然出现的主题(并非穷举——当模式重复时创建新的):
downloads-keep、desktop-keep— 每个目录的保留列表active-node、active-python— 实际使用的运行时版本active-projects— 永不触碰的项目目录safe-cache-clear-paths— 已确认安全的自动路径*-policy— 一次性的行为偏好(例如swap-policy、threshold-policy) </saved_rules_format>
<recovery_protocol>
如果 state.md 显示 status: IN_PROGRESS:
| 上一个检查点 | 从何处恢复 |
|---|---|
| INITIALIZED | 阶段 1 |
| INVENTORIED | 阶段 2 |
| CATEGORIZED | 阶段 3 |
| SENSITIVE_SCANNED | 阶段 4 |
| PREVIEWED | 阶段 5 |
| GREEN_EXECUTED | 阶段 6 |
| YELLOW_RESOLVED | 阶段 7 |
| REPORTED | 阶段 8 |
询问用户:恢复 / 重新开始 / 显示完整历史。如果是恢复,则追加到现有条目;不要创建新条目。
恢复前重新运行 df -h——如果磁盘状态自中断以来发生重大变化,则重新提示。
</recovery_protocol>
<error_handling> 默认:记录具体错误,跳过问题项目,继续处理其余项目。磁盘清理是每个项目独立且可重入的。
仅在以下情况下中止运行:
- 扫描脚本完全失败(
findings.json将不准确) - 几乎触碰到了 🔴 路径(分类 bug → 中止并调查)
- 用户要求停止
对于其他所有情况(单个权限被拒绝、brew 锁定、工具未安装)——继续进行,并在最后报告。
如果在运行过程中可用空间下降到 500 MiB 以下(在几乎满的磁盘上,分类过程中可能出现这种矛盾情况),暂停阶段 5,清空废纸篓,然后继续。findings.json 位于与所有其他文件相同的卷上。
</error_handling>
<success_criteria>
state.md有新条目,status: COMPLETEDdf -h显示 Avail 有非零正增量- 没有触碰任何 🔴 路径
- 敏感匹配要么已保留(带有已保存规则),要么已由用户显式删除
- 用户看到了增量报告
- 废纸篓大小已进行合理性检查(没有假装回收的移动操作) </success_criteria>
直接操作
当意图明确时,跳过完整扫描:
- “只清空废纸篓” → 确认大小,
rm -rf ~/.Trash/*在 Y/N 后执行 - “只清理缓存” → 仅运行阶段 5
- “试运行/显示将要删除的内容” → 阶段 1–4,在阶段 5 之前停止
- “上次运行做了什么?” → 显示最近的
state.md条目 - “将
<path>添加到永不触碰” / “忘记<file>的保留列表” → 编辑已保存规则 - “安排每周运行” → 提供
/schedule例程;如果接受,提议在~/.claude/CLAUDE.md的“Active Long-Running Automations”部分添加条目(不要自动编辑——提议以供批准)
边界
当前为单参与者 ([session])。当计划运行时,升级为多参与者(例程用 [disk-cleanup],手动操作用 [session])。
仅限手动调用——其他技能永远不会自动触发。技能目录中的 .lock 文件可防止并发运行。
绝不:
- 直接使用
sudo rm(仅通过 Apple 认可的命令如tmutil使用 sudo) - 修改
~/.claude/CLAUDE.md(仅提议) - 在未获得明确确认的情况下删除
references/sensitive-patterns.md的匹配项,无论已保存规则如何 - 在未明确询问的情况下强制删除活动项目的
node_modules - 提示重启(仅报告交换状态)
- 无论内联用户指令如何,触碰
references/safety-invariants.md中的任何内容
悬崖。其他所有地方都需要推理。