dsh-notify
> Browser notification for the DeepSeek Harness Web UI β get a system notification the moment a session finishes running.
dsh-notify is a small, behavior-only Web client plugin for DeepSeek Harness (dsh). When you hand the model a long task and switch to another tab or application, it raises a browser notification the instant the task completes, so you never have to keep checking back.
Features
- ποΈ System notification on completion β fires exactly when a session's
runningstate flips to idle, titled with the session name and a Chinese completion body. - π No noise while you watch β it stays silent only when you are actively looking at the session that just finished. It notifies when:
- the page is hidden (you switched tab), or - the browser window lost focus (you switched to another app), or - the completing session is not the currently selected one.
- π Per-session dedup β each notification is tagged by session, so a repeat replaces the previous instead of stacking.
- π Permission asked at the right moment β the permission prompt appears on your first click or keystroke, not while you are away (this is what makes it work in Safari).
- βοΈ Zero UI β no buttons, no settings screen, no host-side changes. It is one browser row in your profile.
Requirements
- DeepSeek Harness with the Web UI (
dsh web, ordsh --profile web). - A modern browser. The Web UI runs on
http://127.0.0.1:<port>, which is a secure context, so theNotificationAPI is available. - On macOS, also allow the browser in System Settings β Notifications, otherwise the OS suppresses the banner even when the page has permission.
Install
dsh-notify is an installable bundle. Install it into a profile from npm, a tarball, or straight from this repository.
# from GitHub (this repo)
dsh plugin --profile web add github:you/dsh-notify
# from npm
dsh plugin --profile web add dsh-notify
# from a local checkout or packed tarball
dsh plugin --profile web add ./dsh-notifydsh plugin forwards to pnpm, so any pnpm spec works. Installing a bundle appends it to the profile's dsh.profile.bundles and applies its patch layer; no manual cordis.yml editing is needed.
> GitHub installs need no build step. This repository commits its built lib/, so dsh plugin add github:you/dsh-notify works directly, with no install-time build allowance to grant.
Usage
Install, then boot the Web UI and grant the notification permission the first time the browser asks (on your first click or keystroke):
dsh --profile webStart a task in any session, switch away, and a system notification appears when the model finishes. There is nothing else to configure.
How it works
The plugin injects the runtime's sessions service and subscribes to the session list snapshot β the same fact source the sidebar reads. A small fold keeps each session's previous running bit, records the first observation without notifying, and dispatches one notification per running β idle edge, gated by the "are you looking at this session" rule above.
The browser half is a CJS bundle registered through window.__ModuleLoader__.load, which the harness's client module system scans and serves under /plugins/dsh-notify/client.js. The node half is a no-op host plugin body.
Development
pnpm install # install dev tooling
pnpm build # bundle lib/index.js (node) and lib/client.js (browser)
pnpm typecheck # tsc --noEmit
pnpm test # vitestBuild artifacts are committed under lib/ so GitHub installs work without a build step.
dsh-notify/
βββ package.json # dsh.client + dsh.bundle.patch manifests
βββ cordis.patch.yml # bundle layer: inserts the dsh-notify row
βββ tsdown.config.ts # builds the node half and browser half
βββ src/
β βββ index.ts # node half (no-op host plugin)
β βββ client/
β βββ index.ts # apply / inject
β βββ watcher.ts # runningβidle edge detection
β βββ notifier.ts # Notification dispatch + permission bootstrap
β βββ types.ts # minimal local runtime views
βββ tests/notify.spec.tsKnown limitations
- Always on β there is no user-facing toggle yet. A settings row (enable/disable, sound, only-when-hidden) is the natural follow-up.
- System notification only β completion does not also produce an in-app toast or a title flash; the sidebar's built-in green "done" dot remains the in-app signal.
- Browser-owned permission β if the user denies the permission prompt, the plugin is disabled for that origin with no in-app recovery.
- No sound β a short chime is deferred.
License
[MIT](LICENSE)