DSH Web 界面的可停靠 IDE 工作台:GPU 加速终端(restty 渲染器 + Rust PTY)、CodeMirror 编辑器、文件浏览器、笔记、沙箱浏览器,以及基于 ripgrep 的内容搜索。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:FleetingEcho/dsh-powerdesk
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本。请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 简体中文
一个 DSH Web 插件,为 DSH 的 Web 界面加上一个 小型 IDE 工作台:GPU 加速的终端、文件浏览器、笔记、代码编辑器、一个 沙箱化的浏览器,以及一个日历 —— 全部自包含,置于一个可停靠的右侧面板 和 一个可停靠的底部面板中(VSCode 风格的双工作台,支持拖拽分屏与跨面板拖拽)。
- 终端 —— 用 restty 渲染
(WebGPU/WebGL2 + WASM VT,Ghostty 血统),后端是 Rust PTY
(napi-rs + portable-pty),
而非原生终端使用的 C++
node-pty。 - 文件浏览器 —— 在任意本地文件夹(通过内置文件夹浏览弹窗选取,而非文本输入框)之上 呈现的目录树。点击文件即在编辑器中打开;每个文件行都有快捷的「复制相对路径」(便于 在聊天中 @ 提及)和「复制绝对路径」操作。
- 笔记 —— 绑定一个本地文件夹,以递归树浏览/编辑其下的
.md文件,支持笔记与 文件夹的内联新建 / 重命名 / 删除。编辑器内嵌于同一标签页(左侧树、右侧编辑器)。 - 编辑器 —— CodeMirror 6,支持 TS/JS/Python/JSON/CSS/HTML/Markdown/Rust/YAML 语法高亮、可选择的 CodeMirror 主题(默认 Dracula)、软换行、Cmd/Ctrl+S 保存。在文件浏览器或笔记中点击文件时自动打开。
- 浏览器 —— 地址栏背后的沙箱 iframe,带有可嵌入性探测,能解释
X-Frame-Options/frame-ancestors拒绝原因,而不是显示空白的「拒绝连接」框。 - 日历 —— schedule-x 日历(月 / 周 / 日视图),基于
一个本地 SQLite 数据库(一个全新的 Rust napi 模块,内置 SQLite,与 PTY crate 同级);
懒加载,绝不在启动时拖慢性能。事件持久化在
<profile 目录>/powerdesk-calendar.db。
这六个功能都以标签页形式出现在插件自有的侧边栏中 —— 一个右侧面板(宽度自由 拖拽、无上限)和一个底部面板(高度可拖拽,横向铺满整个窗口宽度,包括右侧面板下方)。

