DeepSeek Harness plugin

dsh-serverchan-notify

ServerChan3 (Server酱) push notifications when a turn finishes — title, model, project directory, git branch, status and a reply excerpt, with subagent filtering and fire-and-forget delivery.

Jump to install

Source facts

Repository
nickhelion/dsh-serverchan-notify
Latest update
Aug 21, 2026
Category
Notifications & Integrations
GitHub stars
0

Install

Start with a prompt that asks an agent to read the source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to read the page and repository first.

Do not install anything yet. Read this DeepSeek Harness plugin and explain what it does, which files, networks, or credentials it can access, and how to install and remove it.

Plugin page: https://deepseekplugins.org/plugins/nickhelion/dsh-serverchan-notify
GitHub: https://github.com/nickhelion/dsh-serverchan-notify
Plugin: dsh-serverchan-notify
Author: nickhelion
Install command: dsh plugin --profile web add github:nickhelion/dsh-serverchan-notify

Do not run the install command until I confirm.

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

<div align="center">

🔔 dsh-serverchan-notify

A DeepSeek Harness (DSH) plugin that pushes a Server酱3 (ServerChan³) notification to your WeChat every time an agent turn finishes an answer — codex Stop-hook parity for DSH.

[English](README.md) · [简体中文](README.zh-CN.md)

![License: MIT](LICENSE) ![Node ≥ 18](#requirements) ![DSH plugin](https://github.com/topics/dsh-plugin) ![PRs Welcome](#contributing)

</div>

What it does

  • Subscribes to the DSH session event stream (ctx.on("session/event", …)).
  • On every turn/end (completed / error / blocked / max-tokens / aborted), pushes one Markdown notification to Server酱3 → your WeChat.
  • Each notification carries: conversation title, model, project directory, git branch, turn status, finish time, session id, and the latest reply excerpt (truncated at 16 000 chars).
  • Fire-and-forget: a failed push only logs a warning and never blocks or interrupts the agent loop.
  • Skips subagent sessions by default (no spam from internal subtasks).
codex Stop hookthis plugin
Triggerone per finished turnone per finished turn (turn/end)
Key sourceenv / ~/.codex/secrets/…env / config / $DSH_HOME/secrets/… (see [SendKey resolution](#sendkey-resolution))
Failure handlingnever blocks the turnnever blocks the turn
Scopeglobal hooks.jsonglobal $DSH_HOME/cordis.patch.yml (or per profile)

> 🔐 This repository contains no SendKey. Keys come from the environment, a file, or plugin config — never from source code.

Requirements

  • DeepSeek Harness (DSH) with @deepseek-ai/cordis ^4.0.1
  • Node.js ≥ 18
  • A Server酱3 SendKey (free account at <https://sct.ftqq.com/>)

Quick start

1. Get a SendKey

Log in at <https://sct.ftqq.com/>, open the SendKey tab, and copy your key — it looks like sctp<number>txxxx…. The plugin auto-derives your dedicated push domain (https://<number>.push.ft07.com/send/<key>.send); legacy keys without a channel number use https://sctapi.ftqq.com/<key>.send.

2. Save the key (recommended)

mkdir -p ~/.dsh/secrets
echo '你的SendKey' > ~/.dsh/secrets/serverchan_sendkey
chmod 600 ~/.dsh/secrets/serverchan_sendkey

3. Register the plugin

Edit your DSH patch layer and restart the harness:

# global — all profiles (like codex's global hooks.json):
#   $DSH_HOME/cordis.patch.yml   (default ~/.dsh/cordis.patch.yml)
# per profile:
#   $DSH_HOME/profiles/<name>/cordis.patch.yml

- insert:
    - id: serverchan-notify
      name: 'dsh-serverchan-notify'
      config:
        sendkeyFile: '~/.dsh/secrets/serverchan_sendkey'

Plugin rows are only resolved at boot — restart the harness process after editing.

Installing the package

The package declares a dsh.bundle manifest, so it installs with one command (from GitHub until it is on npm):

# install into a profile (github spec — works without an npm publish)
dsh plugin --profile web add github:nickhelion/dsh-serverchan-notify

# npm (once published)
cd ~/.dsh/profiles && pnpm add dsh-serverchan-notify

# manual: clone + symlink into the profile's module tree
git clone https://github.com/nickhelion/dsh-serverchan-notify
ln -s "$(pwd)/dsh-serverchan-notify" ~/.dsh/profiles/node_modules/dsh-serverchan-notify

The bundled cordis.patch.yml inserts the plugin row with all-default config; override any option by addressing the row id serverchan-notify from your own patch layer.

SendKey resolution

The first non-empty value wins, in this order:

#SourceExample
1env var SERVERCHAN_SENDKEYexport SERVERCHAN_SENDKEY=sctp…
2inline config sendkeyconfig.sendkey: 'sctp…'
3env var SERVERCHAN_SENDKEY_FILE (path to a key file)export SERVERCHAN_SENDKEY_FILE=…
4config sendkeyFile (supports ~)config.sendkeyFile: '~/.dsh/secrets/…'
5default file $DSH_HOME/secrets/serverchan_sendkey~/.dsh/secrets/serverchan_sendkey

Configuration

KeyDefaultDescription
sendkeyInline key (overridden by the SERVERCHAN_SENDKEY env var)
sendkeyFile$DSH_HOME/secrets/serverchan_sendkeyPath to a key file; ~ is expanded
reasons[completed, blocked, error, max-tokens, aborted]Which turn/end reasons trigger a push (interrupted is never pushed)
notifySubagentsfalseAlso push subagent sessions (off by default to avoid spam)
timeoutMs8000HTTP timeout in milliseconds
maxResponseChars16000Reply excerpt truncation length
disabledfalseDisable without removing the row (no key read, no subscription)

Sample notification

> DSH 完成:<conversation title> > > - 对话标题:… > - 模型:deepseek-official / deepseek-v4-pro > - 项目目录/home/you/project > - Git 分支main > - 回合状态:完成 > - 完成时间:2026-08-18T21:00:00.000Z > - 会话 IDsession-12 > > ## DSH 最新回复 > > …the latest assistant reply…

Troubleshooting

| Symptom | Fix | | --- | --- | | "未找到 Server酱 SendKey" warning at boot | Provide the key via one of the 5 sources above | | HTTP 403 / timeout in the log | Network / proxy issue; the push domain is derived from the key (<n>.push.ft07.com) | | No push after restart | Confirm the row id is unique and the package resolves — dsh --profile web --dump-config \| grep -A8 serverchan-notify | | Too many pushes | Turn on notifySubagents: false (default) or trim reasons | | Temporarily stop | disabled: true, then restart |

Development

npm install        # installs devDependencies (cordis) for the smoke test
npm test           # smoke test — stubbed fetch, no real push
REPORT=1 npm test  # smoke test + print the assembled payload
npm run test:live  # send one real test push with the configured key

Repository layout

lib/index.js      plugin entry — event subscription, message assembly, HTTP push
test-send.mjs     standalone real push (same key resolution order as the plugin)
smoke-test.mjs    cordis in-process test with a stubbed fetch
package.json      package metadata + npm scripts
README.md         English docs
README.zh-CN.md   中文文档

Contributing

PRs welcome. Two ground rules:

1. Never commit a SendKey (or any absolute machine path) — keys flow through env / file / config only. 2. The event listener must stay non-throwing and fire-and-forget — a notification must never affect the harness.

License

[MIT](LICENSE)