dsh-TUI

ccch1mneyyyMIT活跃维护

给 DeepSeek Harness 编码 Agent 用的终端界面插件,性能高、占用低,带像素鲸鱼和流畅鼠标交互,npm 一条命令就能装。

DSH's officially top-recommended TUI plugin — high performance, low overhead, cute pixel whale, smooth mouse interaction. One-command install via npm. / DSH 官方首推的 TUI 插件,高性能低占用,可爱像素鲸鱼,流畅鼠标交互,npm 一键安装

v0.19.0发布于 2026-11-06 03:32 UTC7,417star +256 / 7 天353fork同步于 2026-11-10 17:33 UTC

怎么上手

由 README 提炼,执行前请确认
npm install -g @deepseek-ai/dsh @deepseek-harness-tui/dsh-tui
dsh-tui
硬件要求按 README 说明

README 未说明显存或 GPU 要求;这是终端 TUI,运行依赖 Node.js 与 deepseek-harness,Windows 另提供 x64 离线一键安装包。

支持 Apple Silicon
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

DeepSeek Harness 的终端交互界面,带像素鲸鱼和流式思考,一条 npm 命令即可装上

给 DeepSeek Harness 编码 Agent 用的终端界面插件,性能高、占用低,带像素鲸鱼和流畅鼠标交互,npm 一条命令就能装。

核心能力

  • 提供像素鲸鱼启动动画与点击唤醒
  • 流式渲染 Markdown、工具卡片和思考过程
  • 支持 / 与 @ 补全、#L12-14 行号范围和历史搜索
  • 双击 Esc 回退时间,并显示上下文进度条与 TPS 仪表
  • 任务完成时按终端类型发送 OSC 777/9 或系统通知

容易踩的坑

