# DSH Web Window Companion
**Close the browser window = stop the dsh web server**
[](LICENSE)
[]()
[]()
[]()
English | [中文](README.md)
## What is this
A bundle plugin for the Web profile of [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH). Once installed, `dsh web` behaves differently:
1. It no longer throws a tab into your default browser;
2. Instead it opens a dedicated **app-mode** (`--app=`) Edge / Chrome window, with the authenticated URL, on a separate browser profile — your everyday browser state is never touched;
3. **Closing that window gracefully stops the dsh web server** — the port is released and no background process lingers.
Made for people who use DSH Web like a desktop app: open the window to work, close it to walk away.
> Prefer a double-click desktop icon instead of the terminal? See the sister project [dsh-win-quick-launcher](https://github.com/big0lives/dsh-win-quick-launcher) (no-terminal launcher). ⚠️ **Use one or the other, never both at once**: they share the same dedicated browser profile, and running both makes the two window processes kick each other off — the window flash-closes and the server gets stopped by mistake.
## Install
Install into the web profile (a git install works — this plugin is plain JavaScript with no build step):
```sh
dsh plugin --profile web add github:big0lives/dsh-web-window-companion
```
From a source checkout, run inside the repository root:
```sh
pnpm dsh plugin --profile web add github:big0lives/dsh-web-window-companion
```
Verify the layer is composed:
```sh
dsh --profile web --dump-config # expect a "# == dsh-web-window-companion" layer
```
Uninstall:
```sh
dsh plugin --profile web remove dsh-web-window-companion
```
## Usage
Nothing to change — start as usual:
```sh
dsh web
```
- The terminal still prints the authenticated URL (`dsh web: http://127.0.0.1:3080/?token=...`) as a fallback if the app window cannot open;
- Close the app window → the server shuts down gracefully (root fiber dispose, exit code 0);
- Under an SSH launch the plugin stays silent and never grabs a window.
## How it works
```
dsh web
└─ once the Loader tree settles, the plugin injects connection / webServer
├─ connection.authenticatedUrl() builds the tokenized URL
├─ spawns the browser: --app= --user-data-dir=
│ └─ dedicated profile ⇒ browser process lifetime == window lifetime
└─ window closed → browser process exits → ctx.root.fiber.dispose() → graceful stop
```
The bundle patch also overrides the stock `web-runtime` row with `openBrowser: false` (restating every other key unchanged) to suppress the default-browser handoff; `printUrl` stays on as the fallback.
- **Zero dependencies, zero configuration, plain JavaScript**: a git install needs no `allowBuilds` allowlist;
- Browser probing order: Edge (x86 → x64) → Chrome (x64 → x86); if none is found a warning is printed and the URL fallback remains.
## Troubleshooting
| Symptom | Cause and fix |
| --- | --- |
| No app window appears | Make sure Edge or Chrome is installed; check the terminal for a `[window-companion]` warning; the printed URL always works |
| A default-browser tab still opens | The plugin layer is not composed — run `dsh --profile web --dump-config` and look for `# == dsh-web-window-companion` |
| Server keeps running after closing the window | The window must be the plugin-opened one on the dedicated profile (no tab strip); a manually opened tab does not own the server's lifetime |
| Want the stock behavior back | `dsh plugin --profile web remove dsh-web-window-companion` fully restores it |
## License
[MIT](LICENSE) © 2026 big0lives