dsh-disk-canvas
把磁盘扫成一张可批注的提案:Agent 标注、你来决定、删前可预览。(DeepSeek Harness 插件)
你在 Finder / SpaceSniffer 里能看到「哪个文件夹最大」,但看不到「它是什么、删了会怎样」。
这个插件把磁盘变成一张画布:每个方块按体积占位、按风险上色,点开有判断和依据;
你的决定(保留 / 待清理 / 待复查)直接标在方块上,汇总成一份可导出的计划。
磁盘画布:左树图、右检查器
同一个目录的两种镜头:树图看「哪里大」,列表逐项过——列表视图
把画布上小到不足 1 像素的项也全列出来,可以勾选后一次处理。
它不删文件。 v0 只做分析与预览,执行权始终在你手里。
安装
dsh plugin --profile web add github:vlln/dsh-disk-canvas
装完刷新页面。升级:把上面的 add 换成 dsh plugin --profile web update dsh-disk-canvas。
- 画布入口:会话页签里的 磁盘画布(与「对话」「轨迹」并排)。
- 整理模式:新建任务时在模式选择器里选 磁盘整理——这个 preset 自带提示词与
disk_canvas_* 工具,其它模式看不到这些工具。
- 前置:macOS + dsh
0.2.1-rc.1 或兼容的 0.2.x。
两种用法
| 用法 | 入口 | 你能做什么 |
|---|
| 看与批注 | 任意会话 → 磁盘画布 页签 | 树图、检视器、保留/待清理/待复查、预览、导出 |
| 让 Agent 参与 | 新建任务 → 模式选 磁盘整理 | Agent 用 disk_canvas_scan / state / claim 扫描与标注,你在画布上改 |
页签与工具是分开的:画布在哪种模式都能打开(它只是数据视图),工具只在「磁盘整理」模式下挂载。
用起来
| 你做什么 | 画布给你什么 |
|---|
| 打开「磁盘画布」页签 | 主目录的第一层,按体积排的树图;左侧色条 = 风险(安全 / 谨慎 / 个人 / 未知 / 高危),标题行右侧是图例与各档数量 |
| 点一个方块 | 右侧检查器:这是什么、为什么、依据与把握、体积 / 占比 / 文件数 / 最近改动 |
| 在画布上拖一个框 | 框里的方块一起选中(⇧/⌘ 点方块是逐个加选),底部浮出批量条:几项、多少 GB、含几个个人内容 / 谨慎项 |
| 点批量条上的决定 | 一次给这十几项写同一个决定;比逐个点快一个数量级 |
| 点右上角列表图标 | 换成列表视图:76 项全在,包括画布上小到点不到的 42 项;行首复选框可以多选,表头复选框是全选;窗口窄了自动收起风险/占比列 |
| 点「按规则选」 | 一键选中「安全 / 谨慎 / 个人 / 未知 / 未审 / 已标待清理」整档(只作用于当前这一层),再走批量条 |
| 点右上角第三个图标(跨层索引) | 扫描时顺带记下的「按名字可清理」的目录:node_modules / Caches / dist·build·target / pycache·.venv / Logs / .Trash / DerivedData。按类分组,显示处数与合计,整组勾选后直接批量决定 |
| 双击索引里的一行 | 跳到那一层:扫它的父目录、选中它,并切回树图(检查器里也有「在画布中定位」) |
| 点第四个图标(隔离区) | 看清理脚本移走了什么:按批次列出原路径与体积、放了几天,可以逐项或整批移回原位 |
| 计划条上的「隔离区 N 项」 | 常驻入口:跑完脚本后不用去找视图,直接看到移走了多少;超过 30 天的批次会变成琥珀色并提醒清空废纸篓 |
| 在画布上滚轮 | 以指针为锚点放大到 6 倍,文字不跟着变大(放大后更多小方块会显示名字);Alt+拖 或 中键拖 平移,0 或右下角百分比复位 |
| 双击目录方块 | 进入该目录(方块放大铺满画布,再淡出成新一层) |
| 标一个决定 | 保留 / 待清理 / 待复查 + 一句备注;方块立刻变样(绿框 ✓ / 红底 ✕ / 黄虚线 ?) |
| 不选任何方块 | 检查器变成总览:审查进度、四档计数、按体积排的待审队列(点一行直接选中) |
| 点「预览清理后」 | 隐藏待清理块,看剩下的结构;磁盘没有任何改动 |
| 在索引里搜路径 | 输入 project / node_modules,只留下匹配的目录(分组自动展开,组头数字跟着变成匹配数) |
| 点「导出」 | 三个产物:清单(Markdown,汇总 + 三张按决定分组的表,给人看)、清理脚本(sh,默认演练)、JSON(机器格式) |
备注边写边存(600ms 防抖),换方块也会先把没落盘的字写掉。右上角的检查器按钮可以收起,
收起后画布占满整宽——只想想看清楚结构的时候用它。
多选时按空格 / K / D / U 会把决定应用到所有选中项;Esc 是「取消选择」,不做返回——
返回交给面包屑和「向上」。
键盘
| 键 | 动作 |
|---|
| 空格 | 循环标记:无 → 待清理 → 保留 → 待复查 → 无(多选时作用于全部选中项) |
| K / D / U | 直接标:保留 / 待清理 / 待复查 |
| Backspace / 0 | 清掉选中项的决定 |
| ← ↑ ↓ → | 按方位在方块之间移动(列表视图里是上下移动) |
| Enter | 进入选中的目录 |
| Esc | 取消选择 / 取消正在拖的框选 |
| 0 | 缩放复位(100%) |
标记直接画在方块上:保留是绿框 + ✓,待清理是红底红框 + ✕,待复查是黄虚线 + ?。
悬停 220ms 出信息卡;左上角路径的每一段都可以点回去。
颜色只用来表达语义(风险与决定),按钮和界面本身一律中性色——不然「蓝色」到底是个人内容还是主按钮,自己也说不清。
定期扫描:两条路
- 插件内定时器(齿轮菜单):关 / 每天 / 每周,宿主进程按间隔重扫上一次的根。简单、不依赖会话,但 dsh 关着就不扫。
- 走 dsh 的定时提醒:在「磁盘整理」模式下对 Agent 说「每周一扫一次」,它用
schedule 工具给当前会话
定一个提醒;到点后提醒投递回这个会话,Agent 再跑一遍扫描并汇报增量。这种方式会真正启动一次会话,
适合「想让我每周给你一份报告」而不是「只想让数据新鲜」。
两者不冲突:定时器管数据,提醒管汇报。
提案快照:把这份审查带走
齿轮菜单里的「提案快照」:
- 导出:
disk-canvas-proposal.json —— 你的决定、Agent 的判断、记住的规则(不含体积明细,很小)
- 导入:只补本地没有的——已经做过的决定不覆盖、已有的规则不重复,导入后会告诉你
「导入 N 条决定、M 条判断、K 条规则,跳过 J 条已有决定」
用途是交接:换台机器接着审、让同事在你看过的判断上继续、或者把一次审查的结论留档。
记住规则 / 自动扫描
右上角的齿轮:
- 自动扫描:关 / 每天 / 每周。开着的时候宿主进程按间隔重扫上一次的根;
启动时如果数据比间隔还旧,会补扫一次。dsh 没开着就不会扫——这不是常驻守护进程。
- 记忆规则:在索引里选中一整类,批量条上勾「记住这类」再给决定,以后扫到同类目录自动这样标。
规则只补「还没有人做过决定」的项,你手动改过的不会被覆盖;撤销规则时,会把它写下且你没改过的决定一起收回。
清理脚本:默认只演练
「导出 → 清理脚本」生成一个 disk-cleanup.sh:
- 不做 rm:把待清理项
mv 到 ~/.Trash/dsh-disk-canvas-<时间戳>/ 下的隔离目录,
并在里面写一份 manifest.tsv(名字 / 体积 / 原路径)——插件据此在「隔离区」视图里提供移回
- 默认演练:直接
sh disk-cleanup.sh 只打印会移动什么;加 --yes 才真的移动
- 已经不在的路径会跳过并提示;
/ 和 $HOME 直接拒绝;路径里的引号会被正确转义
- 脚本里同时包含「当前层」和「索引里的其他层」的待清理项——和你导出的清单是同一批
这是 v0 第一次给出「执行面」,但仍然不碰删除:移动、可逆、默认不动。
持久化与历史
扫描快照、你的决定、Agent 的标注都写在 $DSH_HOME/data/dsh-disk-canvas/ledger.json:
- 每根目录保留最近 20 次扫描 / 90 天 / 总量 ≤ 5 MB(只存顶层聚合,不存整棵树);
- 重启 dsh 后画布用上次快照秒开,不会先重扫;点「重新扫描」才更新;
- 标注按路径全局保留,换目录、换会话、重启都还在;
disk_canvas_history 让 Agent 读历史与增量("这周哪个目录在涨")。
扫描是插件的持久周期,会话只是某次审查;关掉会话不影响账本。
能力面
Preset
| 模式 | 说明 |
|---|
| 磁盘整理 | 自带提示词的磁盘审查 Agent:只分析、标注、预览;工具只有 disk_canvas_*,没有 shell / 删除能力 |
Tools(只挂在「磁盘整理」模式)
| 工具 | 说明 |
|---|
disk_canvas_scan | 扫描一个目录(默认主目录)的直接子项,返回体积最大的若干项与规则标注 |
disk_canvas_state | 读当前画布状态:计划、条目、你的决定 |
disk_canvas_claim | 给某路径写一条判断(风险档 + 把握度),不执行删除 |
disk_canvas_history | 读账本里的历史扫描与增量(最多 20 条) |
preset 里还有官方只读文件工具:read / read_image(dsh-tool-fs 关掉 write/edit)、
glob / grep(dsh-tool-fs-search)。没有 shell、没有写/删工具。
安全与数据
- 只读:没有任何删除、移动、压缩接口;导出的计划由你自己执行。
- 本地:扫描在宿主进程内完成,不发网络请求、不上传路径或清单。
- 落盘但只在本地:扫描快照、决定与标注写在
$DSH_HOME/data/dsh-disk-canvas/ledger.json,不上传、不同步。
- 诚实:没有证据的项标
unknown,不会把「不确定」包装成「安全」。
- 同源:写面(scan / annotate)校验
Origin 与 Host,并限制请求体大小。
已知限制
- macOS 首版;Linux / Windows 未验证。
- 只扫当前一层(双击下钻)。首次扫描边扫边出(100 GB 级主目录约 15–60 秒),单个超大目录可能被条目/时间预算截断并标「部分结果」,不假装扫完。
- 不解析压缩包、虚拟机镜像、快照内部;容器只当普通文件。
- 「永久保留」目前是单次会话内的批注,不是跨会话规则(规则泛化在路线图上)。
- 规则推断基于路径与时间,不是文件内容;对未知目录保持沉默。
- 五档风险里
personal(个人内容)与 unknown 只是分类,不是「可删」;只有你标记的才算决定。
- 不提供回收站 / 隔离区 / 撤销——因为它们属于执行面,v0 刻意没有执行面。
- 历史只保留顶层聚合;要看更早的变化需要在账本上限内重扫。
- 画布面积严格等于体积:小项会小到不足 1 像素(真实主目录里 76 项有 42 项如此),
树图上点不到——列表视图里全都有。这不是 bug,是单层树图对「少量大项 + 长尾小项」的诚实表现。
- 跨层索引是按目录名匹配的(node_modules / Caches / dist / build / target / pycache / .venv / Logs / .Trash / DerivedData),
不是全量文件索引:同名但实际用途不同的目录会进索引(所以 build/target 那组标的是「谨慎」),
反过来名字不在规则里的目录不会被收进来。每组最多展示前 200 条,合计仍按全部算。
- 规则可以在齿轮菜单里导出 / 导入(
disk-canvas-rules.json),换台机器把习惯带走;导入是整体替换。
- 记忆规则按目录名生效,不是按路径:它会在每次扫描后给新出现的同类目录补一个决定(
by: rule),
所以规则开着的时候,扫描会顺带改写一批标注——这是「记住」的含义,撤销规则可以整体收回。
- 自动扫描依赖 dsh 进程活着;没有后台常驻,也没有系统级 launchd 定时器。
- 清理脚本只做「移动到废纸篓」,没有「恢复」按钮——恢复要靠废纸篓自己。
隔离目录没有 30 天自动清理(产品文档里的目标形态),现在是手动的;插件也不会替你清空废纸篓。
- 移回原位时如果原位置已经有同名项,会拒绝并提示——先处理冲突再试。
- 扫描预算:每个直接子项 200 万条目 / 40 秒,全局 90 秒。预算定得太小会让同一个目录每次扫出不同体积
(结果取决于 readdir 顺序),这条踩过坑——被截断的项在检查器里用
≥ 标出来。
- 缩放是几何 + 语义两层:方块和间距按倍率放大,文字/内边距反向缩回去,所以看起来字号不变;
上限 6 倍,不做动画补间。
兼容性
| dsh 版本 | 状态 |
|---|
0.2.1-rc.1 | ✅ 已验证(2026-10-18,真实安装并启动 web profile;页签、preset、工具注册) |
| 其它 0.2.x | ⚠️ 未验证——升级 dsh 后若页签消失,多半是 conversation.view 槽名或 preset 字段变了 |
插件管理
装/卸/启停用官方 CLI:dsh plugin --profile web add|remove dsh-disk-canvas;已装插件在
侧边栏 Plugins 页里查看与配置(Settings 里的「插件」只是只读清单)。
许可
MIT。交互契约见 docs/contract.md。