首次启动需要 pnpm,且 pnpm ≥11 默认拦截带安装脚本的依赖并报 ERR_PNPM_IGNORED_BUILDS;使用 deepseek-official API-key 路线需先设置 DEEPSEEK_API_KEY;主要兼容目标是 DSH 0.2.2-rc.1,旧版宿主走兼容路径,DSH 0.1.7 还要求 @deepseek-ai/schemastery 3.18.3 以上。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.19.0
  1. v0.19.0最新正式版2026-11-06 · 2026-11-06 03:32 UTC

    自 v0.18.0 以来,dsh-TUI 跟上 DSH 0.2.2-rc.1 验证线,让一次 /update 同时对齐 TUI、全局 dsh 引擎与全局启动器, 并修好会话恢复、btw 输入、子代理失败提示与 Codex 后端命令输出等一批问题。

    亮点

    • 适配 DSH 0.2.2-rc.1 — npm 上的 DSH latest 已是 0.2.2-rc.1,而 v0.18.0 的精确 peer 只到 0.2.1-rc.5,升级 DSH 后 TUI 会被判 incompatible 并 skip。本版把 0.2.2-rc.1 加入验证线与 peer 范围,0.2.1-rc.5 及其之前的验证线继续保留;模型选择改用上游的会话级 Agent.model 接缝、工具限制落到每个 Agent 的作用域、适配 cordis 4.1 生命周期与固定动作审批,旧宿主继续走原来的选择引用与请求瀑布。(#1886 by @Lucas2011wastaken)
    • 一次 /update 对齐 TUI、dsh 引擎与全局启动器 — 以前 /update 只换 profile 里的 TUI,全局 dsh 与启动器留在原地,可能出现新 TUI 的 peer 范围装不上当前引擎。现在预检为三层解析同一份计划,按 TUI → 引擎 → 启动器串行执行:引擎只选目标 TUI peer 范围内已发布的最高版本(永不降级、不选 alpha 线),装完用 profile 模块解析与 dsh --version 验证;启动器只动能证明归属的全局安装,多成员 pnpm 组、项目内依赖与有歧义的别名一律不改。TUI 已是最新时也不再短路,仍会补齐引擎与启动器;引擎安装失败后只有能证明启动的入口才允许重启,跳过原因会留在下一次挂载的屏幕与警告里。(#1847、#1849 by @Lucas2011wastaken;#1889 by @AdamPlatin123)
    • 子代理通道整体失败会明说 — 同一 provider 的已结算运行至少失败 2 次且失败过半时,子代理列表上方出现通道降级提示,并建议切换 provider;只有可切换的 claude-code / codex 通道会提示,内建 subagent、workflow 与 teammate 行不误报。(#1794 by @MomentDerek)

    需要留意的行为变化

    • 权限问卷只提供固定动作 — 在 DSH 0.2.2 上,approval 类问题只提供调用方声明的选项,不再有自由文本入口;普通问卷仍可自由输入。(#1886 by @Lucas2011wastaken)
    • /update 的拒绝语义与逃生开关 — 新 TUI 要升级、而当前运行的引擎不在它的 peer 范围内时,即使引擎可以自动升级也会先拒绝,并打印「先升级引擎,再重新 /update」的命令(官方加载校验按运行中的 dsh 判定);引擎装完校验不通过时不重启,但保留已升级的 TUI。DSH_TUI_UPDATE_ENGINE=0 钉住引擎,DSH_TUI_UPDATE_LAUNCHER=0 跳过启动器,DSH_TUI_DSH_PM=npm|pnpm 覆盖包管理器判定。(#1849 by @Lucas2011wastaken;#1889 by @AdamPlatin123)
    • /restart 带回图片,被后端丢弃的输入不再自动重发 — 交接文件从纯文本改为带图片的输入;被判定「确定没执行」的输入会暂存为未送达,由用户决定是否重发。(#1764 by @MomentDerek)
    • 长会话不再重放打字动画,代价是随历史线性增长的内存 — 已完成行的记账不再有 2048 条上限(几万行量级约十几 MB),随会话释放。(#1796 by @MomentDerek)
    • btw 输入框恒为一行 — 长草稿围绕光标开窗、被裁一侧显示 …,不再折行;只支持左右查看,不支持多行编辑。(#1866 by @Lucas2011wastaken)
    • Linux 进程名显示为 dsh-tui — ps -o comm、top 与系统监视器不再显示 MainThread;/proc/<pid>/cmdline 保持不变。(#1841 by @Lucas2011wastaken)
    • rio 与 Orca 启用扩展键编码 — 两者加入 CSI >1u 白名单,Shift+Enter 与修饰键组合可用;名单出问题时可用 DSH_TUI_FORCE_EXTENDED_KEYS=1 / DSH_TUI_DISABLE_EXTENDED_KEYS=1 强制或禁用(disable 优先)。(#1821 by @Plintash;#1840 by @Lucas2011wastaken)

    修复

    • 会话与恢复:会话管理页去掉每个 project 下方重复且容易截断的路径、全部来源统一单行列表,并修好快速连点两个 project 时第二击被当成选词的问题(多击判定现在要求同一个 onClick 祖先);从整屏界面返回或 /resume 后历史消息不再逐条重新「打字」;会话自身收尾的回合显示「会话已停止」而不是用户中断;Linux 上被其他进程复用的旧线程 ID 不再让空闲会话被误判为被占用。(#1755 by @xuzijian2019;#1796、#1764 by @MomentDerek;#1769、#1770 by @FlameTN7)
    • 输入与面板:窄侧栏 btw 草稿不再被挤成 0 宽或按未截断的草稿撑高,尾部和硬件光标留在框内;不带 bracketed-paste 标记的整块文本也先压平成单行。(#1866 by @Lucas2011wastaken)
    • 子代理与后端:Codex 后端下 /usage、/diff 查询成功后会显示输出,补全菜单里按 Enter 直接执行而不用先补空格。(#1775 by @MomentDerek)
    • 终端兼容:Orca 与 rio 的扩展键、Kitty 小键盘码位 57416–57426 补齐,CSI-u 的非打印键不再被当作文本插入。(#1840、#1841 by @Lucas2011wastaken;[#1821](https://github.com/ccch1mneyyy/dsh-TUI/pull/1
  2. v0.18.02026-11-01 · 2026-11-01 03:37 UTC
    查看更新说明

    自 v0.17.0 以来,dsh-TUI 跟上 DSH 0.2.1-rc.5 验证线,修好升级 DSH 后 TUI 被拒绝加载的问题, 让首次启动引导可以直接登录或加 key,接入官方 Git 工作树实验包,并让插件授权跟随插件的安装、启用与卸载。

    亮点

    • 适配 DSH 0.2.1-rc.5,0.2.1-rc.4 列为兼容线 — v0.17.0 只声明支持到 0.2.1-rc.3;npm 上的 DSH 升到 rc.4 / rc.5 后,DSH 的插件兼容检查会拒绝加载它,表现为升级 DSH 后 TUI 打不开。本版把 rc.4 / rc.5 加入验证线与 peer 范围,dst 自动化适配器的验证版本同步加入。按发布包逐文件比对,TUI 用到的上游代码在 rc.3 到 rc.5 之间只改了版本号,宿主复刻指纹不变。(#1806 by @AdamPlatin123)
    • 首次启动引导可以直接登录或加 key — 引导第一步现在能登录订阅账号、添加模型提供方(API key)、重新检查或跳过这一步;订阅登录带回的新模型按 0/1/N 处理:只报结果、直接设为默认,或在内联选择器里挑一个。「添加模型提供方」沿用 /provider 向导,向导的切换题会逐项列出本次启用的模型,并保留「保持当前模型」。(#1647 by @AdamPlatin123)
    • 官方 Git 工作树实验包 — /plugin list 里可以直接开启 DSH 官方的 create_worktree;工具卡标题显示分支名,结果用两行写明检出位置和起点。Minimal 与随包的 liangshen 预设不提供这个工具:Minimal 的持久 shell 不跟随目录,liangshen 为跨平台统一规则一并隐藏。工作树不会自动清理,分支需要另外删除。(#1745 by @MomentDerek)
    • 插件授权跟随插件生命周期 — 安装或启用时按包内声明授予,关闭时撤销,卸载时删除该组件的授权条目,复用同一组件 id 的新包不会静默继承旧授权;确认清单按终端高度折叠,放不下时显示剩余条数。(#1747 by @Lucas2011wastaken)

    需要留意的行为变化

    • /plugin enable 一并授予声明的权限 — 确认页逐行列出包内声明的权限,确认后启用并按声明授予,写入的范围不会超出声明;不想授予就按 Esc 放弃。(#1747 by @Lucas2011wastaken)
    • @~/… 在任意深度都指向家目录 — 与 shell 一致;工作区里真有一个叫 ~ 的目录时,改写成 @./~/… 引用。裸 @~ 的行为不变。(#1739 by @AdamPlatin123)

    修复

    • 会话:DSH 内核上 dsh-tui 行随 agents 服务卸载时,屏幕不再停在「回合进行中」,而是显示会话已结束;没送达的输入暂存、不自动重发,行恢复后重新挂接并重开会话,/restart 会带回排队的文字。(#1759 by @MomentDerek)
    • 输入:@~/ 补全选中子目录后不再消失,发送的 @~/… 不再落进 missing;侧栏聚焦时 Ctrl+V / Alt+V 粘贴进 btw 输入框而不是主聊天草稿,全屏 btw 也能粘贴。(#1739 by @AdamPlatin123;#1785 by @Lucas2011wastaken)
    • 面板与渲染:待办侧栏按宽度完整折行显示长目标、可滚动查看全部条目;展开的工具卡保留用户设置的「工具卡背景」。(#1748 by @Lucas2011wastaken;#1782 by @baobaolaodie)
    • 宿主与插件:带额外第三方 bundle 的 profile 启动时,慢 core 行恢复后的官方 Remote service 注册不再被 root guard 误拒(宿主在装 guard 时物化 root-owned invocation accessor,guard 判定面不变);desktop/web profile 下插件 activation 的根事件派发与服务解析也不再被守卫拒绝,设置保存、模型增删与插件卸载恢复可用。结构性的 root 操作仍被拒绝。(#1732 by @Lucas2011wastaken;#1804 by @MomentDerek)

    兼容与升级

    • DSH 主适配线:0.2.1-rc.5;0.2.1-rc.4、0.2.1-rc.3、0.2.1-rc.2、0.2.0-rc.1、0.2.0-rc.2 以及更早的验证线仍在契约内,契约外版本打漂移警告。
    • 升级 DSH 后 v0.17.0 打不开的用户:TUI 进不去时用不了程序内的 /update,请直接运行下面的 npm 命令升级到 v0.18.0。曾用 dsh plugin allow-version 给 v0.17.0 加过豁免的,升级后不再需要。
    • 从 v0.17.0 升级:程序内 /update,或 npm install -g @deepseek-ai/dsh @deepseek-harness-tui/[email protected]。
    • Windows 离线安装器:DSH 验证范围随契约更新到 0.2.1-rc.5。已装 rc.5 直接保留,rc.4 升到 rc.5,不再像 v0.17.0 的安装器那样降回 rc.3。

    安装

    npm install -g @deepseek-ai/dsh @deepseek-harness-tui/[email protected]
    

    偏好一键安装的用户可下载 Release 中的 dsh-tui-setup.zip(解压后 macOS / Linux 运行 sh install.sh,Windows 双击 install.bat) 或 Windows 离线安装程序 dsh-tui-setup-win-x64.exe;便携包解压即用。

    What's Changed

  3. v0.17.02026-10-24 · 2026-10-24 10:14 UTC
    查看更新说明

    自 v0.16.1 以来,dsh-TUI 跟上 DSH 0.2.1-rc.3 验证线,加入独立 headless CLI、Windows 离线安装器、 /settings 分页与插件底栏字段,并让 TUI 跟随会话的工作目录。

    亮点

    • 独立 headless CLI(dst) — dst run、-p、dst cli 不加载 React / Ink / channel / TUI 偏好即可被脚本驱动,dst dsh 原样转交官方参数;随 npm 包分发,src/ 零改动。自动化适配器当前只验证 DSH 0.2.0-rc.2,使用官方 headless 的持久化与恢复规则,不承诺与任意 TUI preset / fork 会话互通,也不是逐 token 正文流。(#1560 by @T-Auto)
    • Windows 离线安装器 — Release 增加 dsh-tui-setup-win-x64.exe:自带轻量 Node 运行时(系统已有满足版本约束的 Node 则复用)、免管理员、把 npm 全局路径追加到 HKCU 的 PATH、profile 落在 %USERPROFILE%\.dsh\profiles\dsh-tui,卸载不触碰 .dsh 核心数据。暂未做代码签名,首次运行会有 SmartScreen 提示;旧的 dsh-tui-setup.zip 与便携包继续并存。(#1554 by @FlameTN7)
    • /settings 分页 — 设置屏分成「常规 + 插件」页签;不声明 page 的旧插件区块并入常规页,只有一页时不显示页签条。同时修掉 dsh-tui 自己的设置区块会因注册表竞态从屏上消失的问题。(#1619 by @ccch1mneyyy)
    • 插件底栏字段逐项可控 — statusBar.pluginFieldsOrder 决定显示哪些插件字段与链内顺序,默认 * 表示全部(含以后注册的);高级行从 * 进入后原样保存仍写回 *,不会把「还没见过的字段」钉死。(#1628 by @Lucas2011wastaken)
    • 插件侧栏面板可复用宿主渲染 — TuiPanelProps.ui 新增 ui.Markdown 与 ui.CodeBlock,插件不必自己拼围栏、算表格宽度。(#1652 by @Lucas2011wastaken)
    • 会话搜索实验包进入 /plugin list — 官方 session-search 包的开关与用法可直接看到,检索卡标题显示查询词;极简模式仍只提供 shell(有意与上游该包「含 minimal」的描述不同,保持 Minimal 对用户的单 shell 承诺)。(#1707 by @Lucas2011wastaken)
    • 启动页多行草稿带到聊天页 — 启动页用 Shift/Option+Enter 换行后,未发送的文字、光标与图片在切到聊天页时保留,同一批输入中随后的按键按原序重放。(#1703 by @CikeSeven)
    • 会话状态与完成提醒 — 经 OSC 7501 向终端报告 idle / working / blocked / done / error,跨 SSH、容器与多路复用器可用(不包 tmux/screen passthrough);Windows 上 notificationMethod 新增 windows 档,用系统原生 toast 提醒完成(点击跳回尚未包含)。(#1561 by @zerodegress;#1574 by @baobaolaodie)
    • 跟随会话工作目录 — 上游 working_directory 或 Git worktree 把会话切到别的目录后,状态栏、Git 分支、@ 补全、! 命令、技能命令与已加载上下文一起跟随,项目归属不变;已知限制是 cd 之前渲染的工具卡里的相对路径,点击时按当前目录解析。(#1733 by @MomentDerek;#1634 by @baobaolaodie)
    • 会话管理页统一显示项目路径 — 路径放在来源标签下方、横跨两栏,DSH 不再缺目录、外部会话不再逐条重复;超长路径最多四行,可悬停看完整值。(#1264 by @xuzijian2019)
    • DSH 验证线升到 0.2.1-rc.3 — 主适配线与开发树、CI alpha-compat、验证常量同批前移,0.2.1-rc.2 继续作为已验证兼容线。(#1736 by @Lucas2011wastaken)
    • 插件市场元数据 — 随包提供中英文本地化的市场标题/描述、方形像素鲸鱼图标与 dsh-plugin 发现关键字。(#1677 by @ccch1mneyyy)

    需要留意的行为变化

    • /team 只报告状态 — /team on|off 不再是启停入口,只接受 status;需要启停时改用 /plugin enable|disable,旧写法会返回迁移提示。Agent Teams 仍是实验特性,默认关闭;/plugin list 里各实验功能的提示也改成直接说明它的作用。(#1604、#1734 by @Lucas2011wastaken)
    • sidePanel.panels 的显式列表现在是精确集合 — 写过显式 CSV 的用户升级后,之后新注册的插件面板不会自动出现,而是在 /settings 里显示为未勾选行,点一下加回。默认值 * 仍表示全部已注册面板;临时面板的显示/隐藏随之改成运行态,结构上进不了持久设置。(#1683、#1695 by @Lucas2011wastaken)

    修复

    • 输入、选择与复制:Option+方向键按词编辑、Esc 先消费本地层再中断回合、rewind 重复同一段文本时重新回填草稿、退出时选择可恢复且终端输入干净、复制内容与高亮留在锚定面板内、软换行代码块复制不丢内容。(#1657、#1659、#1680、#1693、#1661 by @ccch1mneyyy;#1670 by @MomentDerek)
    • 会话与持久化:detached fork 保留父链、失败的 resume 预检释放预留、频道
  4. v0.16.1v0.16.1 — 独立入口启动回归与更新包体修复2026-10-17 · 2026-10-17 21:33 UTC
    查看更新说明

    这是 v0.16.0 的补丁发版,修两个会影响启动和更新体积的问题。

    修复

    • 独立入口在装有第三方 bundle 的 profile 上启动失败 — #1577 把后端装配放到了延迟根守卫之前。profile 的 dsh.profile.bundles 里有 @deepseek-ai/* 和 dsh-tui 之外的包时,装配会提前解析组合根,根能力守卫立刻装上且撤不掉;DSH 0.2.0-rc.2 的基础行在 ctx.root.accessor('invocation') 处被拒,plugin-manager、llm、commands 等 9 个必需插件无法激活,agent-loop 等不到 llm。现在延迟紧跟在入口绑定根之后,排在装配和内核选择之前,恢复 0.15.0 的守卫时序。(#1598 by @MomentDerek;维护者修复 by @ccch1mneyyy)
    • 更新时不再把其他平台的 Claude SDK 包拉进 profile — pnpm 更新会物化所有平台的 optional dependency;0.15 → 0.16 曾把七个 @anthropic-ai/claude-agent-sdk-* 包(约 1.6GB)装进 profile store,而实际只会链接当前平台的那一个。现在更新和按需安装内核都会按本机 platform/arch/libc 过滤;Claude SDK 仍是按需安装的可选后端,普通更新不会自动加。(#1600 by @ccch1mneyyy)

    兼容与升级

    • 从 v0.16.0 升级:程序内 /update,或 npm install -g @deepseek-ai/dsh @deepseek-harness-tui/[email protected]。
    • 已在 0.16.0 遇到启动失败:升级到 0.16.1 即可,不必再钉回 0.15.0、移除第三方 bundle 或先升 DSH。
    • 一键安装包 dsh-tui-setup.zip、各平台 dsh-tui-standalone-* 便携包与 SHA256SUMS 仍在 Release 资产里。

    安装

    npm install -g @deepseek-ai/dsh @deepseek-harness-tui/[email protected]
    

    偏好一键安装的用户可下载 Release 中的 dsh-tui-setup.zip,解压后按平台运行 install.sh 或 install.ps1;便携包解压即用。

    What's Changed

    Full Changelog: https://github.com/ccch1mneyyy/dsh-TUI/compare/v0.16.0...v0.16.1

  5. v0.16.0v0.16.0 — 实验性 Agent Teams、Auto review 与 DSH 0.2.1 适配2026-10-17 · 2026-10-17 16:53 UTC
    查看更新说明

    自 v0.15.0 以来,dsh-TUI 跟进 DSH 0.2.1 版本线,加入实验性 Agent Teams 与 Auto review 权限预设,并继续完善插件安装、Codex/Claude 后端与终端交互。

    亮点

    • DSH 0.2.1 版本线 — 主适配线升到 0.2.1-rc.2(同时支持 0.2.1-alpha.5、0.2.0-rc.1/rc.2 等已验证版本);启动时按已装 DSH 报告版本线,契约漂移会在 CI 失败。(#1593、#1580 by @CikeSeven)
    • 实验性 Agent Teams — /team on|off 启停上游团队 bundle(写回 profile,有 HMR 时立即生效);Ctrl+A 仪表盘和 agents 侧栏显示成员、状态、Lead 行与只读任务板;成员消息在接收方 transcript 显示为 ✉ <发送者> 气泡;有 teammate 在运行时关闭会先确认并停止它们。默认关闭,需要按 /team on 的提示安装与运行中 DSH 同版本的团队 bundle;开关是 profile 级,尚不支持进入 teammate 会话,/export 不导出团队消息。(#1594 by @MomentDerek;维护者修复 by @ccch1mneyyy)
    • Auto review 权限预设 — 启用 dsh-experimental-auto-review 后,auto 以「自动授权审查」+ EXP 出现在 /permission;选择器先做会话级风险确认(仅本会话、无文件沙箱、每次调用额外一次模型请求);Shift+Tab 在本会话确认过一次之后才进入循环;Auto 不写入下一会话偏好,插件卸载时的自动迁移也不会被误记;拒绝原因按界面语言显示。(#1553 by @MomentDerek;维护者修复 by @ccch1mneyyy)
    • 插件安装与管理 — /plugin install 可从终端安装 bundle(含第一方 feed);/plugin remove|enable|disable 带生命周期确认、残留检查与版本/加载器覆盖处理;/plugin 参数补全提示 spec 形状;组件清单改为从 ESM 入口解析,子路径准入绑定 Loader 解析器。(#1528、#1542、#1549 by @Lucas2011wastaken;#1568 by @ccch1mneyyy)
    • Codex 与后端装配 — Codex 支持非阻塞异步问卷、分页历史下的首条消息回溯;后端按已安装 bundle 组装,/btw 归属到种子侧分支并允许 bundle 在 preset 内打补丁。(#1533、#1565 by @CikeSeven;#1577 by @Lucas2011wastaken;#1552 by @MomentDerek)

    修复

    • 修复滚动锚点在视口上方收缩时丢失、/btw 选中内容发送/复制与底栏提示、launchpad 立绘尺寸、/bg 后台会话压缩被打断、长目标悬停等。(#1536 by @xiaoxiaohaigui;#1550 by @Lucas2011wastaken;#1539 by @ccch1mneyyy;#1525 by @FlameTN7)

    兼容与升级

    • DSH 主适配线:0.2.1-rc.2;继续支持 0.2.1-alpha.5、0.2.0-rc.1/rc.2 等已验证版本。升级 DSH 后首次启动会报告版本线;请按 README//team on 的提示安装对应版本。
    • Agent Teams 仍是实验特性:默认关闭,需把 @deepseek-ai/dsh-experimental-agent-team-profile 按运行中 DSH 的版本装进 profile;开关影响整个 profile,不是单个会话;暂不支持进入 teammate 会话;团队消息不进入 /export。团队服务的 0.2.0-rc.2 真机流程已实测;0.2.1 的团队消息/结果形态按发布包源码核对。遇到问题可 /team off 关闭。
    • Auto review 需要插件:启用 dsh-experimental-auto-review 才出现;只对当前会话生效,不会成为新会话默认;没有文件沙箱,审查放行的调用拥有完全访问;每次工具调用额外一次模型请求;子代理中的拒绝是终局。
    • 一键安装包与便携包:Release 资产包含 dsh-tui-setup.zip(一键安装脚本,含 POSIX shell 与 Windows PowerShell)以及各平台 dsh-tui-standalone-* 便携包和 SHA256SUMS。

    安装

    npm install -g @deepseek-ai/dsh @deepseek-harness-tui/[email protected]
    

    偏好一键安装的用户可下载 Release 中的 dsh-tui-setup.zip,解压后按平台运行 install.sh 或 install.ps1;便携包解压即用,更新时用包内自更新器校验 SHA256SUMS。

    What's Changed

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    dsh-TUI

    An interactive terminal UI for DeepSeek Harness. It ships a pixel-whale header, live work status, streaming thinking, double-Esc time rewind, a context progress bar, and a TPS gauge. Zero core changes: it consumes only DSH's public exports, and is moving from a mounted plugin to an app with its own entry and composition root, where DSH loads in process as the first-party backend. Install to enable; uninstall leaves no patches behind. The prompt footer hides completed goals once the turn is idle; the Todo side panel retains their history. Ctrl+Q folds todos while working and hides/restores the idle goal/todo footer. Clicking its todo header also hides it while idle. Hiding changes only this display: a new goal/todo snapshot or session reveals it again, and /goal clear does not clear todos.

    Split diff cards give one-sided additions and deletions the full body width, without an empty opposite pane. Ordinary edits remain side by side, and mixed files choose their layout separately before folding or streaming reveal.

    Compaction status stays on one line in narrow panes: phase and cancellation hints yield first, then the label is shortened; elapsed time is shown only as a complete field.

    Image files referenced with @path use the same admission and resize/conversion policy as pasted images. Adjustment notices report the stored dimensions and format; required animation conversion is refused instead of dropping frames. Mention images and staged images still share count and stored-byte limits in source order.

    Highlights

    Panels without a verified Component identity are temporary: settings show their title and a distinct number for this run. Their toggles take effect immediately without being saved, and unrelated settings changes preserve that choice. Old actN:panel entries cannot be mapped safely: remove the placeholder and select the current panel again. Verified Components named actN keep their public runtime address; an explicit selection uses component:actN:panel in saved preferences to avoid claiming an old anonymous entry.

    The default reasoning-effort setting offers the current backend/model’s declared tiers, including custom IDs. Saved values absent from that catalog stay visible and stored; while loading or unavailable, only Auto is selectable. On DSH, Auto follows the saved /effort choice, then the configured effort, then the model default. Claude/Codex retain backend preferences for Auto at startup and for resumed sessions; explicitly choosing Auto resets the model default. Explicit settings changes affect the next request; unsupported preferences fall back with a notice and are never forced onto a route.

    Resuming a DSH session preserves its recorded reasoning effort (or its live selection when reattaching). The saved default seeds new sessions; explicit /effort and effort-default settings changes still apply to the current session’s next request.

    • Pixel whale pet — three startup intros, click to wake; freezes after the first task.
    • Launchpad and first-run guide — every ordinary launch lands on a landing page with a real input box (big text + whale + quick actions, dropping whole blocks on short/narrow terminals; whale-girl images use a compact native-canvas footprint instead of leaving a large gap before the title; on by default — /settings launchpad off boots straight into chat); command completion matches chat: Tab fills the input, Enter runs the command and clears it. The first run walks a four-step wizard (accounts & models / language+theme / model+workspace / shortcuts), re-runnable with /setup; its first step signs in to a subscription and catches the models it brings in (none → no question, one → that one, several → you choose), or adds an API key through the /provider wizard, which asks which of the enabled models to switch to or keeps the current one.
    • Terminal-native UI — streaming Markdown, tool cards, / and @ completion, #L12-14 ranges, history search, zh/en UI.
    • Task completion notifications — DSH, Claude and Codex notify after successful live work settles, with no queued follow-up or active goal. The title is “dsh-TUI · Task complete”; the body shows the latest settled reply as a single-line plain-text preview (Markdown formatting removed, up to 200 characters). OSC 777/9 apply an additional 2048-byte sequence budget, including title and protocol bytes, preserving whole graphemes. No reply shows only the title; BEL only rings. /settings → Conversation: taskNotifications = unfocused (default), always, or off; notificationMethod = auto (default), osc9, bel, or windows. Auto uses separate title/body fields on Ghostty/WezTerm (OSC 777) and Kitty (OSC 99); iTerm2/Warp and explicit osc9 use a title prefix; other terminals ring the bell; delivery follows your terminal's notification/bell settings. On local Windows, auto resolves to windows, the system's native notifications: a task-completion toast. The first toast registers that user's AppUserModelID under HKCU, the toast appears about 3 seconds after the task ends (the PowerShell cold start that buys the no-extra-install route), and for DSH sessions an enabled, active external DSH notification plugin in the running profile makes dsh-TUI yield to it (no toast, no bell); an installed but disabled plugin does not suppress notifications; if that AppUserModelID cannot be written, the notification falls back to the bell instead of going silent. jumpBack (Windows, off by default) turns those completion toasts into a way back to the pane that finished; it needs the native toast path (notificationMethod = windows, which auto picks on local Windows). With /settings → Conversation → jumpBack on, the pane title ends with [dsh-tui:<16 hex>], one marker for the life of the process; switching it off removes the suffix at once. While it is on, this process refreshes a marker file at ~/.dsh-tui/notify/jumpback/<session>.json (schemaVersion: 1, marker, pid, startedAt) when the setting is turned on and before each completion it sends, and the first toast that can promise a jump registers the per-user protocol handler (URL Protocol plus shell\open\command) under HKCU\Software\Classes\dsh-tui; a normal exit removes the file, and removes the key once no other live instance still needs it. Only a pre-send probe that finds exactly one target pane (or tab title) puts an activation URI on the toast; clicking it re-runs five checks — same pane, keyboard focus, marker still in the title, foreground window, not minimized — and refuses rather than jumping anywhere else when any of them fails. A click whose target has gone away changes nothing. Layouts that cannot be verified — a pane in an unselected tab that is not that tab's focused pane, profiles using suppressApplicationTitle, and terminals other than Windows Terminal (tested on Windows Terminal 1.24) — get a plain toast whose click changes nothing. The probe adds about half a second before each toast; the first one after enabling can also wait for the helper to compile (a few seconds, once), and a machine whose in-box compiler keeps failing retries it at most every five minutes. External notification senders can read the same marker file and point their own toast at dsh-tui:activate?m=<marker>; the URI and file format are a read-only contract, and this release ships no plugin-side implementation. SSH sessions keep the attached terminal's notification protocol in auto mode; explicit windows still selects the host's native transport. tmux requires set -g allow-passthrough on for OSC notifications and set -g focus-events on for focus reporting. Terminals without focus reporting need always. Replay, cancellation and failures do not notify. Works in inline and fullscreen modes.
    • Native cursor — focused text inputs inherit your terminal's cursor shape, color, blinking, and enabled animation or trail effects in both inline and fullscreen modes. The /model picker shows the same cursor during movement between provider tabs, model rows, and effort levels, then hides it after 0.5 seconds at rest; clipped regions fall back to the model row. The session manager also moves this cursor between the workspace rail, session rows, and search box; typing claims the search caret, and navigation returns it to the focused row. Configure animation and trail effects in your terminal.
    • Images — Kitty/Sixel thumbnails, centered preview with zoom and pan, paste-time fitting, text fallback. Kitty images scale to the reserved cells' physical pixels, including on HiDPI terminals.
    • Mermaid diagrams — mermaid fences drawn as Unicode diagrams.
    • LaTeX math — $…$ and $$…$$ formulas as Unicode text, fractions and limits stacked in display blocks; mathRendering: image typesets block and one-row inline formulas as terminal images on graphics terminals.
    • Timeline rail — every turn clickable; timeline / scrollbar / hidden gutter.
    • Side panel — Ctrl+B splits the chat with a panel column once the terminal is wide enough; drag the divider to resize it. All eight built-in panels are enabled by default, and so are plugin panels registered later (sidePanel.panels: '*'; untick a row in /settings to switch to an explicit list). The header shows each inactive panel's symbol; hover to see its name. Narrow terminals and inline mode keep full-screen panels. In the todo panel a long goal wraps to the panel width with its phase on a separate row; when the content exceeds the viewport, focus the panel and scroll with ↑/↓ or the wheel (every todo is reachable too) (the compact goal row above the chat input stays a single truncated line with a hover tooltip).
    • Live state — activity animation, context bar, TPS, cache hit rate, effort, tokens, session cost estimate (main + subagents), Git and session metadata. Title, trajectory-strip and session-state animations update independently of the transcript and pause when idle or unfocused. Context-bar fill follows backend occupancy; colors estimate content composition. Compaction clears obsolete estimates, and missing composition displays a single used block with a measured used count in both hover details.
    • One session manager — /resume /home /agentview /bg ⌸.
    • Session workflow — /new /compact /export /btw, model hot-switch, fork, rewind, vim, fullscreen draft editor. /btw uses an overlay when its sidebar cannot render. Main-task questionnaires and the fullscreen draft editor take priority while preserving the side question and draft.
    • IDE selection channel — a VS Code selection lands in the prompt.
    • DSH integrations — presets, skills, MCP, goals, todos, subagents, questionnaires.
    • Account sign-in — the standard profile offers pi-ai OAuth for ChatGPT/Codex, Claude, and Grok (plus OpenAI direct and Meta Muse when available), and Host-owned DeepSeek browser sign-in as deepseek-account on DSH 0.2.0-rc.1+. Use /provider or /auth without another plugin. A profile-only update from a global TUI patch that already mounts dsh-tui-auth can still start the official loopback callback listener on demand; fixed-port SSH forwarding still requires the global package to be aligned.
    • Extensions — browser interaction, computer use and more.
    • Built for long sessions — event-driven projection, virtualization, bounded caches.

    Keys and commands: Interaction and commands. Everything else: documentation index.

    Plugin side panels stay enabled when unrelated settings change. Editing the enabled panel list still applies your explicit selection.

    Workspace side-panel counts match the session manager: the current conversation counts; empty logs, subagents, fork ancestors and archived sessions do not. Registered workspaces with no visible conversations remain at zero. Loading and read errors are shown separately; press r to refresh.

    When a DSH 0.2.1+ Agent moves its session to another directory (the working_directory tool or a Git worktree), the status line, Git branch, @ completion, ! commands, clicked paths, skill commands and loaded context follow it, including after /resume. The session stays registered under the project it started in. Relative paths in cards rendered before a move resolve against the session's current directory when clicked; absolute paths keep their target.

    Fullscreen mouse selection stays in the pane where the gesture starts, including chat, sidebar and either diff column. Diagonal, word and line selection copy that pane’s text; soft wraps join independently, source newlines remain, and divider drags only resize.

    Preview

    Featured & Listed

    Among the community plugins recommended by the official lead of DeepSeek Harness, dsh-TUI is the first.

    Featured by the DeepSeek Harness official WeChat account, listed in the dshfind plugin directory, and ranked #7 on GitHub Trending daily (TypeScript).

    Quick Start

    Windows one-click installer (x64)

    Download dsh-tui-setup-win-x64.exe from Releases and run it. Per-user, no administrator, fully offline, and no preinstalled Node or DSH.

    Command-line installation

    Prerequisites: Node.js and deepseek-harness. The deepseek-official API-key route needs DEEPSEEK_API_KEY. On DSH 0.2.0-rc.1+, the standard profile can instead use /auth login deepseek-account and select the separate account route through /model. Other supported accounts can sign in through /provider or /auth after startup.

    The primary compatibility target is DSH 0.2.2-rc.1. This adapter supports its Shell API, V4 session messages, declarative presets, and profile-backed settings; older supported hosts retain their compatibility paths. See configuration.

    On DSH 0.2.1-rc.2 and later, /settings also selects DeepSeek Search / Fetch APIs and edits their endpoint and result limits, supporting custom Loader entry IDs and a masked API key input saved through DSH's credential store. Official Flash model labels show the 1017 release marker while retaining the deepseek-flash model ID.

    /settings groups its sections into pages: the TUI's own settings sit under General, and plugins that declare a page get their own tab (Tab / Shift+Tab, or a click on the strip in fullscreen, switches pages; the strip is hidden when only one page exists).

    On DSH 0.1.7, /settings uses the TUI's actual Loader entry ID, including custom IDs. It requires matching profile dependencies with @deepseek-ai/schemastery 3.18.3 or newer; an incompatible schema stops TUI startup with repair guidance instead of showing an uneditable settings page. Older hosts keep their legacy settings scope.

    The dsh-tui section of /settings is saved in ~/.dsh-tui/settings.json, shared by every kernel; the first launch imports it once from the profile's cordis.patch.yml (and an older host's ~/.dsh/settings.yaml) (see configuration).

    # Install the CLI and this plugin globally (ships the dsh-tui command)
    npm install -g @deepseek-ai/dsh @deepseek-harness-tui/dsh-tui
    
    # Start (first run auto-initializes the profile; needs pnpm)
    dsh-tui
    # Both `dsh-tui` and the short `dst` alias start the same TUI.
    dst
    

    Manual alternative: dsh plugin --profile dsh-tui add @deepseek-harness-tui/dsh-tui. The repo's sh install.sh runs that step and checks the required commands. Afterwards dsh-tui and dsh --profile dsh-tui are equivalent.

    New-user note: pnpm ≥11 blocks dependencies with install scripts by default and reports ERR_PNPM_IGNORED_BUILDS. Updates skip foreign-platform natives — the @img/sharp-* packages and the Claude SDK's per-platform bundles — so only this machine's binaries are fetched. /update and dsh-tui update write both settings automatically. An update never installs the Claude SDK on its own: it enters a profile only when you pick that backend in the kernel picker, which then installs the pinned SDK for the running platform. No manual step needed. Details: Getting started.

    After startup the TUI checks for newer versions in the background. It never blocks the first frame. Type /update for a one-shot upgrade of the whole set — TUI, dsh engine and global launcher. It restarts automatically and resumes the current session, and refuses instead of leaving an incompatible or unbootable TUI/engine combination. Launcher alignment is normally best effort, but a failure after the engine advances blocks the restart and prints a repair command. If the registry has a newer dsh release outside the TUI's validated line, it says so and waits for a TUI update rather than installing an unvalidated engine. Launcher alignment only touches proven global installs; local npm/npx packages, ambiguous aliases and multi-member pnpm groups stay unchanged. See Getting started for the profile lifecycle, source builds, and troubleshooting, including migration from the former dsh-cc-tui package.

    CLI

    Automation: dst -p "task", dst run --json, dst session list --json. The independent engine does not load the TUI or inherit its profile/preferences; it uses official DSH headless/services (validated on 0.2.0-rc.2, 0.2.1-rc.2, 0.2.1-rc.3, 0.2.1-rc.4 and 0.2.1-rc.5). dst cli --help lists its commands; dst dsh <argv...> forwards native DSH. See Automation CLI for protocol, limits, resume restrictions, and Node/Python/PowerShell integration examples.

    CommandPurpose
    dsh-tui / dstStart the TUI; dst is a short alias for the same program
    dsh-tui --resume [id] · dsh-tui update · dsh-tui doctorResume a session · align the TUI, dsh engine and global launcher as one set · pre-flight environment checks
    dsh-tui safeRead-only diagnostics, plugin inventory and repair guidance; safe --rescue builds a clean rescue profile
    dsh-tui version · dsh-tui helpLauncher and profile versions and usage; both work even without a dsh install

    Leading DSH options such as --dump-config and --patch <path> are forwarded unchanged; other arguments go to the app in dsh --profile dsh-tui. Use dsh-tui -- --resume=sid-1 ./notes to send --resume=sid-1 ./notes as literal prompt text, without selecting a session or workspace. When invoking DSH directly, use dsh --profile dsh-tui -- -- --resume=sid-1 ./notes: the first -- belongs to DSH, the second to the app. Host options can precede a literal prompt: dsh-tui --patch ./overlay.yml -- --resume=sid-1 applies the overlay and sends --resume=sid-1 as prompt text without resuming that session. Safe mode: Getting started.

    Importing conversations from other agents (dsh-tui migrate)

    Bring Claude Code, Codex, OMP, zcode, or Grok Build conversation histories into the DSH session store, then browse and resume them by their original working directory via /resume:

    dsh-tui migrate                # list importable counts per agent (writes nothing)
    dsh-tui migrate claude-code    # import every Claude Code conversation (likewise codex / omp / zcode / grok-build)
    dsh-tui migrate codex --dry-run  # preview what would land, write nothing
    
    • Read-only source: migration only reads the foreign agent's local store; artifacts are written through the official JsonlSessionPersistence backend, so imported sessions are first-class (openable, continuable).

    • Idempotent: one deterministic UUID per source conversation — re-importing skips what is already present instead of stacking duplicates.

    • Structure preserved: user/assistant messages, reasoning traces, tool calls with their results, and the source's context compactions (as native compaction checkpoints) are rebuilt turn by turn; harness-injected machine text opens no turn. An imported session can pick the work straight up. In-TUI browsing: the session screen (/resume) shows a tab per agent that has conversations; picking one imports just that conversation and opens it. In-TUI: /migrate (optionally /migrate <agent> [--dry-run]) runs the same import in a child process and reports through the notification flow. CLI alternative: dsh-tui migrate ... from any shell runs the same import. Full guide: Session migration.

    • More agents (pi, opencode, …) extend the adapter registry as adapters land; grok-build reads GROK_HOME when set.

    VS Code: use the integrated terminal or the dsh-tui-vscode extension. See VS Code guide. Herdr: run dsh-tui in a Herdr pane; idle / working / blocked are reported through its local integration API. Any terminal: dsh-tui reports idle / working / blocked / done / error over the pty with OSC 7501 (Program Status Protocol), so terminals and agentic inboxes that implement it can show what the session is doing; terminals that do not implement it ignore the sequence. Set DSH_TUI_PROGRAM_STATUS=0 to turn it off.

    Bare --resume (-c, --continue) reopens the last session of the backend this launch selected. Startup recovery only ever targets that backend: a backend with no last session, or a derived target that belongs to a different backend than the one that actually booted (an unknown backend id falling back to DSH, --backend naming a backend that is not installed, a remembered kernel that is not the marker's source), refuses with a clear error and exit code 1 — never a silent cold start, never another backend's session, never a new session. An explicit --resume <id> passes that id to the selected backend as-is. The one exception is safe mode's "retry normal startup": it retries the kernel and session recorded in last-run.json, so a record whose backend is gone degrades to a warning plus a cold start — that retry is the last way back.

    Experimental: Claude backend

    dsh-TUI can also run its session on Claude: the same interface, driving the Claude Code CLI through the Claude Agent SDK. Your project's CLAUDE.md, settings, hooks, MCP servers and plugins load as the CLI loads them.

    # once, in the dsh-tui profile directory (the SDK is an optional dependency)
    cd ~/.dsh/profiles/dsh-tui && pnpm add @anthropic-ai/[email protected]
    dsh-tui --backend claude     # or pick Claude in /kernel; that choice is remembered
    

    The easiest install: open the kernel picker (the launchpad "Kernel" entry or /kernel) and press Enter on the dim Claude row — the wizard locates the profile directory and installs the pinned SDK for you; the command above is its manual equivalent. The confirmation shows the exact package and version. Closing the wizard, including clicking outside it on the launchpad, cancels a pending installation.

    • Sign-in: a /channel relay profile, your dsh-auth anthropic sign-in (/login), ANTHROPIC_API_KEY or cloud-provider variables, or an existing claude login, in that order. A claude on PATH is used when present, then one in the native install directory under your home (~/.local/bin, or %USERPROFILE%\.local\bin on Windows); every candidate has to launch and report a version, and the SDK's bundled binary is used only when none does.
    • Works: streaming, tool cards, approvals and questions, /model, /effort, Claude's permission modes (/permission, Shift+Tab), /compact, /context, /mcp, /resume, /fork, double-Esc rewind, subagents, background jobs, images, /btw, and the USD cost Claude reports.
    • Not available: DSH-only commands such as /tree, /preset, /provider, /workspace, /agentview and /bg. One process runs one backend; /kernel switches by restarting into a new session.
    • Startup: the screen appears before the session opens, with only a light profile composed (this package plus the profile's third-party plugins); see Claude backend. The DSH kernel starts from the same entry and loads DSH in the same process behind its first screen; DSH_TUI_HOST_ENTRY=0 restores the old launch path for every kernel.

    Details and known limitations: Claude backend.

    Experimental: native Codex backend

    Run your own Codex through codex app-server, sharing its configuration, login, instructions, skills, hooks, MCP and native threads:

    npm install -g @openai/[email protected]
    dsh-tui --backend codex
    dsh-tui --backend codex --resume <thread-id>
    

    Protocol baseline 0.160.1, minimum 0.144.0; other versions may show drift. CODEX_EXECUTABLE selects a binary; /kernel remembers the backend. codex resume <id> can open the same thread after the other writer exits. This is not migrate codex, which imports history into DSH. With native credentials, a writer conflict for an idle thread retained by the official background server triggers a reconnection to that server. Managed subscription credentials and /channel connections use private app-server processes.

    Streaming/tool cards, approvals, questions, steer/queue/interrupt, model and effort controls, Plan, /review, /diff, /usage, /init, skills and MCP share the existing UI. Async questions open the questionnaire while Codex continues working; answers steer the turn (or queue if unavailable), and dismissing the question leaves work running. Shift+Tab only toggles Plan, keeping its underlying permission preset; Full Access requires an explicit choice. Existing Codex settings are respected, not overwritten with defaults. /login offers ChatGPT OAuth, a device code or an API key (the last writes to Codex’s own credential store). Relay /channel connections take precedence; managed subscription tokens are only injected on first-party routes. dsh-TUI does not write ~/.codex/config.toml or log out your native Codex account. A provider env_key from your own config (e.g. DEEPSEEK_API_KEY) that the shell did not export is injected from the DSH credential store when the ref is stored there — the active store first, then the default ~/.dsh one — so keep the key in the store, no per-shell export needed. When nothing can supply it, the session still starts and the reason is reported once as a start notice: Codex itself rejects every turn of that provider.

    For Claude and Codex, /channel tokens (CHANNEL_* refs) belong to the active DSH_HOME only. Disconnecting a channel cannot revive a token from the default home; reconnect it in the active home if needed. Provider env_key credentials retain the fallback described above.

    TPS includes hidden reasoning time and excludes tool execution time. Live text estimates are corrected when Codex reports output token usage. Decode spans of 500ms or less are excluded from TPS samples; token and cost totals still include all reported usage.

    Native browsing/archive, fork/conversation rewind (the first message requires Codex app-server 0.160.1+), paged history, images, subagents, polled background terminals, goals and /btw//recap use the existing surfaces. /logout removes only the matching dsh-auth credential; already-loaded managed tokens require a normal restart, not native logout. The real 0.160.1 app-server passed nine credential-free offline checks and eight daemon-resume checks, with no model turn or charge; real subscription login, credentialed model calls and real-TTY interaction were not run. Only Codex identification/title changes automatically, not palette or companion. Using ChatGPT subscription tokens in third-party clients is subject to OpenAI’s terms. Full instructions and current boundaries: Codex backend.

    Experimental: DSH Agent Teams

    DSH's experimental Agent Teams lets the session's agent (the Lead) create named teammates that share the working directory, message each other and coordinate on a shared task board. It ships with dsh, is off by default, and /plugin list advertises it. Switch it on:

    /plugin enable @deepseek-ai/dsh-experimental-agent-team-profile
    

    The switch enables or disables the bundle in the profile, so it persists across restarts, and on a dsh --profile launch it applies at once — running sessions included: the model is told which tools came and went. /team appears in Help and / completion only once the team service is mounted, and only reports: /team (or /team status) shows the bundle, the service and this session's teammates. /team on|off was removed; typing it points at /plugin enable|disable. Turning the bundle off while teammates run asks first, and switching off stops them: the team service releases the teammates still running as it unloads. Inside a teammate session the other teammates' runs are not visible, so the question counts them as possibly running. The team record stays in the session and comes back when the bundle is enabled again.

    If the running DSH does not ship the bundle (/plugin list stays silent), switch DSH to one of the supported lines first (0.2.2-rc.1, 0.2.1-rc.5, 0.2.1-rc.4, 0.2.1-rc.3, 0.2.1-rc.2, 0.2.1-alpha.5, 0.2.0-rc.1 or 0.2.0-rc.2). To install it into the profile explicitly, run dsh plugin --profile dsh-tui add @deepseek-ai/dsh-experimental-agent-team-profile@<your-dsh-version>: the team packages ship in lockstep with DSH and pin their DSH peers exactly, so the version must match.

    While a request carries spawn_teammate, dsh-TUI drops subagent / subagent_fork from it, and the team's send_message / list_agents / interrupt_agent / wait_agent take the place of the legacy controls of the same names, so spawn_teammate is the delegation tool; with the team off the legacy tools are back. Subagents that are not team members (workflow, ralph) keep subagent. A teammate shows up as a subagent row, a message between members as a ✉ <sender> bubble in the receiving session (a teammate's received messages show on its subagent detail as agent messages), and the other team tools as one-line cards (send_message with its target and sent). The agents dashboard (Ctrl+A) and the agents side panel switch to a team view: each teammate under its member name with running / idle / provisioning / failed (a teammate whose turn ended is idle — a message wakes it — not done), the Lead line, the remaining subagents, a read-only task board (status, owner, blocked, write-scope warnings) and a banner when the team record was rejected. A delegation provider whose settled runs fail at least twice and at least half the time gets one degraded-channel line above the list; the built-in subagent route, workflow members and per-type Claude children are excluded because there is no provider to switch to.

    Limits: the switch covers the whole profile, not one session (a launch without the profile plugin service, or without hot reload, needs dsh plugin and a restart); there is no "enter teammate session" yet, and /export leaves team messages out. Upstream limits apply: teammates share one working directory, a team lives in one process, and a task owner is never released automatically. Subagent failure badges and the Companion error state share session-scoped unread status. Opening that child’s detail or main view acknowledges only that failure; a new run or failure alerts again. Acknowledgements survive panel remounts and session switches during this process, but a cold restart starts unread. Opening the dashboard alone does not acknowledge every child. Task status stays failed.

    Keybindings & Mouse

    Enter send · Tab complete · Ctrl+Enter interrupt and send · Alt+Up recall the last message · Esc closes local layers before interrupting a running turn, double-Esc rewinds on empty idle input · Ctrl+B side panel · Ctrl+O details · Ctrl+R history (↑/↓ and Ctrl+R are scoped to the current project) · Ctrl+V paste · Ctrl+Shift+E fullscreen draft editor · ? shortcuts · ← open the session manager (DSH backgrounds the current session first). In both the launchpad and chat, Ctrl+U deletes from the caret to the current line start, preserving text to the right and whole image chips. It edits only the focused input.

    In the launchpad input, Shift+Enter (or Option+Enter) opens chat and inserts a newline at the caret, keeping the draft and staged images unsent. Continue typing there, then press Enter to send.

    In both the launchpad and chat, Alt/Option+←/→ moves by whitespace-delimited words and Alt/Option+Backspace deletes the previous word, like Ctrl+W. On macOS, configure your terminal to send Option as Meta.

    Use Alt+Up / Alt+Down to page through question text and details, or approval previews on very short terminals, without moving the choice focus; these keys are remappable in /settings → Shortcuts. Fullscreen also supports the wheel over the preview. Complete OAuth links remain readable when browser and clipboard helpers are unavailable. Fixed-action permission questions offer only the caller's choices; ordinary questionnaires still accept free text.

    Text, cursor position and staged image attachments on the launchpad or in chat while the backend starts are preserved when the session becomes ready. Press Enter after it is ready to send; an earlier Enter preserves the draft without queuing it. Opening a new session while startup is pending clears the previous draft and its images.

    The goal bar stays on one summary line: hovering truncated goal text in fullscreen or split shows the whole objective, and a bare /goal prints the full status — objective, phase, rounds or budget, available commands — as a transcript block in the /plugins shape. Inline mode sees no pointer events, so that block is how its users read a long objective.

    While the model is working: Enter steers, Tab queues a follow-up, Ctrl+Enter interrupts and sends. Input that names a command is still a command — with or without arguments — so /model or /new reach their own gate (and the / overlay sinks the commands that affect the running conversation) instead of silently becoming an interruption; only text that is not a command — and a direct skill gesture such as /skill-name … — steers.

    When DSH ends a turn because its session was disposed, the transcript shows “Session stopped”; user interruption keeps its existing prompt for what to do next. This describes the reported stop reason and does not recover a stuck session or its queued inputs.

    Windows Neovim/Vim terminals identified by NVIM or VIM_TERMINAL retain VT input instead of enabling ConPTY mode 9001. For another incompatible embedded host, set DSH_TUI_DISABLE_WIN32_INPUT_MODE=1 before launch (PowerShell: $env:DSH_TUI_DISABLE_WIN32_INPUT_MODE="1"). The same gate applies at startup and after resume. Native Windows Terminal, conhost and VS Code keep their existing mode unless disabled; the opt-out can remove modified-Enter reporting.

    Extended key reporting (Kitty keyboard protocol and xterm modifyOtherKeys) is enabled for a fixed terminal list: iTerm2, kitty, WezTerm, Ghostty, rio, Orca, tmux, Warp and Windows Terminal. A terminal missing from that list can opt in with DSH_TUI_FORCE_EXTENDED_KEYS=1, and DSH_TUI_DISABLE_EXTENDED_KEYS=1 opts an allowlisted terminal back out for SSH or nested xterm.js hosts (it wins when both are set). Outside native Windows, where win32-input-mode reports Enter's modifiers instead and is not touched by this switch, a terminal without extended keys cannot tell Shift+Enter from Enter, and Ctrl+J is the newline fallback.

    On native Windows, fragmented Win32 input records are reassembled across short input delays instead of appearing as numeric protocol text. The platform check only reports that this machine might run the private mode (win32-input-mode); a bare ESC[ fragment is held only after one record has actually been decoded, while a fragment whose own shape is already record-specific holds on its own (which is how even the first record can survive a split). Windows terminals that never enter the mode (mintty, GitBash) therefore keep the classic VT path: a lone Esc keeps its normal response time, and a letter typed after a timed-out ESC[ is not swallowed.

    Incomplete records are held for a bounded recovery window (1 second from first capture, never extended by later input; 64 bytes max); past either bound the hold ends and input is handled as before. Unrecognized complete CSI sequences are not inserted as text; after a damaged CSI prefix, a bare ASCII letter can be consumed as its terminator, while normal Win32 key records and bracketed-paste text retain their own boundaries.

    A session's very first record can still leave residue if it is split before its record-specific shape forms; once any record has been decoded, every split position is covered. Inside the recovery window, literal input starting with [digit;… cannot be told apart from a protocol prefix — it may be held, or re-joined to a preceding Esc. To type it, wait for the window to close, or avoid that shape right after Esc.

    Terminal replies that arrive split are reassembled the same way (native Windows ConPTY is the common source): while the app still has a query awaiting its answer, an unfinished DA1 / DA2 / DSR / DECRPM / XTVERSION tail — even one split again after the introducer Esc was flushed — is held across input delays, but only while its shape can still complete into the response type that query expects. It is then consumed as the reply it completes instead of entering the prompt as protocol text.

    That claim is evidence-gated, and this is the difference from earlier builds: no query awaiting an answer means nothing is claimed, so a literal [?61;4c typed right after Esc still enters the prompt exactly as before.

    The window is bounded like the record hold (about a second, never extended by later input; 64 bytes max); past either bound it ends, and bytes still shaped like an unfinished reply prefix are dropped rather than shown.

    Inside that window, with a query of the matching response type outstanding, same-shaped literal input can still be claimed as a reply; to type it, wait for the window to close (about a second), or avoid that shape while a query is outstanding.

    Fragmented SGR mouse reports no longer land in the prompt as text: an incomplete report header is held until the rest arrives, and a report that completes is handled as a mouse event. The hold is armed only while mouse reporting is actually active (fullscreen, with mouse tracking enabled); inline sessions and terminals that never enable tracking keep the existing behavior. The claim window is bounded from first capture (at most 1 second; 64 bytes max), and a continuation arriving inside it is still claimed rather than replayed. Release has no timer: once a parse call sees either bound exceeded, it replays the held bytes as ordinary keys in arrival order — literal input can be delayed, but is never dropped. A completed text-only assistant reply containing only a leading ⏵ status line remains visible in the conversation and can be selected for copying. Live status lines and status lines followed by a real answer stay out of the transcript body.

    Plugin slash-command results, including errors, remain as local transcript blocks for scrolling and copying during the current session. Indentation and line breaks are preserved. Each report retains at most 200 lines, 65,536 UTF-16 code units and 4,000 terminal cells per line, plus a visible truncation marker. The local display rows are not sent as model input or replayed as conversation history. The backend may separately persist command audit events and their results. Older local report blocks are evicted within the shared 600-row budget. Explicit built-in report layouts (such as /goal) keep their existing formatting.

    Mouse (fullscreen): drag to select and copy, double/triple click to select a word or line, click tool cards, timeline ticks and [Image #N] previews.

    Automatic copies keep the text selected; press Esc to clear it or start a new selection to replace it. Selection highlighting skips trailing padding and blank rows while preserving spaces within text and code indentation. Inline mode uses the terminal's native selection.

    When a fullscreen selection starts in a code block's body, soft-wrapped rows join without adding frame padding or newlines, in both light and full frames. Hard line breaks and the existing hard-line inset remain part of screen copying.

    During a fullscreen text drag, the native cursor follows the selected text's edge using your terminal's enabled cursor animation or trail effects. Moving into trailing padding or blank rows keeps it at the nearest selected text edge. Releasing or cancelling the drag restores the focused input's caret.

    File paths in prose can open the file-action menu; automatic detection does not extract a path from inside a slash-delimited token such as working/idle/needs-input or a date such as 2024/01/15.

    Pasting: the launchpad accepts clipboard images and pasted image paths as [Image #N] attachments; Enter sends them with the first message. Commands that do not accept images preserve the draft and its attachments. Image chips behave like chat: arrows step across them, Backspace at the end or Delete at the start removes the whole image, and Ctrl+W never splits a chip. Text pasted on the launchpad is folded to one line. In chat, native and bracketed paste keeps ordinary text and newlines, and never submits itself on arrival. On Windows terminals that deliver a paste as win32-input-mode key records, a record stream leaked into the payload is decoded back into the characters its Uc field encodes — newlines included — so the composer's line count matches what was pasted; only records with no character meaning are stripped (a multi-line paste no longer leaves stray _), and a complete record is always consumed before an ESC-less tail, so no payload character is deleted along with an orphan escape. Pasted CRLF collapses to a single newline; genuine underscores and bracketed-paste text are untouched.

    Dropped files: a native Windows desktop drop (Windows Terminal / OpenConsole) arrives as an OSC 8 hyperlink; the parser restores its file:// URI to a decoded local path before paste hygiene runs, so the ]8;id=…; parameter bytes never reach the draft. Image paths enter the existing image staging pipeline; other files are inserted as a referenceable path (a path containing whitespace arrives in the composer's quoted "…" single-token form). Only file:// URIs are restored, and it is fail-closed: a remote authority/UNC, a payload carrying several distinct URIs, or a URI that carries several tokens is refused and stays literal text rather than guessed. Fullscreen drag-copy uses the final highlight. If a live row changed during a drag, move the selection back to stable text to establish a new baseline. A stationary selection whose copied text changes is still refused; automatic scroll/resize does not clear that protection.

    The pixel whale, large title and context/TPS colors follow the same terminal color depth as other text: monochrome, 16-color, 256-color or truecolor. Apple Terminal and tmux use the shared fallback; NO_COLOR and FORCE_COLOR retain the existing shared color policy.

    If resume reports that another DSH process owns the writer, release the session in that process (for example, dsh web) and retry in the same TUI. The foreground session stays intact; do not delete session or lock files to bypass single-writer protection.

    Full reference: Interaction and commands.

    Built-in Commands

    /resume · /home · /agentview · /bg · ⌸ open the same session manager: workspace rail, live state, filter, ★ pins. Also /model /new /compact /export /btw /tree /fork /rewind /settings /setup /status /cost /jobs /skills /mcp /provider /auth /login /update.

    On DSH, /fork keeps the current session open and creates a resumable copy; a copy with history records its parent and appears in the same session family.

    /dsh, /codex, and /claude switch directly to the named kernel, just like choosing it in /kernel: the choice is remembered and the process restarts into a new session. A running turn blocks switching; choosing the current kernel keeps the session. Availability checks and the Claude install wizard follow the same picker flow.

    /model shows models and reasoning effort on one page. DSH has provider tabs with Recently used first, moving the current model to the top; Tab / Shift+Tab select the next / previous provider. Codex and Claude open their model catalogs directly, without provider or recents tabs. ↑/↓ select a model, ←/→ adjust its effort, Enter applies the model and any explicit effort draft, and Esc cancels. Changing only the model preserves the backend's preference handling. Mouse users can click the available tabs, models, effort levels, and select/cancel hints; clicking an effort level immediately applies the focused model and that effort and closes the picker. The wheel moves through models.

    Short terminals keep the focused model and select/cancel actions visible, hiding descriptions and neighboring models first, then the effort row when only two rows remain. Shortcuts sit below the title and effort levels have their own section; DSH, Claude, and Codex use the terminal background while covering the text underneath.

    In /provider's model list, focus a model and press Tab to edit its context window, max output tokens, reasoning efforts, and image input capability.

    The session manager focuses the most recently used session in the current workspace; if there is no history, it focuses the new-session card. Moving between the workspace rail and session list preserves the selected session, including when the mouse enters the list. Switching to another workspace selects its latest session; switching back also starts from its latest session instead of restoring an earlier selection. Press ← to move to the workspace rail. DST preloads the session list in the background after startup and updates the cache on success. The manager paints the last successful list immediately. Opening /resume while that read is pending shares the request and receives results that have already arrived. This first-paint snapshot survives restarts on DSH, Claude and Codex and is isolated by backend and storage directory. With or without a snapshot, all three backends prioritize the current workspace before filling in other workspaces. Fresh sessions and titles merge into the list immediately; cached rows from other workspaces remain until the full read finishes. Background updates preserve a session the user has selected manually. Claude and Codex first request up to 32 recent sessions within their native cwd scope: Claude's SDK includes Git worktrees in the same repository, while Codex matches the session cwd exactly. Codex listings reuse the running connection and read the first 32 regular results alongside the state DB shortcut, then fill in later pages. The browser groups sessions by their own cwd. DSH resolves the current workspace's metadata first and publishes it before reading other workspaces' logs, even when it has fewer than 32 sessions. Titles that require a deeper DSH log scan appear first with a fallback name and update in place when recovery finishes. The session manager shows the selected workspace's absolute path once, beneath the source tabs (wrapping when needed; hover reveals exceptionally long paths). Session rows show their title and essential status/time instead of repeating the directory; DSH size and model remain in the title tooltip. With DSH's current JSONL backend, startup and /new keep initial permission events in memory until further session activity saves the complete log. Flushing a session that holds only initialization leaves it unstored. Restarting an unstored empty session starts fresh. The project rail uses one line per directory on every backend and source tab; the selected project’s path appears once above the panes.

    Removing a workspace registration keeps its sessions accessible under a "History only" directory in the rail. History-only directories offer edit and new-session actions; rename and remove are available for registered workspaces.

    If a /resume attempt fails or is cancelled before switching, it releases any session occupancy acquired by that attempt so the session can be retried.

    On Linux, stale TUI occupancy and mount locks can be reclaimed when the old PID has been reused by a non-leader thread. This requires readable /proc identity data in the same PID namespace; uncertain identities remain occupied. Reuse by another process can still retain a stale claim, so this is not a general fix for PID reuse across platforms.

    Background jobs: card headers open the focused task panel. Click the card body or use Ctrl+O to toggle the command between its first statement and full script. Commands and output use separate colored edges with ❯ (> on Windows) and ≡ on their first rows; output always stays at the latest two visible rows. /jobs and the side panel keep the full output scrollable, while e toggles the focused command. Consecutive blank script lines collapse to one.

    Background sessions: On the DSH backend, /bg or ← on an empty prompt backgrounds the current session and opens the session manager; Esc returns to it. Background sessions run in this process and stop when the TUI exits. Logs survive. On Claude/Codex, those entries open the session manager without backgrounding the session.

    Full commands: Interaction and commands.

    Configuration & Extensions

    Agent presets, themes, MCP servers, environment variables: Configuration · Themes.

    With the DeepSeek brand, Companion skins deepy and whaleGirl replace the maid portrait; choose whale and enable Maid portrait to use it. Claude uses its own artwork; Codex uses its own raster portrait or the maid character-art fallback. Both brands ignore these settings for splash artwork. See Configuration.

    DSH profiles inherit official reporting defaults: DeepSeek API requests carry plugin package identities and incremental Session logs to the configured baseURL, including third-party gateways, while OpenTelemetry uploads a Session-log prefix only after explicit feedback. User overrides remain supported; see reporting settings.

    How It Works

    dsh profile → dsh-base → dsh-TUI Cordis patch → agent preset + DSH services
      → session/event → Channel projection → React components → Ink/Yoga renderer → terminal
    

    The TUI handles interaction and presentation. The session log is the source of truth. DSH services own models, tools, and persistence. Long sessions render in O(visible window).

    Runtime path, module boundaries, performance notes and persistence locations: Architecture and limitations.

    Known Limitations

    • Injected plugin context has no standalone display; it counts into the context segments.

    • /model changes the next request’s route in the same session; history and session ID are preserved. The last used route is recorded when the next request starts. On DSH 0.2.2, API/plugin selections also update the next-model readout; late events from a previously fixed step do not overwrite the selected model's capacity metadata. DSH versions before 0.1.2-alpha.3 refuse switching and prompt an upgrade because their subagents inherit the original route.

    • Ctrl+V needs platform clipboard tools; unsupported bitmap formats are rejected.

    • Windows Terminal/ConPTY sixel frames check the last transmitted raster’s cursor position before parking, using measured cell geometry and encoded band controls. Detected drift uses the same physical clear and redraw as Ctrl+L. Probes allow one pending reply (500 ms), skip resize/handoff, and pause for 60 seconds after an unanswered query or three repairs within 10 seconds. Set DSH_TUI_SIXEL_CURSOR_HEAL=0 to disable; DSH_TUI_DEBUG records probe/recovery decisions. This bounded mitigation cannot detect every kind of pixel corruption or repair ConPTY itself.

    • Shutdown drains only the actual renderer-owned input after terminal cleanup and a 150-ms settle window. Embedders retaining only unmount keep that input lease; wrappers replacing the method must pass the renderer’s shutdownInput lease to finishExit. Custom input drains its own buffered bytes; a device-specific kernel drain can be supplied as the bounded synchronous render({ drainStdin }) callback. Revoked/replaced owners and non-TTY input are not drained. The window does not guarantee arbitrary SSH latency.

    • Local Windows copying uses PowerShell with UTF-8 stdin. Copies run in order; each PowerShell attempt has a two-second timeout (Windows PowerShell, then PowerShell 7). If both fail, OSC 52 remains the fallback and requires terminal support. SSH never writes the remote native clipboard.

    • Catchable exits explicitly end synchronized output (DEC 2026) as part of terminal cleanup, even without a final frame. SIGKILL, native aborts and a fully blocked JavaScript event loop cannot guarantee in-process cleanup; recovery then requires the terminal or an external supervisor.

    • While the TUI owns an active raw input, it reasserts OS raw mode on input-gap/focus recovery and every five seconds without waiting for a key. This repairs externally reset cooked/ECHO state even when Node still reports isRaw=true; recovery may take one interval while the event loop runs. The periodic check stops during editor pauses and shutdown/handoff and does not resend display protocols.

    • A dropped file is restored from its OSC 8 file:// URI alone: multi-file drops, non-Windows terminal drop encodings and terminator-less truncated frames are not covered, and the hyperlink's own display name is never used.

    • A background session lives inside this process and stops when the TUI exits.

    • /thinking is not persisted; the kernel minimal agent preset (极简模式, one persistent-shell tool) mounts no compaction and does not prune tool results — a long session can hit the context limit, oversized tool output stays in the context in full, and /compact plus the questionnaire are unavailable under it (Help and / completion mark the entry, and entering the preset says so once); that is a different thing from the /settings → Minimal UI (极简界面) display switch; /update needs a dsh --profile launch and is refused while a turn is running.

    • The status-bar ≈¥ and /cost are session estimates that include subagent usage (priced per each agent's model × peak/idle × cache components); unofficial or unlisted models show tokens only and are marked unpriced. The platform bill is authoritative.

    • Fragmented SGR mouse reports are covered at the mechanism level with controlled fixture comparisons; the reporter environments (macOS → SSH, WSL2 with dsh web) have not been re-tested.

    Full list: Architecture and limitations → Known limitations.

    Development

    pnpm dev keeps the full install/build/pack checks by default. For explicit local iteration, set DSH_TUI_DEV_FAST=1 (for example, DSH_TUI_DEV_FAST=1 pnpm dev -- --no-launch). A miss runs frozen install, compile, pack without repeating prepare, and isolated profile installation. An unchanged hit skips all four stages only while source/config and compiler-loader contents, Node/pnpm/npm/dsh versions, compiled and vendor output, the tarball, and the installed package/profile match. Replacing pnpm/npm/dsh without changing its reported version requires one normal (non-fast) development run. Internal document links such as CLAUDE.md -> AGENTS.md are fingerprinted; external, excluded, dangling or cyclic links and unreadable inputs disable reuse with a diagnostic. Failures invalidate the success stamp before work begins. The script prints stage durations and cache hits. Run normal pnpm build and focused regressions before publishing; fast mode does not change release gates. The monorepo development host (pnpm tui, scripts/run.ts) enables heap forensics only with DSH_TUI_HEAP_WATCH=1; unset it or use 0 to disable it. It samples every 15 seconds and takes one snapshot at each heap threshold of 1024, 1536, 2048, 2560 and 3072 MiB. Its own completed files in $DSH_HOME retain at most four 64-KiB logs and two snapshots totaling at most 1024 MiB. DSH_TUI_HEAP_MAX_MB changes the snapshot budget (integer 1–16384; invalid values use 1024). A single oversized snapshot is removed too; the latest diagnostic may therefore be a