当 dsh 需要你注意时发出桌面通知——权限确认、提问、计划审批、回合完成、目标、出错、工作流——并提供设置页「通知」选项卡,改动即时生效。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:knownothing114/dsh-notify
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
该插件的 README 只有英文版本。
A dsh plugin that raises a desktop notification whenever dsh needs your attention.
dsh itself gives no cue when it needs the human in the loop: a permission confirmation is pending, an ask_user_question prompt or a plan review is waiting for your answer, a turn/session has finished, a goal completed or got blocked, the agent hit an error, or a workflow run ended. When the terminal or the browser tab is in the background, all of these are easy to miss. This plugin listens to the dsh host event bus and fires a native desktop notification at exactly those moments — system notification (macOS / Linux), a popup (Windows), a terminal bell, or your own command.
The plugin is a pure observer: every listener is passive. In particular, the approval/request listener only reminds you and never decides for you — it always forwards the request through next(), so the approval chain behaves exactly as if the plugin were not installed.
Features
| Trigger | Fires when | Default |
|---|---|---|
approval |
A permission-confirmation request (sandbox escalation, operations that need approval, …) | on |
question |
ask_user_question prompt / exit_plan_mode plan review waiting for you |
on |
turnComplete |
A turn completes (the agent finished replying and is waiting for your next input) | on |
goal |
A goal completes or gets blocked | on |
error |
The session hits an error | on |
workflow |
A tool_workflow run ends |
on |
Notification channels (channel):
auto(default): macOS →osascriptsystem notification; Windows → PowerShell popup; other platforms →notify-sendosascript/notify-send/powershell: force a specific channelbell: terminal bell (\x07) — zero-dependency fallbackcustom: run your own command template (placeholders{title}{body}{app})none: disable
Zero runtime dependencies beyond two @deepseek-ai packages (settings + schemastery). Works in any dsh profile (web, headless, custom).
Every option is also editable from the web GUI: Settings → 通知 (Notifications) tab (see Settings tab). Changes are written to the settings document and apply immediately — no restart.
Installation
Example for the web profile (any other profile works the same):
# 1. Add the plugin to the profile's dependencies.
# A local directory is linked into node_modules by pnpm; a git URL or an
# npm package name also work.
dsh plugin --profile web add /path/to/dsh-notify
# or from this repository:
dsh plugin --profile web add git+https://github.com/knownothing114/dsh-notify.git
# or (once published to npm): dsh plugin --profile web add dsh-notify
The command installs the dependency and registers the bundle automatically. Verify that dsh.profile.bundles in the profile manifest contains dsh-notify, and add it manually if your dsh version did not:
// ~/.dsh/profiles/web/package.json
{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-notify" // ← add this line
]
}
}
}
# 2. Restart dsh web. Plugins load at boot; HMR only hot-reloads config.
Configuration
Sensible defaults are built in — usually nothing to change. To tune it, override the row by id dsh-notify in the profile's cordis.patch.yml (or a --patch overlay). An override replaces the row's whole config, and the plugin deep-merges partial input over its defaults, so you can write only the keys you want to change:
# ~/.dsh/profiles/web/cordis.patch.yml
- id: dsh-notify
config:
channel: auto # auto | osascript | notify-send | powershell | bell | custom | none
appName: dsh # source name shown in the notification ({app} in custom templates)
sound: true # play a sound with the notification (macOS)
minIntervalMs: 3000 # minimum interval between two notifications (burst guard)
rootsOnly: true # only alert for root sessions; ignore subagents / background children
verbose: false # also log every notification through the dsh logger
customCommand: "" # command template when channel is custom, e.g.:
# terminal-notifier -message {body} -title {title}
triggers:
approval: true
question: true
turnComplete: true
goal: true
error: true
workflow: true
enabled: true # master switch
Settings tab (web)
With the web profile, the plugin registers a dedicated 通知 (Notifications) tab in Settings. It shows every option from the section above and lets you change them with a staged form (Save / Discard / whole-section Reset):
- master switch, channel, app name, sound, min interval, root-sessions-only, verbose logging, custom command
- the six trigger switches
Config precedence (highest wins): settings document ($DSH_HOME/settings.yaml, written by the tab, hot-applied) → profile patch (cordis.patch.yml config:) → built-in defaults. The host plugin reads the config live on every notification, so a change in the tab takes effect immediately.
The browser half lives in dist/client.js (a prebuilt bundle in the dsh client-module format, served at /plugins/dsh-notify/client.js); the host half registers the notify settings namespace. A restart of dsh web is required when the plugin package is first installed or upgraded; afterwards the tab's changes need none.
Note: dsh's API proxy only exposes curated settings namespaces to the web UI by default (model providers plus an explicit allowlist). The plugin therefore wraps the proxy's settings handlers so its notify namespace is readable and writable through the standard settings RPCs — every other namespace keeps the core allowlist behavior.
How it works (event mapping)
| Trigger | Listens to |
|---|---|
approval |
host-side approval/request waterfall (passive: return next(), never participates in the decision) |
question / plan review |
tool/call inside session/event (tools ask_user_question / exit_plan_mode); the question text is extracted from the tool arguments |
turnComplete |
turn/end inside session/event (reason.kind === "completed") |
goal |
goal/changed (operations complete / block); body carries the objective |
error |
agent/error |
workflow |
tool-workflow/run-end inside session/event (non-completed stop reasons alert too) |
All listeners are registered at the root context, which — per dsh's scope-routing rules — receives every agent- and session-scoped event; rootsOnly filters out subagent noise through ctx.agents.roots(). Notifications are dispatched with detached spawn processes: they never block the agent loop, and failures are only logged.
Uninstall
dsh plugin --profile web remove dsh-notify
# Also remove "dsh-notify" from dsh.profile.bundles in
# ~/.dsh/profiles/web/package.json, then restart.
FAQ
- No notification? Check that the resolved
channelmatches your system: on macOS, trychannel: osascriptexplicitly (andverbose: trueto see each notification in the dsh log); Linux needsnotify-send(libnotify); also check Do Not Disturb and notification permissions. - Too noisy? Increase
minIntervalMs, or switch off individualtriggersentries. - Subagents spamming? Keep
rootsOnly: true. - Config change not applied?
cordis.patch.ymledits are hot-reloaded by HMR; adding/removing plugins or editingpackage.jsonbundles requires a restart ofdsh web.
Development
cd dsh-notify
npm install # installs @deepseek-ai/dsh-settings + @deepseek-ai/schemastery
npm test # node --test: unit tests + apply() smoke tests + client form tests (30 cases)
Project layout
├── lib/index.mjs host plugin (event listeners, settings namespace, apiProxy exposure)
├── dist/client.js browser bundle (Settings → 通知 tab), served at /plugins/dsh-notify/client.js
├── cordis.patch.yml bundle patch mounting the plugin row
├── docs/
│ ├── README.zh-CN.md 简体中文文档
│ ├── README.ja.md 日本語ドキュメント
│ └── third-party-settings-namespace-exposure.md developer note: exposing a third-party
│ settings namespace to the web UI
├── test/ node --test suites (unit, render, interaction, integration)
└── package.json plugin manifest (exports, dsh.bundle / dsh.client declarations)
License
链接
同类插件
xmanrui/dsh-im★ 1923
通过二维码或机器人凭据将 IM 机器人接入 DeepSeek Harness(支持飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord 和 WhatsApp 共 9 种渠道)。
shaobeichen/dsh-pocket★ 1699
手机远程访问 DSH Web 界面:扫码即用局域网或公网(cloudflared 隧道)访问,实时同屏、移动端适配布局,带设置页管理。
inclusionAI/Avernet#deepseek-harness-channel-bcn★ 626
通过 WebSocket V2 将 DeepSeek Harness 接入 Avernet Bot 协作网络,支持自动注册、Agent 会话隔离、工具调用事件和多 Bot 路由工具。
Oscar-Williams/dsh-deepcanary★ 90
面向 DeepSeek Harness 的证据优先注意力监督,提供 C0–C3 策略、去重 Inbox 提醒、静默时段和脱敏结果记录。
omdsh-dev/dsh-notification★ 88
回合完成桌面通知,按结果分控 + 关键词过滤。
whyihaveyou/dsh-suite#plugin-notify★ 59
回合完成、错误或待审批时推送 IM webhook(飞书/企微/钉钉/Slack/Discord/自定义)与本地通知。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。