dsh-local-terminal
August 15, 2026 · View on GitHub
为 DeepSeek Harness Web UI 提供 VS Code 风格的本机 zsh 终端。
A VS Code-style local zsh terminal plugin for the DeepSeek Harness web UI.
功能
- 终端嵌入对话区底部,不遮挡聊天内容和输入框。
- 点击
Terminal展开或收起面板,关闭按钮也可收起;`Ctrl+`` 快速开关。 - 面板顶边可拖动调整高度,双击恢复默认高度。
- 终端与终端列表之间的竖直分割线可拖动调整宽度,双击恢复默认宽度。
- 支持多个相互独立的 zsh 会话。
- 终端列表支持切换、关闭,以及右键重命名或关闭。
- 终端列表标签页支持上下拖动排序(白色指示条预览插入位置)。
- 面板收起后保留 PTY、输出、滚动位置和进程状态。
- 面板开关、尺寸、会话列表(命名/顺序)与激活标签持久化到 localStorage,刷新页面自动恢复。
- WebSocket 断线自动重连(指数退避);服务端 PTY 断线保留 60 秒并重放断线期间的输出。
Cmd+V/Ctrl+Shift+V粘贴;Ctrl+Shift+F或Find按钮在终端内搜索。Cmd+A全选、Cmd+K清屏(均提供Ctrl+Shift+别名,不劫持 shell 的Ctrl+A/Ctrl+K)。- 终端区域右键菜单:Copy / Copy as HTML / Paste / Select All / Clear / Restart,视口内自动避让。
- 标签右键
Split Terminal竖向分屏,同一组最多 6 个窗格,全部共享组名(如zsh 1);侧边栏每组显示为一行并带数量角标。 - 双窗格分割线可拖动(双击复位);3 个及以上窗格等宽排列。点击窗格切换焦点(蓝色描边提示)。
Join Terminals把组内窗格拆回独立标签;关闭组会关闭组内全部终端。- 分屏组、窗格顺序与分割比例随会话状态一起持久化。
- 右键终端列表空白处或空舞台:
New Terminal新建会话、Move Tabs Left/Right切换标签栏位置、Hide Tabs隐藏标签栏;布局偏好持久化。 - 面板标题行提供 VS Code 风格的终端选择器(
zsh 1 ▾,与 Find/Clear/Restart 并列):点击弹出下拉,列出全部终端组(✓ 当前组)并可直接切换,底部提供Show Tabs恢复标签栏。 - 面板高度变化时通知对话视图重新布局,避免虚拟列表裁切滞后。
- 使用 xterm.js、Unicode 11 宽度规则和 Nerd Font 回退字体。
环境要求
- macOS。
- DeepSeek Harness,且已配置
webprofile。 - Node.js
22.19或更高版本。 - 系统存在
/bin/zsh。
插件会启动真实的本机 shell。终端中运行的命令拥有启动 dsh web 的用户权限,请只在可信设备和可信 DSH 插件环境中使用。
安装
从 GitHub 安装到 DSH 的 web profile:
dsh plugin --profile web add github:Daisuki0721/dsh-local-terminal
安装后启动或重启 Web UI:
dsh web
浏览器打开 DSH 页面后,Terminal 按钮会显示在 Agent preset 右侧。
从本地源码安装
git clone https://github.com/Daisuki0721/dsh-local-terminal.git
cd dsh-local-terminal
pnpm install
pnpm build
dsh plugin --profile web add "$PWD"
使用
- 点击对话区顶部的
Terminal打开底部面板。 - 点击工具栏的
+创建新的 zsh 会话。 - 点击右侧终端名称切换会话。
- 右键终端名称进行重命名或关闭。
- 拖动面板上边界调整高度;双击上边界恢复默认高度。
- 拖动终端列表左侧的竖直分割线调整列表宽度;双击恢复默认宽度。
- 再次点击
Terminal或点击面板右上角的关闭按钮收起面板。
快捷键:Ctrl+`` 开关面板;Cmd+V/Ctrl+Shift+V 粘贴;Ctrl+Shift+F 打开搜索(Enter 下一个、Shift+Enter 上一个、Esc` 退出);刷新页面后会话列表、命名、顺序与面板尺寸自动恢复,运行中的 shell 会在 60 秒内重连并保留输出。
Clear 只清除当前终端的可见缓冲区;Restart 只重启当前 zsh 会话。
安全设计
后端 WebSocket PTY 路由采用以下限制:
- 只接受
127.0.0.1、localhost和 IPv6 loopback 请求。 - 校验浏览器请求的 Host、Origin 和同源关系。
- 拒绝浏览器标记为 cross-site 的请求。
- 对 WebSocket 输出设置背压上限。
- 每个 WebSocket 连接对应一个独立 PTY,连接销毁时终止其 shell。
不要把 DSH Web 服务代理到不受信任的公网地址。loopback 校验是本插件安全边界的一部分。
更新
dsh plugin --profile web remove @dsh-external/dsh-local-terminal
dsh plugin --profile web add github:Daisuki0721/dsh-local-terminal
卸载
dsh plugin --profile web remove @dsh-external/dsh-local-terminal
开发
pnpm install
pnpm typecheck
pnpm test
pnpm build
项目结构:
src/index.ts Host 插件入口
src/routes.ts loopback WebSocket upgrade 路由
src/pty-session.ts node-pty 会话管理
src/client/ Web UI、终端列表和布局逻辑
cordis.patch.yml DSH loader 插件声明
构建产物位于 lib/。插件仅依赖公开发布的 @deepseek-ai/* SDK,不需要 DeepSeek Harness 源码 checkout。
常见问题
安装后没有出现 Terminal 按钮
确认插件存在于 web profile,然后完整重启 dsh web。单纯刷新浏览器不能加载新的 Host 插件。