DeepSeek Harness Plugin

yxiaoy6/dsh-taskbar-alert

Stars ★ 0 Category Notifications & Integrations Added 2026-10-22

Flashes the DeepSeek Harness taskbar button on Windows when an approval, a question or a plan review is waiting, or when a turn finishes.

Install

# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)

dsh plugin --profile web add github:yxiaoy6/dsh-taskbar-alert

Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).

README

When the agent needs you — an approval, a question, a plan review — or when a turn finishes, the DeepSeek Harness window and its Windows taskbar button flash. If you switched to another app, minimised DSH, or another window covers it, you still won't miss the moment that needs your decision.

Trigger When
🔔 Approval A tool call needs your permission and the approval card is waiting
🔔 Question / plan review ask_user_question or a plan review is waiting for an answer
✅ Turn finished The root conversation finished its turn

Behaviour

  • Uses the native Win32 FlashWindowEx: it flashes the taskbar button and the window frame.
  • Window in the background: FLASHW_ALL | FLASHW_TIMERNOFG, so it keeps flashing until you bring DSH back to the foreground (or until flashSeconds expires).
  • Window already in the foreground: a fixed burst of 3 FLASHW_ALL flashes. Windows' TIMERNOFG means "an active window does not flash", which would leave you with no feedback at all while you stare at the screen waiting for an approval.

How it works

The host half (index.js) listens to three host events and needs no page:

  • approval/request — approval requests;
  • user-questions/request — questions and plan review;
  • agent/status — the root agent going from running to idle, i.e. a finished turn.

⚠️ Approval and question listeners must be registered with { prepend: true }. Both are cordis waterfall events: listeners run outermost-first, and any listener that does not call next() ends the entire chain. DSH's session controller registers an approval/request listener at boot that forwards the request to the page and waits for your click — it never calls next(). A plugin is a bundle mounted later, so a plain listener sits at the tail of the chain and is never invoked. That is exactly why "only the completion flash works, approval does not". prepend: true puts the observer at the front; it flashes and then calls next() so the answerer still makes the decision.

The flash itself is performed by one long-lived PowerShell helper. At start it compiles the user32.dll interop once with Add-Type, then serves flash / stop / quit commands on stdin. It locates windows by a visible top-level window whose title contains DeepSeek Harness, so window recreation and multiple windows still match.

The helper is warmed up 2.5 s after the plugin loads so the first alert is instant; turn the warm-up off to start it lazily on the first alert instead (about 1–2 s of compilation latency).

Settings

The plugin declares its own Config (@deepseek-ai/schemastery), so Settings → Plugins → Taskbar Flash Alert shows these fields:

Field Default Meaning
approval true Flash on approval requests
question true Flash on questions / plan review
complete true Flash when a turn finishes
flashSeconds 0 Auto-stop after N seconds; 0 = flash until the window is activated
warmup true Warm the PowerShell helper in the background so the first alert is instant

You can also edit the config of the entry in the profile's cordis.patch.yml.

Limits

  • Windows only. The flash is a Win32 call; on other platforms the plugin stays silent.
  • Flash only, no icon colour change. Turning the taskbar icon red or adding a red badge requires the app's main process to call BrowserWindow.setOverlayIcon; the DSH Desktop Electron shell does not expose that to plugins (its own flashFrame is only used for its update prompt). This plugin implements the flashing half.
  • Targets the DSH Desktop window. It only works inside DSH Desktop (an Electron window whose title contains DeepSeek Harness). A browser tab will not flash — use a notification plugin such as dsh-notify-me there.
  • Each alert spawns or reuses one hidden powershell.exe (about 30–60 MB resident). Set warmup to false if that matters; the helper then starts on demand and is reaped when the plugin unloads.
  • It is only an attention cue: it never approves anything for you.

Install

dsh plugin --profile <your-profile> add dsh-taskbar-alert

Or install the bundle directory directly with plugin_manager install_bundle <this directory>.

Development self-check

node --check index.js
node probe.mjs

probe.mjs loads the plugin into a fake context that reproduces cordis' dispatch rules: it first registers an answerer that never calls next() (mimicking the real session controller), then loads the plugin, then dispatches one approval/request, one user-questions/request and one agent/status. The output should contain:

[probe] approval outcome: allowed-once | bridge claims: 1
[probe] question outcome: {"answers":[]} | bridge claims: 1
[dsh-taskbar-alert] OK flash 1
[dsh-taskbar-alert] OK flash 1
[dsh-taskbar-alert] OK flash 1
[dsh-taskbar-alert] OK stop 1

bridge claims: 1 proves the decision is still made by the answerer (the plugin does not steal it); the three OK flash 1 lines prove all three triggers reached FlashWindowEx and matched one harness window.

Run probe.mjs in a non-sandboxed terminal: the sandbox forbids child-process pipes (spawn EPERM) and the helper cannot start.

License

MIT

Content from the project README on GitHub ↗

Links

More in this category

View the whole category →

Community comments

Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.