在 Linux 上以桌面窗口运行 dsh,并管理服务与更新
31.4/100
综合分
8
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Quan-Robin/DSH-desktop-for-Linux该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 109 处,展示前 67 条)
- 读取本地文件src/main.js:25
if (!root || !fs.existsSync(path.join(root, 'node', 'bin', 'node'))) return false; - 读取本地文件src/main.js:266
const loaded = JSON.parse(fs.readFileSync(file, 'utf8')); - 写入本地文件src/main.js:281
fs.mkdirSync(path.dirname(file), { recursive: true }); - 写入本地文件src/main.js:283
fs.writeFileSync(tmp, JSON.stringify(config, null, 2)); - 写入本地文件src/main.js:284
fs.renameSync(tmp, file); - 发起网络请求src/main.js:311
const res = await fetch(`http://127.0.0.1:${port}/`); - 读取本地文件src/main.js:346
const st = fs.statSync(file); - 写入本地文件src/main.js:352
fs.writeFileSync(file, keep); - 写入本地文件src/main.js:355
fs.appendFileSync(file, `[${new Date().toISOString()}] ${buf.toString()}`); - 读取本地文件src/main.js:369
return fs.existsSync(path.join(b.base, 'node', 'bin', 'node')) && - 读取本地文件src/main.js:370
fs.existsSync(path.join(b.base, 'dsh', 'node_modules', '@deepseek-ai', 'dsh', 'lib', 'bin.js')); - 读取本地文件src/main.js:378
if (fs.existsSync(path.join(base, 'node', 'bin', 'node'))) { - 写入本地文件src/main.js:409
fs.writeFileSync(file, s); - 执行外部命令来自配置/变量src/main.js:531
const proc = spawn(bin, args, { - 执行外部命令固定命令src/main.js:602
spawn('taskkill', ['/pid', String(proc.pid), '/T', '/F']); - 执行外部命令固定命令src/main.js:618
execFile('ss', ['-tlnpH'], { timeout: 3000 }, (err, stdout) => { - 发起网络请求src/main.js:941
fetch(`http://127.0.0.1:${config.port}/api/set-session`, { - 删除本地文件src/main.js:1096
fs.rmSync(path.join(config.sourceDir, 'dist'), { recursive: true, force: true }); - 执行外部命令固定命令src/main.js:1098
const proc = spawn('bash', ['-lc', 'npm run dist'], { - 写入剪贴板src/main.js:1132
clipboard.writeText(cmd); - 执行外部命令固定命令src/main.js:1146
const inst = spawn('pkexec', ['dpkg', '-i', deb], { stdio: ['ignore', 'pipe', 'pipe'] }); - 执行外部命令来自配置/变量src/main.js:1210
execFile(args[0], args.slice(1), { timeout: 10000 }, (err, stdout) => { - 删除本地文件src/main.js:1350
fs.rmSync(dest, { recursive: true, force: true }); - 读取本地文件src/ws-tree.js:49
raw = fs.readdirSync(abs, { withFileTypes: true }); - 读取本地文件src/ws-tree.js:63
try { st = fs.statSync(p); } catch { return { ok: false, error: 'not-found' }; } - 读取本地文件src/ws-tree.js:67
try { buf = fs.readFileSync(p); } catch (e) { return { ok: false, error: e.message }; } - 读取本地文件src/balance.js:92
const yaml = fs.readFileSync(path.join(dshHome, '.credentials.yaml'), 'utf8'); - 请求外部主机api.deepseek.comsrc/balance.js:101
const res = await fetch('https://api.deepseek.com/user/balance', { - 发起网络请求src/balance.js:101
const res = await fetch('https://api.deepseek.com/user/balance', { - 读取本地文件src/balance.js:126
try { st = fs.statSync(file); } catch { return null; } - 发起网络请求src/balance.js:137
const res = await fetch(`http://127.0.0.1:${port}/api/session.list`, { - 发起网络请求src/balance.js:173
const res = await fetch(`http://127.0.0.1:${port}/api/state?client=desktop`, { signal: AbortSignal.timeout(1500) }); - 发起网络请求src/balance.js:204
const res = await fetch(`http://127.0.0.1:${port}/api/usage`, { signal: AbortSignal.timeout(1500) }); - 发起网络请求src/balance.js:219
const res = await fetch(`http://127.0.0.1:${port}/api/prompt`, { - 发起网络请求src/balance.js:232
const res = await fetch(`http://127.0.0.1:${port}/api/approve`, { - 读取本地文件src/balance.js:248
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; } - 读取本地文件src/balance.js:323
try { st = fs.statSync(f); } catch { continue; } - 读取本地文件src/balance.js:478
return Buffer.from(decompress(new Uint8Array(fs.readFileSync(file)))); - 执行外部命令固定命令src/usage-parse.js:16
execFile('zstd', ['-dc', '-q', file], { maxBuffer: 512 * 1024 * 1024, timeout: 30000 }, (err, stdout) => { - 读取本地文件src/usage-parse.js:19
const buf = fs.readFileSync(file); - 写入剪贴板plugin/dsh-plugin-desktop/lib/client-menu.js:177
async function writeClipboard(text) { - 写入剪贴板plugin/dsh-plugin-desktop/lib/client-menu.js:179
try { await navigator.clipboard.writeText(text); return } catch {} - 读取剪贴板plugin/dsh-plugin-desktop/lib/client-menu.js:184
async function readClipboard() { - 读取剪贴板plugin/dsh-plugin-desktop/lib/client-menu.js:186
try { return await navigator.clipboard.readText() } catch {} - 写入剪贴板plugin/dsh-plugin-desktop/lib/client-menu.js:192
await writeClipboard(text) - 读取剪贴板plugin/dsh-plugin-desktop/lib/client-menu.js:452
add(root, "粘贴", async () => replaceSelection(editable, await readClipboard()), "Ctrl+V") - 发起网络请求plugin/dsh-plugin-desktop/lib/client-menu.js:593
const r = await fetch(path); - 写入剪贴板plugin/dsh-plugin-desktop/lib/client-menu.js:676
navigator.clipboard?.writeText(marker).catch(() => {}); - 发起网络请求plugin/dsh-plugin-desktop/lib/files-panel-client.js:43
const r = await fetch(path); - 写入剪贴板plugin/dsh-plugin-desktop/lib/files-panel-client.js:126
navigator.clipboard?.writeText(marker).catch(() => {}); - 执行外部命令固定命令plugin/dsh-plugin-desktop/lib/index.js:718
const branch = execFileSync('git', ['-C', root, 'branch', '--show-current'], { encoding: 'utf8', timeout: 3000 }).trim(); - 执行外部命令固定命令plugin/dsh-plugin-desktop/lib/index.js:719
const status = execFileSync('git', ['-C', root, 'status', '--porcelain'], { encoding: 'utf8', timeout: 3000 }); - 执行外部命令固定命令plugin/dsh-plugin-desktop/lib/upstream-patch.js:58
const root = execSync('npm root -g', { timeout: 4000, encoding: 'utf8' }).trim(); - 读取本地文件plugin/dsh-plugin-desktop/lib/upstream-patch.js:78
try { if (fs.existsSync(f)) return f; } catch { } - 读取本地文件plugin/dsh-plugin-desktop/lib/upstream-patch.js:86
try { src = fs.readFileSync(file, 'utf8'); } catch { return 'unreadable'; } - 读取本地文件plugin/dsh-plugin-desktop/lib/upstream-patch.js:90
try { if (!fs.existsSync(backup)) fs.writeFileSync(backup, src); } catch { } - 写入本地文件plugin/dsh-plugin-desktop/lib/upstream-patch.js:92
try { fs.writeFileSync(file, out); } catch { return 'write-failed'; } - 读取本地文件plugin/dsh-plugin-desktop/lib/ws-tree.js:49
raw = fs.readdirSync(abs, { withFileTypes: true }); - 读取本地文件plugin/dsh-plugin-desktop/lib/ws-tree.js:63
try { st = fs.statSync(p); } catch { return { ok: false, error: 'not-found' }; } - 读取本地文件plugin/dsh-plugin-desktop/lib/ws-tree.js:67
try { buf = fs.readFileSync(p); } catch (e) { return { ok: false, error: e.message }; } - 读取剪贴板src/inject/session-menu.js:264
add(root, '粘贴', function () { return readClipboard().then(function (text) { replaceSelection(editable, text); }); }, 'Ctrl+V'); - 写入剪贴板src/inject/session-menu.js:519
function writeClipboard(text) { - 写入剪贴板src/inject/session-menu.js:521
return navigator.clipboard.writeText(text).catch(function () { legacyCopy(text); }); - 读取剪贴板src/inject/session-menu.js:526
function readClipboard() { - 读取剪贴板src/inject/session-menu.js:528
return navigator.clipboard.readText().catch(function () { - 写入剪贴板src/inject/session-menu.js:536
return writeClipboard(text).then(function () { toast(message); }); - 读取剪贴板src/inject/session-menu.js:780
add(root, '粘贴', function () { return readClipboard().then(function (text) { replaceSelection(editable, text); }); }, 'Ctrl+V');
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
涉及外部主机:api.deepseek.com
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
README
由 DeepSeek 最新模型翻译生成DeepSeek Harness Desktop
DeepSeek Harness(dsh)的桌面壳应用:用 Electron 窗口内嵌 dsh 的 Web UI,自动管理 dsh 服务进程,并提供系统托盘。
本项目完全由 DeepSeek 系列模型创建并维护。
这是社区非官方桌面端(第三方项目,与 DeepSeek 官方无关)。
功能
- 自动启动 dsh:通过 npx -y @deepseek-ai/dsh web 拉起服务(官方安装方式);若目标端口已有 dsh 服务在跑则直接复用,不重复启动
- 内嵌 Web UI:窗口加载 http://127.0.0.1:3080(端口可配置),支持完整的 dsh 功能(会话、模型、插件、工作区等)
- 系统托盘:显示/隐藏窗口、在系统浏览器中打开、重启服务、退出(退出时自动终止 dsh 子进程)
- 设置面板(菜单栏「文件 → 设置」或托盘菜单,内嵌浮层、居中于主窗口):检查并更新 dsh(npm)、切换界面语言(中文/English);菜单栏「帮助」暂未实现(已禁用)
- dsh 更新检测:启动时自动检查 npm 上的 @deepseek-ai/dsh 新版本(非侵入通知);也可在设置中手动检查并一键更新
- 关闭行为:默认关闭窗口 = 隐藏到托盘(可在配置中关闭)
展开完整文档(README 剩余 1 节)
DeepSeek Harness Desktop
DeepSeek Harness(dsh)的桌面壳应用:用 Electron 窗口内嵌 dsh 的 Web UI,自动管理 dsh 服务进程,并提供系统托盘。
本项目完全由 DeepSeek 系列模型创建并维护。
这是社区非官方桌面端(第三方项目,与 DeepSeek 官方无关)。
功能
- 自动启动 dsh:通过 npx -y @deepseek-ai/dsh web 拉起服务(官方安装方式);若目标端口已有 dsh 服务在跑则直接复用,不重复启动
- 内嵌 Web UI:窗口加载 http://127.0.0.1:3080(端口可配置),支持完整的 dsh 功能(会话、模型、插件、工作区等)
- 系统托盘:显示/隐藏窗口、在系统浏览器中打开、重启服务、退出(退出时自动终止 dsh 子进程)
- 设置面板(菜单栏「文件 → 设置」或托盘菜单,内嵌浮层、居中于主窗口):检查并更新 dsh(npm)、切换界面语言(中文/English);菜单栏「帮助」暂未实现(已禁用)
- dsh 更新检测:启动时自动检查 npm 上的 @deepseek-ai/dsh 新版本(非侵入通知);也可在设置中手动检查并一键更新
- 关闭行为:默认关闭窗口 = 隐藏到托盘(可在配置中关闭)
- 伴生插件(独立仓库发布,可选增强,非本应用依赖):dsh-plugin-desktop(dsh plugin add github:Quan-Robin/dsh-plugin-desktop 安装,或托盘/设置页一键安装)。定位:大部分桌面端功能 + 小部分插件功能——安装后解锁:当前会话感知(替代请求嗅探)、实时轮次状态、快捷输入发送通道、页内完整右键菜单与「置顶会话」扩展(client 注入)。未安装时:本应用仍完整可用,仅这些增强能力不生效(保持极简原版体验),右键/置顶/文件面板等页内功能此时由应用自身注入提供(见下条)
- 页内右键菜单 + 置顶会话(免插件):会话/工作区/输入框/链接的完整右键菜单(适配自社区 dsh-session-context-menu(baihejiangnan),MIT;检测到原版插件时自动让位并把「置顶」注册进其扩展菜单);「📌 置顶」独立分区显示在会话列表上方——不动原列表、不影响按时间排序,置顶状态由桌面端保管,托盘也可直达
- 右侧文件面板(Ctrl+Shift+E,免插件):当前工作区文件树(懒加载、噪声目录过滤),单击插入 [file: 路径] 引用、双击预览、📂 打开工作区目录(右侧栏参考社区 dsh-workspace-explorer,MIT);「搜索」标签全文找文件、「变更」标签看 git 状态与 diff、「终端」标签停靠 PTY 终端(需伴生插件 v0.4,经 dsh spawnTerminal 接缝,xterm.js);概览卡显示会话 tokens、会话/本轮花费(复用余额估算链路)与 TTFT/输出速度/轮耗时(伴生插件自算)
- 会话调色板:Ctrl+Shift+P 模糊切换会话(带 ● 未读标记)、Ctrl+Shift+F 跨会话全文搜索——结果点击直达
- 审批直达:DSH 等待工具审批时弹原生通知 + 小弹窗(批准/拒绝/详情,需伴生插件);DS-pet 桌宠同步提醒并可直接批准/拒绝
- 路径直达:Ctrl+点击对话中的文件路径 → 文件管理器定位
- 会话导出 Markdown:页内右键「导出为 Markdown」/ 调色板 Ctrl+E——本地会话文件直出到下载目录(无需浏览器下载)
- Prompt 模板库:Ctrl+Shift+T 调色板模板模式,本地 JSON 持久化,点选插入输入框,Ctrl+S 保存新模板
- 错误通知:DSH 运行出错时系统通知(需伴生插件 v0.4,notifyOnError 可关)
- 全局快捷输入:Ctrl+Shift+D 任意位置唤出迷你输入条,Enter 发送到当前会话(需伴生插件;快捷键在 config.json 的 quickInputShortcut 修改);拖到窗口、页面未处理的文件会以路径填入输入条
- 窗口记忆 / deep link / 多 profile:窗口位置大小跨重启保留(拔屏自动回退);dsh://session/<id> 从外部定位会话;多套 DSH_HOME+端口配置一键切换(托盘「配置」),账号/项目互不串数据
- 日志:dsh 子进程输出写入 userData/dsh.log,便于排查问题
运行
需要 Node.js(dsh 要求 ^22.19.0 || >=24.0.0)。首次运行会通过 npx 下载 dsh 包,可能需要几分钟。
npm install
npm start
安装为 Linux 应用(deb / AppImage)
npm install
npm run dist
产物在 dist/:
- deb(推荐):sudo dpkg -i dist/deepseek-harness-desktop_0.1.11_amd64.deb,安装到 /opt/DeepSeek Harness/,应用菜单出现 DeepSeek Harness 入口(图标为你提供的图片)。postinst 会自动配置 chrome-sandbox 权限(支持 user namespaces 的现代内核用 0755,否则 SUID 4755),安装后即可全沙箱运行。
- AppImage:chmod +x "dist/DeepSeek Harness-0.1.11.AppImage" 后直接运行,无需安装。
两种方式启动后行为一致:自动复用/启动 dsh 服务、托盘、窗口图标均为你的图片。
更新机制(双路径)
AppImage 自更新(electron-updater):
1. 构建新版并发布:把 dist/DeepSeek Harness-x.y.z.AppImage 和 dist/latest-linux.yml 上传到你自己的 HTTP(S) 服务器(或 GitHub Releases)
2. 在用户机器配置 updateUrl 指向该目录(例如 "updateUrl": "https://example.com/dsh-desktop/")
3. 应用启动时静默检查更新,发现新版本自动下载,完成后弹窗提示重启安装
latest-linux.yml 在每次 npm run dist 时自动生成(含 sha512 校验与差分更新信息);example.invalid 占位地址不会被请求。
deb 本机自打包安装(推荐,适合本机开发/自用):
配置 sourceDir 指向本机源码目录后,托盘菜单出现「从源码构建并安装」:
1. 本机执行 npm run dist 打包全新 deb
2. 通过 pkexec 弹系统授权框(polkit,密码由系统收取,不经过应用)
3. dpkg -i 安装后自动重启应用
适合「改完代码 → 一键重装系统版本」的迭代流程。注意:升级前先退出正在运行的旧实例(pkill -f "opt/DeepSeek Harness/deepseek-harness-desktop"),避免单实例锁冲突。
dsh 自身的更新(与桌面端版本无关):
dsh 通过 npm 发布,桌面端在启动时自动检测(也可在设置中手动检查):
1. 比较本机 dsh --version 与 npm 上的最新版本
2. 发现新版本 → 设置窗口点「立即更新」→ 执行 npm install -g @deepseek-ai/dsh(npm prefix 为用户目录时无需管理员权限)
3. 更新完成后选择重启服务即生效(Web UI 由 dsh 进程提供,新版本即新界面)
注意:npm 更新后,正在运行的旧 dsh 进程不会自动升级——完全退出再启动、或托盘「重启服务」后生效。
配置
配置文件位于用户数据目录(Linux 为 ~/.config/deepseek-harness-desktop/config.json,macOS 为 ~/Library/Application Support/deepseek-harness-desktop/config.json,Windows 为 %APPDATA%\deepseek-harness-desktop\config.json)。不创建该文件即使用默认值:
{
"port": 3080,
"dshCommand": "npx",
"onClose": "ask",
"language": "zh"
}
| 字段 | 默认值 | 说明 |
| port | 3080 | dsh 服务端口 |
| dshCommand | "npx" | 启动方式:"npx"(官方推荐,自动下载);"global"(使用 PATH 上的 dsh);"bundled"(便携版,使用内置 node 运行内置 dsh——见下文「Linux 便携版」);或自定义可执行文件的绝对路径 |
| dshHome | "" | dsh 数据目录(会话/凭据/profile)。留空 = ~/.dsh;便携版(bundled)留空 = 应用旁 data/,完全隔离 |
| closeBehavior | "" | 关闭窗口时的行为:""(未设置——首次关闭时询问并记住);"tray"(隐藏到托盘继续运行,dsh 不中断);"quit"(完全退出并停止 dsh);"ask"(每次都询问)。可在设置面板中更改 |
| updateUrl | "" | 自动更新源(仅 AppImage 生效):generic HTTP(S) 服务器或 GitHub Releases 地址。留空 = 禁用自动更新 |
| sourceDir | "" | 本机源码目录:设置后托盘菜单出现「从源码构建并安装」,一键在本机打包 deb 并用系统授权安装(留空 = 隐藏该功能) |
| stopExternalDsh | true | 完全退出时,若端口上还有终端启动的外部 dsh web 服务,一并终止(仅杀命令行匹配 dsh web 的进程,不误伤其他服务;保留后台到托盘时不受影响) |
| language | "zh" | 界面语言:"zh"(中文)或 "en"(English)。可在设置窗口中切换,立即生效 |
Linux 便携版
不依赖系统 Node/pnpm/dsh 的独立版本:
npm run bundle # 下载 node + pnpm + dsh(固定版本)到 bundled/
npm run dist:portable # 构建目录 + 打包 zip(dist-portable/DeepSeek-Harness-x64.zip)
产物为解压即用目录(类似 Antigravity-x64 形态):
DeepSeek-Harness-x64/
├── deepseek-harness # 启动器(入口,自动处理 sandbox) ├── deepseek-harness-desktop # 实际可执行 └── resources/ ├── app.asar └── bundled/ # 内置 node + pnpm + dsh 运行时
运行:./DeepSeek-Harness-x64/deepseek-harness(解压后直接双击/执行;sandbox 不可用时自动加 --no-sandbox)
开箱即用:无需任何配置——自动检测内置运行时并启用 bundled 模式,默认数据目录 = 应用旁 data/(不碰 ~/.dsh);配置端口被外部服务占用时自动顺延(绝不显示宿主机自己的会话)。
配置完全隔离:便携版的全部应用数据(config、余额状态、日志、缓存)都在应用旁 data/app/——普通版与便携版、或多个便携副本的关闭行为等设置互不影响,可同时运行(各自独立窗口、独立 dsh 服务、独立数据)。
- 内置 dsh 版本固定(scripts/download-bundled.sh 中可改),更新 = 重新 npm run bundle + dist:portable
- bundled 模式自动修复内置 dsh 的已知插件 bug(dsh-plugin-vetting 正则)
开发说明
- src/main.js:Electron 主进程(窗口、菜单栏、设置窗口、托盘、dsh 子进程管理、配置、npm 更新检测),没有渲染进程代码——界面就是 dsh 的 Web UI
- src/preload.js + src/settings.html:设置窗口(contextBridge 暴露最小 IPC 面:状态/检查更新/更新 dsh/切换语言)
- src/sni.js:自己实现的 StatusNotifierItem(GNOME Wayland 托盘)
- 托盘/窗口图标是代码内联生成的 PNG(data URL),没有二进制资源文件
- 窗口安全设置:主窗口 contextIsolation: true、nodeIntegration: false、sandbox: true(加载的是远程 dsh Web UI);设置窗口使用最小 preload(contextBridge 暴露状态/更新/语言 IPC);外部链接一律交给系统浏览器打开
已知限制
- dsh 仍处于 developer preview,接口与行为可能随版本变化
- 若 port 端口被非 dsh 的 HTTP 服务占用,应用会误判为已有服务并直接连接预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Quan-Robin/DSH-desktop-for-Linux
在 Linux 上以桌面窗口运行 dsh,并管理服务与更新
相关插件 · 开发 / 工程
隐私简历生成器reactive-resume/reactive-resume
Reactive Resume 已迁至 GitHub 上的…
★ 45,125已汉化MCP
71.7
AI 架构文档生成器sopaco/deepwiki-rs
🚀 Litho 已进化为 Terrain —— 给你的 AI 智能体一张会呼吸的代码库地图。
★ 3,157已汉化DSH
70.8
长时任务执行闭环AMAP-ML/LongHorizon-Harness
面向 Computer-Use Agent 的 Loop Engineering
★ 1,764已汉化DSH
70.5
AI 编程纪律方法包GanyuanRan/Aegis
让 AI 编程 agent 变得可信:少返工、更安全、说“完成”前先给证据。
★ 1,384已汉化DSH
69.6
多代理编排运行时Enderfga/claw-orchestrator
面向编程智能体的运行时。把 Claude Code、Codex、Antigravity、Grok…
★ 586已汉化MCP
69.4
记忆进化插件csyangwen/dsh-memory-evolve
dsh-memory-evolve 使用场景指南
★ 461已汉化DSH
67.9