🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

工作区终端 emircanerkul/dsh-terminal

DeepSeek Harness
emircanerkul42 天前有提交已提供中文文档扫描:含敏感能力

在聊天页内嵌分屏终端,按工作区保留会话

28.2/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/7 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add emircanerkul/dsh-terminal
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么
dsh 原生插件 · dev
装得上吗
曾在 dsh 0.2.0-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.1-rc.5,本站尚未在新版下复验
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 42 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 19 处,展示前 19 条)
  • 发起网络请求
    client.js:66
    fetch('/terminal/shortcuts', { headers: { 'cache-control': 'no-cache' } })
  • 发起网络请求
    client.js:102
    fetch('/terminal/shortcuts', {
  • 发起网络请求
    client.js:116
    fetch('/terminal/shortcuts', {
  • 发起网络请求
    client.js:170
    fetch('/terminal/shortcuts')
  • 读取本地文件
    src/index.js:35
    const BOOT_JS = readFileSync(ASSETS['term-boot.js'], 'utf8')
  • 读取本地文件
    src/index.js:46
    const parsed = JSON.parse(readFileSync(path, 'utf8'))
  • 写入本地文件
    src/index.js:54
    mkdirSync(dirname(path), { recursive: true })
  • 写入本地文件
    src/index.js:55
    writeFileSync(path, JSON.stringify(obj, null, 2))
  • 启用终端会话(PTY)
    src/sessions.js:87
    : nodePty.spawn('/bin/bash', ['-l', '-i'], opts)
  • 读取本地文件
    src/http.js:16
    const buf = readFileSync(file)
  • 执行外部命令固定命令
    src/http.js:27
    execFile('/usr/bin/which', [cmd], (err, out) => cb(!err && out.trim()))
  • 执行外部命令固定命令
    src/http.js:35
    execFile('/bin/ps', ['-axo', 'pid=,ppid=,comm=,args='], { maxBuffer: 8 * 1024 * 1024 }, (err, out) => {
  • 发起网络请求
    web/embed.js:408
    fetch('/terminal/workspace' + q, { headers: { 'cache-control': 'no-cache' } })
  • 发起网络请求
    web/embed.js:467
    fetch(url, { headers: { 'cache-control': 'no-cache' } })
  • 发起网络请求
    web/embed.js:577
    fetch('/terminal/bin?cmd=' + nav, { headers: { 'cache-control': 'no-cache' } }).then(function (r) { return r.json() }).then(function (j) { var btn = n
  • 发起网络请求
    web/embed.js:601
    fetch('/terminal/shortcuts', { headers: { 'cache-control': 'no-cache' } })
  • 发起网络请求
    web/terminal/boot.js:68
    const dataDispose = term.onData((d) => fetch(base + '/input?token=' + TOKEN + '&cwd=' + encodeURIComponent(CWD), { method: 'POST', headers: { 'content
  • 发起网络请求
    web/terminal/boot.js:73
    fetch(base + '/resize?token=' + TOKEN + '&cwd=' + encodeURIComponent(CWD), { method: 'POST', headers: { 'content-type': 'application/json' }, body: JS
  • 发起网络请求
    web/terminal/boot.js:125
    fetch(base + '/input?token=' + TOKEN + '&cwd=' + encodeURIComponent(CWD), { method: 'POST', headers: { 'content-type': 'text/plain' }, body: c + '\r'
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 内嵌分屏终端
  • 按工作区保留会话
  • 流式PTY终端

面向 DeepSeek Harness(dsh)的工作区感知网页终端插件,在 /terminal 跑流式 PTY 终端,并内嵌由 xterm.js 驱动的分屏终端停靠栏。

README

由 DeepSeek 最新模型翻译生成
dsh-terminal ⚠️ 已停止维护。 从 v0.1.6-alpha.1 起,dsh 已在 Web 侧边栏内置官方终端(支持多标签页、选择 shell、刷新后恢复会话)。本插件不再维护,也不再需要——请改用内置终端。 面向 DeepSeek Harness(dsh)的、感知工作区的 Web 终端插件。 由 web 配置档以宿主插件形式加载:它在 /terminal 提供终端页面(PTY 输出走 SSE 流式传输,按键通过 POST 发送),并把分屏终端停靠栏嵌入聊天栏,让你不用离开页面就能对当前工作区运行 nvim/lazygit。 演示 快速浏览感知工作区的终端停靠栏。 为什么说它「感知工作区」 - 每个工作区根目录一个 PTY,SSE 断开后依然存活——切换对话时,各工作区的终端和回滚缓冲都会保留。 - 会话受 LRU 上限(默认 8)和空闲回收器双重约束,所以再也不会访问的终端最终会被释放。 - 停靠栏会向服务器询问当前活跃聊天的权威工作区根目录(并对照真实的工作区注册表校验),从而锁定目标。
展开完整文档(README 剩余 1 节)
dsh-terminal

⚠️ 已停止维护。 从 v0.1.6-alpha.1 起,dsh 已在 Web 侧边栏内置官方终端(支持多标签页、选择 shell、刷新后恢复会话)。本插件不再维护,也不再需要——请改用内置终端。

面向 DeepSeek Harness(dsh)的、感知工作区的 Web 终端插件。
由 web 配置档以宿主插件形式加载:它在 /terminal 提供终端页面(PTY 输出走 SSE 流式传输,按键通过 POST 发送),并把分屏终端停靠栏嵌入聊天栏,让你不用离开页面就能对当前工作区运行 nvim/lazygit。

演示

快速浏览感知工作区的终端停靠栏。

为什么说它「感知工作区」

- 每个工作区根目录一个 PTY,SSE 断开后依然存活——切换对话时,各工作区的终端和回滚缓冲都会保留。
- 会话受 LRU 上限(默认 8)和空闲回收器双重约束,所以再也不会访问的终端最终会被释放。
- 停靠栏会向服务器询问当前活跃聊天的权威工作区根目录(并对照真实的工作区注册表校验),从而锁定目标。

安装

直接从 GitHub 仓库安装:

dsh plugin --profile web add github:emircanerkul/dsh-terminal
dsh web

或者克隆到本地,再从本地目录安装:

git clone https://github.com/emircanerkul/dsh-terminal.git
cd dsh-terminal
npm install
npm run check
dsh plugin --profile web add .
dsh web

加载

web 配置档通过补丁层挂载本插件,并按包名解析它(这样 DSH 运行时的客户端插件发现机制才能找到它的 dsh.client 部分——即「设置 → 插件」卡片)。在 cordis.patch.yml 中:

- insert:
- id: terminal
name: 'dsh-terminal'

同时把 dsh-terminal 链接进配置档的共享安装目录,让加载器和客户端模块扫描器都能解析到它:

ln -s /absolute/path/to/dshterm ~/.dsh/profiles/node_modules/dsh-terminal

插件在 package.json 中声明了客户端部分(dsh.client +
exports["./client"],实现在 client.js),用来贡献「设置 → 插件」卡片;宿主通过
GET/POST /terminal/shortcuts 提供配置,并存放在一个小文件存储里(~/.dsh-terminal/shortcuts.json),因此插件保持自包含,从不等待共享的设置服务。插件行见 src/index.js(inject: ['webServer', 'sandboxPolicy'])。

目录结构

terminal.mjs entry point (re-exports src/index.js — the mounted path) src/ host-side server code index.js plugin assembly + teardown, idle-reaper timer constants.js 限制、MIME 表、资源清单、路径根、开关 palette.js 唯一固定的终端配色(没有主题切换器) pty.js 单一 node-pty 访问器 sessions.js PTY 生命周期管理器(LRU + 空闲回收) http.js 请求体读取器 / 静态服务器 / JSON 文本响应辅助函数 workspace.js 工作区根解析辅助函数 auth.js 页面 token 签发 + ?token= 校验辅助函数 page.js /terminal 页面 HTML 构建器 routes/ 所有 HTTP 路由 + 聊天栏嵌入注入点(按区域拆分) index.js installRoutes() 装配 + 共享路由辅助函数 terminal.js /terminal、/stream、/input、/resize、/kill api.js /bin、/workspace、/debug、/sessions assets.js /terminal/assets/* embed-tap.js 聊天栏嵌入注入 web/ 浏览器端资源,由 /terminal/assets/* 提供 embed.js 聊天栏 SPLIT-PANE 停靠区(客户端 iframe LRU) terminal/ 终端页面引导 + 内置 xterm fonts/ nvim/lazygit PUA 图标使用的 Nerd Font test/ 单元测试(TerminalSessions)+ 模块冒烟测试框架

配置 / 静态资源映射

src/constants.js 保存各项开关值(MAX_SESSIONS、MAX_CLIENTS_PER_SESSION、 IDLE_MS、REAPER_MS、MAX_INPUT_BYTES、MAX_RESIZE_BYTES),以及 ASSETS 清单,把公开的 /terminal/assets/<name> URL 映射到 web/ 下的文件。

HTTP 接口(需鉴权 = 来自 /terminal 页面的 ?token=)

| 方法 | 路径 | 用途 |
| GET | /terminal | 终端页面(签发鉴权 token) |
| GET | /terminal/stream | SSE:工作区的 PTY 输出 |
| POST | /terminal/input | 把按键输入送进 PTY |
| POST | /terminal/resize | 调整 PTY 大小 |
| GET | /terminal/bin | 命令(lazygit/nvim)是否在 PATH 上? |
| GET | /terminal/proc | 当前占用该工作区终端的可执行文件(或 null) |
| GET | /terminal/debug | 最近一次嵌入上报的检测诊断信息 |
| GET | /terminal/workspace| 权威的活动工作区根 + 列表 |
| GET | /terminal/sessions| 各工作区实时 PTY 调试列表 |
| GET | /terminal/shortcuts| 生效的停靠区热键(Settings → Plugins → Terminal) |
| POST | /terminal/kill | 结束某个工作区的终端 |
| GET | /terminal/assets/| 静态文件(embed、bootstrap、xterm、fonts) |

键盘快捷键

停靠区注册全局快捷键,无论焦点在哪都会触发——聊天、侧边栏,还是终端本身(配置会转发到终端页面,该页面在 xterm/lazygit 看到它们之前捕获匹配的组合键,然后让 dock 执行动作):

| Action | Default | Notes |
| Toggle dock | Ctrl+\ | restores the last size/position (persisted) |
| Toggle popup mode | Ctrl+Shift+\ | open/close the full-screen floating modal |
| Open lazygit | Ctrl+Shift+G | → lazygit, only at an idle shell prompt |
| Open nvim | Ctrl+Shift+E | → nvim ., only at an idle shell prompt |

重新打开时会恢复之前的尺寸和分屏,因为这些按工作区持久化。启动器会先请求 /terminal/proc,它会扫描当前工作区的 PTY 进程树,查找任何非 shell 程序(lazygit、nvim、vim、htop……)。如果有程序在运行——不管是什么——快捷键就不会输入新命令;而是弹出一条简短提示,让你先关闭正在运行的应用(Ctrl+C / :q)。所以当 lazygit 开着时按 Ctrl+Shift+E,不会在它上面输入 nvim .——而是弹出提示「running lazygit — close it first」。另一个工作区或独立终端里的 lazygit 永远不算数:每次 /terminal/proc 调用只遍历当前活动工作区的 PTY。

快捷键与布局无关:每个快捷键同时匹配 event.key 或* event.code(物理按键,且可接受多个 code)。在 US 布局上,1 左边的键是 Backquote;在 UK/ISO(「British PC」)布局上,该键报告 IntlBackslash(在 Ctrl 下产生 key="0"),所以切换键同时匹配两者,因此在那种布局上 Ctrl+ 也能切换 dock。mod 取值为 ctrl | meta | alt | any;注意 Cmd+ 是 macOS 上的系统「切换窗口」快捷键,所以 meta 默认值永远到不了页面——ctrl 才是安全的跨平台默认值。每个绑定通过 key(字符)、code(物理按键;可给出多个 code)或两者同时设置。切换/模态同时接受 US 的 Backquote 和 UK/ISO 的 IntlBackslash 物理 code。

在 Settings → Plugins → Terminal 中配置绑定。 设置卡片通过 GET /terminal/shortcuts 读取当前绑定,并通过 POST /terminal/shortcuts 保存;宿主将它们持久化到 ~/.dsh-terminal/shortcuts.json。dock 在每次页面加载时从 GET /terminal/shortcuts 获取生效配置,并合并覆盖 web/embed.js 中的默认值(不再有 localStorage 覆盖路径)。web/embed.js 每页都会重新加载,所以在设置面板中保存后,普通浏览器刷新就能应用新绑定。

Development

npm run check # syntax-check every source + web asset
npm test # unit tests for PTY lifecycle (TerminalSessions)
node test/smoke.mjs # mount the plugin against a mock ctx (wiring smoke test)

Reload behaviour (important):
- web/embed.js is injected as a tiny loader that pulls /terminal/assets/embed.js
每次页面加载都从磁盘重新读取 —— 嵌入内容的修改,普通刷新浏览器即可生效。
- web/terminal/boot.js 只在模块加载时读取一次,然后固化进 /terminal 页面,所以改 boot.js 需要重启 web 配置档。
- src/** 下的服务端改动同样需要重启 web 配置档。
- Settings → Plugins → Terminal 卡片来自 dsh.client 那一半,所以只有重启 web 配置档、重新对齐 loader 条目名,并且浏览器加载新的客户端 bundle 之后才会出现(页面也要刷新)。此后,保存的绑定刷新一下就会在 dock 里生效。

赞助

由 erklab 赞助 —— 以生产级系统构建,兼具 AI 驱动的速度与以人为本的精度。
预览分享卡片长什么样 ↓emircanerkul/dsh-terminal
分享 · DeepSeek Harness Hub
emircanerkul/dsh-terminal

在聊天页内嵌分屏终端,按工作区保留会话

回到顶部