为何选择 Powerdesk
- 真正快的终端 —— restty(WebGPU/WebGL2 + WASM VT,Ghostty 血统)渲染于 Rust PTY(napi-rs + portable-pty)之上,而非原生终端使用的 C++
node-pty—— 终端 I/O 显著更快、更轻量。 - 不离开聊天的完整 IDE —— ripgrep 内容搜索、CodeMirror 6 编辑器、文件浏览器、笔记、沙箱浏览器,全部作为标签页置于可停靠的右面板 + 底面板中。无需上下文切换离开 DSH 页面。
- 双面板 VSCode 风格工作台 —— 把任意标签页拖到面板边缘即可分屏,或在右/底面板之间整体迁移;两棵分屏树共享同一套拖拽系统。
- 零构建安装 ——
lib/与 macOS / Linux-x64 的 Rust PTY 二进制均已提交,dsh plugin add只是拷贝文件:无构建步骤、无需 Rust 工具链、无需allowBuilds条目。 - 打造你自己的标签页 —— 把一个 React 组件加
powerdesk.json打包成.tgz,即挂载为侧边栏标签页;模板(templates/extension/)让你几分钟内pnpm pack出成品。 - 默认沙箱化 —— 浏览器标签页不带
allow-same-origin运行,拒绝回环地址,并探测X-Frame-Options/frame-ancestors以解释拒绝原因,而非显示空白框。
快速安装
dsh plugin --profile web add https://github.com/FleetingEcho/dsh-powerdesk.git
需要 DSH >=0.0.1,且 dsh CLI 在 PATH 中。安装后硬刷新浏览器(Cmd/Ctrl+Shift+R)。终端在 macOS(两种架构)与 Linux x86_64 上开箱即用;其它平台首次使用时构建一次 Rust PTY(见安装)。
环境要求
- DSH
>=0.0.1,且dshCLI 在PATH中(dsh --version)。加载进某个 DSH profile(默认web)。 - Node.js 20+ 和 pnpm 9+(若从源码安装)。
- Rust 工具链(
rustup)—— 仅当你的平台还没有已提交的预编译二进制时才需要;macOS 用户永远不需要 Rust。
PTY 插件按平台三元组查找(src/rust-pty-deps.ts)。三个三元组已有已提交到仓库的二进制,随每次安装分发;其余平台首次使用时从源码构建:
| 操作系统 | 架构 | 三元组 | 预编译? |
|---|---|---|---|
| macOS | Apple Silicon | darwin-arm64 |
✅ 已提交 |
| macOS | Intel | darwin-x64 |
✅ 已提交 |
| Linux | x86_64 (glibc) | linux-x64-gnu |
✅ 已提交 |
| Linux | aarch64 (glibc) | linux-arm64-gnu |
从源码构建 |
| Windows | x86_64 | win32-x64-msvc |
从源码构建 |
| Windows | ARM64 | win32-arm64-msvc |
从源码构建 |
安装
只选一种 —— 不要同时启用两个通道(会让 host 半边双重挂载并渲染出两个侧边栏)。目前没有发布 npm 包,两个通道都直接从 GitHub 仓库安装。
方式 A —— 从 GitHub(推荐)
dsh plugin --profile web add https://github.com/FleetingEcho/dsh-powerdesk.git
仓库是公开的,因此普通 HTTPS URL 即可匿名安装。pnpm 会从仓库里读出包名,不需要 dsh-powerdesk@ 前缀 —— 不过 dsh-powerdesk@<url> 可用来锁定分支或标签(...git#my-branch)。偏好 SSH?git+ssh://git@github.com/FleetingEcho/dsh-powerdesk.git 也可以(需要 GitHub 上已注册 SSH key)。
lib/(构建好的 client/host JS)与 macOS / Linux-x64 的 Rust PTY 二进制都已提交,因此无构建步骤、无需 allowBuilds —— 终端在这些平台上立即可用。
cd ~/.dsh/profiles/web/node_modules/dsh-powerdesk
pnpm build:rust # 需要 Rust 工具链(rustup);cargo build --release
方式 B —— 从源码(用于开发)
git clone https://github.com/FleetingEcho/dsh-powerdesk.git
cd dsh-powerdesk
pnpm install
pnpm build # tsc (lib/types) + tsdown (lib/*.js + 懒加载 chunk)
pnpm build:rust # cargo build --release → prebuilt/<triple>/dsh_powerdesk_pty.node
pnpm test # vitest(可选自检)
# 把本地 checkout 注册到你的 DSH profile。
# 用绝对路径(link:. 相对于 profile 目录解析会损坏):
dsh plugin --profile web add "dsh-powerdesk@link:$PWD"
任一方式之后:硬刷新浏览器(Cmd/Ctrl+Shift+R)。客户端半边改动热重载无需重启 DSH;host 半边改动(src/*.ts,含 Rust PTY 层)需重启 DSH(pm2 restart dsh-web,或 dsh web)。
使用
点击窗口右上角的切换按钮簇 —— 一个打开/折叠右面板,另一个控制底面板。把标签页拖到面板边缘即可分屏,拖到中心则合并/重排,从一个面板拖到另一个则整体迁移。每个打开的标签页在非活动时都保持挂载,因此切换标签页不会丢掉终端的连接或编辑器的撤销历史。
终端
在当前会话的工作目录打开;每个会话可开多个终端,直到配置的配额上限(标签页标题显示序号:Terminal 1、Terminal 2、…)。工具栏有复制按钮。字体家族 / 字重 / 大小与终端主题是持久化偏好 —— 在「设置 → Powerdesk」编辑。如果原生 PTY 二进制缺失或加载失败,终端会显示带修复命令的修复横幅(见修复)。
文件浏览器
点击头部的文件夹名按钮打开文件夹浏览弹窗(逐级点入子目录,「选择此文件夹」)。可添加多个文件夹书签并从同一按钮切换。点击目录行展开,点击文件行即在编辑器中打开(打开文件会自动把文件浏览器分到独立面板一次,避免编辑器叠在上面)。悬停文件行显示:@ 复制相对于书签根的路径(便于 @ 提及),另一个复制图标复制绝对路径。
笔记
首次使用会提示绑定一个文件夹(随时可点击文件夹名重新绑定)。笔记递归列出该文件夹下所有 .md / .markdown 文件 —— 子树中不含 markdown 的目录会被整枝剪掉 —— 并在树(左)旁呈现内联编辑器(右,可经分隔条调节),两者同处一个标签页。头部操作:新建笔记、新建文件夹;每个文件的操作(悬停):重命名、删除(删除文件夹是递归的)。
编辑器
不直接打开 —— 它是文件浏览器和笔记打开文件的目标。基于 CodeMirror 6,支持 TypeScript/JavaScript、Python、JSON、CSS、HTML、Markdown、Rust、YAML 语法高亮;可选择的 CodeMirror 主题(默认 Dracula),在「设置 → Powerdesk」选择,并对已打开的编辑器即时生效(auto 跟随应用明暗模式)。软换行;Cmd/Ctrl+S 写回。有未保存编辑时标签页显示一个脏点。
浏览器
在地址栏输入 URL 回车。地址栏上有后退 / 前进 / 刷新 / 在浏览器中打开按钮。
- 沙箱 —— iframe 不带
allow-same-origin运行(被访问页面无法读取 GUI 的存储或访问其 API),也不带allow-top-navigation。一个临时解锁按钮会为可信站点放下沙箱;沙箱关闭时红色状态条告警。 - 地址栏 —— 只接受
http/https;javascript:、data:、file:被拒绝。回环地址(localhost、127.0.0.0/8、::1、0.0.0.0)被拒绝,以免被浏览页面探测本地服务。 - 嵌入拒绝 —— 当站点设置
X-Frame-Options/ 不允许*的frame-ancestorsCSP 时,插件会先探测 header,并显示带**「在浏览器中打开」和「强制加载」**的原因面板,而非空白框。这是浏览器层面强制的、按站点的限制;「在浏览器中打开」是从这里查看此类站点的唯一方式。 - 外链 —— 浏览器标签页认领
http://外链点击(聊天中点 http 链接在侧边栏打开);https://留给系统浏览器。
日历
一个 schedule-x 日历(月 / 周 / 日视图),基于本地 SQLite 数据库。点击**「新建事件」**创建(标题经提示输入),拖拽即可移动/调整时长,点击事件确认删除。数据库位于 <profile 目录>/powerdesk-calendar.db,事件在重启与插件更新后仍保留。该标签页为懒加载 —— schedule-x 及其 preact 运行时仅在首次打开时下载,绝不在启动时加载 —— 当平台缺失 SQLite 原生二进制时,标签页降级为修复横幅。
设置
「设置 → Powerdesk」为每种标签类型显示一张带启用开关的卡片 —— 关闭某标签类型会把它从每个面板的 + 菜单隐藏,并使 openTab 对它空操作(持久化在 localStorage)。点击卡片主体即打开该功能面。

卡片下方是一个外观区块,包含终端的字体家族 / 字重 / 大小,以及两个主题选择器 —— 终端主题与Codemirror 主题 —— 各带「系统默认」选项以跟随应用明暗模式。任一更改都会即时应用到已打开的终端 / 编辑器。

更新
# 方式 A(GitHub 通道)—— pnpm 固定已解析的 commit,升级需移除再添加:
dsh plugin --profile web remove dsh-powerdesk
dsh plugin --profile web add https://github.com/FleetingEcho/dsh-powerdesk.git
# 方式 B(源码)—— 拉取、重建,仅在改了 host 半边时重启:
git pull && pnpm install && pnpm build && pnpm build:rust
然后硬刷新浏览器。host 半边改动需重启 DSH;客户端半边只需硬刷新。
卸载
dsh plugin --profile web remove dsh-powerdesk
# 源码通道:还需回退你加到 profile 的 link: 依赖,再 pnpm install。
硬刷新(或重启 DSH)让挂载行消失。
修复
如果终端显示 "Rust PTY loading failed" —— 即原生 PTY 二进制缺失、损坏或为错误平台构建 —— 就地重建(无需重装):
cd ~/.dsh/profiles/web/node_modules/dsh-powerdesk # GitHub 通道
# — 或你的本地 dsh-powerdesk checkout # 源码通道
pnpm build:rust # 需要 Rust 工具链(rustup)
然后硬刷新并重启 DSH(host 半边启动时重新读取二进制)。
安装排错
插件安装但未加载 —— 检查 bundle 行是否已添加;dsh.profile.bundles 必须在依赖旁列出 dsh-powerdesk:
cat ~/.dsh/profiles/web/package.json
如果依赖在但 bundle 行不在,插件就以普通依赖挂载、永不加载 —— 这是损坏的 link: 安装的症状(见方式 B 注释);用绝对路径或「安装 → 方式 A」的 git URL 重新添加。host 半边改动只在 DSH 重启后生效。
配置
插件配置(在 dsh.profile.bundles 中)
dsh-powerdesk:
terminalsPerSession: 3 # 每个会话的最大活动终端数
reconnectGraceMs: 30000 # 掉线的 pty 保持这么久以便重连
shell: '' # 覆盖交互式 shell('' 则自动探测)
extensionsEnabled: false # 允许用户安装扩展(见「扩展」)
extensionsDir: '' # 扩展存放位置('' = ~/.dsh/powerdesk/extensions)
用户偏好(localStorage,无 host 往返)
| 偏好 | 存储 key | 说明 |
|---|---|---|
| 终端字体家族 / 字重 / 大小 / 主题;CodeMirror(编辑器)主题 | dsh-powerdesk:prefs |
在「设置 → Powerdesk」(外观)中编辑。 |
| 文件浏览器文件夹书签 | dsh-powerdesk:explorer-bookmarks |
多个书签及当前活动项。 |
| 笔记绑定文件夹 | dsh-powerdesk:notes-folder |
单个文件夹,可重绑。 |
| 笔记树列宽 | dsh-powerdesk:notes-tree-width |
经分隔条拖拽。 |
| 每种标签类型的开关 | dsh-powerdesk:tabs-enabled |
从设置卡片设置。 |
环境变量
| 变量 | 用途 |
|---|---|
DSH_POWERDESK_PTY_PATH |
指向 .node 插件的绝对路径;优先级高于一切解析。 |
DSH_POWERDESK_PTY_TRIPLE |
覆盖探测到的平台三元组(如 linux-x64-musl)。 |
DSH_RESTTY_SHELL |
覆盖 Windows shell 探测(默认:PATH / 已知安装目录中第一个 pwsh.exe,否则 powershell.exe)。 |
PREBUILT_BASE |
覆盖预编译二进制下载基 URL(默认:GitHub releases)。 |
DSH_HOME |
覆盖 DSH home(默认 ~/.dsh)。 |
DSH_CMD |
覆盖 install.sh 使用的 dsh CLI(默认:dsh,然后 npx)。 |
扩展
Powerdesk 可以把你自己的 React 组件挂载为侧边栏标签页。一个扩展就是一个打包脚本加一份 powerdesk.json 清单,以 .tgz 从设置卡片上传。
安全 —— 先读这一段
扩展运行在 DSH 页面自身的 origin 内,对 DOM、你的会话和网络有完全访问权 —— 与 Powerdesk 自身特权相同。没有沙箱(且在扩展共享 host 的 React 实例的前提下也不可能存在)。这是一个可信本地扩展功能,不是市场:只安装你读过代码或信任作者的代码。该功能默认关闭 —— 有意开启:
dsh-powerdesk:
extensionsEnabled: true
安装 / 移除
设置 → Powerdesk → 扩展 → 上传扩展… 接受的上传(按字节而非文件名判定):.tgz / .tar.gz / .tar(根目录必须含 powerdesk.json),或裸 .js / .js.gz(卡片询问 id 和显示名)。每个扩展原子安装到 <extensionsDir>/<id>/;卡片显示磁盘路径和来源归档的 sha256。移除 删除该目录;想不卸载就禁用,用其卡片上的开关。
编写
cp -r templates/extension ~/my-extension
cd ~/my-extension && pnpm install
$EDITOR powerdesk.json # 选一个 id 和标题
pnpm build && pnpm pack # -> my-extension-0.0.0.tgz
组件契约、清单参考及扩展加载机制见 templates/extension/README.md。不要打包 React —— 它是外部的,host 把它自己的实例传给你;第二份 React 有自己的 hook dispatcher,你调用的每个 hook 都会抛错。
限制: 上传 16 MiB,解压后归档 32 MiB,每归档 64 文件,每文件 8 MiB。含符号链接、硬链接、设备节点、绝对路径或 .. 段的归档在解析时即被拒。
开发
pnpm install
pnpm build # tsc (lib/types) + tsdown (lib/*.js + 懒加载 chunk)
pnpm build:rust # cargo build --release → prebuilt/<triple>/dsh_powerdesk_pty.node
pnpm typecheck # tsc --noEmit
pnpm test # vitest run
pnpm watch # tsdown --watch(保存时重建 bundle)
Rust crate(rust/)使用 napi-rs + portable-pty。restty 与 CodeMirror 住在懒加载 chunk(lib/client-terminal.js、lib/client-editor.js)里,首次使用时拉取,保持初始 bundle 较小(约 196 KB)。
lib/ 与 prebuilt/ 是提交进仓库的,而非 gitignore —— GitHub 安装通道是纯文件拷贝、无构建步骤,所以 git 里是什么,安装的就是什么。任何源码改动后,运行 pnpm build(Rust 层改了则加 pnpm build:rust)并提交结果再 push,否则 GitHub 安装会静默发布陈旧代码。Sourcemap(lib/**/*.map)保持 gitignore。
鸣谢
受 DSH-better-sidebar 启发 —— 衷心感谢其作者提供的面板 / 停靠布局,以及 Powerdesk 所依托的侧边栏外壳基础。Powerdesk 在那一基础之上成长为自有的插件架构,以性能优先的终端(restty 渲染器 + Rust PTY)重新设计,并从零构建了分屏树 / 文件 / 笔记 / 编辑器 / 浏览器 / 扩展各功能面。
许可证
MIT。
链接
同类插件
strukto-ai/mirage#dsh★ 3502
把文件系统与 bash 提供者换成 mirage 虚拟工作区:文件工具与 shell 命令作用于挂载的资源(RAM、S3、Redis、Slack、Gmail、Notion、Postgres)而非宿主磁盘,支持按挂载点设置读/写/执行模式、按命令选择沙箱(进程内 monty、pyodide、quickjs;远程 docker、e2b、daytona),并可在虚拟终端中安装 CLI(git、gh、slack、linear、ntn、gws,或自行注册的程序树)作为命令头词。
hust-open-atom-club/oh-dsh★ 248
社区发行版:TUI、桌面端与 Web UI 统一体验,分层安装、一步到位。
lire1131/dsh-undo-plugin★ 75
DSH 撤销/回退系统:配置变更自动存档,一键撤销/恢复/回退到任意版本,支持 WebUI 与离线 CLI/GUI 工具(DSH 启动失败也能救)。
Jayden-X-L/forkprobe★ 67
同一任务并行试跑多个技能,对比结果选出最优。
forrestchang/dsh-multica-runtime★ 46
让 dsh 运行时跑在 Multica 上。
omdsh-dev/dsh-plugin-check★ 24
插件健康检查:扫描清单协议/patch 格式/构建陷阱,零依赖只读。