本地 DeepSeek Harness 网页服务的轻量桌面壳——一键安装、启动、监控与内嵌预览本地服务,关闭后驻留系统托盘持续运行。

面向新用户:直接下载对应平台的安装包,双击安装即可,无需自己动手搭建环境。
| 平台 | 安装包 | 大小 |
|---|---|---|
| Windows 10/11(64 位) | 下载 .exe(NSIS 安装包) | ~2.0 MB |
| macOS Apple Silicon | 下载 .dmg / 下载 .pkg | ~2.9 MB |
| macOS Intel(64 位) | 下载 .dmg / 下载 .pkg | ~3.0 MB |
| Linux x86_64 | 下载 .deb / .rpm / .AppImage —— 支持范围见下 | ~10 MB(AppImage ~88 MB) |
所有安装包统一发布在 GitHub Releases,选择最新版本、下载对应平台的安装包即可。
产物命名:
dhd_{版本}_{平台}[_{兼容下限}]_{架构}.{后缀}——dhd是 DeepSeek Harness Desktop 的 缩写,由发版流水线在打包后统一改名(tauri 把产物名写死在打包器里、没有模板可配)。用缩写是为了短、 且不含空格:名字里带空格时 GitHub 会把空格换成.,下载页上的名字和本地打包产物对不上, 命令行里也得到处加引号。看一眼文件名就知道该下哪个包:dhd_1.0.5_windows_x64-setup.exe dhd_1.0.5_macos_arm64.dmg / dhd_1.0.5_macos_arm64.pkg dhd_1.0.5_macos_x64.dmg / dhd_1.0.5_macos_x64.pkg dhd_1.0.5_linux_glibc2.35_amd64.deb dhd_1.0.5_linux_glibc2.35_x86_64.rpm dhd_1.0.5_linux_glibc2.35_x86_64.AppImage只改了文件名:安装后的应用、macOS 的
.app、窗口标题与卸载项仍然是 DeepSeek Harness Desktop,dhd只出现在下载到的安装包名字上。Linux 名字里的
glibc2.35是兼容下限(下一节),不是版本号的一部分。 架构标记:macOS 的.dmg/.pkg统一用arm64/x64(tauri 的 dmg 原生产物名是aarch64/x86_64,两者不一致,已在发版时归一);Linux 的.deb用 Debian 的amd64,.rpm/.AppImage用通用的x86_64。
三个 Linux 包都构建在 ubuntu-22.04 上,所以要求 glibc ≥ 2.35 且系统提供 webkit2gtk-4.1。
这是 tauri v2 + webkit2gtk-4.1 能取到的最低基线(再往下的 Ubuntu 20.04 只有 webkit2gtk-4.0), 所以不为各发行版单独打包——滚动发行版(Arch 等)直接用 AppImage 即可:
| 系统 | 建议产物 |
|---|---|
| Ubuntu 22.04+ / Debian 12+ / Mint 21+ / Pop!_OS 22.04+ | .deb |
Fedora 36+ / openSUSE Tumbleweed(rpm 系,仓库需提供 webkit2gtk4.1) | .rpm |
| Arch / CachyOS / Manjaro 等滚动发行版 | .AppImage(需自备 webkit2gtk-4.1 与 libayatana-appindicator) |
| ❌ RHEL / Rocky / Alma 9(glibc 2.34)、openSUSE Leap 15.x(2.31)、Ubuntu 20.04(无 webkit2gtk-4.1) | 低于基线,跑不起来 |
兼容下限由发布流水线里的
Verify glibc floor步骤实测二进制引用的最高 GLIBC 符号版本校验: 一旦构建基线变动导致实际下限超过2.35,流水线会直接失败,不会让文件名说谎。
AppImage 版在 Mesa ≥ 26.1 的系统上会黑屏(CachyOS / Arch / Fedora 等滚动发行版), 终端报:
Could not create default EGL display: EGL_BAD_PARAMETER. Aborting...
根因:AppImage 里打包了按 Ubuntu 构建的 libwebkit2gtk-4.1.so.0,但没有打包自己的
libEGL —— 于是这份 WebKit 是跑在你系统的 Mesa 上的。Mesa ≥ 26.1 会拒绝它调用
eglGetPlatformDisplay() 的方式,直接 EGL_BAD_PARAMETER。窗口本身建得起来(所以主窗口是
黑的、设置窗口是白的,取决于窗口背景色),但 WebView 一帧都画不出来。
失败点在 EGL display 创建,早于 WebKit 读取任何渲染路径开关。因此:
⚠️ 所有环境变量对这个黑屏都无效 ——
WEBKIT_DISABLE_DMABUF_RENDERER、WEBKIT_DISABLE_COMPOSITING_MODE、LIBGL_ALWAYS_SOFTWARE=1、EGL_PLATFORM=surfaceless全都试过,行为完全一致(这正是失败时机在它们之前决定的)。别再在这条路上花时间。
同一台机器上从源码构建是正常的,因为发行版自带的 WebKit 是配着它自己的 Mesa 编译的。
已修复(打包侧):自 v1.0.7 起,AppImage 不再打包 WebKitGTK / GTK / GStreamer
(发布流水线里加了 Slim the AppImage 步骤),改用宿主自己那套 —— 宿主那份天生配着
宿主的 Mesa 编译。用户不需要做任何事,也不会有任何手动步骤。代价是宿主需自备
webkit2gtk-4.1 与 libayatana-appindicator(和 .deb / .rpm 的依赖契约一致)。
⚠️ 下面所有操作都只发生在 AppImage 自己解包出来的副本(~/下载/squashfs-root)里,
不会动你系统上的任何文件;不想要了 rm -rf squashfs-root 即可,重跑 AppImage 也不受影响。
只删 WebKit 不够:系统的 WebKit 会去配包里那份 Ubuntu 的 GStreamer,接着报
undefined symbol: gst_debug_log_id(两套 GStreamer 混用)。要整条栈一起换:
sudo pacman -S webkit2gtk-4.1 libayatana-appindicator # 前提
./dhd_1.0.6_linux_glibc2.35_x86_64.AppImage --appimage-extract
for f in squashfs-root/usr/lib/*.so*; do
b=$(basename "$f")
[ -e "/usr/lib/$b" ] && rm -f "$f"
done
rm -rf squashfs-root/usr/lib/gstreamer-1.0 squashfs-root/usr/lib/webkit2gtk-4.1
./squashfs-root/AppRun
另一条确认可行的路:从源码构建(pnpm install && pnpm tauri:build)。
上游 tauri 的「真正可移植 AppImage」修复仍在开放状态(tauri#12491 未合并), 所以升级 tauri 拿不到这个修复,必须自己处理打包。
| 现象 / 日志关键词 | 含义 | 处理 |
|---|---|---|
| 窗口黑,但看得到转圈和「正在启动服务…」 | WebKit 正常,是前端 bundle 或 dsh 服务没起来 | 属应用层问题,请附日志反馈 |
Failed to get GBM device | DMA-BUF 渲染器 | 试 WEBKIT_DISABLE_DMABUF_RENDERER=1 |
bwrap / sandbox 相关 | WebKit 沙箱起不来 | 安装 bubblewrap(Arch:sudo pacman -S bubblewrap) |
Linux 安装说明:
.deb/.rpm会自动声明 WebKitGTK 4.1、GTK3 与托盘(AppIndicator)依赖, 用sudo apt install ./xxx.deb或sudo dnf install ./xxx.rpm装即可,依赖会一起拉齐; AppImage 不打包系统库,需要目标机自备这些库 —— dpkg 系是sudo apt install libwebkit2gtk-4.1-0 libayatana-appindicator3-1,Arch 系是sudo pacman -S webkit2gtk-4.1 libayatana-appindicator:
chmod +x dhd_x.y.z_linux_glibc2.35_x86_64.AppImage
./dhd_x.y.z_linux_glibc2.35_x86_64.AppImage
💡 轻量:以上为 v0.1.2 实测大小(Windows 2.02 MB、macOS 2.91
3.01 MB),各版本略有差异——全平台安装包都只有 23 MB,秒级下载、秒级安装。Linux 侧.deb/.rpm约 10 MB;AppImage 因为要自带运行时而接近 88 MB(体积大但仍远小于 Electron 应用)。
首次使用(两步完成):
pnpm add -g @deepseek-ai/dsh@latest 安装 DSH 并启动本地服务(仅在 dsh 未安装时执行);
- Windows 若提示 SmartScreen,请选择「更多信息 → 仍要运行」。
- macOS 应用未签名,首次打开需在「系统设置 → 隐私与安全性」中点击「仍要打开」,或右键应用选择「打开」。
@deepseek-ai/dsh(pnpm)并启动本地网页服务,无需任何手动配置。已安装的 dsh 在启动时不会被更新或重装(保留现有版本,避免 @latest 覆盖引发兼容性问题);仅当 dsh 缺失或安装损坏(读不出版本)时才安装。PNPM_HOME):未运行过 pnpm setup 的机器也会自动完成临时 PATH 注入与用户级 PATH 持久化,安装后立即启动,下次打开不再重装。不按 pnpm 主版本设卡:你装的是哪个版本就用哪个(含 11),启动链不会强制降级或重装你的 pnpm——本应用也从不提权(不会用 sudo 装东西,也不会引导你去改系统级目录)。| 链接 | 说明 |
|---|---|
| DeepSeek Harness 官网 | 产品官网 |
| GitHub 仓库 | DeepSeek Harness 官方开源仓库 |
| 开发者文档 | 快速上手指南 |
| 插件开发 | 插件开发文档 |
💡 换新设备/新环境后若报
cargo metadata ... program not found,说明 Rust 工具链未安装。 构建前会先执行scripts/check-rust.mjs自检并给出安装指引(Windows 可运行winget install Rustlang.Rustup后重开终端)。
Linux 构建依赖(Ubuntu / Debian 基线,其它发行版换成对应的包名):
sudo apt install -y libwebkit2gtk-4.1-dev libgtk-3-dev \
libayatana-appindicator3-dev librsvg2-dev patchelf file wget rpm
⚠️
libappindicator3-dev与libayatana-appindicator3-dev在 Ubuntu 22.04 上互相冲突, 同时安装会让 apt 直接失败(E: Unable to correct problems, you have held broken packages), 只装 ayatana 那一个。构建期真正链接的是
libwebkit2gtk-4.1(webkit2gtk-sys)与libgtk-3(gtk-sys);AppIndicator 是运行时依赖——libappindicator-sys用libloading在运行时 dlopenlibayatana-appindicator3.so.1(回退libappindicator3.so.1),构建期不查 pkg-config。rpm提供rpmbuild,只有需要打.rpm时才必须。
pnpm install
pnpm tauri:dev # 开发模式(Vite + Tauri),app id: com.deepseek.harness.desktop.dev
pnpm tauri:debug # 开发模式 + RUST_BACKTRACE / WebView2 日志
开发模式下,壳层 UI 运行在 Vite dev server
http://localhost:6089(支持浏览器预览), 由本应用托管的dsh web服务运行在 6088 端口。
pnpm tauri:build # 当前平台全量打包
pnpm tauri:build:win # Windows NSIS 安装包(.exe)
pnpm tauri:build:mac # macOS DMG
pnpm tauri:build:mac:app # macOS .app
pnpm tauri:build:mac:universal # macOS 通用(universal-apple-darwin)DMG
pnpm tauri:build:linux # Linux 三件套(.deb + .rpm + .AppImage)
pnpm tauri:build:deb # 只打 .deb
pnpm tauri:build:appimage # 只打 .AppImage
Linux 产物落在
src-tauri/target/release/bundle/{deb,rpm,appimage}/。 务必在目标发行版的最低版本上构建(推荐 Ubuntu 22.04):glibc 只向下兼容, 在 Ubuntu 24.04 上构建的产物在 22.04 上会报GLIBC_x.xx not found。CI 固定 用ubuntu-22.04就是这个原因。
Windows 打包依赖离线 NSIS 工具链:
scripts/setup-nsis.mjs会把libs/中的nsis-3.11.zip+nsis_tauri_utils.dll(SHA1 校验)部署到%LOCALAPPDATA%\tauri\NSIS,构建全程不访问网络(该脚本在非 Windows 上直接跳过)。
推送 v* 标签即可自动构建并直接发布(非草稿)Windows / macOS 安装包:
git tag v0.1.0
git push origin v0.1.0
或使用一键发布脚本(自动 bump 版本 → 同步版本文件 → 提交 → 打标签 → 推送):
pnpm release # 自动 bump patch 并发布(0.1.0 → 0.1.1)
pnpm release 0.2.0 # 指定版本发布
pnpm release minor # bump minor 并发布
pnpm release:tag-only # 仅给当前版本打标签推送(不 bump)
流水线(.github/workflows/release.yml):质量门禁(tsc + vite 构建 + Rust 测试)→ 创建已发布的正式 Release → 矩阵构建(Windows NSIS / macOS arm64 / macOS x64 / Linux deb+rpm+AppImage,基线 ubuntu-22.04)→ 用 scripts/tag-release-assets.mjs 把产物统一改名为 dhd_{版本}_{平台}[_{兼容下限}]_{架构} 后追加到同一 Release;Linux 腿会先用 objdump 实测二进制引用的最高 GLIBC 符号版本,与文件名里的 glibc2.35 对不上就直接失败。tauri 的产物名写死在打包器里、没有模板可配,所以改名只能放在 build 之后、上传之前;改名后的路径由脚本写进 $GITHUB_OUTPUT,上传步骤直接消费这份列表而不是 glob,避免改名与 glob 漂移导致漏传。
另有一条 Linux 构建验证流水线(.github/workflows/linux-build.yml):只要改动
src-tauri/**、src/** 等路径就自动跑 cargo fmt --check + cargo test + 打包,
产物只作为 Actions artifact 留存、不进 Release。它的意义是:Linux 专用代码
(cfg(target_os = "linux") 分支、独立预览窗口、/proc 端口反查、notify-rust 通道)
只有在 Linux 上才会被编译到,Windows/macOS 本地开发看不到这些分支的编译错误。
| 页面 | 说明 |
|---|---|
/ 启动封面 | 纯展示的封面页:居中 logo + 标题 + 渐变「启动应用」按钮(含流光动效)。只在未启动时出现——服务已运行直接进预览页,启动/安装中直接进状态页。封面不参与启动流程(不检测环境、不安装、不启动),点按钮只是把启动意图交给状态页。停止服务后回到本页。 |
/loading 服务状态页 | 启动/安装/重启的唯一流程承载页:全屏 loading 按阶段展示检测环境 → 安装依赖 → 启动服务,就绪自动进入预览页;失败或停止时给出重试 / 启动服务 / 查看日志入口。 |
/preview 预览页 | 内嵌本地服务(Windows/macOS 原生子 webview 悬浮在内容区);标题栏可刷新。Linux:宿主页面在独立预览窗口中打开,本页显示说明与「重新打开 / 在浏览器中打开」入口。服务断连时标题栏指示灯变红。 |
系统托盘(右键菜单):打开 恢复窗口,浏览器中打开 用默认浏览器打开服务地址,退出 停止服务并结束进程。
Tauri 2 · Rust · Vite 8 · React 19 · Ant Design 6 · React Router · Zustand
src/ 前端(React + Zustand + React Router)
pages/ Launch / Loading / Terminal / Preview
store/ 应用状态机与事件接线
lib/tauri.ts Tauri invoke/event 桥接
src-tauri/ Rust 后端
src/dsh.rs 工具解析、进程管理、日志泵、URL 探测
src/preview.rs 预览承载(Win/macOS 子 webview;Linux 独立预览窗口)
src/session_events.rs 服务事件订阅(含 Cookie 换取)
capabilities/ 权限声明
scripts/ setup-nsis(离线 NSIS)/ sync-version / release-tag / tag-release-assets(发版改名)/ verify-*
libs/ 离线 NSIS 工具链(nsis-3.11.zip + nsis_tauri_utils.dll)
dsh web 默认监听 127.0.0.1:3080(正式版);应用通过解析其 stdout 的 http://... 行 + TCP 探活确认服务就绪。SameSite=Strict Cookie)在打包正式版里无法靠 DOM iframe 直接完成——壳顶层为 tauri://localhost,iframe 相对它是跨站,Strict Cookie 永不发回。因此预览一律以顶层文档加载宿主地址:Windows/macOS 用同窗口的原生子 webview(按内容区坐标悬浮在壳界面之上),Linux 用独立预览窗口——Tauri 在 Linux 把子 webview 交给窗口的 GtkBox 承载,wry 的坐标定位只在 GtkFixed 父容器里生效,无法悬浮,故改用独立窗口承载,认证与桥接语义完全相同(见 src-tauri/src/preview.rs 文件头)。非 Tauri 浏览器预览(开发模式顶层为 http://localhost)退回 iframe 直接内嵌,必要时把宿主 host 改写为 localhost 保持同站。com.deepseek.harness.desktop.dev、服务端口 6088、UI 端口 6089。lsof,缺失时自动退回 /proc 反查(不依赖外部命令);⑥ 托盘需要系统的 libayatana-appindicator3-1(.deb/.rpm 已自动声明)——真缺了也不会启动失败:应用会跳过托盘照常运行,此时关闭主窗口即退出(.AppImage 用户请自行确认装了该库)。206 commits
Rust
50.4%
TypeScript
35.6%
CSS
7.1%
JavaScript
4.3%
Python
2.4%
本地 DeepSeek Harness 网页服务的轻量桌面壳——一键安装、启动、监控与内嵌预览本地服务,关闭后驻留系统托盘持续运行。

面向新用户:直接下载对应平台的安装包,双击安装即可,无需自己动手搭建环境。
| 平台 | 安装包 | 大小 |
|---|---|---|
| Windows 10/11(64 位) | 下载 .exe(NSIS 安装包) | ~2.0 MB |
| macOS Apple Silicon | 下载 .dmg / 下载 .pkg | ~2.9 MB |
| macOS Intel(64 位) | 下载 .dmg / 下载 .pkg | ~3.0 MB |
| Linux x86_64 | 下载 .deb / .rpm / .AppImage —— 支持范围见下 | ~10 MB(AppImage ~88 MB) |
所有安装包统一发布在 GitHub Releases,选择最新版本、下载对应平台的安装包即可。
产物命名:
dhd_{版本}_{平台}[_{兼容下限}]_{架构}.{后缀}——dhd是 DeepSeek Harness Desktop 的 缩写,由发版流水线在打包后统一改名(tauri 把产物名写死在打包器里、没有模板可配)。用缩写是为了短、 且不含空格:名字里带空格时 GitHub 会把空格换成.,下载页上的名字和本地打包产物对不上, 命令行里也得到处加引号。看一眼文件名就知道该下哪个包:dhd_1.0.5_windows_x64-setup.exe dhd_1.0.5_macos_arm64.dmg / dhd_1.0.5_macos_arm64.pkg dhd_1.0.5_macos_x64.dmg / dhd_1.0.5_macos_x64.pkg dhd_1.0.5_linux_glibc2.35_amd64.deb dhd_1.0.5_linux_glibc2.35_x86_64.rpm dhd_1.0.5_linux_glibc2.35_x86_64.AppImage只改了文件名:安装后的应用、macOS 的
.app、窗口标题与卸载项仍然是 DeepSeek Harness Desktop,dhd只出现在下载到的安装包名字上。Linux 名字里的
glibc2.35是兼容下限(下一节),不是版本号的一部分。 架构标记:macOS 的.dmg/.pkg统一用arm64/x64(tauri 的 dmg 原生产物名是aarch64/x86_64,两者不一致,已在发版时归一);Linux 的.deb用 Debian 的amd64,.rpm/.AppImage用通用的x86_64。
三个 Linux 包都构建在 ubuntu-22.04 上,所以要求 glibc ≥ 2.35 且系统提供 webkit2gtk-4.1。
这是 tauri v2 + webkit2gtk-4.1 能取到的最低基线(再往下的 Ubuntu 20.04 只有 webkit2gtk-4.0), 所以不为各发行版单独打包——滚动发行版(Arch 等)直接用 AppImage 即可:
| 系统 | 建议产物 |
|---|---|
| Ubuntu 22.04+ / Debian 12+ / Mint 21+ / Pop!_OS 22.04+ | .deb |
Fedora 36+ / openSUSE Tumbleweed(rpm 系,仓库需提供 webkit2gtk4.1) | .rpm |
| Arch / CachyOS / Manjaro 等滚动发行版 | .AppImage(需自备 webkit2gtk-4.1 与 libayatana-appindicator) |
| ❌ RHEL / Rocky / Alma 9(glibc 2.34)、openSUSE Leap 15.x(2.31)、Ubuntu 20.04(无 webkit2gtk-4.1) | 低于基线,跑不起来 |
兼容下限由发布流水线里的
Verify glibc floor步骤实测二进制引用的最高 GLIBC 符号版本校验: 一旦构建基线变动导致实际下限超过2.35,流水线会直接失败,不会让文件名说谎。
AppImage 版在 Mesa ≥ 26.1 的系统上会黑屏(CachyOS / Arch / Fedora 等滚动发行版), 终端报:
Could not create default EGL display: EGL_BAD_PARAMETER. Aborting...
根因:AppImage 里打包了按 Ubuntu 构建的 libwebkit2gtk-4.1.so.0,但没有打包自己的
libEGL —— 于是这份 WebKit 是跑在你系统的 Mesa 上的。Mesa ≥ 26.1 会拒绝它调用
eglGetPlatformDisplay() 的方式,直接 EGL_BAD_PARAMETER。窗口本身建得起来(所以主窗口是
黑的、设置窗口是白的,取决于窗口背景色),但 WebView 一帧都画不出来。
失败点在 EGL display 创建,早于 WebKit 读取任何渲染路径开关。因此:
⚠️ 所有环境变量对这个黑屏都无效 ——
WEBKIT_DISABLE_DMABUF_RENDERER、WEBKIT_DISABLE_COMPOSITING_MODE、LIBGL_ALWAYS_SOFTWARE=1、EGL_PLATFORM=surfaceless全都试过,行为完全一致(这正是失败时机在它们之前决定的)。别再在这条路上花时间。
同一台机器上从源码构建是正常的,因为发行版自带的 WebKit 是配着它自己的 Mesa 编译的。
已修复(打包侧):自 v1.0.7 起,AppImage 不再打包 WebKitGTK / GTK / GStreamer
(发布流水线里加了 Slim the AppImage 步骤),改用宿主自己那套 —— 宿主那份天生配着
宿主的 Mesa 编译。用户不需要做任何事,也不会有任何手动步骤。代价是宿主需自备
webkit2gtk-4.1 与 libayatana-appindicator(和 .deb / .rpm 的依赖契约一致)。
⚠️ 下面所有操作都只发生在 AppImage 自己解包出来的副本(~/下载/squashfs-root)里,
不会动你系统上的任何文件;不想要了 rm -rf squashfs-root 即可,重跑 AppImage 也不受影响。
只删 WebKit 不够:系统的 WebKit 会去配包里那份 Ubuntu 的 GStreamer,接着报
undefined symbol: gst_debug_log_id(两套 GStreamer 混用)。要整条栈一起换:
sudo pacman -S webkit2gtk-4.1 libayatana-appindicator # 前提
./dhd_1.0.6_linux_glibc2.35_x86_64.AppImage --appimage-extract
for f in squashfs-root/usr/lib/*.so*; do
b=$(basename "$f")
[ -e "/usr/lib/$b" ] && rm -f "$f"
done
rm -rf squashfs-root/usr/lib/gstreamer-1.0 squashfs-root/usr/lib/webkit2gtk-4.1
./squashfs-root/AppRun
另一条确认可行的路:从源码构建(pnpm install && pnpm tauri:build)。
上游 tauri 的「真正可移植 AppImage」修复仍在开放状态(tauri#12491 未合并), 所以升级 tauri 拿不到这个修复,必须自己处理打包。
| 现象 / 日志关键词 | 含义 | 处理 |
|---|---|---|
| 窗口黑,但看得到转圈和「正在启动服务…」 | WebKit 正常,是前端 bundle 或 dsh 服务没起来 | 属应用层问题,请附日志反馈 |
Failed to get GBM device | DMA-BUF 渲染器 | 试 WEBKIT_DISABLE_DMABUF_RENDERER=1 |
bwrap / sandbox 相关 | WebKit 沙箱起不来 | 安装 bubblewrap(Arch:sudo pacman -S bubblewrap) |
Linux 安装说明:
.deb/.rpm会自动声明 WebKitGTK 4.1、GTK3 与托盘(AppIndicator)依赖, 用sudo apt install ./xxx.deb或sudo dnf install ./xxx.rpm装即可,依赖会一起拉齐; AppImage 不打包系统库,需要目标机自备这些库 —— dpkg 系是sudo apt install libwebkit2gtk-4.1-0 libayatana-appindicator3-1,Arch 系是sudo pacman -S webkit2gtk-4.1 libayatana-appindicator:
chmod +x dhd_x.y.z_linux_glibc2.35_x86_64.AppImage
./dhd_x.y.z_linux_glibc2.35_x86_64.AppImage
💡 轻量:以上为 v0.1.2 实测大小(Windows 2.02 MB、macOS 2.91
3.01 MB),各版本略有差异——全平台安装包都只有 23 MB,秒级下载、秒级安装。Linux 侧.deb/.rpm约 10 MB;AppImage 因为要自带运行时而接近 88 MB(体积大但仍远小于 Electron 应用)。
首次使用(两步完成):
pnpm add -g @deepseek-ai/dsh@latest 安装 DSH 并启动本地服务(仅在 dsh 未安装时执行);
- Windows 若提示 SmartScreen,请选择「更多信息 → 仍要运行」。
- macOS 应用未签名,首次打开需在「系统设置 → 隐私与安全性」中点击「仍要打开」,或右键应用选择「打开」。
@deepseek-ai/dsh(pnpm)并启动本地网页服务,无需任何手动配置。已安装的 dsh 在启动时不会被更新或重装(保留现有版本,避免 @latest 覆盖引发兼容性问题);仅当 dsh 缺失或安装损坏(读不出版本)时才安装。PNPM_HOME):未运行过 pnpm setup 的机器也会自动完成临时 PATH 注入与用户级 PATH 持久化,安装后立即启动,下次打开不再重装。不按 pnpm 主版本设卡:你装的是哪个版本就用哪个(含 11),启动链不会强制降级或重装你的 pnpm——本应用也从不提权(不会用 sudo 装东西,也不会引导你去改系统级目录)。| 链接 | 说明 |
|---|---|
| DeepSeek Harness 官网 | 产品官网 |
| GitHub 仓库 | DeepSeek Harness 官方开源仓库 |
| 开发者文档 | 快速上手指南 |
| 插件开发 | 插件开发文档 |
💡 换新设备/新环境后若报
cargo metadata ... program not found,说明 Rust 工具链未安装。 构建前会先执行scripts/check-rust.mjs自检并给出安装指引(Windows 可运行winget install Rustlang.Rustup后重开终端)。
Linux 构建依赖(Ubuntu / Debian 基线,其它发行版换成对应的包名):
sudo apt install -y libwebkit2gtk-4.1-dev libgtk-3-dev \
libayatana-appindicator3-dev librsvg2-dev patchelf file wget rpm
⚠️
libappindicator3-dev与libayatana-appindicator3-dev在 Ubuntu 22.04 上互相冲突, 同时安装会让 apt 直接失败(E: Unable to correct problems, you have held broken packages), 只装 ayatana 那一个。构建期真正链接的是
libwebkit2gtk-4.1(webkit2gtk-sys)与libgtk-3(gtk-sys);AppIndicator 是运行时依赖——libappindicator-sys用libloading在运行时 dlopenlibayatana-appindicator3.so.1(回退libappindicator3.so.1),构建期不查 pkg-config。rpm提供rpmbuild,只有需要打.rpm时才必须。
pnpm install
pnpm tauri:dev # 开发模式(Vite + Tauri),app id: com.deepseek.harness.desktop.dev
pnpm tauri:debug # 开发模式 + RUST_BACKTRACE / WebView2 日志
开发模式下,壳层 UI 运行在 Vite dev server
http://localhost:6089(支持浏览器预览), 由本应用托管的dsh web服务运行在 6088 端口。
pnpm tauri:build # 当前平台全量打包
pnpm tauri:build:win # Windows NSIS 安装包(.exe)
pnpm tauri:build:mac # macOS DMG
pnpm tauri:build:mac:app # macOS .app
pnpm tauri:build:mac:universal # macOS 通用(universal-apple-darwin)DMG
pnpm tauri:build:linux # Linux 三件套(.deb + .rpm + .AppImage)
pnpm tauri:build:deb # 只打 .deb
pnpm tauri:build:appimage # 只打 .AppImage
Linux 产物落在
src-tauri/target/release/bundle/{deb,rpm,appimage}/。 务必在目标发行版的最低版本上构建(推荐 Ubuntu 22.04):glibc 只向下兼容, 在 Ubuntu 24.04 上构建的产物在 22.04 上会报GLIBC_x.xx not found。CI 固定 用ubuntu-22.04就是这个原因。
Windows 打包依赖离线 NSIS 工具链:
scripts/setup-nsis.mjs会把libs/中的nsis-3.11.zip+nsis_tauri_utils.dll(SHA1 校验)部署到%LOCALAPPDATA%\tauri\NSIS,构建全程不访问网络(该脚本在非 Windows 上直接跳过)。
推送 v* 标签即可自动构建并直接发布(非草稿)Windows / macOS 安装包:
git tag v0.1.0
git push origin v0.1.0
或使用一键发布脚本(自动 bump 版本 → 同步版本文件 → 提交 → 打标签 → 推送):
pnpm release # 自动 bump patch 并发布(0.1.0 → 0.1.1)
pnpm release 0.2.0 # 指定版本发布
pnpm release minor # bump minor 并发布
pnpm release:tag-only # 仅给当前版本打标签推送(不 bump)
流水线(.github/workflows/release.yml):质量门禁(tsc + vite 构建 + Rust 测试)→ 创建已发布的正式 Release → 矩阵构建(Windows NSIS / macOS arm64 / macOS x64 / Linux deb+rpm+AppImage,基线 ubuntu-22.04)→ 用 scripts/tag-release-assets.mjs 把产物统一改名为 dhd_{版本}_{平台}[_{兼容下限}]_{架构} 后追加到同一 Release;Linux 腿会先用 objdump 实测二进制引用的最高 GLIBC 符号版本,与文件名里的 glibc2.35 对不上就直接失败。tauri 的产物名写死在打包器里、没有模板可配,所以改名只能放在 build 之后、上传之前;改名后的路径由脚本写进 $GITHUB_OUTPUT,上传步骤直接消费这份列表而不是 glob,避免改名与 glob 漂移导致漏传。
另有一条 Linux 构建验证流水线(.github/workflows/linux-build.yml):只要改动
src-tauri/**、src/** 等路径就自动跑 cargo fmt --check + cargo test + 打包,
产物只作为 Actions artifact 留存、不进 Release。它的意义是:Linux 专用代码
(cfg(target_os = "linux") 分支、独立预览窗口、/proc 端口反查、notify-rust 通道)
只有在 Linux 上才会被编译到,Windows/macOS 本地开发看不到这些分支的编译错误。
| 页面 | 说明 |
|---|---|
/ 启动封面 | 纯展示的封面页:居中 logo + 标题 + 渐变「启动应用」按钮(含流光动效)。只在未启动时出现——服务已运行直接进预览页,启动/安装中直接进状态页。封面不参与启动流程(不检测环境、不安装、不启动),点按钮只是把启动意图交给状态页。停止服务后回到本页。 |
/loading 服务状态页 | 启动/安装/重启的唯一流程承载页:全屏 loading 按阶段展示检测环境 → 安装依赖 → 启动服务,就绪自动进入预览页;失败或停止时给出重试 / 启动服务 / 查看日志入口。 |
/preview 预览页 | 内嵌本地服务(Windows/macOS 原生子 webview 悬浮在内容区);标题栏可刷新。Linux:宿主页面在独立预览窗口中打开,本页显示说明与「重新打开 / 在浏览器中打开」入口。服务断连时标题栏指示灯变红。 |
系统托盘(右键菜单):打开 恢复窗口,浏览器中打开 用默认浏览器打开服务地址,退出 停止服务并结束进程。
Tauri 2 · Rust · Vite 8 · React 19 · Ant Design 6 · React Router · Zustand
src/ 前端(React + Zustand + React Router)
pages/ Launch / Loading / Terminal / Preview
store/ 应用状态机与事件接线
lib/tauri.ts Tauri invoke/event 桥接
src-tauri/ Rust 后端
src/dsh.rs 工具解析、进程管理、日志泵、URL 探测
src/preview.rs 预览承载(Win/macOS 子 webview;Linux 独立预览窗口)
src/session_events.rs 服务事件订阅(含 Cookie 换取)
capabilities/ 权限声明
scripts/ setup-nsis(离线 NSIS)/ sync-version / release-tag / tag-release-assets(发版改名)/ verify-*
libs/ 离线 NSIS 工具链(nsis-3.11.zip + nsis_tauri_utils.dll)
dsh web 默认监听 127.0.0.1:3080(正式版);应用通过解析其 stdout 的 http://... 行 + TCP 探活确认服务就绪。SameSite=Strict Cookie)在打包正式版里无法靠 DOM iframe 直接完成——壳顶层为 tauri://localhost,iframe 相对它是跨站,Strict Cookie 永不发回。因此预览一律以顶层文档加载宿主地址:Windows/macOS 用同窗口的原生子 webview(按内容区坐标悬浮在壳界面之上),Linux 用独立预览窗口——Tauri 在 Linux 把子 webview 交给窗口的 GtkBox 承载,wry 的坐标定位只在 GtkFixed 父容器里生效,无法悬浮,故改用独立窗口承载,认证与桥接语义完全相同(见 src-tauri/src/preview.rs 文件头)。非 Tauri 浏览器预览(开发模式顶层为 http://localhost)退回 iframe 直接内嵌,必要时把宿主 host 改写为 localhost 保持同站。com.deepseek.harness.desktop.dev、服务端口 6088、UI 端口 6089。lsof,缺失时自动退回 /proc 反查(不依赖外部命令);⑥ 托盘需要系统的 libayatana-appindicator3-1(.deb/.rpm 已自动声明)——真缺了也不会启动失败:应用会跳过托盘照常运行,此时关闭主窗口即退出(.AppImage 用户请自行确认装了该库)。206 commits
Rust
50.4%
TypeScript
35.6%
CSS
7.1%
JavaScript
4.3%
Python
2.4%