# dsh-unread-dot
> A DeepSeek Harness (DSH) plugin: while the app is hidden or unfocused, show an **unread red dot** on the macOS Dock icon and play a **bubble chime** when a session finishes or needs you. Clears automatically when you return.




Built entirely on the Chrome **Badging API** (`navigator.setAppBadge` / `navigator.clearAppBadge`) — no macOS system settings, no notification permission, no banners.
> ⚠️ **Prerequisite**: open DSH Web in Chrome and install it as an app via **More → Cast, save and share → Install…** so it runs in its own macOS window (PWA). `setAppBadge` only works inside an installed web app.
## Behavior
| Scenario | Dock icon | Sound |
| --- | --- | --- |
| Session running while you're away | 🔴 plain red dot (no number) = still working | silent |
| Session finished while you're away | 🔴 red number +1 = results waiting | 🔊 bubble chime |
| Session needs your input | 🔴 red number +1 | 🔊 bubble chime (once per away period) |
| You return to the app | auto-cleared | — |
## Why the Badging API
The plugin encodes "is there new info, and what kind" with the three states the Badging API supports:
```js
navigator.setAppBadge(3) // red numbered badge: 3 unread results
navigator.setAppBadge() // plain red dot: a session is running
navigator.clearAppBadge() // clear: you're back, everything is read
```
- **No permission, no banner, no system settings**: the badge is a system-level persistent marker the page calls directly
- **Dot vs number**: number = unread result count, plain dot = running (the clearest distinction the API can express)
- Compatibility: DSH Web must be installed as a PWA (Chrome "Install page as app"); the API is supported from Chrome 81; from Chrome 152 the badge/notifications are attributed to the web app itself
## Install
1. Add the plugin package to your DSH profile (e.g. `web`):
```sh
dsh plugin --profile web add github:Bing-Bryan/dsh-unread-dot
```
2. Append it to `dsh.profile.bundles` in the profile's `package.json`:
```json
"dsh": {
"profile": {
"bundles": [ "...", "dsh-unread-dot" ]
}
}
```
3. Restart `dsh web`, then configure it in Settings → **Dock 角标与通知**.
## Settings
| Setting | Default | Description |
| --- | --- | --- |
| Dock badge | on | Master switch: number badge when finished/waiting, cleared on return |
| Activity dot while running | on | Plain red dot while a session is generating a reply during minimize |
| Chime (bubble pop) | on | Plays the built-in bubble sound (bubble.mp3, 0.4s) on completion / needs-you |
| Test chime | button | Plays the bubble pop once to verify the sound |
## How it works
1. The plugin subscribes to the DSH session list (`sessions.list`) and tracks **read/unread** state: when the window regains focus, all current attention states are marked as read
2. While minimized/unfocused, only **newly occurring** completion/waiting events light up the badge and chime (old events don't accumulate)
3. Running sessions only show the **activity dot** (plain red), never counted into the number
4. The chime plays an embedded base64 MP3 via `Audio`, with a cross-window lock so multiple open windows only sound once
## Compatibility
- macOS Chrome (installed as PWA / "Install page as app")
- Badge: `setAppBadge` requires an installed web app context
- No server-side dependency — pure client plugin, HMR hot-reload with zero restarts
## License
MIT © 2026 Bing-Bryan
The built-in sound effect `bubble.mp3` is an edited clip based on [Pixabay audio: Nature bubble in water](https://pixabay.com/sound-effects/nature-bubble-in-water-422579/) (Pixabay license: free for commercial use, no attribution required).