# 🐋 DeepSeek Harness — 桌面版
**一个 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 的原生 macOS 桌面外壳 —— 双击即用,无需终端。**
[](https://github.com/Evan1u/deepseek-harness-desktop/releases)
[](#)
[](LICENSE)
[](https://github.com/Evan1u/deepseek-harness-desktop)
*[English](README.md) · [中文](README.zh.md)*
---
## ✨ 这是什么
DeepSeek Harness 很强,但启动它得打开终端敲 `dsh web`。这个 App 用一个**轻量 Electron 外壳**把它包了起来——双击后,它会启动 `dsh --profile web --no-open --port 0`,等待本地 URL,然后在原生窗口里渲染**完全相同的 Web GUI**。所有 web 功能,零差异、零终端。
| 🖥️ 无需终端 | 🐋 灵动托盘 | 🎯 忙闲感知 | 🌗 深/浅自适应 | 🔄 自动更新 |
|:---:|:---:|:---:|:---:|:---:|
| 双击即用 | 两套图标可切换 | 图标反映真实负载 | 图标随系统切换 | GitHub Releases |
## 🐋 托盘图标 —— 活的、可切换
菜单栏图标**不是一个静态图案**,它会反映 DeepSeek Harness 正在做什么:
- **空闲** → 安静的静止图标;
- **工作** → 动态图标,**速度**跟随后端忙碌程度(运行中的会话数 + 任务数)。
右键图标可在**两套风格**间切换:
| 风格 | 静止 | 工作 |
| 🐟 Fish Swing (默认) | 静止鲸鱼 | 摆动鲸鱼——工作越多摆得越快 |
| 🔮 Thinking Orb | 搜索球 | 聆听球——点阵波纹球 |
两套风格都会自动适配深/浅色菜单栏,选择会在下次启动时记住。
 🐟 Fish Swing |
 🔮 Thinking Orb |
### 忙碌度 → 动画
| 忙碌度 | 状态 | 频率 |
| --- | --- | --- |
| 0 | 静止 | — |
| 1 | 轻 | 慢(约 1.8 秒/循环) |
| 2 | 中 | 中(约 1.2 秒/循环) |
| 3 | 重 | 快(约 0.8 秒/循环) |
> 忙碌度 = 运行中的会话数 + 运行中的任务数,实时读取自 harness 自身的事件流。
### 摆动幅度
右键菜单栏图标 → **Swing Amplitude** → 选一档:
| 档位 | Subtle | Default | Strong | Stronger | Strongest |
| --- | --- | --- | --- | --- | --- |
| 旋转 | 6° | 9° | 12° | 15° | 18° |
## 🚀 使用指南
双击 `.app`——或拖进「应用程序」。首次启动若被 Gatekeeper 拦截(未签名),*右键 → 打开*。
- **左键**托盘图标 → 唤出窗口
- **右键** → Open / Quit / Icon Style / Swing Amplitude
- **红色关闭按钮** → 藏到托盘,App 在后台继续运行
🔧 工作原理
```
DeepSeek Harness.app
└─ Electron 主进程
├─ 定位 dsh(DSH_BIN 覆盖 → /opt/homebrew/bin/dsh → … → PATH)
├─ 启动:dsh --profile web --no-open --port 0
├─ 解析 stdout:"dsh web: http://127.0.0.1:"
├─ BrowserWindow.loadURL(那个 URL)
└─ 生命周期:退出时 SIGTERM · 后端崩溃弹重试对话框
```
后端绑定 `127.0.0.1` 的系统分配端口,`/api` 的 loopback 信任栅栏无需额外配置即可通过,也不存在固定端口冲突。
> ⚠️ **不要**同时用另一个终端 `dsh web` 打开同一个会话——会话存储是单写者,两个活着的后端写同一份日志会损坏它(历史会报 `corrupt session log: seq gap in committed region`)。
📦 开发 / 打包
```sh
npm install # 安装 electron + electron-builder
npm start # 从源码运行
npm run pack # 构建 .app(release/mac-arm64/DeepSeek Harness.app)
npm run dist # 同时构建 .dmg 和 .zip
```
产物输出到 `release/`。若钥匙串里有 **Developer ID Application** 证书,electron-builder 会自动签名;否则保持未签名,供本地使用。
🔏 签名与公证(消除 Gatekeeper)
签名 + 公证需要 Apple Developer Program 会员与 Developer ID 证书。工具链与构建配置都已就绪——你只需提供凭证。
**一次性设置**
1. 加入 [Apple Developer Program](https://developer.apple.com/programs/)(付费)。
2. 创建 **Developer ID Application** 证书:Xcode → Settings → Accounts → Manage Certificates → `+` → Developer ID Application。用 `security find-identity -v -p codesigning` 验证。
3. 创建 **App Store Connect API key**(Developer 角色):[App Store Connect](https://appstoreconnect.apple.com/) → Users and Access → Integrations → App Store Connect API → Team Keys → 生成 → 下载 `.p8` → 记下 **Key ID** 与 **Issuer ID**。
**构建 + 公证**
```sh
npm run pack # 证书装好后会自动签名
APPLE_API_KEY_PATH=~/.appstoreconnect/AuthKey_XXXXXX.p8 \
APPLE_API_KEY_ID=XXXXXXXXXX \
APPLE_API_ISSUER_ID=00000000-0000-0000-0000-000000000000 \
./scripts/notarize.sh
```
🔄 自动更新(GitHub Releases)
App 启动时(之后每小时)自动检查更新,发现新版本会提示 **Restart now**。用 GitHub token 发布新版本:
```sh
GH_TOKEN=github_pat_xxx ./scripts/publish.sh
```
> 注:macOS 自动更新在签名后的 App 上最可靠;未签名的个人构建是尽力而为。
## ⚙️ 配置
| 变量 | 用途 |
| --- | --- |
| `DSH_BIN` | `dsh` 可执行文件的绝对路径(默认 `/opt/homebrew/bin/dsh`)。 |
| `DSH_HOME` | 从环境继承;与 CLI 共用 `~/.dsh` 的 profiles、凭据与会话。 |
🗺️ 路线图
- [x] v0.1 —— Electron 外壳包裹 `dsh web`(完整 web 功能对等)
- [x] 跟随系统明暗切换的 Dock 图标
- [x] 忙闲感知的动态托盘 + 关窗后台常驻
- [x] 两套可切换的托盘图标风格(Fish Swing / Thinking Orb)
- [x] 自动更新(GitHub Releases)
- [ ] 签名 + 公证——配置就绪,待 Apple Developer 凭证
- [ ] 原生 IPC 传输——通过 `file://` 加载 `dist`,借 `window.__DSH_TRANSPORT__` 把 `/api` 走 `ipcRenderer`
*为 DeepSeek Harness 社区用心打造。*