A Windows desktop app wrapper around the DeepSeek Harness (DSH) web UI: double-click to launch, lives in the system tray, no browser required.
Built with WinForms + WebView2. No Electron, no bundled Chromium.
| Approach | Processes | Notes |
|---|---|---|
| Electron | 6–8 + ~150 MB of bundled Chromium | Heaviest |
| This project (WebView2) | 1 exe + 5–6 child processes | Reuses the system WebView2 runtime |
WebView2 is a shared runtime that ships with Windows — it is not the Edge browser:
the process is named msedgewebview2.exe, and msedge.exe is never started.
It is included with Windows 11; Windows 10 may need the Evergreen Runtime.
- Straight into DSH — opens directly into the DSH UI, not a splash or button page
- Close does not quit — the × button minimizes to the system tray and the backend keeps running
- Tray interaction — left click restores the window, right click opens a menu
- Single instance — launching again focuses the existing window instead of opening a second one
--hidden— starts silently into the tray, ideal for auto-start on login- No third-party dependencies — only the bundled .NET Framework 4.x and the WebView2 runtime
- Small — the exe is ~400 KB (including the embedded fallback page and icon, excluding WebView2 DLLs)
- Configurable — URL, port and log path all come from a JSON file
- Self-healing — reloads when DSH restarts with a new token, rebuilds the engine if it crashes, restarts itself if the UI hangs
Every time DSH restarts (for example after the monitoring platform triggers an automatic recovery) it issues a new access token, while the frontend already loaded in the page still holds the old one. That is the root cause of "the desktop window goes black after a while and the buttons stop responding". This app defends against it on four levels:
| Mechanism | Trigger | Action |
|---|---|---|
| Token following | the token in logFile differs from the one the page was loaded with |
reload with the new token |
| Crash recovery | WebView2 renderer crashes / browser process exits | reload, or rebuild the engine if needed |
| UI watchdog | the UI thread stops responding | process-level self-restart |
| Orphan cleanup | a msedgewebview2.exe whose host is already dead is found at startup |
terminate it so it cannot fight over the user data folder |
Token following requires logFile to point at the DSH log file. Without it the app falls back
to manual refresh (the "Refresh" button in the toolbar). If a navigation itself fails, it is
retried once after 6 seconds.
The official repository already ships a desktop app: apps/desktop, an Electron shell
that bundles its own Python / Node.js / pnpm distributions and defaults to port 19387.
(The CLI refuses to launch the desktop profile by hand — it is owned by the Electron app.)
Official Desktop (apps/desktop) |
This project | |
|---|---|---|
| Stack | Electron (bundled Chromium) | WinForms + system WebView2 |
| Runtime | Bundles its own Python / Node.js / pnpm | Reuses your existing DSH and system runtime |
| Size | Large (full runtime + installer) | exe ~400 KB (excluding WebView2 DLLs) |
| Port | Ships its own service, default 19387 | Attaches to your existing DSH (default 3080) |
| Installation | Installer (releases require code signing) | Portable, just a folder |
| Build tooling | electron-builder + signing certificate | The bundled csc.exe, no SDK needed |
| Native folder picker | Electron folder dialog | Reuses DSH's own picker |
| Maintained by | Official | Third party |
- Want something that works out of the box, feature-complete, officially maintained → use the official
apps/desktop. - Already running DSH (say, registered as a Windows service) and just want a lightweight window → use this project. It does not duplicate the runtime; it is only a shell.
- This project does not take over your service: DSH is still provided by your own service or process, so it will not conflict with an existing deployment.
| Purpose | Requirement |
|---|---|
| Run | Windows 10/11; .NET Framework 4.6+; WebView2 runtime |
| Build | The csc.exe bundled with Windows (no .NET SDK and no Visual Studio required) |
| Icon generation (optional) | Chrome or Edge (to rasterize SVG into PNG) |
Check whether the WebView2 runtime is installed:
Test-Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}'powershell -ExecutionPolicy Bypass -File .\build.ps1The build script will:
- download the
Microsoft.Web.WebView2SDK from nuget.org (if not already present locally) - place the managed DLLs and the native
WebView2Loader.dllintodist\ - compile
src\DesktopApp.cswith thecsc.exebundled with Windows
Artifacts land in dist\:
dist\
├─ DeepSeekHarness.exe
├─ Microsoft.Web.WebView2.Core.dll
├─ Microsoft.Web.WebView2.WinForms.dll
├─ WebView2Loader.dll
├─ DeepSeekHarness.ico <- generated by tools\make-icon.ps1 (optional)
└─ dsh-launcher.json <- your config; do not commit it to git
Copy config\dsh-launcher.example.json to dist\dsh-launcher.json and edit it:
{
"mainUrl": "http://127.0.0.1:3080/",
"dshWebUrl": "",
"monitorUrl": "",
"chromePath": "",
"logFile": "",
"port": 3080,
"minimizeToTray": true,
"followToken": true,
"tokenPollMs": 3000,
"watchdogMs": 8000,
"autoCleanOrphans": true
}| Field | Description |
|---|---|
mainUrl |
Page loaded when the window opens. Defaults to the local DSH |
dshWebUrl |
Target of the tray item "Open web page". Hidden when empty |
monitorUrl |
Target of the tray item "Open monitoring platform". Hidden when empty |
chromePath |
Browser used by "Open in Chrome". Auto-detected when empty |
logFile |
Path to the DSH log file. Used to extract the token-bearing URL, giving login-free startup and token following. Skipped when empty |
port |
Local DSH port, default 3080 |
minimizeToTray |
When false, the × button quits directly |
followToken |
Whether to reload automatically when the token changes, default true |
tokenPollMs |
Token polling interval in milliseconds, default 3000 |
watchdogMs |
Watchdog interval in milliseconds, default 8000 |
autoCleanOrphans |
Whether to clean up orphan WebView2 processes at startup, default true |
Double-click dist\DeepSeekHarness.exe.
To start it on login, put a shortcut in
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\
and append --hidden to the target so it goes straight to the tray.
Every time DSH Web starts it prints a URL carrying a token:
dsh web: http://127.0.0.1:3080/?token=<randomly generated on each start>
Opening that URL plants a persistent signed cookie (the signing key lives in
$DSH_HOME/.credentials.yaml and survives restarts).
So as long as logFile points at that log, the app loads the latest token URL
automatically, with no manual login; the cookie is persisted under
%LOCALAPPDATA%\DeepSeekHarness\webview2.
Show main window
────────────────────────
Open web page <- dshWebUrl (hidden when empty)
Open monitoring platform <- monitorUrl (hidden when empty)
────────────────────────
Back to local DSH
Open current page in Chrome
────────────────────────
Quit
The repository contains no brand icons (to avoid trademark issues). Generate one from your local DSH installation with the script:
powershell -ExecutionPolicy Bypass -File .\tools\make-icon.ps1 -Source "<path to your favicon.svg>"Pipeline: SVG -> headless Chrome rasterization -> multi-size ICO (16/24/32/48/64/128/256, all BMP/DIB entries).
You can also pass a PNG directly: -Source "logo.png".
.
├─ build.ps1 one-step build
├─ CHANGELOG.md changelog
├─ README.md English (this file)
├─ README.zh-CN.md Chinese
├─ config\
│ └─ dsh-launcher.example.json config template
├─ src\
│ ├─ DesktopApp.cs main app: WebView2 + tray + single instance + self-healing
│ ├─ Launcher.cs alternative: minimal launcher panel (opens in your browser)
│ ├─ home.html fallback page shown when the local service is down
│ ├─ logo.png icon embedded into the fallback page
│ └─ MakeIcon.cs multi-size ICO generator
├─ tools\
│ └─ make-icon.ps1 icon pipeline (SVG -> PNG -> ICO)
└─ docs\
└─ BUILD.md full build walkthrough and pitfalls (Chinese)
- The exe is not a single process: the DSH UI is HTML/CSS/JS, so any exe that displays it needs a browser engine. This project reuses the system WebView2, which is lighter than Electron, but it still spawns 5–6 child processes.
logFiledepends on the log: if DSH was started in the foreground and the URL was only printed to the console, the token in the log will be stale and the app falls back to cookie authentication. WhenlogFileis empty there is no token following, so you must click "Refresh" after DSH restarts.- 8.3 short paths affect the process name: when launched through a short path the process is named
DEEPSE~1; a normal double-click givesDeepSeekHarness. Match processes by command line, case-insensitively.
More implementation details and pitfalls: docs/BUILD.md (Chinese).
See CHANGELOG.md (Chinese).
Jason
- Blog: https://blog.20240606.xyz
- GitHub: https://github.com/666su