dsh-desktop-shell
A desktop launcher shell for DeepSeek Harness (dsh): a thin Electron wrapper that gives the dsh web profile a native window and a system-tray home.
What it does
Double-click the app → it checks whether the dsh web server is already listening (default http://127.0.0.1:3080); if not, it starts it for you; then it opens the web UI in a native window.
- Tray-resident — closing the window hides it to the system tray instead of quitting; tray menu: open main window / quit.
- Single instance — launching again focuses the existing window.
- Ownership-aware — a web server the shell started is stopped when the shell quits; a pre-existing one (your own terminal, another tool) is left untouched.
- Configurable — the dsh command, working directory, extra environment variables, port, and window title all live in
config.json; no hardcoded machine paths, no bundled API endpoints.
Install the dsh side (the bundle)
This repository is a dsh profile bundle: its package.json declares dsh.bundle.patch, so installing it into the web profile activates a patch layer that pins the web server to loopback 127.0.0.1:3080 and mounts a small glue plugin (prints a ready line, warns if the server ever binds beyond loopback).
From a git checkout:
dsh plugin --profile web add github:ikashana/dsh-desktop-shell
From npm (once published):
dsh plugin --profile web add dsh-desktop-shell
Then start dsh web as usual (dsh --profile web) — or let the shell below start it for you.
Install the shell (the desktop app)
Requirements: Node.js ≥ 18 (Electron downloads at install time).
git clone https://github.com/ikashana/dsh-desktop-shell.git
cd dsh-desktop-shell
npm install
cp config.json.example config.json # then edit to match your environment
npm start
The only required edit is dshCommand (and cwd if dsh lives elsewhere): point it at your dsh CLI, or at your checkout's node + source entry for a from-source install, e.g.
{
"dshCommand": ["C:/path/to/node.exe", "--import", "tsx/esm", "apps/cli/src/bin.ts", "--profile", "web"],
"cwd": "C:/path/to/deepseek-harness"
}
On Windows, prefer an absolute path to node.exe; a bare dsh resolves through its .cmd shim, which child_process refuses to spawn without a shell (CVE-2024-27980 hardening) — the shell handles that case too, but an explicit executable is most reliable.
config.json
| Field | Default | Meaning |
|---|---|---|
port |
3080 |
Port the web server listens on. Keep in sync with the bundle patch's webserver.port if you change it. |
dshCommand |
["dsh", "--profile", "web"] |
Argv of the command that starts the dsh web server. |
cwd |
shell directory | Working directory for dshCommand. |
env |
{} |
Extra environment variables for the web process (e.g. provider endpoints your dsh install reads from env). |
title |
dsh Desktop |
Window and tray title. |
Desktop shortcut (Windows)
$WshShell = New-Object -ComObject WScript.Shell
$lnk = $WshShell.CreateShortcut("$HOME\Desktop\dsh Desktop.lnk")
$lnk.TargetPath = "C:\path\to\dsh-desktop-shell\node_modules\electron\dist\electron.exe"
$lnk.Arguments = "`"C:\path\to\dsh-desktop-shell`""
$lnk.WorkingDirectory = "C:\path\to\dsh-desktop-shell"
$lnk.IconLocation = "C:\path\to\dsh-desktop-shell\assets\icon.ico"
$lnk.Description = "dsh Desktop · DeepSeek Harness launcher shell"
$lnk.Save()
Logs
The shell writes shell.log and web.log into Electron's userData directory (Windows: %APPDATA%\dsh-desktop-shell\) — the first place to look when the web server fails to come up.
Platform notes
Developed and tested on Windows. The tray behavior is cross-platform; process-tree teardown uses taskkill on Windows and falls back to kill() elsewhere. The window icons are rendered from the dsh favicon (assets/favicon.svg, MIT) — re-render with node_modules\electron\dist\electron.exe make-icon.js if you want a custom look.
Layout
├── main.js # Electron main process: window / tray / single instance / web lifecycle
├── lib/index.js # dsh bundle glue plugin (loopback check + ready line)
├── cordis.patch.yml # dsh profile patch layer (loopback-pinned webserver + glue row)
├── config.json.example
├── make-icon.js # icon renderer (favicon.svg → PNG)
└── assets/ # icons + favicon source
License
MIT. assets/favicon.svg is copied from the MIT-licensed deepseek-harness repository.
No comments yet. Be the first to write one.