DSH Plugins Marketplace

DSH Plugins

Plugins

/

Development & Infrastructure

/

dsh-uniterminal

W

dsh-uniterminal

Identified★ 2

在 DSH 右侧栏里提供 SSH 终端、SFTP 文件管理与端口转发的插件;密码交给操作系统密码箱保管,插件自身不实现加密。SSH terminal, SFTP and port forwarding in the DSH right sidebar. Remembered passwords live in the OS credential store; the plugin implements no crypto of its own.

UniTerminal · DSH 远程终端插件

npm license CI GitHub

SSH / SFTP / 端口转发,挂在 DSH 右侧栏里。一个侧边栏标签里装多条会话(顶部会话栏切换;同一台主机连两次显示 #2), 每条会话的终端、文件、隧道三视图并列。

截图

主机列表:分组 · 搜索 · 行内「测试 / 连接」,行尾 ⋯ 是其余操作终端:一个侧边栏标签装多条会话,顶部会话栏切换(同一主机连两次显示 #2)
连接表单:记住的密码交给操作系统密码箱SFTP:目录浏览、上传下载、进度外观:字体、字号、行高、主题模式

截图使用演示数据(主机名 demo01–demo03,地址为 RFC 5737 文档保留段 192.0.2.0/24)。 图片用绝对 URL 引用:npm 页面不解析相对路径,相对写法在 npmjs.com 上会显示破图。

状态

项值
版本0.2.18(0.x:API 与配置项仍可能变,按语义化版本升号;变更见 CHANGELOG)
许可证MIT(见 LICENSE)——可自由使用、修改、商用,保留版权声明即可
环境DSH >=0.2.1-rc.2、Node >=20

本插件把密码交给操作系统密码箱保管(Windows 凭据管理器 / macOS 钥匙串 / Linux Secret Service),自己不实现任何加密。 只有「这台机器没有系统密码箱」时才回落到明文文件,并在界面上如实说明——细节见 docs/SECURITY.md。

主机管理 → 连接 → ┌ 终端 (xterm + shell)
                  ├ 文件 (SFTP:浏览 / 上传 / 下载 / 删除)
                  └ 隧道 (-L 本地转发 / -R 远程转发 / -D SOCKS5)

安装

前提:DSH >=0.2.1-rc.2(见本包 package.json 的 dsh.engines)、Node >=20。

一条命令(推荐)

DSH 自带 CLI 会把「装包 + 登记到 profile」一步做完:

dsh plugin --profile desktop add @winking-r/dsh-uniterminal@latest

--profile 填你的 profile 名 —— ~/.dsh/profiles/ 下有哪些目录就用哪个(常见 desktop 或 web)。 装完重启 DSH,右栏会出现 UniTerminal 标签。

装的时候命令以退出码 1 结束、并打印 Ignored build scripts: cpu-features, ssh2,是预期现象——包已经装好了, 但自动登记可能被这一步打断。确认 dsh.profile.bundles 里有本包名,没有就手动加一行(见「故障排查」)。

profile 目录在工作区之外:若你的会话按 workspace-write 沙箱运行(例如让 AI 代装), 写 ~/.dsh/profiles/<名>/ 会被拒绝(EPERM)。放行一次全权限,或干脆自己在终端里跑那两条命令。

没装 dsh 命令,或者要装本地构建(link: / tgz)时,用下面的手动方式,效果等价。

手动方式(等价,两步)

cd ~/.dsh/profiles/desktop

# npm 上的正式包
pnpm add @winking-r/dsh-uniterminal

# 或者:改代码即生效(开发用)
pnpm add "link:<本仓库绝对路径>"

# 或者:装打包好的 tgz(不需要自己构建)
pnpm add "file:<tgz 绝对路径>"

然后在 ~/.dsh/profiles/desktop/package.json 的 dsh.profile.bundles 数组里追加一行本包名:

"@winking-r/dsh-uniterminal"

重启 DSH。若右栏没有自动出现本插件,用右栏的 + 手动添加一个 UniTerminal 标签。

装完怎么确认真的好了

命令说"成功"不算数,冷启动跑一次才算。三条都能验,都不需要看源码:

检查怎么做期望
宿主半边挂了请求 http://127.0.0.1:<DSH 的端口>/api/uniterminal/health{"ok":true}
AI 工具注册了问 AI 能不能列会话;或看 ~/.dsh/uniterminal/diag.log 里的 agent-tools.registered 事件uniterminal_list_sessions 与 uniterminal_exec 都在
凭据进了系统密码箱~/.dsh/uniterminal/security.json 的 storage 字段keychain 且 degraded 为 false(不是 file)

三条都对,就可以放心把密码交给它了。

右栏承载:官方 sidebarRight 或第三方 DSH-better-sidebar

本插件双注册 + 运行时探测(src/client/right-pane.ts):

你的 DSH 里装了插件注册到结果
DSH-better-sidebarctx.betterSidebar(优先)右栏像 IDE 那样多标签并存,本插件占一个标签
只有官方 @deepseek-ai/dsh-client-ui-sidebar-rightctx.sidebarRightTabs回落到官方右栏标签

两种都能用;没有 better-sidebar 也能跑(会自动回落)。 若右栏始终不出现本插件,先确认这两者至少有一个已启用 —— 诊断见 docs/acceptance-m0.md(target=none 表示两套注册表都不可用)。

改动代码后必须重启 DSH:宿主半边(lib/index.js)在启动时加载,硬刷新页面不会生效。

卸载

# 先从 dsh.profile.bundles 里删掉本包名,然后
cd ~/.dsh/profiles/desktop
pnpm remove @winking-r/dsh-uniterminal

重启 DSH。主机档案与凭据留在 ~/.dsh/uniterminal/,如需一并清除请见下方「数据存放」。

功能

域能力
主机添加 / 编辑 / 删除(二次确认)/ 分组;从 ~/.ssh/config 导入;连接前「测试」连通性;孤儿会话可接管或关闭(接管不需要重新输入密码)
认证密码、私钥(读本地路径或粘贴内容)、两者可同时启用;按主机「记住密码」;跳板链 ProxyJump
终端xterm.js,自适应尺寸,断线重连;面板重挂载与页面刷新后会话与输出不丢(存档落 sessionStorage)
文件SFTP 浏览、多选上传(带进度、可取消)、下载、新建目录、删除
隧道-L 本地转发、-R 远程转发、-D SOCKS5;仅监听 127.0.0.1;随会话关闭自动回收
AI 可调用注册两个工具:uniterminal_list_sessions(发现会话)与 uniterminal_exec(在会话里执行命令并取回 stdout/退出码)。任何 AI 会话无需额外上下文即可使用。默认 mode=exec(独立通道、不碰用户终端);mode=shell 会把命令与标记打进用户正在看的终端并留在屏幕上,仅用于延续 shell 状态

配置项(DSH 插件设置)

键默认说明
termxterm-256color终端 TERM 类型
bufferBytes1 MiB(1048576)每个会话的输出回放缓冲
connectTimeoutMs20000连接超时(毫秒)
knownHostsPolicyreject未知主机指纹策略:reject 拒绝并要求显式信任 / trust 自动信任并落盘
agentExecon面向 AI 会话的 exec 入口:off 时既不注册 uniterminal_exec 工具,/sessions/exec 也一律 403
appearance内置默认终端外观默认值(字体、字号、行高、字距、主题模式与四个颜色)。用户改过的值存 ~/.dsh/uniterminal/appearance.json;插件写不了宿主配置,只把这里当默认值来源

数据存放(~/.dsh/uniterminal/)

文件内容敏感性
profiles.json主机、分组、认证方式、跳板链。绝不含密码或私钥内容低
credentials.json记住的口令与粘贴的私钥(明文)——只在没有系统密码箱的机器上存在高
security.json凭据登记(mode: plain + storage: keychain|file,即"密码存在哪")低
vault.bin旧版(已停用)加密凭据文件——不再被读取,可在界面上「清理旧版凭据」删掉—
known_hosts.json已信任的主机指纹低
appearance.json终端外观偏好(字体、字号、行高、主题与颜色),只影响界面低
diag.log诊断事件(不含任何凭据内容)低

安全

密码存在哪、谁能读到它、怎么清、怎么迁移:docs/SECURITY.md(威胁模型 + 已知限制)。

一句话版:有系统密码箱就用系统密码箱(Windows 凭据管理器 / macOS 钥匙串 / Linux Secret Service), 插件自己不实现任何加密;没有系统密码箱的机器回落明文文件,界面上会如实说明。

已知限制(请先读这一段)

  1. 凭据存在哪,取决于这台机器有没有系统密码箱:
    • 有(Windows 凭据管理器 / macOS 钥匙串 / Linux Secret Service)→ 密码交给操作系统保管,插件不实现任何加密;旧的明文库会逐条搬进密码箱,搬完删掉,不留明文副本。
    • 没有 → 回落明文文件 credentials.json,靠 chmod 0600 与 Windows 账户目录权限保护;Windows 上 chmod 实际无效,真实防护来自 NTFS ACL。不要在多用户共用的机器上勾选「记住密码」。
    • 密码箱这一刻用不了(被锁 / 服务没起)→ 临时改用本机文件,界面会明说;此前存在密码箱里的条目暂时取不到。 界面表单页常驻小字会说明当前用的是哪一种(详见 docs/SECURITY.md)。 早期试用版若在本机留下旧格式凭据文件,界面会提示「清理旧版凭据」——清理只删掉那份读不出来的旧数据,明文库里已记住的密码不受影响。
  2. 不提供终端锁屏(明确不做的决策,不是遗漏)。离开座位时已连接的会话没有保护——需要时请自行锁屏或断开连接。
  3. -R 远程转发可用,但停止隧道不会立即释放服务端的远端端口,要等会话关闭(ssh2 不提供 cancel-tcpip-forward);在此期间到达的连接会被明确拒绝,不会穿透。
  4. 跳板链每跳使用同一套凭据(同一口令或同一私钥)。「跳板机用 A 钥、目标机用 B 钥」尚未支持。
  5. 覆盖式上传优先用 OpenSSH 的 posix-rename@openssh.com 做原子替换;服务器不支持时会退化为「先删目标再改名」,存在极短窗口(目标暂时不存在)。
  6. SFTP 路径记忆、-R 端口即时释放在待办中。
  7. shell 模式拒绝交互式/全屏程序(vi/vim/nano/less/top/htop/watch/man/tmux/screen/ssh/su):它们会占满用户终端、提示符回不来。按分段首词判定,sudo vim、xargs vim 之类仍可绕过——真正的防线是审计日志。
  8. AI 命令执行的安全边界:工具默认开启,但只能操作你已打开的会话——AI 无法自行建立连接或提交凭据。每次执行都会写入 diag.log(命令预览截断 120 字符并 scrub 口令/私钥)。如不需要,把 agentExec 设为 off。

结构

src/
  index.ts           宿主入口:注册路由、装配 store、启动 WS 桥
  routes.ts          HTTP API(全部 exact 路由 + loopback 围栏)
  ws-bridge.ts       终端 WebSocket(每会话一条升级路径,回放 ring buffer)
  config.ts          插件配置 schema
  engine/            协议无关层
    types.ts           SessionHandle / 通道能力接口
    registry.ts        协议注册表(ssh 已实现;telnet/serial 留位)
    ssh-transport.ts   ssh2 适配:认证、跳板链、SFTP 通道缓存、转发通道
    session-manager.ts 会话生命周期、重连、通道能力访问器
    ring-buffer.ts     输出回放缓冲
    sftp.ts            SFTP 能力与三级 rename 策略
    tunnel.ts          -L/-R/-D 隧道管理与回收
  store/             持久化
    profile-store.ts / known-hosts.ts / security.ts / ssh-config-import.ts
  client/            React 半边(预打包进 __ModuleLoader__)
    UniterminalTab.tsx  列表 / 表单 / 三视图切换
    TerminalView.tsx    xterm 封装
    SftpPanel.tsx       文件面板
    TunnelPanel.tsx     隧道面板

API 一览

全部 29 条路径(src/routes.ts 的 UNITERMINAL_ROUTES)。除最后一行的内部端点外,都是用户可见接口; 所有端点都要求 loopback 来源,非回环地址一律 403。

方法路径用途
GET/api/uniterminal/health健康检查
GET/POST/api/uniterminal/profiles主机列表(GET)/ 新增与编辑(POST)
DELETE/api/uniterminal/profiles/<id>删除主机
POST/api/uniterminal/profiles/import导入 ssh_config(预览,不写盘)
POST/api/uniterminal/profiles/test测试连通性
POST/api/uniterminal/profiles/key · /profiles/key/delete粘贴私钥 / 清除
POST/api/uniterminal/profiles/forget-password取消「记住密码」并删掉那条凭据
POST/api/uniterminal/folders新建分组
POST/api/uniterminal/folders/rename分组改名
POST/api/uniterminal/folders/delete删除分组
GET/api/uniterminal/groups分组列表
POST/api/uniterminal/groups/color设置分组颜色
POST/api/uniterminal/hosts/trust首次连接信任主机指纹(写入 known_hosts.json;指纹已变则 409 拒绝)
GET/POST/api/uniterminal/appearance外观设置:读取(GET)/ 保存增量(POST)
GET/POST/api/uniterminal/sessions会话列表(GET)/ 建立会话(POST)
POST/api/uniterminal/sessions/exec执行命令(mode: exec 独立通道 / shell 打进当前 shell)
POST/api/uniterminal/sessions/close断开连接
GET/POST/api/uniterminal/sftp/download · /sftp/upload流式下载 / 上传
POST/api/uniterminal/sftp/opls / stat / mkdir / unlink / rmdir / rename / chmod
GET/POST/api/uniterminal/tunnels隧道列表(GET)/ 启动(POST)
POST/api/uniterminal/tunnels/stop停止隧道(-R 的服务端端口要等会话关闭才释放)
GET/api/uniterminal/security凭据状态(mode 恒为 plain,另带 storage / degraded / legacy:密码存在哪、是否临时降级、本机是否还留着旧版文件)
GET/api/uniterminal/security/refs已记住的条目名(只有名字,没有密钥)
POST/api/uniterminal/security/clear-legacy清理旧版凭据文件(破坏性动作,body 需 confirm: true)
WS/api/uniterminal/ws/<sessionId>终端数据流
GET/POST/api/uniterminal/diag · /monitor · /sftp/upload-progress内部用:前端诊断上报、状态栏采样轮询、上传进度轮询。供本插件前端自己用,接口形状不承诺稳定

开发与验证

pnpm typecheck    # tsc --noEmit
pnpm test         # vitest,915 用例 / 64 文件
pnpm build        # tsdown → lib/index.js (ESM) + lib/client.js (CJS)

915 个用例覆盖:路由匹配器(复刻宿主 prefix 语义)、凭据库与密码箱降级、profile store 与分组迁移、SFTP 通道复用、隧道 loopback 围栏与回收、跳板链 sock 传递、上传原子提交与中断清理、前端组件的键盘可达性与对比度。

验收记录见 docs/acceptance-*.md,决策与踩坑台账见 docs/superpowers/plans/ledger-m0.md(含 20 余条裁定与教训)。

故障排查

出问题先看 ~/.dsh/uniterminal/diag.log——事件里只有 id、路径、状态与错误文本,不含口令或私钥(写入前 scrub)。 报问题时把最后 50 行贴出来,足够定位大多数故障。

tail -n 50 ~/.dsh/uniterminal/diag.log

常见症状:

症状先查什么
装的时候报 ERR_PNPM_IGNORED_BUILDS、命令退出码 1包其实已经装好了。 ssh2 的可选加速件 cpu-features 声明了构建脚本,pnpm 默认不执行它们、并因此以非零码退出。副作用是自动登记那一步会被跳过——去 ~/.dsh/profiles/<你的 profile>/package.json 的 dsh.profile.bundles 里手动加一行 "@winking-r/dsh-uniterminal",再重启 DSH 即可
插件在右栏不出现dsh.profile.bundles 里有没有追加本包名;重启过 DSH 没有(硬刷新不够)
连接报 unknown host key主机指纹未信任;走一次「首次连接信任主机指纹」流程,或在设置里把 knownHostsPolicy 设为 trust
提示「系统密码箱不可用」密码箱被锁 / 服务没起;此时新密码会临时写进本机文件,此前存在密码箱里的条目暂时取不到
状态栏一直空白远端不是 Linux(解析器按 /proc 取值),或该会话已断开

设计取舍(供后续维护参考)

  • 认证方式以界面为准:请求里带 auth 就覆盖磁盘存档;未表态时才用存档默认值。明确表态(只选私钥)失败就报错,绝不静默降级用密码。
  • 能力访问器,不暴露会话句柄:SessionManager 只暴露 openSftp(id) / openTunnels(id),路由层拿不到会话控制面。
  • SFTP 每连接一个通道(缓存 Promise + 失效重建);隧道通道与真实 TCP 连接 1:1。
  • 上传原子化:写临时文件 → 成功才改名;中断或失败清理临时文件。
  • 诊断日志不含凭据:diag.log 只记 id / 路径 / 错误文本,口令与私钥在写入前 scrub。

许可证

MIT © 2026 WinKing-R

可以自由使用、修改、分发、商用,保留版权与许可声明即可。软件按「原样」提供,不附任何担保—— 这个插件会连 SSH、执行命令、读写远端文件,请自行承担使用风险。

Comments

Loading…

From the same category

awesome-dsh-plugin

by awesome-dsh-plugin

A curated list of plugins for DeepSeek Harness (dsh) · DeepSeek Harness 插件精选列表

Development & Infrastructure

★ 21.5k

CC0-1.0

Python

Oct 29, 2026

Index only — not installable

by 0xsline

DeepSeek Harness (DSH) ecosystem: curated plugins, tools, and infrastructure from dsh-external/hub and the public dsh-plugin topic.

Development & Infrastructure

★ 1.3k

CC0-1.0

Python

Oct 16, 2026

Index only — not installable

by Yuuyuko-uu

DSH 鱼的记忆:给会话一份会淡忘的长期记忆,每条都带时间

Development & InfrastructureMemory & ContextSessions & MessagesManifest valid

★ 394

MIT

JavaScript

Oct 29, 2026

dsh plugin --profile web add dsh-fish-memory

by pax-beehive

Open-source CLI, schemas, resolver, and DSH agent tools for DSH Plugin Hub

Development & Infrastructure

★ 276

MIT

TypeScript

Oct 20, 2026

Index only — not installable

by xiajiajun516

DeepSeek Harness (DSH) backup & restore plugin — export, import, migrate and sync your complete DSH configuration, plugins, MCP servers, skills and workspace. One-click migration to another machine.

Development & InfrastructureManifest valid

★ 274

MIT

TypeScript

Oct 29, 2026

dsh plugin --profile web add dsh-config-manager

by ECNU

DBLP and arXiv literature search, BibTeX retrieval and full-text acquisition with session-owned background jobs; an EduWork-maintained fork of SihanLv/dsh-literature.

Tools & CapabilitiesUI & ExperienceDevelopment & InfrastructureMemory & Context

★ 259

MIT

JavaScript

Oct 30, 2026

Index only — not installable