DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
P

dsh-power-button

Power Button

Self-contained power control for DSH: sidebar power button with an upward 重启/关机 menu plus a Windows-shutdown-style overlay. Own restart & shutdown engine (no dependency on other plugins), MIT licensed.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:keyiadiannao/dsh-power-button#c51713526aa8d6ed3fc858aa7111735132026feb
READMECompatibilityVersions
Power button in the sidebar footerRestart / Shutdown menuShutdown confirm dialogShutdown progress overlayRestart completed toast

Compatibility and provenance

Power Button is published as dsh-power-button and currently resolves to version 0.4.34. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
11/2/2026

Versions

0.4.34stable
11/2/2026
0.4.33stable
11/2/2026
0.4.32stable
11/2/2026
Show 17 more versionsCollapse versions
0.4.30stable
11/1/2026
0.4.24stable
11/1/2026
0.4.23stable
10/28/2026
0.4.15stable
10/22/2026
0.4.12stable
10/7/2026
0.4.9stable
10/7/2026
0.4.6stable
10/3/2026
0.4.4stable
10/3/2026
0.4.3stable
10/2/2026
0.4.2stable
10/2/2026
0.4.1stable
10/2/2026
0.3.0stable
10/2/2026
0.2.6stable
10/2/2026
0.2.5stable
9/30/2026
0.2.3stable

Related plugins

Loading related plugins…

Latest
0.4.34
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 12
Weekly downloads
0
Last push
11/2/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
9/30/2026
0.2.1stable
9/11/2026
0.2.0stable
8/20/2026

Related plugins

More verified plugins in ui-customization.

Client Ui Skill Explorer@linxin666/dsh-client-ui-skill-explorerDSH skill center: browse loaded skills by source (bundled / project / user / custom / runtime), enable or disable, create and delete, in a web GUI panel.Client Ui Task Board@linxin666/dsh-client-ui-task-boardHost-authoritative task board for the DSH Web GUI with real session execution, Host cron scheduling, and optional cross-platform idle-sleep protection; mounted without DSH source changes.Client Ui Git Graph@linxin666/dsh-client-ui-git-graphExternal dsh web GUI plugin: a blank-session git branch selector + Git graph, with real host-side git operations and guards, as a dsh profile bundleClient Ui Market@linxin666/dsh-client-ui-marketWorkshop browser card: browse skins, pets and community plugins from dsh-market.com and install them in the GUI (assets into the DSH home directories, plugins through the optional plugin manager).

README

dsh-power-button

English | 中文

A self-contained power & lifecycle controller for DeepSeek Harness: a sidebar power button with a Restart / Shutdown menu and a full-screen transition overlay. The restart engine is built in — no third-party dependencies.

Developed with DeepSeek AI assistance; reviewed before release.

Features

  • Sidebar power button in the footer action slot, theme-aware and styled to match the adjacent Settings trigger.
  • Restart / Shutdown menu with a Windows-style full-screen overlay; the page reloads by itself after a confirmed restart.
  • Self-contained restart engine: a detached .cjs helper takes over relaunching DSH through an ARM → COMMIT → ACK handshake, waits for the old process, the port and the session logs, then relaunches the same invocation in the same cwd. A --port 0 command line is pinned to the port the old process actually bound. In the Desktop app the restart is handed to Electron instead, when that app advertises a restart protocol. No PowerShell, no taskkill.
  • /restart and /shutdown commands, a restart_harness model tool (registration is skipped when another plugin already owns the name), and a read-only restart_status tool for checking whether a restart happened.
  • Localized UI and host notices (zh / en), following the profile's locale.preference.
  • Startup housekeeping: helper logs and scripts, per-restart handshake records, and undelivered notices older than 7 days are pruned from the runtime directory.

Screenshots

① Sidebar power button — theme-aware footer entry.

Power button in the sidebar footer

② Restart / Shutdown menu — two actions, one click away.

Restart / Shutdown menu

③ Shutdown confirm dialog — the default focus sits on Cancel; only an explicit confirm stops the process.

Shutdown confirm dialog

④ Shutdown progress overlay — shows the current stage while the process winds down.

Shutdown progress overlay

⑤ Restart completed toast — after the auto reload, a notice confirms DSH is back.

Restart completed toast

Install

