JamesYasR/dsh-system-notify ↗★ 0

dsh-system-notify

Codex-style desktop notifications for DeepSeek Harness: task finished, errors, questions and goals, with configurable events, custom sounds, notification style, privacy, interactive approve/answer buttons and click-to-focus. Windows and Ubuntu.

Package
dsh-system-notify
Compatibility
Unverified
Version
1.1.0
License
MIT
Last updated
Oct 27, 2026

Install

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:JamesYasR/dsh-system-notify

dsh-system-notify

Codex-style desktop notifications for DeepSeek Harness: a toast and a sound when a task finishes, fails, needs your input, or a goal completes — with configurable events, sounds, notification style, privacy level, quiet hours and click-to-focus.

Built for Windows 10/11 and Ubuntu 22.04/24.04 (best-effort macOS support).

CI License: MIT DSH


Why not just a notify script?

Codex only runs a hook when a turn completes. This plugin is event-aware:

Codex-style notify scriptdsh-system-notify
Turn complete✅✅ with summary, project, duration
Turn error⚠️ manual scripting✅ with error message/code
Questions / approvals❌✅ “Input needed” / “Approval needed”
Goal completed / blocked❌✅
Subagent / workflow finished❌✅ optional
Notification style❌✅ privacy / simple / standard / detailed
Sound selection❌✅ system / chime / alert / custom WAV/OGG
Quiet hours & cooldown❌✅
Click to focus DSH❌✅ configurable
Settings UI❌✅ Settings → System Notifications

Everything is local. No network calls, no telemetry, no data leaves the machine.

Features

  • 11 notification events — turn complete/error/blocked/max-tokens/aborted, input needed, approval needed, goal complete/blocked, subagent finished, workflow finished.
  • Four styles — privacy (event only), simple, standard, detailed.
  • Interactive approvals — approve or reject a tool call directly on the toast; the outcome is returned to DSH.
  • Interactive questions — choose a listed option from the toast, pick from a checklist for multi-select, or type a custom answer in an input dialog.
  • Custom sounds per event — upload a WAV/OGG from the settings page (stored beside the config); separate files for normal and error events, plus the two bundled sounds.
  • Sound — system sound, two bundled original chimes, or your own file; separate normal/error sounds; volume on Ubuntu.
  • Delivery modes — toast + sound, toast only, or sound only.
  • Quiet hours — suppress normal notifications overnight, optionally still notify on critical errors.
  • Rate control — minimum task duration, per-event cooldown, optional subagent-session filtering.
  • Click to focus — on Windows the toast uses DSH Desktop's official dsh://open deep link; on Ubuntu it can focus a window via wmctrl/xdotool, then falls back to opening a link. The whole click action can be disabled.
  • Agent tool (opt-in) — send_desktop_notification lets the model send an explicit notification when you asked to be pinged.
  • Bilingual UI — Chinese/English settings page; notification text follows the system locale or can be forced to Chinese/English.
  • Zero runtime dependencies — Node built-ins and the OS notification stack.

Notification styles

Given this event:

kind=turnComplete
session=Refactor the settings page
project=D:\workspace\demo
summary="Finished the settings page and verified save / test / sound."
duration=1m 12s
StyleWhat you see
Privacy (隐私)Title only: Task completed — no session, summary, path or error details.
Simple (简洁)Task completed · Refactor the settings page
Standard (标准)Title + session + summary + demo · took 1m 12s
Detailed (详细)Title includes session + summary + full path + turn 3 · took 1m 12s · code …

Errors are always delivered with critical urgency (Linux) and the error sound; privacy mode still hides the message content.

Requirements

Windows

  • Windows 10 (1809+) or Windows 11.
  • DSH Desktop. The plugin uses:
    • PowerShell 5.1 + WinRT toast APIs (built into Windows);
    • the DSH Desktop AUMID com.deepseek.dsh for the toast identity (when it is unavailable the helper falls back to other registered toast sources, ending at PowerShell);
    • the dsh://open deep link (registered by DSH Desktop) for click-to-focus;
    • a per-user dsh-system-notify:// action protocol registered automatically for interactive approve/answer buttons.
  • Custom notification sounds are played by the PowerShell helper through System.Media.SoundPlayer; they must be PCM WAV. The two bundled sounds are WAV.
  • Toast notifications respect Focus Assist / Do Not Disturb. If you see nothing, check that Windows notification permission for “DeepSeek Harness” is enabled.

Ubuntu

Install the notification and sound helpers (most desktops have some of them already):

