前言¶
DSH 的侧边栏自带归档,但没有真正删除会话的入口:想丢掉一个误开的会话,只能让它躺在归档里继续占磁盘。删掉一个工作区更干脆,磁盘上的会话不受影响,只是 cwd 再也匹配不到任何已注册工作区,侧边栏连列它的地方都没有。工作区一多,侧边栏也是一长条平铺,没有分组。
dsh-session-hygiene 就是补这三处缺口的插件。它由 liudapeng0311 维护,分类 admin-security,社区目录上 Star 为 0,功能不代表成熟度未经广泛验证,源码可以直接读。
这是什么¶
一句话定位:给 DSH 的会话生命周期补上三件事——可恢复的删除、孤儿会话清理、工作区分类。作者在 README 里强调,插件全程是增量式的:不替换或隐藏任何内置行,也不改写这些组件以外的 DOM,卸载后侧边栏回到 shell 原始渲染状态。
三个触发点分别落在:
- 会话行的
...菜单:新增 Delete session (to trash)。 - Settings → Session cleanup:扫描孤儿会话,支持归档、移入回收站、恢复、永久删除。
- Settings → Workspace categories:新建分类,侧边栏显示分组标题,支持拖拽分配与折叠。
核心功能¶
删除会话进回收站,而不是直接 unlink¶
在侧边栏把鼠标放到某个会话上,打开 ... 菜单,选择 Delete session (to trash)。会话行立即从列表消失,但数据只是被移动。
底层步骤按顺序是:先停掉正在运行的任务并隐藏该行,再把会话 id 从所有工作区解绑并取消 pin,然后把 <home>/sessions/<group>/<id>/ 整个目录改名移进回收站,同时记录一条 preview,并通过 api-session/removed 让已打开的页面无刷新地丢掉这一行。投影缓存(projection cache)会保留,所以恢复回来的会话还能显示原来的标题和开场提示。
如果移动报 “the session data is still in use”,说明还有另一个视图占着这个目录,切到别的会话再试。移动失败时归档会回滚,会话照原样显示。
清理被删掉工作区留下的孤儿会话¶
打开 Settings → Session cleanup,页面打开时就扫描,Rescan 可以重新扫。
Orphaned sessions 的定义是:header.cwd 匹配不到任何已注册工作区的已存储会话。每一行显示标题、开场 preview、原属工作区、目录名和大小。处理方式有三种:
- 逐行 Move to trash。
- 批量 Archive N:放进 shell 的归档里,跳过 subagent 会话(通常由父会话持有)。
- 批量 Move all to trash:包含 subagent,会要求二次确认。
另有一类 Detached 会话:cwd 匹配的工作区存在,但那个工作区没有把这个会话列进去,所以侧边栏把它归到了 Ungrouped。它们显示在标签页上方的一条 strip 里,提供 Attach all,比删进回收站更省事也更安全——会话本身是健康的。
回收站:恢复或永久删除¶
Trash 标签页列出被移入的内容:
- Restore 把目录改名回记录中的路径,并重新挂到拥有该
cwd的工作区。如果原路径已经被占用,会返回409拒绝,得先挪走或删掉占用物;如果原工作区已不存在,会话以未分组状态回来,因为没有任何工作区认领它的cwd。 - Delete permanently 会 unlink 目录并丢掉投影缓存条目。这是唯一不可逆的操作,界面会指明具体删除什么,且需要再点一次确认。
工作区分类¶
打开 Settings → Workspace categories:
- Add category,可直接内联重命名,用 ↑/↓ 调顺序,Delete 删除分类后,其下工作区自动回到未分类。
- 通过下拉框给工作区分配分类,或者在侧边栏把工作区行拖到某个分类标题上。
- Save and regroup 写入分配结果,并重排工作区注册表,使每个分类的行连续排列,未分类工作区排在最后。内置的拖拽排序仍然有效,插件只在保存时重排。
- Clear assignments 把所有工作区打回未分类,但不删除分类本身。
- 点击标题可以折叠/展开分类,折叠状态会被记住。Show category headers in the sidebar 开关可以只隐藏分组条而不取消分配。
一个分类只有在行连成一块时才会显示标题;被拆开时它宁可不显示标题,也不在归属别的分类的行上面放标题。分组条是插件自己挂上去的节点,插件移除后侧边栏完全复原。
安装与启用¶
插件发布在 npm registry 上,可以在 DSH 的 Plugins 页面安装,也可以通过 agent:
plugin_manager install_bundle dsh-session-hygiene
如果要装本地 checkout,传它的绝对路径:
plugin_manager install_bundle <path to this checkout>
插件的 host 端 JavaScript 不热重载,装完需要重启一次 host。卸载在 DSH 的 Plugins 页面移除 bundle 即可,侧边栏的分类条会立即消失。
一个实务提醒:卸载前请先把回收站清空或恢复。插件移除后 <home>/storages/session-hygiene/ 目录仍然留在磁盘上,但回收站里的会话已经没有任何 UI 能恢复,只能照着各自的 entry.json 手工把目录改名回去。
典型用法¶
下面按 README 的路径走一遍最常见的清理流程。
1. 删掉误开的会话,之后又后悔¶
侧边栏找到会话 → ... 菜单 → Delete session (to trash) → 打开 Settings → Session cleanup → Trash 标签页 → 选中那行 → Restore。
2. 清理删掉工作区后残留的大量孤儿会话¶
先 Settings → Session cleanup 看 Orphaned sessions 列表,确认不是误判(见下面的已知限制),再选择批量 Archive N;确认不会再用,再选 Move all to trash,按提示二次确认。subagent 会话请保留在归档之外,它们是父会话的一部分。
3. 把工作区按项目归类¶
Settings → Workspace categories → Add category → 用工作区行的下拉框或侧边栏拖拽做分配 → Save and regroup。之后侧边栏会出现带标题的分组条,点标题折叠。
数据落在哪里¶
插件只写 <home>/storages/session-hygiene/ 这一处:
<home>/storages/session-hygiene/
categories.json
trash/<sessionId>__<stamp>/
entry.json
session.v4.jsonl.zstd ...
entry.json 记录 sessionId、cwd、from(原目录)、title、preview、createdAt、sizeBytes、deletedAt。这是插件唯一自己创建的文件,也是恢复能力的来源。想手工清空回收站,删掉这个目录树即可。投影缓存是派生产物,进回收站时刻意保留,永久删除时才一并清除。
适用场景与注意¶
适合这类人:在 DSH 里把工作区当项目用、会话数量已经上百,删工作区时想顺带处理掉它留下的会话,并且希望删除动作有后悔药。
需要注意几点:
- 插件以当前 dsh 进程的权限运行,安装前先读一遍源码和许可证再启用。本插件许可证为 MIT,仓库地址见文末。
- 已知限制:孤儿判定拿
header.cwd和工作区注册表记录的目录对比,磁盘上把目录改名过的会话会被误判成孤儿;删除工作区时仍然不会提前警告它有多少会话,插件只在事后把它们列在 Settings 里,因为要拦内置删除流程就得接管sidebar.workspaces这个 shell 所有的singleslot;subagent 会话会单独标记、不进 Archive N,但会进批量回收站;分类标题依赖行连续,单行分类中间插入行会按上方标题猜,未必准确;host 端 JS 不热重载,安装或更新后都要重启。 - 此插件是社区目录(独立站点)上的第三方包,与 DeepSeek / 幻方没有官方从属关系。
结尾¶
dsh-session-hygiene 做的事很收敛:把删除变成可恢复的移动,把删掉工作区留下的孤儿暴露出来,再给侧边栏加上分组。三件事都是加法,不改变内置行为。你如果正在被会话堆积和离散工作区困扰,值得试一轮;如果只是想先看看实现,entry.json 的字段设计和 README 里的槽位表都写得比较清楚。
- 目录页:https://www.skillhub.cn/plugins/liudapeng0311/dsh-session-hygiene
- GitHub:https://github.com/liudapeng0311/dsh-session-hygiene