DSH Desktop Hub — DeepSeek Harness 桌面管理控制台(Electron + TypeScript)。用多标签页管理 Harness、插件、MCP、技能,双击即用。
54.2/100
综合分
63
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/6 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add FlashingChen/dsh-desktop-hub该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · market
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 28 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包dsh-desktop-hub(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/30 09:03:47
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 92 处,展示前 74 条)
- 读取本地文件src/core/credentials-migration.ts:111
if (existsSync(runtimeBin) && existsSync(nodeBin)) return true - 读取本地文件src/core/credentials-migration.ts:133
if (!existsSync(p)) continue - 读取本地文件src/core/credentials-migration.ts:134
const j = JSON.parse(readFileSync(p, 'utf8')) - 执行外部命令来自配置/变量src/core/credentials-migration.ts:143
const r = spawnSync(dshExec, ['--version'], { encoding: 'utf8', timeout: 3000 }) - 读取本地文件src/core/credentials-migration.ts:162
const j = JSON.parse(readFileSync(join(process.cwd(), 'resources', 'runtime-manifest.json'), 'utf8')) - 读取本地文件src/core/credentials-migration.ts:190
if (!existsSync(path)) return { format: 'missing', text: undefined } - 读取本地文件src/core/credentials-migration.ts:192
const text = readFileSync(path, 'utf8') - 读取本地文件src/core/dsh-spawn.ts:48
const readShim = dependencies.readShim ?? ((file: string) => readFileSync(file, 'utf8')) - 读取本地文件src/core/harness.ts:41
return candidates.find((path) => existsSync(path)) ?? null - 读取本地文件src/core/harness.ts:98
if (existsSync(runtimeBin)) { - 读取本地文件src/core/harness.ts:99
if (existsSync(nodeBin)) return { exec: runtimeBin, node: nodeBin } - 读取本地文件src/core/harness.ts:128
profilePackage = JSON.parse(readFileSync(join(home, 'profiles', profile, 'package.json'), 'utf8')) - 读取本地文件src/core/harness.ts:156
text = readFileSync(file, 'utf8') - 读取本地文件src/core/harness.ts:240
patches.push(readFileSync(file, 'utf8')) - 执行外部命令固定命令src/core/harness.ts:802
const result = spawnSync('taskkill', ['/pid', String(pid), '/T', ...(force ? ['/F'] : [])], { - 发起网络请求src/core/market.ts:293
const response = await fetch(url, { - 读取本地文件src/core/market.ts:898
if (!existsSync(file)) return [] - 读取本地文件src/core/market.ts:900
const parsed = JSON.parse(readFileSync(file, 'utf8')) as unknown - 写入本地文件src/core/market.ts:912
mkdirSync(cacheDir, { recursive: true }) - 写入本地文件src/core/market.ts:918
writeFileSync(tmp, text, { encoding: 'utf8', mode: 0o600 }) - 写入本地文件src/core/market.ts:920
renameSync(tmp, file) - 删除本地文件src/core/market.ts:924
unlinkSync(file) - 写入本地文件src/core/market.ts:925
renameSync(tmp, file) - 删除本地文件src/core/market.ts:928
unlinkSync(tmp) - 写入本地文件src/core/mcp.ts:846
mkdirSync(dir, { recursive: true }) - 读取本地文件src/core/mcp.ts:849
mode = statSync(file).mode & 0o777 - 写入本地文件src/core/mcp.ts:858
copyFileSync(file, candidate, constants.COPYFILE_EXCL) - 写入本地文件src/core/mcp.ts:860
chmodSync(backup, mode) - 写入本地文件src/core/mcp.ts:863
writeFileSync(candidate, content, { mode: mode ?? 0o600, flag: 'wx' }) - 删除本地文件src/core/mcp.ts:869
unlinkSync(tmp) - 写入本地文件src/core/mcp.ts:884
renameSync(from, to) - 读取本地文件src/core/plugins.ts:49
pkg = JSON.parse(readFileSync(join(profile.dir, 'package.json'), 'utf8')) - 执行外部命令来自配置/变量src/core/plugins.ts:393
child = spawn(plan.executable, plan.args, { - 读取本地文件src/core/pnpm.ts:85
const source = existsSync(workspaceFile) ? readFileSync(workspaceFile, 'utf8') : '' - 读取本地文件src/core/pnpm.ts:85
const source = existsSync(workspaceFile) ? readFileSync(workspaceFile, 'utf8') : '' - 读取本地文件src/core/pnpm.ts:108
const currentSource = existsSync(workspaceFile) ? readFileSync(workspaceFile, 'utf8') : '' - 读取本地文件src/core/pnpm.ts:108
const currentSource = existsSync(workspaceFile) ? readFileSync(workspaceFile, 'utf8') : '' - 读取本地文件src/core/skills.ts:159
const initial = lstatSync(file) - 读取本地文件src/core/skills.ts:162
const before = statSync(real) - 读取本地文件src/core/skills.ts:239
const entryStat = lstatSync(p) - 读取本地文件src/core/skills.ts:428
const mode = statSync(path).mode & 0o7777 - 写入本地文件src/core/skills.ts:434
writeFileSync(temp, text, { encoding: 'utf8', flag: 'wx', mode }) - 写入本地文件src/core/skills.ts:435
chmodSync(temp, mode) - 读取本地文件src/core/skills.ts:440
if (!isReplaceConflict(error) || !existsSync(path)) throw error - 写入本地文件src/core/skills.ts:508
mkdirSync(dir, { recursive: true }) - 读取本地文件src/core/skills.ts:512
if (existsSync(file)) { - 写入本地文件src/core/skills.ts:522
writeFileSync(file, text, { flag: 'wx' }) - 写入本地文件src/core/skills.ts:532
writeFileSync(file, text, { flag: 'wx' }) - 写入本地文件src/core/skills.ts:706
mkdirSync(root, { recursive: true }) - 发起网络请求src/core/skills.ts:791
const dl = await fetch(url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) }) - 发起网络请求src/core/skills.ts:839
const detailResponse = await fetch(`${apiBase}?owner=${encodeURIComponent(owner)}`, { - 发起网络请求src/core/skills.ts:858
const response = await fetch(fileUrl, { - 删除本地文件递归src/core/skills.ts:890
rmSync(tmpParent, { recursive: true, force: true }) - 读取本地文件src/core/workspace-lock.ts:116
current = snapshot(lstatSync(path)) - 读取本地文件src/core/workspace-lock.ts:125
return { snapshot: current, record: parseRecord(readFileSync(path, 'utf8')) } - 写入本地文件src/core/workspace-lock.ts:153
renameSync(canonical, movedPath) - 写入本地文件src/core/workspace-lock.ts:182
writeFileSync(fd, `${JSON.stringify({ version: 1, token, pid: process.pid })}\n`) - 写入本地文件src/core/workspace-lock.ts:238
writeFileSync(fd, `${JSON.stringify(record)}\n`) - 读取本地文件src/main/main.ts:168
const source = roots.find((root) => existsSync(join(root, 'package.json'))) - 执行外部命令固定命令src/main/main.ts:175
const proc = spawnProcess('pnpm', args, { - 写入本地文件src/main/main.ts:206
mkdirSync(destination, { recursive: true }) - 写入本地文件src/main/main.ts:208
copyFileSync(join(source, file), join(destination, file)) - 读取本地文件src/main/main.ts:211
const packageJson = JSON.parse(readFileSync(join(profile.dir, 'package.json'), 'utf8')) as { - 读取本地文件src/main/main.ts:229
if (!existsSync(installedPackage)) throw new Error('桌面管理器 DSH 插件未能链接到 web profile') - 读取本地文件src/main/main.ts:230
const installedManifest = JSON.parse(readFileSync(installedPackage, 'utf8')) as { name?: unknown } - 读取本地文件src/main/main.ts:252
if (!existsSync(file)) continue - 读取本地文件src/main/main.ts:254
const value = JSON.parse(readFileSync(file, 'utf8')) as unknown - 发起网络请求src/main/main.ts:331
const res = await fetch(url, { headers: { Accept: 'application/json' }, signal: ctrl.signal }) - 写入剪贴板src/main/main.ts:543
clipboard.writeText(text) - 发起网络请求src/main/main.ts:1049
permissionHandlers.request(permission, callback, details) - 读取本地文件src/main/renderer-server.ts:58
void readFile(join(root, asset.file)).then((body) => { - 写入本地文件src/main/smoke.ts:108
mkdirSync(dirname(out), { recursive: true }) - 写入本地文件src/main/smoke.ts:109
writeFileSync(out, image.toPNG()) - 执行外部命令固定命令src/main/updater.ts:53
const result = spawnSync('codesign', ['-dv', '--verbose=4', runtimeApp.getPath('exe')], {
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
界面预览
4 张 · 点击查看大图功能亮点
- 管理Plugin
- 管理MCP与Skills
README
由 DeepSeek 最新模型翻译生成DSH Desktop Hub
无需 Node.js,不碰 YAML,一站式使用和管理 DeepSeek Harness。
DeepSeek Harness 官方 Web UI 桌面客户端 —— 支持 DeepSeek 账号登录,并内置插件、MCP 与 Skills 管理台。
注:本项目是社区维护的开源项目,非 DeepSeek 官方产品。
社区交流
欢迎加入 QQ 交流群,获取使用帮助、交流插件与功能想法。
| QQ 交流群 |
| 群名:dsh-desktop-hub · 群号:1106611027 |
为什么不是普通 Desktop
不是套壳。官方 Web UI 原样保留在 Harness Tab 里,同时把三个命令行场景搬进同一个窗口:
- 开箱即用:内置 Node.js + DeepSeek Harness 运行时(约 586MB),下载即用,本机不需要安装任何环境。
- 一体化:在 Harness 对话、插件市场、MCP 市场、Skills 市场之间切换,不用再开终端敲 dsh plugin / 手写 YAML。
- 安全:所有写操作原子落盘、自动备份 .bak-<ts>、官方 HMR 热生效,改错了随时可恢复。
展开完整文档(README 剩余 1 节)
DSH Desktop Hub
无需 Node.js,不碰 YAML,一站式使用和管理 DeepSeek Harness。
DeepSeek Harness 官方 Web UI 桌面客户端 —— 支持 DeepSeek 账号登录,并内置插件、MCP 与 Skills 管理台。
注:本项目是社区维护的开源项目,非 DeepSeek 官方产品。
社区交流
欢迎加入 QQ 交流群,获取使用帮助、交流插件与功能想法。
| QQ 交流群 |
| 群名:dsh-desktop-hub · 群号:1106611027 |
为什么不是普通 Desktop
不是套壳。官方 Web UI 原样保留在 Harness Tab 里,同时把三个命令行场景搬进同一个窗口:
- 开箱即用:内置 Node.js + DeepSeek Harness 运行时(约 586MB),下载即用,本机不需要安装任何环境。
- 一体化:在 Harness 对话、插件市场、MCP 市场、Skills 市场之间切换,不用再开终端敲 dsh plugin / 手写 YAML。
- 安全:所有写操作原子落盘、自动备份 .bak-<ts>、官方 HMR 热生效,改错了随时可恢复。
- 及时更新:Windows 与 macOS 发布版启动后自动检查 GitHub Releases,侧边栏提示新版本;用户确认后下载并重启安装,不必再手动打开 GitHub。
核心能力
三类扩展市场
插件、MCP 与 Skills 共用一个目录体验:搜索、查看来源、来源等级与权限,确认后分别安装到当前 profile 或用户级 skills。插件默认来自 DSH Plugin Market 发布的 Awesome DSH Plugin 清单,MCP 合并官方 Registry 与 DSH MCP Market,Skills 合并 ClawHub 与 SkillsMP。npm 只在插件安装预检时读取 manifest,不作为主市场搜索源;网络不可用时回退到本地缓存和随包精选目录。
市场数据来源声明:各来源的运行时地址、用途、缓存策略、许可证边界和安全限制见 MARKET_SOURCES.md。上游目录的收录不等于 DSH 安全背书。
DeepSeek 账号登录
账号登录、退出与授权状态统一由 Harness 设置管理。Desktop Hub 提供插件、MCP 与 Skills 管理,不再提供独立的账号管理入口。也可以在 Harness 设置中配置 API Key。
MCP 市场与配置转换 —— 粘贴即用
Claude Code / Cursor 导出的 MCP JSON,粘贴进去 → 自动转换成 DSH 插件行 YAML(${VAR} 自动转 !!js process.env.VAR,sse / 非法 serverName 会警告)→ 确认后写入 profile patch,官方 HMR 热生效。市场条目若声明环境变量,会在安装卡片中先填写密钥,DSH 将值写入当前 MCP 配置,用户不需要再手动设置系统环境变量。
MCP 转换流程演示
技能市场与管理
扫描用户级 / 随包全部技能(rank 规则,同名低 rank 生效、高 rank 标「被遮蔽」);支持导入 .skill / .zip / GitHub 仓库链接,或直接新建用户级技能,模型可见 / 用户可见一键切换。
插件市场与管理
按组合包 / 依赖分类展示 web 配置档的插件清单;安装、移除、更新真实执行 dsh plugin;聚合仓库(缺 dsh.bundle)拒绝误装,避免把仓库根目录装成插件。
快速开始
1. 下载安装:macOS 下载 DMG(v0.3.5 起已签名并公证,可直接打开);Windows 下载 EXE(当前未签名,首次运行需放行一次:SmartScreen → 更多信息 → 仍要运行)。
2. 连接账号:在 Harness 设置中登录 DeepSeek 账号或配置 API Key。
3. 开始使用:直接对话;需要外部工具时,到 MCP / 技能 / 插件 Tab 管理。
当前为预览版(macOS arm64,已签名并公证;Windows x64 未签名)。
Roadmap
| 状态 | 项目 |
| ✅ | 基础版:Harness 主界面 + 桌面管理面板 + MCP / 技能 / 插件管理 + 内置运行时 |
| ✅ | 扩展中心 MVP:插件市场、MCP 市场、技能市场(随包精选目录) |
| ✅ | DeepSeek 账号:使用 Harness 内置的账号设置 |
| 🚧 | 配置档切换(当前固定 web) |
| Planned | Model Manager(API Key / 模型管理面板) |
| Planned | Doctor(环境自检与一键修复) |
| ✅ | Windows 安装包(NSIS,x64,与 macOS 并行发布) |
| ✅ | 后台托盘:关闭窗口后继续运行 Harness,可从托盘显示或退出 |
| Planned | Linux 安装包 |
| ✅ | 应用更新(GitHub Releases 检查、下载与重启安装) |
| ✅ | 首次访问引导:Spotlight 分步教程,侧栏「使用引导」可重看 |
| ✅ | macOS 签名与公证(Developer ID,v0.3.5 起;应用内更新同步启用) |
社区与反馈
应用内置“反馈”Tab。匿名/署名反馈会提交到可访问的反馈服务,再由 bot 整理为 GitHub Issue,普通用户不需要访问 GitHub。诊断环境信息默认不附加,用户可以单独复制诊断信息或完整反馈;网络不可用时可复制内容发送到 QQ 群。
- Issues:维护者与能访问 GitHub 的开发者直接查看问题
- Discussions:使用讨论与想法交流
- QQ 交流群:群号 1106611027,二维码见应用内反馈 Tab
本项目是活项目:CI 每个 tag 自动出包,Roadmap 上的能力持续在长。Star 一下跟踪进展。
开发者 / Architecture
想参与开发?请先阅读 贡献指南。
架构
渲染进程(sandbox) preload 主进程 核心逻辑 捆绑运行时 ┌──────────────────┐ ┌──────────────────┐ ┌────────────────────┐ ┌──────────────────┐ ┌─────────────────────────┐ │ 六 Tab 壳 │ │ window.dshDesktop│ │ IPC handlers │ │ src/core/ │ │ resources/ │ │ index.html │──▶│ contextBridge │──▶│ harness:url │──▶│ harness.ts │──▶│ node/(Node v24.10.0) │ │ renderer.ts │ │ preload.cjs │ │ plugins:list/ │ │ plugins.ts │ │ dsh-runtime/ │
│ (harness iframe) │◀──│ (CJS, sandbox) │◀──│ install/remove/ │ │ mcp.ts │ │ @deepseek-ai/dsh │
│ │ │ │ │ update │ │ skills.ts │ │ (0.1.7-rc.2) │
│ │ │ │ │ mcp:list/convert/ │ └──────────────────┘ │ │ │
│ │ │ │ │ apply/update/ │ │ spawn(detached) ▼ │
│ │ │ │ │ delete │ └──── dsh web --port 0 ─────┘ │
│ │ │ │ │ skills:list/create/ │ │ │
│ │ │ │ │ toggle │ │ │
│ │◀──│ harness:frame- │ │ harness:frame-loaded │ http://127.0.0.1:PORT │
└──────────────────┘ └──────────────────┘ └────────────────────┘ └─────────────────────────────────┘
flowchart LR
UI["渲染进程(sandbox)六 Tab 壳 index.html + renderer.ts"]
PRE["preload.cjscontextBridge → window.dshDesktop"]
MAIN["主进程 main.tsIPC handlers + harness 生命周期"]
CORE["src/core 纯逻辑harness / plugins / mcp / skills"]
RT["捆绑运行时 resources/Node v24.10.0 + @deepseek-ai/dsh@0.1.7-rc.2"]
WEB["dsh web → http://127.0.0.1:PORT"]
UI -->|IPC invoke| PRE --> MAIN
MAIN --> CORE
CORE -->|spawn detached 进程组| RT
RT --> WEB
WEB -->|iframe src| UI
生命周期:
启动 → registerIpc() → resolveDshExec()(打包内 runtime 优先,回退 PATH) → spawn dsh web --port 0(独立进程组)→ 解析 127.0.0.1:PORT → 轮询 HTTP 200(就绪超时 120s) → BrowserWindow(1280×800,sandbox + contextIsolation + preload.cjs) → 加载六 Tab 壳(file://dist/renderer/index.html) → renderer 经 IPC 取 harness URL → iframe 挂载官方 Web UI → 创建系统托盘;普通关闭按钮隐藏窗口,托盘菜单可重新显示或退出退出 → 托盘「退出」/应用菜单 → will-quit → harness.stop():SIGTERM 进程组 → 2s 兜底 SIGKILL → app.quit
- 默认(无 flag)=产品行为:启动 harness + 六 Tab 壳;关闭窗口后继续驻留托盘,托盘菜单提供「显示窗口 / 退出」。
- 冒烟模式:--smoke(不启 harness,DOM + 真实数据断言);--harness-smoke(真实 harness + iframe 加载断言)。
目录结构
dsh-desktop-hub/
├── src/
│ ├── main/main.ts # Electron 主进程:窗口 + 托盘 + IPC + harness 进程生命周期 │ ├── preload/preload.ts # contextBridge 白名单 API(sandbox,编译为 preload.cjs) │ ├── renderer/ # 六 Tab 壳:index.html + renderer.ts(纯脚本,无模块) │ └── core/ # 纯逻辑(可单测):harness.ts / plugins.ts / plugin-ops.ts / pnpm.ts / mcp.ts / skills.ts / feedback.ts / diagnostics.ts ├── tests/ # node --test 单测(从 dist/ 导入,需先 build) ├── scripts/ │ ├── build-preload.mjs # preload 以 CJS 编译并重命名为 .cjs │ ├── copy-renderer.mjs # 拷贝 index.html → dist/renderer │ ├── bundle-runtime.mjs # 下载 Node + npm 安装 dsh 到 resources/ │ ├── generate-icon.mjs # 生成品牌图标 build/icon.png(1024×1024,深蓝鲸鱼 + hub 节点) │ ├── capture-demo.mjs # README 演示截图/GIF 捕获(合成演示 profile,不碰真实数据) │ ├── verify.mjs # 一键门禁:契约 + 构建 + typecheck×2 + 单测 │ └── verify-m1.mjs # M1 实机验证:dsh web 启动 → HTTP 200 → 优雅停止 ├── resources/ # 捆绑运行时(node_modules 忽略):nd/(Node 本体+shim)+ rt/(dsh runtime,锁文件入库) ├── assets/demo/ # README 截图与 GIF(脚本生成,可重跑) ├── build/icon.png # 应用图标(electron-builder 引用,macOS 自动转 icns) ├── release/ # electron-builder 产物(gitignore):DMG arm64 + NSIS EXE x64 ├── dist/ # tsc 产物(gitignore) ├── tsconfig.json # 主进程 + core + preload(NodeNext,outDir dist) ├── tsconfig.preload.json # preload:CommonJS → dist/preload/preload.cjs ├── tsconfig.renderer.json # renderer:纯脚本 → dist/renderer ├── electron-builder.yml # appId com.dshdesktophub.app;mac DMG+zip(arm64);asar: false └── package.json
开发命令
| 命令 | 说明 |
| npm install | 安装依赖(electron / typescript / electron-builder / electron-updater / yaml) |
| npm run build | 三套 tsc(main+core → preload CJS → renderer)+ 拷贝 index.html,产物 dist/ |
| npm run typecheck | 顺序检查 tsconfig.json 与 tsconfig.renderer.json(main + core + preload + renderer) |
| npm test | node --test 单测(自动发现 tests/,Windows 兼容;需先 build,测试从 dist 导入) |
| npm start | 产品模式:启动 harness + 六 Tab 壳(需 dsh 可用且 ~/.dsh 存在 web profile);默认反馈地址为 https://feedback.flashingchen.xyz/v1/feedback,可用 DSH_FEEDBACK_ENDPOINT 覆盖 |
| npm run smoke | 骨架冒烟(不启 harness):六 Tab DOM + 真实插件/MCP/skills 数据断言,截屏 artifacts/m0-smoke.png |
| npm run smoke:harness | 真实 harness 冒烟:iframe 挂载 + 状态「已连接」,截屏 artifacts/m1-harness.png |
| npm run verify:m1 | M1 实机验证:真实启动 dsh web → HTTP 200 → 优雅停止 → 端口关闭无孤儿 |
| npm run verify | 一键门禁:骨架契约 + 构建产物 + typecheck×2 + 单测全绿(npm test 已改为先 build) |
打包命令
npm run build # 1. 构建 dist/
node scripts/bundle-runtime.mjs # 2. 捆绑运行时(首次/更新):下载 Node v24.10.0 +
安装 @deepseek-ai/dsh@0.1.7-rc.2 到 resources/
npx electron-builder --mac dmg zip --arm64 # 3. macOS:DMG 首装 + zip(签名版本的更新载荷)
npx electron-builder --win nsis --x64 # 4. Windows:release/DSH-Desktop-Hub-<version>-x64.exe
- bundle-runtime.mjs:下载官方 Node v24.10.0(win/darwin/linux × x64/arm64)到 resources/nd,用捆绑 npm 以 --ignore-scripts 安装锁定版本 @deepseek-ai/dsh@0.1.7-rc.2 到 resources/rt;该版本提供官方账号授权 RPC;RUNTIME_TARGET=win32 可在 macOS 上交叉捆绑 Windows 运行时(含 .cmd shim 生成)。nd/.zip 与 nd/.tar.gz 只作为下载校验/复用缓存,不进入安装包。
- electron-builder.yml:files 含 dist// + 解压后的 resources//,并排除 Node 官方压缩缓存;asar: false(产物直放 resources/app,压低 Windows 安装路径深度);mac 目标 DMG + zip(arm64,签名后 zip 作为自动更新载荷)+ Windows 目标 NSIS(x64,assisted per-user,可选择安装目录);macOS 签名与公证由 Release CI 的 secrets 驱动。
- 打包后的应用在 PATH 仅 /usr/bin:/bin(无系统 node/dsh)的环境下可用捆绑运行时启动。
凭据文件导致启动失败(Issue #45)
旧版桌面端捆绑的 DSH 0.1.0-rc.6 只支持平铺凭据文件;较新的 DSH 会写入包含 version: 1、refs 和可选 records 的格式。共用同一个 DSH_HOME 时,旧运行时会将数字版本字段误当成凭据,报 the value for "version" ... must be a string 并退出。
捆绑运行时现锁定为 0.1.7-rc.2,直接支持版本化凭据格式,也由官方凭据提供器迁移合法的旧版平铺格式,并提供官方 DeepSeek 账号授权流程。无需手动给 version 加引号或删除凭据。请勿将凭据文件上传到 Issue。
实机回归:构建后,将 DSH_TEST_RESOURCES 设置为包含 rt/、nd/ 的运行时目录,使用捆绑 Node 执行 scripts/smoke-credentials.mjs。脚本在临时 DSH_HOME 中分别验证新版凭据原样保留、旧版凭据迁移、HTTP 200 与退出后端口关闭,不读取真实用户凭据。
Release
推送 v* tag 后,GitHub Actions 自动完成发布(无需手动构建/上传):
1. 创建 draft Release(自动生成 release notes)
2. 并行构建:macOS arm64 DMG(macos-15)与 Windows x64 NSIS 安装包(windows-latest),各自执行 verify → 捆绑运行时 → electron-builder
3. 双平台都成功后自动转正发布,上传 .dmg / .dmg.blockmap / .zip / .zip.blockmap / .exe / .exe.blockmap / latest.yml / latest-mac.yml(双平台的 .zip / .exe 均为 electron-updater 更新载荷)
git tag v0.3.0
git push origin v0.3.0
resources/ 采用「蓝图入库」:nd/node.exe、rt/package-lock.json 提交进仓库;rt/node_modules(数百 MB)被忽略,由 bundle-runtime.mjs 在打包时从锁文件重建(npm ci)。
验证基线
| 层级 | 内容 |
| 契约测试 tests/skeleton.test.mjs | 骨架文件齐全;package.json 脚本与 devDependencies;六 Tab 契约;contextIsolation + sandbox + nodeIntegration:false;tsconfig strict |
| Harness tests/harness.test.mjs(5 例,不依赖真实 dsh) | findDsh 可解析;dshHome 默认/覆盖;真实 web profile 发现(首个 bundle = dsh-base);忽略非 profile 目录;parseHarnessUrl |
| Plugin tests/plugins.test.mjs(17 例) | bundles ∪ dependencies 分类;排序稳定;buildPluginCommand 命令形态;normalizeInstallSpec GitHub 链接归一化;聚合仓库识别/拦截;pnpm ignored builds 与 Git prepare 授权、显式拒绝保护;runPluginOp 退出码 + 取消;deactivatePluginIfActive 幂等清理(remove 后残留激活行) |
| Plugin 生命周期 tests/plugin-ops.test.mjs(2 例) | 启动立即返回 token;完成推送失败时仍可查询终态 |
| 权限策略 tests/permissions.test.mjs(7 例) | Harness iframe 剪贴板权限精确放行;主帧、其他来源与未知权限继续拒绝 |
| MCP tests/mcp.test.mjs(18 例) | 混合 stdio+http 解析;sse / 非法 serverName 警告;格式拒绝;YAML 与官方示例同构;${VAR} → !!js process.env.VAR;patch 提取 / 替换 / 编辑 / 删除保留注释;空 patch 新建 / 备份事务;!!js 行在 merge/update/delete 后保真(AST 行级操作 + $js 哨兵) |
| Skills tests/skills.test.mjs(15 例) | rank 合并 + shadowed;custom/bundled 根扫描;frontmatter 往返一致;kebab-case 校验落盘;可见性切换(含扁平 skill 文件名回退);zip/.skill 导入(含资源文件、包裹目录剥离、拒绝无 SKILL.md、目录穿越拒绝);GitHub URL 解析;ClawHub 固定版本导入 |
| npm run smoke | 六 Tab 就绪;反馈面板/二维码存在;Plugin/Skills 面板加载完成;MCP 转换端到端(preview 含 dsh-mcp-client / streamable-http);不依赖特定 profile 数据 |
| npm run smoke:plugin | 临时 DSH_HOME 中执行真实 dsh plugin remove,确认退出码与 package.json 依赖删除;不触碰用户 profile |
| npm run smoke:harness | harness 就绪;iframe 挂载 http://127.0.0.1:PORT;状态条「已连接」(#harness-status);重启后 iframe 重挂载到新端口 |
| npm run verify:m1 | 真实 dsh web 启动并 HTTP 200(页面 ≥100B);优雅停止后端口关闭、无孤儿进程 |
已知限制
- profile 固定:ACTIVE_PROFILE 常量 = 'web',暂无 UI 切换(Roadmap 中)。
- 市场目录:Plugin 使用 DSH Plugin Market / Awesome DSH Plugin 清单,MCP 使用官方 MCP Registry + DSH MCP Market,Skills 使用 ClawHub + SkillsMP;在线结果经过 schema 校验并缓存到本地,插件与 GitHub source 的 Skill 在可用时显示 GitHub star 数。Plugin 安装前校验 dsh.bundle,npm 锁定精确版本,GitHub 尽量锁定 commit;ClawHub Skills 锁定版本后只写入 SKILL.md。
- Routing Suite 聚合仓库:https://github.com/yjh051108/dsh-routing-suite 不是单一 DSH bundle,根目录缺 package.json/dsh.bundle;Plugin Tab 会拒绝直接安装。应按仓库说明分别装配 injector、router-standard preset 与可选 mode-boost。
- 无完整 Settings / 其他系统:API Key/模型配置请使用官方 Web UI 内能力;应用更新入口已在壳层侧边栏提供;反馈 Tab 已加入,但生产提交依赖可访问的 feedback API。
- git 来源插件的构建授权:pnpm ≥10 拒绝依赖构建脚本时,Hub 会解析 pnpm 给出的包名或完整 Git depPath,逐包请求用户确认;确认后才原子写入 profile 的 pnpm-workspace.yaml.allowBuilds 并重试一次。该授权仍属于在本机执行第三方代码。
- MCP !!js 反引号模板兼容:patch 里用反引号模板写 Bearer ${...}(官方 README 示例写法)超出 yaml 解析器语法,MCP 面板会拒绝解析并提示;请改用单引号字符串 !!js 'Bearer ${...}'(语义为字面字符串)或行级 process.env.X。
- MCP 无文件导入:MCP 面板支持粘贴 JSON(${VAR} 自动转 !!js process.env.VAR;默认合并写入,可选全量替换),暂无 .mcp.json 文件选择器。
- 退出边界:正常退出走 SIGTERM 进程组清理 + 单实例锁;Harness 意外退出可在 UI 一键重启;强杀(timeout / group-kill)仍可能遗留 dsh 子进程。
- 打包范围:macOS DMG + zip(arm64)自 v0.3.5 起已签名并公证(Developer ID,应用内更新同步启用);Windows NSIS 安装包(x64)未签名(首次运行需按平台放行一次);Linux 待做。Windows 正式安装版支持自动更新;macOS 未签名版本会明确提示手动下载 DMG,开发模式不会联网检查。
- 体积:resources/ 捆绑运行时约 586MB(gitignore),首包体积较大。
- 反馈服务配置:桌面端默认请求 https://feedback.flashingchen.xyz/v1/feedback,也可通过 DSH_FEEDBACK_ENDPOINT 覆盖;服务不可达时复制反馈仍可用。服务端启用 Cloudflare Rate Limiting(每个 edge client IP 每 60 秒 10 次,限流策略具有边缘位置级最终一致性)。私有 github-issue-server/ 不随公开仓库发布。
- 写操作落真实 profile:MCP「写入 patch」真实修改 ~/.dsh/profiles/web/cordis.patch.yml(写入前自动 .bak-<ts> 备份);插件安装/移除真实执行 dsh plugin。
License
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
FlashingChen/dsh-desktop-hub
DSH Desktop Hub — DeepSeek Harness 桌面管理控制台(Electron + TypeScript)。用多标签页管理 Harness、插件、MCP、技能,双击即用。
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,025未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,358已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13938 个插件含 PR 收录与…
★ 350已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7