dsh plugin --profile web add "github:keyiadiannao/dsh-power-button#master"

Restart DSH; a power button appears in the sidebar footer. Requires Node ≥ 22.19.

Configuration

Configured through the profile's cordis layer (cordis.patch.yml or the settings UI):

KeyDefaultMeaning
enableModelTooltrueRegister the restart_harness model tool. Set false to keep restart on the GUI button and /restart only.
maxDelayMs5000Upper bound (ms) for the model tool's delayMs. The effective floor is 1000 ms.
restartWakeModequietWhat the session that asked for a restart is told afterwards. quiet stages the notice for its next step without waking anything; notify also wakes that session once it is live, so the model reports the restart without a user message. Neither mode restarts anything on its own.
- id: dsh-power-button
  config:
    enableModelTool: true

How it works

Restart is an explicit ARM → COMMIT → ACK handshake. The old process does not exit until a live helper owns the relaunch; every failure before the ACK keeps the old process running. After spawning the successor, the helper waits up to 180 seconds for readiness. The browser allows a five-minute polling budget for the full restart, including shutdown and preparation. A refused request remains an error even if later health probes fail.

click power → Restart
[host]    POST /api/dsh-power-button/restart
          write the per-restart helper .cjs (0600: it embeds the relaunch argv)
          spawn `node <helper>` detached
[helper]  ARM  → status { stage: 'armed' }
[host]    wait for ARMED (5 s), then write the COMMIT file for this restartId
[helper]  ACK  → status { stage: 'committed' }
[host]    only now: unref the helper, flush live sessions (≤5 s),
          request exit after delayMs with a 15 s watchdog behind it
[helper]  wait for the old PID to exit, the port to free, the session logs to settle
          write the v2 marker, then spawn DSH with the same invocation and cwd
          poll /health until instanceId differs and restart.restartId matches
[client]  reload

Five invariants hold this together:

  • The helper lives outside the process tree (detached, a real .cjs file — a multi-line node -e is mangled by Windows CreateProcess), so terminating DSH cannot kill it mid-flight.
  • Success is confirmed by a per-process instanceId that must change, so a brief outage never fakes it.
  • The launcher's exit channel is read at ctx.get('appExit'), never as a property: it is an optional host service this plugin does not inject, and a property read resolves to undefined — which would skip graceful disposal and hard-kill instead.
  • Exit is bounded end to end, and the bounds are derived rather than duplicated: graceful exit gets a 15 s watchdog, the pre-exit flush cap is 5 s, and the helper's patience for the old PID is computed from both, so they cannot drift into the helper giving up first.
  • The successor's environment is re-read from the registry, not inherited: a process environment is a snapshot from its launcher, so a variable changed with setx or System Properties would otherwise never reach the relaunched instance. The block is composed in the order Windows uses — the inherited block as the base layer, machine values over it, then user values shadowing those — and a REG_EXPAND_SZ value is resolved against the block as it stands at its own stage, so a machine value cannot see a user-only name. That isolation is between registry layers, not a byte-exact replay of how Windows builds the block: names the launcher already carried stay visible at every stage, which is deliberate because some of them — SystemRoot on a real machine — exist only in the process environment. PATH keeps both halves (machine first) and each part is expanded according to its own type before duplicates are dropped. It is read through reg export (UTF-16LE), so non-ASCII values survive on any console code page; the export is a transient file under the harness home that is deleted in the same call, and it inherits that directory's ACL exactly as .credentials.yaml does — the file mode is not a privacy guarantee on Windows. A variable deleted from the registry still cannot be seen, and a directory deleted from a registry PATH survives while the launcher's block still carries it — it cannot be told apart from one a package manager injected at launch, and dropping those would break children that resolve tools by name. Non-Windows platforms keep plain inheritance.

Shutdown posts /api/dsh-power-button/shutdown and stops without relaunching. It is irreversible, so the button and /shutdown both open a confirm dialog; the model is never given shutdown.

Desktop