sudo apt install libnotify-bin libglib2.0-bin pulseaudio-utils wmctrl
  • libnotify-bin provides notify-send (fallback when gdbus is unavailable).
  • libglib2.0-bin provides gdbus and dbus-monitor — required for clickable notifications.
  • pulseaudio-utils provides paplay (PipeWire systems usually provide pw-play; both are supported).
  • wmctrl (or xdotool) is used to focus the DSH window on click. Without it, clicking falls back to opening the configured link.
  • zenity is used for interactive text input and multi-choice dialogs. Install it with sudo apt install zenity; without it those flows fall back to the Chat UI (direct option buttons still work).

Clickable notifications use the standard org.freedesktop.Notifications DBus interface: gdbus raises the notification with a default action, and dbus-monitor listens for ActionInvoked.

macOS (best effort)

osascript displays notifications and afplay plays sounds. Click-to-focus requires terminal-notifier (brew install terminal-notifier); without it notifications are display-only.

Install

From GitHub

dsh plugin --profile desktop add github:JamesYasR/dsh-system-notify

From a local checkout

dsh plugin --profile desktop add /absolute/path/to/dsh-system-notify

Or use the DSH Web UI: Settings → Plugins → Install and provide the GitHub spec or the local directory.

After installation open Settings → System Notifications (系统通知). The plugin is enabled by default. The settings page shows the detected backends and any missing OS packages.

Settings reference

The config lives at:

  • Windows: %APPDATA%\dsh-system-notify\config.json
  • Linux/macOS: $XDG_CONFIG_HOME/dsh-system-notify/config.json (default ~/.config/dsh-system-notify/config.json)

Override the location with DSH_SYSTEM_NOTIFY_CONFIG=/path/to/config.json.

KeyDefaultMeaning
enabledtrueMaster switch.
events.turnCompletetrueNormal turn completion.
events.turnErrortrueTurn ended with an error.
events.turnBlockedtrueTurn blocked (suppressed if a question was just raised).
events.turnMaxTokenstrueOutput hit the token limit.
events.turnAbortedfalseUser cancelled/interrupted.
events.needsInputtrueask_user_question is waiting.
events.approvalRequesttrueA tool waits for approval.
events.goalCompletetrueLong-running goal completed.
events.goalBlockedtrueLong-running goal blocked.
events.subagentCompletefalseA subagent run ended.
events.workflowCompletefalseA workflow run ended.
stylestandardprivacy / simple / standard / detailed.
languageautoauto / zh / en.
sound.enabledtruePlay sounds at all.
sound.normalsystemSound for normal events: none / system / chime / alert / custom.
sound.erroralertSound for error events (same values).
sound.customPath""Legacy shared custom audio path (still honoured).
sound.customNormalPath""Custom audio for normal events; also set sound.normal: "custom".
sound.customErrorPath""Custom audio for error events; also set sound.error: "custom".
sound.volume800–100, Ubuntu only (paplay/pw-play).
deliverybothboth / toast / sound.
quietHours.enabledfalseEnable the quiet window.
quietHours.start / end22:00 / 08:00Local time; overnight windows supported.
quietHours.allowCriticaltrueCritical events still notify during quiet hours: errors, goal-blocked, and blocking prompts (input/approval).
minDurationSec0Only notify for successful turns at least this long.
cooldownSec10Minimum gap between same-category notifications. Critical errors bypass it.
include.sessionTitletrueShow the session title.
include.summarytrueShow the assistant summary / question / error message.
include.workspacetrueShow the project name (standard) or full path (detailed).
include.durationtrueShow elapsed time.
include.sessionIdfalseShow the short session id.
summaryMaxChars140Summary truncation limit (40–500).
ignoreSubagentSessionstrueDo not notify turn events from subagent sessions.
click.enabledtrueClicking the toast summons DSH.
click.urldsh://openDeep link or URL opened on click.
click.focusWindowTitleDeepSeek HarnessUbuntu window-title match for wmctrl/xdotool.
click.openFallbacktrueOn Ubuntu, open the link when no window matches.
interactive.enabledtrueUse action buttons / answer prompts on the notification.
interactive.timeoutSec20How long the notification owns the prompt before the Chat UI takes over (5–300).
interactive.maxOptions3Direct option buttons before the “Choose…” dialog is used (1–3).
appNameDeepSeek HarnessApp name shown by Linux notifications.
windows.appIdcom.deepseek.dshWindows toast AUMID; change only for a custom shell build.
iconPath""Custom PNG icon; empty uses the bundled icon.
agentToolfalseRegister the send_desktop_notification tool.

Click-to-focus behaviour

Windows

