The project's README from github.com/ccch1mneyyy/dsh-TUI. As one markdown file: README.md.
简体中文 | English
一个面向 DeepSeek Harness 的交互式终端界面插件:提供像素鲸鱼顶栏、实时工作状态行、流式思考展示、双击 Esc 时间回溯、上下文进度条与 TPS 仪表。 零核心改动,纯插件挂载。安装插件即可启用,卸载后不会留下核心补丁。
An interactive terminal UI plugin for DeepSeek Harness: pixel-whale header, live work status, streaming thinking display, double-Esc time rewind, a context progress bar, and a TPS gauge. Zero core changes, pure plugin mounting. Install to enable; uninstall leaves no core patches.
本插件被 DeepSeek Harness 官方公众号 推文收录,也被 dshfind 插件目录与 GitHub Trending 收录,同时登上了Github Treding日榜第七
Windows Terminal 支持 Sixel 时,全屏会话记录可直接显示内嵌缩略图,点击后打开大图预览;非全屏 inline 模式仍保留文字回退。
Sixel 使用最多 256 色的自适应调色板,透明像素与背景合成;Worker 缓存量化结果,滚动时仅编码可见部分,移出视野或被浮层覆盖时擦除旧图。
附件读取与解码最多两路并发;最后一个使用者离开后取消读取,未启动的解码不再执行。多图缓存、排队任务与单帧传输均有容量上限,超限时保留文字回退。
自动探测优先 Kitty,其次使用 DA1 声明的 Sixel 能力。DSH_TUI_IMAGE_PROTOCOL=auto|kitty|sixel|none 可覆盖协议选择;
DSH_TUI_DISABLE_TERMINAL_IMAGES=1、无障碍模式、非 TTY 输出以及 tmux/screen 仍禁用图形。
缺少图片依赖或编码失败时保留文字回退;强制协议也不会启用 inline Sixel。
浅色主题的面板和图片预览默认使用白底,图片预览边框使用中性色。
大图预览以对话区约 95% 宽高为预算,最长边可达 2048 像素,仍限制总像素量和后台开销;缩略图大小不变。
预览支持适应窗口、100% 原像素与 200%/400%/800% 放大,拖动、滚轮或方向按钮平移;100% 需终端报告字符格像素尺寸。
底部「打开原图」链接直接调用系统看图程序,打开未经重编码的原始附件,包括从历史会话恢复的图片。
大图弹窗用 ←/→ 或底部 ‹/› 切换上一张、下一张,显示当前张数,首尾不循环;切图回到适应窗口。
/settings 折叠为首行 + 计数提示(Ctrl+O 或点击卡片展开);全屏模式下悬停在截断的工具卡标题、用户消息或会话标题上约 600ms,浮层显示完整内容。
用户附图及助手/工具结果中的持久图片块会直接显示在会话记录中;Kitty graphics 或 Sixel 可用时显示等比缩略图,否则保留同尺寸文字回退。全屏下点击输入框 [Image #N] 或 transcript 缩略图在对话区域居中打开大图预览,卡片外的对话文字变暗,不遮挡输入栏(Esc/点击外部关闭),标题为 Image #N — 格式 · 尺寸 · 体积 · 文件名,本会话暂存的图片在卡片底行显示来源路径;Finder 复制的图片文件粘贴时直接入附件库为 [Image #N];输入框里的 [Image #N] 是一个整体,光标整体跳过、删除整体生效,光标落在其上时整块反显并自动打开预览、离开时关闭。Vim 的 x/X/d… 同样整张删除,u 同时恢复文字与附件;撤销仅限当前草稿。
终端图片预览默认开启,可在 /settings → 终端图片预览 或配置 terminalImages: false 中关闭,使用 /restart 后生效。已保存的 /settings 选择优先于 Cordis 配置;若曾保存为开启,请在 /settings 中关闭后再 /restart。关闭时保留文字信息并跳过预览解码,不影响向模型发送图片;DSH_TUI_DISABLE_TERMINAL_IMAGES=1 始终强制关闭预览。/resume 按工作目录分类浏览、搜索与预览历史会话(左键恢复、右键弹出操作菜单;可固定常用会话——「已固定」分组置顶显示,行内 ★ 或 Ctrl+P 切换,持久化到 ~/.dsh-tui),另有 /agentview 会话总览(空输入 ← 一键后台化,后台会话派发、预览、回复与停止一站式管理)、/new、/compact、/export、/btw,模型热切换(新会话默认推理强度可在 /settings → 默认推理强度 预设),原生subagent,会话fork,自动更新,输入框 /vim vim 编辑模式、鼠标选区编辑(拖选高亮、Shift+click 扩展、双击选词、Ctrl+C 复制选区)与全屏草稿编辑(Ctrl+Shift+E 或输入行 ⛶ 按钮:行号 + 当前行高亮、Enter 换行、Ctrl+Enter 发送、滚轮滚动、点击/拖选,长草稿独占整屏;/settings 可关);可在vs code中以vscode插件形式启动,已上架 VS Code Marketplace。/skills 展示当前 profile、用户与项目发现的技能;dsh-TUI 不预装通用技能。moon8;读取旧版本地配置中的 claude 值时自动映射为 moon8,选择器只显示当前预设。/settings → whaleIdle 可关)。开始第一个任务后永久定格为静态标准帧,零持续开销。鲸鱼娘的 22 帧手绘原图与闲置行为移植自 dsh-ui-whale(作者 @lhh010),特此致谢。
首屏:像素鲸鱼顶栏 |
前置条件:安装Nodejs与deepseek-harness,注册DEEPSEEK_API_KEY。
安装命令:
npm install -g @deepseek-ai/dsh @deepseek-harness-tui/dsh-tui
启动命令:
# 完整命令
dsh-tui
# 如果你不想按键盘七次
dst
如果你想手动安装,可以使用仓库根目录的 install.sh:
sh install.sh
# 或:dsh plugin --profile dsh-tui add @deepseek-harness-tui/dsh-tui
# 之后 dsh-tui 与 dsh --profile dsh-tui 等价
新用户提示:若
dsh plugin安装时报ERR_PNPM_IGNORED_BUILDS(pnpm ≥11 默认阻止带安装脚本的依赖,如@google/genai、protobufjs——这些脚本运行时不需要,忽略即可),在 profile 的pnpm-workspace.yaml里加入:allowBuilds: '@google/genai': false protobufjs: false
/update与dsh-tui update会自动写入这份配置,无需手工处理。
更面向零基础的安装流程、profile 叠加机制、源码构建与常见问题见安装与快速开始。
想为 dsh-TUI 做插件/扩展?欢迎加入生态!
dsh-working-activity(实时工作状态行:TUI 槽位 + activity/status 会话事件双出口)按当前实现成熟度给出的非正式分级,帮助插件作者评估投入;正式状态与兼容性协定以 准入与开发指南为准:
| 分级 | 接缝 |
|---|---|
| 稳定候选(形态冻结;如有破坏性变更,先在次版本弃用告警再移除) | 六 设置区块 · 八 全屏场景 · 十 托管对话框 · 十一 状态行 · 十二 键盘快捷键 · 十三 条目渲染器 |
| 实验性(仍可能随 dsh-std / 准入规范演进调整) | 九 决策事件 · toast 通知(ctx.tuiToast,新增) |
| 跟随上游(稳定性由 cordis / dsh 官方机制决定) | 一 会话事件 · 二 官方 prompt 槽位 · 三 技能打包 · 四 主题 · 五 system prompt 段 · 七 profile 组合 |
另:@deepseek-harness-tui/dsh-tui/api(纯类型入口)为实验性公开面。
@deepseek-harness-tui/dsh-tui/test-utils 公共子路径已移除——它包含可注入真实
activationId 的测试助手,不适合作为公共生产 API;需要 headless 测试请复制仓库内
scripts/lib/plugin-test-utils.ts 的思路,在自己的测试环境走正式准入流程。
公共面的导入迁移:
ctx.tuiPluginHost.grants.corrupt 已不存在。新的 HostGrantFacade 只暴露
allows(pluginCtx, permission, scope)、defaultOf、knownPermissions 和
onChange(pluginCtx, listener);损坏的 grant 文件不再通过一个布尔字段暴露给插件。
onChange 是 subscribe 类托管能力:必须传入调用 activation,受 shadow 门禁约束,
返回的取消函数绑定到该 activation,避免文件轮询/监听器泄漏。需要诊断时请使用
ctx.tuiPluginHost.selfCheck()、/doctor,或通过显式诊断查询在宿主侧检查
grant 文件状态。createAdmissionCatalog 不再从 ./plugin-host 导出;诊断请使用
ctx.tuiPluginHost.selfCheck() 与 /doctor。ctx.tuiPluginHost.grants 改为调用方安全的 HostGrantFacade:
grants.allows(pluginCtx, permission, scope) 由宿主从当前 activation 推导身份,
不再接受任意 GrantPrincipal/完整 GrantStore。GrantStore、GrantPrincipal 不再是公开导出的插件 API;它们保留在
src/adapter/standard/grants.ts 作为宿主内部实现类型。需要构造/校验 grant
文件的宿主方请走仓库内部路径,生态测试不要在公共包依赖这些类型。@deepseek-harness-tui/dsh-tui/test-utils 子路径已删除;仓库内的
scripts/lib/plugin-test-utils.ts 仅用于本仓库无头验证,不属于公共契约。
生态插件请在自己的测试环境通过正式 admission 流程复现。TUI 的 shadow/门禁只覆盖自有托管接缝;以下由 Cordis/上游 DSH 拥有的路径属于已写死的 平台边界,不会被门禁描述为全路径覆盖:
ctx.get('commands').register / ctx.get('commands').execute(C-070);ctx.plugin() / candidate.plugin() 子插件安装(Cordis 平台);@deepseek-ai/dsh-agent-presets);@deepseek-ai/dsh-system-prompt);@deepseek-ai/dsh-skill)。这些路径在 verify-adapter-shadow 中以 platform-known boundary 显式列出。
此外,verify-adapter-shadow 还显式记录两类门禁已知边界:未列入
NON_SERVICE_POLICY 的内部 TUI 状态/视图辅助类,以及 src/screens/
src/components 的 React UI 状态与事件处理——它们不是 adapter capability
入口,门禁不将其描述为已覆盖。
本轮把 Command / LocalStorage / MessageObserver 从“无实探的 staged”
推进到了“有可逆实探的 live”(在 legacy/new 模式下异步执行),并实现最小
KernelRuntime 与 passive/replay harness:
find / list 验证可见,并以内存 fake agent session 执行一次,确认
execute 返回 success;无论成功失败都在 finally 反注册。该操作不写任何
DSH 持久化 session 日志,唯一瞬时副作用是进程内命令注册表的一次
commands/change 通知。finally 删除;不触碰任何真实插件
namespace,也不保留探针数据。session:* 通配订阅不会收到任何探针消息,探针结束后订阅数回到原值。这些 live probe 方法不是插件可见的公开 service 方法,宿主内核通过内部 host-only accessor 调用。DSH_TUI_ADAPTER_MODE 默认是 legacy,不会加载新 Kernel、不会执行可逆 live probe。该模式保留旧发布语义,使用独立的 buildLegacyHostDescriptor 路径:只要 Command / LocalStorage / MessageObserver 的既有服务行已挂载,describe() / hostDescriptor() 就发布这些契约供插件准入使用;构建结果会在 warnings 中明确标注为 legacy 兼容声明,与新模式 live-only 的公开 descriptor 分离。DSH_TUI_ADAPTER_MODE 时才默认 legacy;显式值只接受 legacy / passive-shadow / replay-shadow / new(忽略大小写与首尾空白),空值或未知值会报错并拒绝启动。非 legacy 模式在 Kernel 未就绪、refresh skipped/failed 或已释放时返回空契约 descriptor,不回退兼容发布。host-probe-access 内部的 token 是模块级不导出符号,普通包 exports 路径也拒绝 deep import。但插件与宿主同进程时,绝对路径加载内部文件仍无法被 exports 阻止——这是 trusted-in-process 边界,不是安全沙箱;宿主不会用“插件不可调用”这类无限定承诺。内部注册函数不会覆盖已引导的宿主 probe runner。scripts/verify-adapter-replay-harness.ts
或 src/adapter/kernel/replay.ts 在隔离 replay context 上运行,否则 fail-closed
并输出明确提示。node --import tsx/esm scripts/verify-adapter-replay-harness.ts(门禁脚本),
或在代码中调用 runReplayShadow({ schemaVersion: 'tui-adapter-replay/v1', ... })
获取 { kernelContracts, legacyContracts, missing, extra, lifecycles } 对比报告。
P5 起还支持真实 DSH session snapshot/transcript 的
runChannelReplay(...) / verify:adapter-channel-conformance,走
tui.dsh/v1alpha1#Channel 的 Provider/Consumer 与协议校验。Command / LocalStorage /
MessageObserver 保持 staged/degraded,不伪造完整支持。DecisionEvents
维持逐 feature probe + 真实 channel/dispatch 拓扑发布规则。admissionCompat 平行视图,并删除
src/plugin-spec/* 与 src/dsh-adapter/{grants,host-descriptor}.ts compat
shim。生产代码直接导入 src/adapter/standard/*;verify:compat-removal
现在扫描 src/、scripts/、bin/、生成 lib/(存在时)与 package export
图,verify:package 也会拒绝 npm tarball 中的旧 shim;仍保留的兼容别名
(ExtensionGrants、envelopeSchema、createAdmissionCatalog、
facadeFromLegacy 等)已明确标注为 P6 范围外/长期兼容面。KernelRuntime 管理 driver 注册/mount、detection、
declared → staged → live、清理与诊断快照;生产 Host Descriptor、getHostFacade()、
/doctor、/plugins 均走该 runtime。Workspace / Scenes / Settings /
Extensions 不再用“注册+list+dispose”冒充整个能力 live。只有实际通过
只读/可逆探针验证的方法才进入 live(如 host.workspaces.list、
host.workspaces.resolve、host.scenes.register、host.settings.register、
host.status.set、host.command-trees.children 等);
host.toast.show 因尚未验证真实生产 deliver 路径,保持 degraded;
rename / runCommand / commandShell / scenes.open /
settings.subscribe / 快捷键 dispatch / command-tree descriptions 等未验证
方法保持 degraded/staged。Presentation 的交互 ask 已桥接到真实
QuestionStore,approve 在 P3 明确 staged。legacy 的 TuiPluginHostRuntime 会把
ADAPTER_KERNEL_SLICES 传入生产 KernelRuntime,进入 mount/refresh/
descriptor 流程;依赖的服务未挂载时对应 slice 降级而不是崩溃。
DSH_TUI_ADAPTER_SLICES 现在会按 slice id / capability / effect 矩阵过滤
kernel slices,不再是无效果的死参数。AdapterRuntimeOptions。之后同