The Desktop application runs the Host as a child of its Electron shell, so exiting that child invokes the app's crash recovery and replaying its command line yields a Host without a window or its original IPC channel. Two cases, decided by what the host advertises:

  • Host advertises a restart protocol (DSH_DESKTOP_RESTART_PROTOCOL in the Host environment, IPC channel connected): the plugin writes the restart marker, flushes live sessions, and asks the shell to restart; Electron owns the relaunch. If the shell does not take over within 20 seconds, the request fails, the transition is released, and the button works again.
  • Host advertises nothing (every released DeepSeek Harness so far): restart and shutdown are refused with 503 and reason: "desktop-unsupported"; no helper or exit is scheduled. Use the application's Quit menu or tray action, then reopen it — closing the main window can leave the app running in the tray.

Making the first case available means changing DeepSeek Harness itself, which is outside this plugin's boundary; the steps are in docs/desktop-restart-protocol.md.

Safety

  • Destructive POSTs go through the deployment's own browser-trust fence and authentication via ctx.connection.requestRejection — the call the host's /api route uses. /api/dsh-power-button/* is longer than the official /api prefix, so longest-prefix matching never routes these requests through that fence; delegating keeps them under the operator's real policy, including LAN authorities derived from an all-interface bind and any trustedHosts / --trusted-host declaration.
  • On a host with no connection service (a profile without the web bundle) the plugin falls back to its own rules: Host must be a loopback authority or one the host declared, plus the cross-site and full-authority Origin checks. That fallback is narrower than the official fence and can only refuse; it does not provide browser-session authentication.
  • A refusal answers with a stable reason code and logs the observed Host / Origin / sec-fetch-site / remote address. host-fence and not-authenticated mean the deployment decided, not this plugin.
  • An at-most-once latch rejects duplicate transitions, so a concurrent second POST gets 409.
  • The model tool's delayMs is floored at 1000 ms — the model cannot kill the process before its own turn settles.
  • The restart marker is consumed on boot, so a later ordinary launch never misreports a restart. Command lines are redacted in logs; helper and marker files are written 0600, the runtime directory 0700.

Restart awareness

Three audiences, deliberately not one:

  • The UI shows a localized "Restarted" toast. The restart identity stays on /health for the process's whole life; acknowledging the toast clears only the pending flag.
  • The session that asked gets a notice shaped by restartWakeMode — Agent.inject() when quiet, Agent.followup() when notify. Only a restart with a recorded causal session gets one: a GUI click records none and is never attributed to whichever conversation happens to be open. At most one notice per session is queued and it is deleted once delivered.
  • Every other session can call restart_status, which reports whether a restart happened, its id, stage, the instances involved, timings, who asked, and whether the running process is the instance that restart produced.

The plugin never appends a model-visible event and never forges a turn: awareness is handed to the Agent API, whose inject() durably stages an agent/inbox/spliced record for the next legitimate step. Delivery is once per notice in normal operation; a crash between the inbox write and the deletion can repeat it, and the notice text is written so a repeat is harmless.

/health also reports appExit: "available" | "missing" — whether the launcher-provided exit channel actually resolves here, which turns a delayed restart into a one-request diagnosis. Both exit paths log the pre-exit flush tally (live / fulfilled / rejected / timedOut), so a refused or partial durable write is visible afterwards instead of looking like a clean exit.

Development

pnpm build            # tsdown: host + client bundle (committed to lib/)
pnpm typecheck        # tsc --noEmit over src
pnpm typecheck:tests  # the root tsconfig excludes tests/
pnpm test             # vitest: unit + process-level acceptance
pnpm check            # all of the above, in order

CI runs both typechecks, tests and build on Windows, Ubuntu and macOS, gates that the committed lib/ matches a fresh build byte for byte, and checks the pnpm pack tarball; a separate Linux job repeats everything on Node 22.19, the floor engines.node declares. tests/restart-runtime.spec.ts runs the exact helper the host generates as a real process against real TCP ports - the relaunch chain, no relaunch without COMMIT, bounded spawn retries, a stale instance refused, and the failure diagnoses - and the suite isolates DSH_HOME, so it never touches your real ~/.dsh.

License & Attribution

MIT. The "detached helper relaunch" idea follows anweat/dsh-restart (MIT); the implementation is independently written (real .cjs file, no PowerShell, dynamic port), no code copied.

Thanks to @qq1131909103: PR #8 established that the Desktop Host belongs to the Electron shell, which is why this plugin refuses power actions there instead of spawning a competing Host, and what docs/desktop-restart-protocol.md is built on.