ZYar-er
dsh-notify-bell
Semantic notification sounds for DeepSeek Harness: complete/approval/question/block/error via BEL or WAV, with Web UI bell toggle
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 15, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-notify-bell
A community plugin for DeepSeek Harness (DSH) — semantic notification sounds.
Semantic notification sounds for DeepSeek Harness (DSH).
Developer Preview · v0.12.0
🎧 Listen to the notification sounds →
dsh-notify-bell lets you step away from the DSH Web UI without missing important agent events.
Instead of notifying on every internal event, it focuses on moments when the agent actually needs your attention:
- ✓ Complete — the task finished
- 🔐 Approval — a tool operation needs your approval
- ❓ Question — the agent is waiting for an answer
- ⚠ Blocked — the goal cannot continue
- ✗ Error — the agent encountered an error
Each event uses a distinct semantic sound rather than encoding meaning by counting beeps.
Features
- Semantic notifications for complete, approval, question, block, and error events
- Official Cordis plugin form: exported
Configschema (fail-loud validation) +dsh.bundlepatch - WAV sound pack
- BEL fallback
- Native Windows audio support
- WSL → Windows audio support
- Native Linux audio support
- Runtime mute/unmute from the DSH Web UI
- Light/dark theme support
- Phosphor
bell/bell-slashnotification button - Configurable event sounds
- Configurable minimum duration for completion notifications
- Automatic fallback when audio playback is unavailable
- No runtime dependencies beyond the official
@deepseek-ai/schemastery
Platform Support
Windows / WSL
On Windows and WSL, WAV playback uses:
PowerShell
→ System.Media.SoundPlayer
→ Windows Audio
WSL paths are converted automatically with wslpath.
Linux
The plugin automatically probes available audio players in this order:
paplay
pw-play
aplay
ffplay
No additional player is installed by the plugin.
Fallback
When WAV playback is unavailable, the plugin falls back to the terminal BEL (\a) when a TTY is available.
Audio playback failures never crash DSH.
Installation
Published on npm as dsh-notify-bell. The plugin follows the official
DSH plugin format (see the
plugin tutorials):
it is a Cordis bundle that declares its own cordis.patch.yml via
dsh.bundle, exports a Config schema, and installs with the official
CLI:
dsh plugin --profile web add dsh-notify-bell
dsh plugin add installs the package and appends it to the profile's
dsh.profile.bundles, so the bundle layer is applied automatically on the
next boot. No manual patch editing is required.
From source / GitHub
From a checkout of this repository:
dsh plugin --profile web add ./dsh-notify-bell
Or install straight from GitHub (sources only, so pin a commit for supply-chain safety):
dsh plugin --profile web add github:zyar-er/dsh-notify-bell#<commit-sha>
Configuration
The plugin exports a Schemastery Config schema: Cordis validates the
config of the plugin row and fills defaults at load time, and invalid
values fail loudly instead of being silently ignored.
Via the profile patch (recommended)
Add a config block to the plugin row in your profile's
cordis.patch.yml (or your own --patch overlay):
- id: notify-bell
config:
minDuration: 10
soundPack: wav
events:
complete:
sound: done
block:
sound: block
Via the legacy config file
The plugin also reads ~/.config/dsh/notify-bell.json (override with the
DSH_NOTIFY_BELL_CONFIG environment variable). This file is the
runtime-state layer: the Web UI bell toggle persists enabled here, and
it keeps older deployments working. Merge priority is:
explicit cordis.yml config > notify-bell.json > schema defaults
Example file:
{
"enabled": true,
"minDuration": 10,
"objective": {
"maxLength": 120
},
"events": {
"complete": {
"enabled": true,
"sound": "done"
},
"block": {
"enabled": true,
"sound": "block"
},
"approval": {
"enabled": true,
"sound": "permission"
},
"question": {
"enabled": true,
"sound": "question"
},
"error": {
"enabled": true,
"sound": "error"
}
},
"soundPack": "wav",
"playback": "browser",
"wav": {
"directory": "~/.config/dsh/notify-bell/sounds",
"fallback": "bell"
},
"bell": {
"gapMs": 150,
"permissionGapMs": 300
}
}
Playback location
playback chooses where the notification sound is played
(soundPack only affects playback: backend; the browser always plays
the package's bundled WAV files). The default is browser; you can
also change it at runtime from the bell popover in the DSH Web UI (no
restart needed):
browser: the backend classifies events and writes logs, but plays nothing locally. It pushes the semantic sound over Server-Sent Events (GET /notify-bell/events), and the DSH Web UI plays the matching WAV (/notify-bell/sounds/*.wav, served from the package'ssound-showcase/sounds). One sound per notification.backend: the host plays the sound (BEL or WAV viasoundPack); the browser stays silent.none: logs only — nothing is pushed to the browser and no local audio is played.
Browser notes:
- The browser uses Web Audio; autoplay policy requires one user
gesture (
pointerdown/keydown) before the first sound. Until then playback is silently refused and a locked state is recorded in the console (console.debug), never thrown. - No
both, no backend fallback, no multi-tab coordination yet. enabled=falsestill silences everything: the backend pushes nothing and the browser plays nothing.enabledandplaybackare independent settings.
Completion threshold
Tasks shorter than minDuration do not play a completion sound.
Approval and question notifications are immediate because they indicate that the agent is waiting for the user.
Runtime mute
The notification button in the DSH Web UI can enable or disable notifications instantly.
When disabled:
- all notification sounds are muted
- DSH itself continues running normally
- the current configuration is preserved
- no restart is required
Web UI
A notification button (bell) is added next to Session log:
Session log 🔔
Clicking the bell opens a compact notification settings popover:
- Notifications: an On/Off switch (enabled =
bellicon, disabled =bell-slash). - Playback: a radio group with Browser (play in the browser) / Backend (play on the host) / None (logs only).
Changes apply immediately and are persisted to
~/.config/dsh/notify-bell.json — no DSH restart needed. The icon and
popover follow the current light/dark theme.
Event Details
Complete
Triggered when the agent finishes its final answer to a user request — the durable session event that the DSH Web UI itself uses to close a turn:
session/event
type = turn/end
data.reason.kind = completed
Only main sessions notify (subagent turns with delegationDepth >= 1 are
ignored), and the turn must actually produce a final assistant text answer:
the last assistant/message must contain a non-empty text block and no
tool/call may follow it. Empty no-op turns (a queued message cleared before
it was claimed) and tool-call-only/concludes-turn endings are silently ignored.
goal/changed with operation = complete no longer plays a sound.
The duration is turn/end.time - turn/start.time; requests shorter than
minDuration are logged but do not play a sound. If the plugin loads mid-turn
but still observes the final assistant/message, the completion is logged
without a sound; if it loads only after that final answer, the turn stays
silent because the final-answer condition cannot be verified.
Approval
Triggered by the durable:
approval/asked
This represents a tool operation waiting for user approval.
approval/decided does not generate another notification.
Question
Triggered by the durable session event:
tool/call
name = ask_user_question
This represents the agent explicitly asking the user a question.
The response does not generate another notification.
Block
Triggered when a goal enters:
goal/changed
operation = block
Error
Triggered by the DSH agent loop's:
agent/error
This represents an agent-level error, not an ordinary command returning a non-zero exit code.
Sound Architecture
Notifications are represented by semantic sound names:
done
permission
question
block
error
The event layer does not know how a sound is physically played.
Current backends:
semantic sound
↓
soundPack
├── wav
│ ├── Windows / WSL
│ └── Linux
│
└── bell fallback
This makes it possible to add other backends later without changing the DSH event handling.
Testing
Current test suite:
All tests passing — 6 node:test cases (1 unit script with 171+ assertion checks inside + 5 session-layer integration).
Real-world verification has been completed for:
- task completion
- approval requests
- user questions
- Web UI mute/unmute
- WSL → Windows WAV playback
The error notification path is covered by tests; deliberately breaking credentials is not required for normal validation.
Developer Preview
DSH is still in developer preview, so its plugin and event APIs may change.
This plugin intentionally avoids modifying the DSH core and relies on currently available plugin/event interfaces.
Community testing is especially welcome for:
- Windows native
- WSL
- Linux audio playback
- approval notifications
- question notifications
- sound loudness and comfort
- configuration compatibility
- DSH upstream changes
Please include your DSH version, OS/environment, relevant event, and reproduction steps when reporting an issue.
Credits
Sound assets are from react-sounds.
Icons use Phosphor Icons.
Built for DeepSeek Harness.
License
The dsh-notify-bell source code is licensed under the MIT License.
This repository also distributes third-party sound and icon assets. See NOTICE.md for their respective licenses and attribution.