The toast is created with activationType="protocol" and launch="dsh://open", plus an Open DSH action button. DSH Desktop registers that protocol and its single-instance handler restores, shows and focuses the primary window. This is the same path DSH itself uses for deep links, so it needs no extra registry keys or helper process from the plugin.

  • Turn click.enabled off to make the toast non-clickable.
  • Running DSH as a web app without Desktop? Set click.url to your DSH web URL; the click then opens that URL in the default browser.

Ubuntu

Clickable notifications cannot be produced by plain notify-send, so the plugin uses:

  1. gdbus … Notify with a default action label (“Open DSH”);
  2. a short-lived dbus-monitor that watches ActionInvoked for that notification id;
  3. on click, xdotool / wmctrl focuses a window whose title matches click.focusWindowTitle, otherwise xdg-open (if click.openFallback).

If gdbus is missing, the plugin falls back to notify-send. If dbus-monitor is missing, gdbus still raises the notification but clicking it cannot be observed, so the toast is not clickable. If you use DSH in a browser on Ubuntu, set click.focusWindowTitle to something in the browser window title (e.g. DeepSeek Harness) and/or change click.url to the DSH URL. On Wayland, wmctrl/xdotool may be unavailable; the click then falls back to opening click.url.

Interactive notifications

When interactive.enabled is on (default), approval and single-question requests can be answered directly from the toast. The plugin briefly owns the request, shows the action UI, and returns the choice to DSH. If you do nothing for interactive.timeoutSec (default 20 s), choose Open DSH, privacy style is active, the delivery mode is sound-only, or a platform helper is missing, the request is delegated to the normal Chat UI — the same prompt you would have seen anyway.

RequestOn the notification
Tool approvalApprove / Reject / Open DSH; Approve returns allowed-once, Reject returns rejected.
Single choice questionOne button per option (up to 3), Choose… for overflow, Other… for free text, Open DSH.
Multi-select questionChoose… opens a checklist, Other… opens text input, Open DSH.
Question without optionsOther… opens a text input, Open DSH.
Multiple questions in one requestFalls back to the normal Chat UI.

Windows mechanics

The plugin registers a per-user protocol handler under HKCU\Software\Classes\dsh-system-notify (no admin rights). Each button is an activationType="protocol" action carrying a one-time interaction id + token and the local DSH origin; lib/responder.ps1 posts the choice to the same-origin /dsh-system-notify/respond route. Other… opens a Windows input box; Choose… opens a WinForms list/checklist. The protocol is removed when the plugin is disabled or unloaded.

Ubuntu mechanics

Clickable notifications use the freedesktop ActionInvoked signal (requires gdbus + dbus-monitor). Other… and Choose… open zenity dialogs. Direct option buttons work without zenity. Action visibility ultimately depends on the notification daemon; GNOME may show fewer buttons for many-option questions.

Security / behaviour

  • Action ids are random per interaction and validated against the live pending set; a stale or forged action gets 410.
  • Interactive mode never triggers when notification style is Privacy, since option labels and question text are content.
  • In-flight prompts are dismissed on timeout/abort, and the normal Chat prompt is opened instead.

Custom notification sounds

The settings page has Choose file buttons next to the normal/error sound selectors. Uploaded files are validated by container magic and stored in:

/sounds/--.wav|ogg
  • Maximum 5 MiB; WAV on Windows, WAV/OGG on Ubuntu.
  • Separate files for normal and error events; the legacy shared sound.customPath still works as a fallback.
  • The file is stored locally; nothing is uploaded to the network. Remove old files from that directory manually if you no longer need them.
  • Preview sound plays the current normal sound without saving.

Event sources

NotificationDSH source
Turn completed / error / blocked / max-tokens / aborteddurable turn/end session event with its reason
Needs inputuser-questions/request (notified before delegating to the normal answerer)
Approval neededapproval/request (notified before delegating)
Goal completed / blockedgoal/changed with operation complete / block
Subagent finishedsubagent/end
Workflow finishedworkflow/end
Customagent tool send_desktop_notification

Duplicate suppression: a question suppresses the immediately following blocked turn notification (60 s window), and a goal notification suppresses a redundant turn-complete toast (8 s window).

Privacy

  • Notification content stays in process memory (the Windows payload is passed to the PowerShell helper through an environment variable) and in the OS toast. The plugin itself writes only the config file; Windows Notification Center may retain shown toasts according to OS settings.
  • The config file is written with user-only permissions where the OS supports them (0600).
  • Privacy style removes session titles, summaries, paths, session ids and error text from the notification. The event categor