DeepSeek Harness — Desktop (macOS / Apple Silicon)
English | 中文
A thin Electron shell around the existing dsh CLI. Double-click the app and it boots dsh --profile web --no-open --port 0, waits for the local URL, and renders the exact same Web GUI in a native window — so every web feature is available with zero divergence, no terminal required.
✨ Animated menu-bar whale
The tray whale in the macOS menu bar is alive — it sways while DeepSeek Harness is working and rests when idle. Its sway speed (and a touch of the swing angle) tracks how busy the backend is: a gentle glide during a single chat, a lively waggle while parallel jobs run.

| Busyness | State | Frequency | Amplitude |
|---|---|---|---|
| 0 | Still | — | 0° |
| 1 | Light | Slow (~2.4 s/cycle) | ±4° |
| 2 | Medium | Medium (~1.7 s/cycle) | ±6° |
| 3 | Heavy | Fast (~1.1 s/cycle) | ±8° |
Busyness = running sessions + running jobs, read live from the harness's own event streams.
🚀 Getting Started
Launch — double-click the .app, or drop it into Applications and open from there. If macOS warns on first launch (unsigned build), right-click → Open.
Tray — the whale in the menu bar is the tray:
- Left-click → show the window; right-click → Open / Quit.
- Clicking the window's red close button hides the window to the tray; the app keeps running in the background.
Update — the app checks GitHub Releases on launch (then hourly) and offers Restart now when a newer version is out. To install manually, grab the latest .dmg or .zip from Releases.
How it works
DeepSeek Harness.app
└─ Electron main process
├─ resolve dsh (DSH_BIN override → /opt/homebrew/bin/dsh → … → PATH)
├─ spawn: dsh --profile web --no-open --port 0
├─ parse stdout: "dsh web: http://127.0.0.1:<port>"
├─ BrowserWindow.loadURL(that URL)
└─ lifecycle: SIGTERM on quit · retry dialog on backend crash
The backend binds 127.0.0.1 on an OS-assigned port, so the /api loopback trust fence passes with no extra configuration and there is no fixed-port conflict (it can run alongside a terminal dsh web).
Develop / run
npm install # installs electron + electron-builder (project-local npm cache)
npm start # run from source
Package
npm run pack # builds the .app (release/mac-arm64/DeepSeek Harness.app)
npm run dist # also builds .dmg and .zip
Output lands in release/. If a Developer ID Application certificate is present in your Keychain, electron-builder signs it automatically (hardened runtime + entitlements); otherwise the app is left unsigned for local use.
Code signing & notarization (remove Gatekeeper)
Signing + notarization require an Apple Developer Program membership and a Developer ID certificate. The toolchain (notarytool, stapler) and the build config are already wired up — you only need to supply the credentials.
One-time setup
- Join the Apple Developer Program (paid).
- Create a Developer ID Application certificate and install it in Keychain:
Xcode → Settings → Accounts → (your Apple ID) → Manage Certificates →
+→ Developer ID Application. Verify withsecurity find-identity -v -p codesigning(it should now list one). - Create an App Store Connect API key (Developer role):
App Store Connect → Users and Access → Integrations → App Store Connect API → Team Keys → generate → download the
.p8→ note the Key ID and Issuer ID.
Build + notarize
npm run pack # signs automatically once the cert is in Keychain
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
scripts/notarize.sh zips the app, submits it via notarytool, staples the ticket, and validates. Once notarized, Gatekeeper stops complaining — even for apps distributed to other machines.
Auto-update (GitHub Releases)
The app checks for updates with electron-updater, published to GitHub Releases at Evan1u/deepseek-harness-desktop.
Publish a new release — requires a GitHub Personal Access Token with repo scope:
GH_TOKEN=github_pat_xxx ./scripts/publish.sh
This builds the .zip/.dmg, uploads them plus latest-mac.yml, and running apps auto-detect, download, and offer to restart into the new version.
Note: reliable macOS auto-update is best with a signed app; for an unsigned personal build it is best-effort (Gatekeeper may still prompt on the replaced bundle).
Configuration
DSH_BIN— absolute path to thedshexecutable (defaults to/opt/homebrew/bin/dsh).DSH_HOME— inherited from the environment; the desktop app uses the same~/.dshprofiles, credentials, and sessions as the CLI.
Roadmap
- v0.1 — Electron shell wrapping
dsh web(full web parity). - Appearance-adaptive Dock icon (light/dark variants follow the system).
- Busyness-aware animated tray whale + close-to-tray (background resident).
- Auto-update (GitHub Releases).
- Code signing + notarization — config and scripts ready, pending Apple Developer credentials.
- Native IPC transport — load
distoverfile://and bridge/apioveripcRenderervia the harness'swindow.__DSH_TRANSPORT__hook (no HTTP server).
No comments yet. Be the first to write one.