dsh-tui-find
September 19, 2026 · View on GitHub

dsh-TUI 的跨会话全文搜索插件 —— 对本机全部 dsh 会话(zstd 帧链 + 明文 JSONL)做即时增量搜索:命中可读、可复制、可恢复会话。
English · MIT · 零第三方运行时依赖
这是什么
dsh-TUI 有 resume 浏览器、会话内 / 搜索与 Ctrl+R 输入历史,但没有跨会话内容检索——对话滚出当前窗口就成了不可搜索的档案。本插件补上这一块:
- 即时:fzf 式纯内存过滤,结果流式渐进出现;多词 AND、JS 正则、拼音(全拼/首字母)、标题限定、时间窗口。
- 可读可复制:split 分栏(左列表 · 右内容,/resume 同款风格)或全屏预览,锚定命中消息、命中词高亮,一键复制原文或日志路径。
- 可恢复:
↵恢复会话,二次确认;右键上下文菜单(仅 0.10+ 宿主)。
安装
dsh plugin --profile dsh-tui add -w dsh-tui-find@latest
--profile 换成实际 profile 名($DSH_HOME/profiles/ 下的目录名,未设 DSH_HOME 时为 ~/.dsh)。CLI 把包收录进 profile 的 bundle 列表并自动应用包内 cordis.patch.yml,无需手动改配置;安装 / 升级 / 卸载后需重启 dsh-TUI(或 /restart)生效——宿主 /reload 不重载插件代码。
本地开发安装:npm install && npm pack(prepack 自动构建并跑全量测试),然后 dsh plugin --profile dsh-tui add -w ./dsh-tui-find-<版本号>.tgz;不要直接安装源码目录。
升级与卸载
升级:重跑安装命令(幂等);版本未变先 npm cache clean --force,重启后用 /plugins 验证。
卸载:dsh plugin --profile dsh-tui remove -w dsh-tui-find,重启生效。若 profile package.json → dsh.profile.bundles 仍残留条目(CLI 版本差异),手动删除即可;/settings 保存过的设置留在 settings.yaml、重装后继续生效,想归零删除 dsh-tui-find 命名空间键。卸载只影响本插件:会话数据全程只读、不受影响。
使用
| 操作 | 说明 |
|---|---|
/find <关键词> | 带参直接出结果(空格分隔多词) |
/find | 空参进全屏搜索场景 |
Alt+F | 全局入口快捷键(shortcut 配置可改键或 off 关闭) |
场景内按键:
| 键 | 动作 |
|---|---|
| 任意字符 | 即时过滤;空查询列出最近会话 |
Tab / Alt+T | 切换范围(本仓库 ⇄ 全部)/ 时间窗口(全部 ⇄ 近 7 天 ⇄ 近 30 天) |
Alt+R / Alt+N | 切换正则匹配 / 仅搜索标题 |
↑↓ / PgUp PgDn | 条目间移动 / 翻页 |
→ / ← | split 布局:右移聚焦右栏阅读窗,左移回到列表(阅读窗始终在屏上,无需打开/关闭) |
Alt+P | classic 布局:打开全屏预览(锚定命中消息、命中词高亮);阅读窗内 ↑↓ 逐行滚动、PgUp/PgDn 翻页、n/N 命中跳转(循环回绕)、滚轮按档滚动 |
Alt+C / Alt+E | 复制命中原文(预览内为当前命中:n/N 停驻的那条,或自由滚动后视口上方最近的一条;该会话没有命中时回退为视口顶部那条消息)/ 折叠、展开当前会话命中(与行尾 ▸ (+N) 徽标同一动作) |
Alt+H | 键位帮助面板 |
↵ / Esc | 恢复会话(二次确认)/ 清空查询、返回、退出场景 |
鼠标:左键选中、悬停高亮、滚轮按宿主同样的档距移动选择(一档 ≈ 3 行;在阅读窗内则按档滚动阅读窗);命中超过 3 条的会话在最后一条命中行右端显示 ▸ (+N) 徽标,点它即展开该会话全部命中(展开后同一位置变 ▴ 收起,箭头转向表示"折回去",悬停时徽标带背景高亮——这是唯一一个不跟随整行点击的控件,整行点击仍是"选中并进入恢复确认");右键开上下文菜单(仅 0.10+ 宿主):复制消息文本 / 复制会话日志路径 / 恢复该会话。
场景布局由
layout配置选择:split(默认)在终端 ≥ 100 列时同屏显示"左侧列表 + 右侧会话内容阅读窗"(与 /resume 浏览器同风格)——选中项自动锚定右栏、右栏可独立滚动/复制/右键,→聚焦右栏、←回到列表(Alt+P在 split 下不再使用),窄终端自动回退单栏;classic维持"单栏列表 +Alt+P全屏预览"。
阅读窗是只读视图,没有光标:
↑↓直接逐行滚动、PgUp/PgDn与滚轮按档滚动,n/N跳到视口之外的上一个/下一个命中(循环回绕)——选中在只读预览里没有意义,所以窗口本身就是位置。因此同一屏永远只有一处选中高亮:左栏持焦点时右栏不带任何强调,→聚焦右栏后边框点亮、左栏仍保留自己的高亮。两种形态下阅读窗都保证命中词在视口内:命中落在消息深处(视口装不下)时直接在命中行开窗,而不是停在看不到关键词的消息头。提示行也按宽度取词:先丢低优先键(滚动与返回键永远保留),极端窄终端再截断兜底,任何宽度都严格占一行,不会换行挤掉内容行。
结果按会话分组、每会话默认展示前 3 条命中(
(+N)提示),最近优先;场景打开即开始扫描,结果随会话解析流式出现,头部实时显示进度。
启动约 10 秒后插件在后台预建一次索引(
warmup配置可关),此后首次/find即刻出列表;0.10+ 宿主在提示符上方显示"后台索引 n/m"进度行,点按即取消。预热只把冷解码挪到空闲期,不减少总解码量。
默认快捷键是
Alt+F而非Ctrl+Shift+F:主流终端把后者留给自身的"查找"功能并截获按键。冲突时用shortcut配置改成任意含Ctrl或Alt的组合键。
检索范围
- 索引:用户消息、助手文本、会话标题;
indexTools开启后含工具调用摘要,indexThinking开启后含 thinking 文本。 - 匹配:默认大小写不敏感子串(CJK 天然正确,无分词依赖);多词 AND(双引号短语保留内部空格、至多 16 词);正则模式下整个查询是一个模式、不拆词。
- 拼音(默认开,
pinyin可关):纯字母词同时按拼音匹配汉字——全拼(zhangsan→ 张三)、默认读音链(zhongqing→ 重庆)、首字母(zs→ 张三、bjdx→ 北京大学,一个字母对一个字、可跨词连续);全拼从音节起点匹配(不会把上一音节的尾字母接到下一字首字母),首字母则按你打字的样子连续拼接;多音字按全部读音参与、ü 按键盘习惯写作 v;内置 3500 常用字读音表,表外字按自身折叠;正则模式不扩展拼音。 - 标题限定(
Alt+N即时切换):只匹配会话标题、消息正文不参与——适合"找那个会话";无标题会话不命中。 - 默认范围:本仓库(按会话 cwd 匹配当前工作目录,与 resume 浏览器同语义,含子目录会话)。
配置
在 cordis.patch.yml 的插件行上覆盖(全部可选):
- insert:
- id: dsh-tui-find
name: 'dsh-tui-find'
defaultScope: 'all' # 初始范围:repo(默认) | all
defaultTime: 'all' # 初始时间窗口:all(默认) | 7d | 30d
layout: 'split' # 界面布局:split(默认,左列表+右阅读窗,需≥100列) | classic(单栏+全屏预览)
caseSensitive: false # 大小写敏感匹配(默认关)
regex: false # 默认启用正则匹配(默认关;场景内 Alt+R 即时切换)
pinyin: true # 拼音搜索(默认开;纯字母词同时按全拼/首字母匹配汉字)
titleOnly: false # 仅搜索标题(默认关;场景内 Alt+N 即时切换)
indexTools: false # 索引工具调用摘要(默认关)
indexThinking: false # 索引 thinking 文本(默认关)
sessionRoot: '' # 手动指定会话根目录(默认自动探测)
maxMessageChars: 4000 # 单条消息索引字符上限
warmup: true # 后台预热索引(默认开;关闭后 /find 打开时才扫描)
lang: 'auto' # zh | en | auto(跟随宿主语言)
shortcut: 'alt+f' # 全局入口组合键(必须含 ctrl 或 alt;'off' 关闭全局入口)
除 lang 外的选项都可以在 TUI 内直接改:/settings → dsh-tui-find(会话搜索) 卡片。布尔/选择项一改即存,文本项回车确认,写入宿主设置服务的用户层并按层级覆盖插件行默认值;卡片文案跟随 TUI 语言。
lang: auto 跟随 dsh-TUI 语言链:DSH_TUI_LANG → ~/.dsh-tui/lang.json → 系统 locale → 中文,/lang 切换即时生效。
会话根目录按序探测(首个命中即用):sessionRoot 配置(排他覆盖)→ DSH_TUI_SESSION_ROOT 环境变量 → $DSH_HOME || ~/.dsh + /sessions → ~/.dsh-tui/sessions。
隐私与安全
- 全程只读:只读打开会话日志,不触碰 history lock,不改写历史。
- 世代命名:dsh 的会话日志按格式世代命名(
session.jsonl、session.vN.jsonl,各有.zstd压缩变体)。同一会话目录取编号最高的世代、同世代内压缩版优先——迁移窗口里并存的旧世代日志不会被索引。 - 落盘最小化:对话内容只存内存、绝不落盘。唯一例外是水位日志
~/.dsh-tui/dsh-tui-find/watermark.json——仅记录路径与字节/修改时间/偏移等元数据、绝无对话文本(0700/0600 + tmp+rename 原子写,DSH_TUI_FIND_WATERMARK=off可关)。 - 增量解码与容错:追加只解新增帧、同尺寸触碰零解码,缩水/改写/编码翻转自动回退全量;不完整尾帧按 RFC 8878 结构校验跳过,不崩溃、不残留。
- 恢复需确认:恢复是丢弃当前上下文的破坏性切换,
↵二次确认,当前会话工作中给醒目警告。
开发
npm install # 开发依赖
npm run build # tsc → dist/
npm test # pretest 自动构建并生成 fixture,vitest 全量
npm run verify:hosts # 双宿主矩阵:隔离副本换宿主包,0.9.3 与 0.10.1 各跑一次 build+test
测试覆盖(353 项):帧链解析、扫描器(mtime 缓存复用、水位增量解码、世代命名枚举)、搜索(多词 AND / 正则 / 拼音含跨词首字母 / 标题限定 / 时间窗 / 范围过滤)、折叠构建与冻结旧实现的逐字段等价对照、折叠的内存表示(缓存的是扁平串而不是逐码点拼接出来的 ConsString 绳,按保留堆断言)、预览阅读器(含命中落点开窗、输入即重定位、无光标逐行滚动、窗口基准的 n/N、Alt+C 的当前命中选取与提示行按宽度取词且严格一行)、键位帮助(按布局取词、鼠标折叠徽标)、场景接线(真实宿主渲染器 + SGR 鼠标注入与右键派发,含 split 分栏布局、←/→ 焦点移交、选择锚定、宽度回退、滚轮步幅、徽标折叠不触发恢复与折叠后悬停不落到邻卡)、宿主代际分派、事件清洗、显示宽度、准入与真实 fiber 挂载、启动竞态防护、后台预热索引(预算/中止/缓存键形状/表下界)与 tuiStatus 进度视图。
环境要求
- dsh-TUI v0.9+(v0.15 community-draft 插件体系)。0.9.x 与 0.10.x 双版本验证(
npm run verify:hosts);0.10-only 能力一律软探测 + 优雅降级,不强制升级宿主 - Node
^22.19 || >=24;Windows / macOS / Linux
许可
MIT