Introduction¶
Developers running the DeepSeek Harness (DSH) WebUI encounter a specific annoyance: dsh web is a single Node process. After configuration changes, installing new bundles, or if the process simply crashes, the UI disconnects—you have to go back to the terminal, find that process, manually type the start command again, and refresh the browser. The restart action itself isn’t hard, but having to leave the browser to do it every time is very disruptive.
Breaking this down into requirements means two things: triggering a restart directly from the WebUI; and having something responsible for bringing it back up after the process exits so the page recovers automatically. dsh-web-restart is a plugin that combines these two actions. DSH’s philosophy is “everything is a plugin,” so this infrastructure capability fits perfectly as a plugin to fill this gap.
What is this¶
dsh-web-restart is maintained by QIN-SMART, licensed under MIT, current version 0.1.0, with runtime dependency @deepseek-ai/schemastery ^3.18.1. It does two things:
- Adds a “⇄ Restart DSH” button at the bottom of the DSH WebUI sidebar. When clicked, the process exits, the page enters a mask state and polls, and the page auto-refreshes once the service recovers.
- Provides a companion macOS launchd LaunchAgent (
launcher/macos/) withKeepAliveto automatically startdsh webafter it exits or crashes, supporting login startup.
One thing needs to be clarified first: the plugin itself cannot self-bootstrap after death—the process is gone, so naturally the button cannot be rendered. Therefore, the restart button and the external daemon are two halves that must go together; neither can function without the other.
Core Features¶
Restart Button (Client-side)¶
- Injects the sidebar footer slot
sidebar.footer.actionto render the “⇄ Restart DSH” button. - Two-step confirmation to prevent accidental triggers. Implementation does not rely on
window.confirmbecause it is silently disabled in embedded/sandboxed WebViews. - Upon triggering, a full-screen mask is attached to
documentElement(max z-index) prompting “Restarting DSH…”. It polls every 2 seconds to check if the service has recovered and auto-refreshes the page when it does.
Host-side: Endpoints, Commands, and Exit Modes¶
- Registers a same-origin HTTP endpoint
POST /api/_dsh/restartvia thewebServerservice. Since the browser and server are same-origin,fetchworks directly without relying on an active session. - The endpoint returns
202upon hit, waits for a slight delay to ensure the response is flushed to disk, then executes the exit. - Two exit modes:
mode: "exit"(default):process.exit(), handed to launchdKeepAliveto restart.mode: "exec": Spawns a newdsh webwithin the same process andunrefsit; the old process exits. Suitable for scenarios without an external daemon, running manually from the terminal.
- Optional
tokenvalidation, supporting bothAuthorization/X-Dsh-Restart-Tokenheaders. - Also registers the
/restartslash command (enableCommand). The trigger mechanism is dual-channel: the primary is the DSH official RPC (remote.commands.execute("/restart")), with a fallback to same-originfetch.
launchd Daemon and Dock Icon¶
KeepAliveautomatically restarts crashed/exited processes, supporting login startup.- The install script copies
dsh-web-start.shto~/Library/Application Support/dsh-web/and hands it to launchd—because macOS TCC privacy protection prevents launchd from reading scripts in directories like~/Documents. - The startup script auto-detects the paths for
nodeanddsh(nvm / PATH) and can be overridden viaNODE_BIN/DSH_ENTRY/DSH_HOMEenvironment variables. - Comes with AppleScript source code, which can be compiled into a Dock
.appicon that opens the browser upon clicking. - launchd logs are located at
~/.dsh/dsh-web.launchd.logand~/.dsh/dsh-web.launchd.err.log.
Installation and Activation¶
The plugin installs into your DSH profile directory, defaulting to ~/.dsh/profiles/web/.
Method A: Install from GitHub (Recommended in README). Note that <your-username>/<repo-name> is a placeholder in the README text; please replace it with the actual repository you host:
cd ~/.dsh/profiles/web
pnpm add "dsh-web-restart@github:<你的用户名>/<仓库名>"
Then add "dsh-web-restart" to the end of the dsh.profile.bundles array in ~/.dsh/profiles/web/package.json:
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-web-restart" // ← Add this line
]
}
}
It takes effect after restarting dsh web.
Method B: Local Link (For development):
cd ~/.dsh/profiles/web
pnpm add "link:/绝对/路径/dsh-web-restart"
Similarly, add "dsh-web-restart" to the bundles array and restart to take effect.
The four default configuration items (mode / token / flushMs / enableCommand) can be overridden in the profile’s cordis.patch.yml, for example, setting a token:
- id: web-restart
name: dsh-web-restart
token: my-secret
macOS: Install Daemon and Dock Icon¶
First, install the launchd daemon:
chmod +x launcher/macos/*.sh
launcher/macos/dsh-web-control.sh install
Common sub-commands:
| Command | Action |
|---|---|
dsh-web-control.sh status |
View launchd status |
dsh-web-control.sh restart |
Manual restart |
dsh-web-control.sh stop / start |
Stop / Start (Stop does not disable auto-start) |
dsh-web-control.sh uninstall |
Uninstall |
Next, compile the Dock icon using macOS’s built-in osacompile:
mkdir -p build
osacompile -o build/DSH.app launcher/macos/DSH-Web-Launcher.applescript
cp -R build/DSH.app /Applications/
The README also provides an alternative approach using Automator: create a new “Application” → Run Shell Script:
~/Library/Application Support/dsh-web/dsh-web-start.sh
sleep 3
open http://127.0.0.1:3080
Save as DSH.app and drag it to the Dock / Launchpad.
Development and Testing¶
After changing the code, run these two steps first:
node --check index.mjs lib/client.js # Syntax check
node validate.mjs # Host logic self-test (stub ctx, no service startup)
Use Cases and Notes¶
Suitable for: macOS users who use DSH WebUI as a background service and want to restart directly from the browser or have it automatically recover after a crash or exit. If there is no external daemon currently and it is running manually from the terminal, change mode to "exec"; the daemon script included in the repo only covers launchd.
A few notes:
- The restart button and the external daemon are two halves that go together. If you only install the plugin without the launchd daemon, the default
mode "exit"will kill the process and it won’t return. - macOS TCC restrictions: launchd cannot read scripts in directories like
~/Documents. The install script has already handled this (copied to~/Library/Application Support/dsh-web/), so do not manually move the startup script back to the Documents directory. - If the restart endpoint is accessed beyond the local machine, it is recommended to configure
tokenvalidation incordis.patch.yml.
Security note: This plugin runs with the permissions of the current dsh process and possesses the ability to trigger a process exit. It is recommended to check the source code and license (MIT) before installing to ensure the behavior meets expectations.
Summary¶
dsh-web-restart solves a small but frequent problem: changing “Restart DSH” from “going to the terminal to type a command” to “clicking a button in the browser,” and then letting launchd ensure the process definitely comes back. The button handles the trigger and UI recovery, while launchd handles bringing up the process; both halves must be in place for it to be complete.
- Community directory page: https://www.skillhub.cn/plugins/QIN-SMART/dsh-web-restart (Community-maintained independent site, no official affiliation with DeepSeek / HF)
- GitHub: https://github.com/QIN-SMART/dsh-web-restart