New:Socket for Asana Is Now Available.Learn more
Get Started

dsh-serverchan-notify

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dsh-serverchan-notify

DeepSeek Harness plugin: push a ServerChan3 (Server酱) notification whenever an agent turn finishes an answer — codex Stop-hook parity

latest
Source
npmnpm
Version
1.0.2
Version published
Maintainers
1
Created
Source

🔔 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 · 简体中文

License: MIT Node ≥ 18 npm version CI DSH plugin PRs Welcome

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)
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.

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 npm installation is one command:

# recommended
dsh plugin --profile web add dsh-serverchan-notify

# fixed version
dsh plugin --profile web add dsh-serverchan-notify@1.0.2

# GitHub monorepo fallback
dsh plugin --profile web add 'github:nickhelion/dsh-plugins#main&path:/packages/serverchan-notify'

# local development
git clone https://github.com/nickhelion/dsh-plugins.git
dsh plugin --profile web add "$PWD/dsh-plugins/packages/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 完成:

  • 对话标题:…
  • 模型:deepseek-official / deepseek-v4-pro
  • 项目目录/home/you/project
  • Git 分支main
  • 回合状态:完成
  • 完成时间:2026-08-18T21:00:00.000Z
  • 会话 IDsession-12

DSH 最新回复

…the latest assistant reply…

Troubleshooting

SymptomFix
"未找到 Server酱 SendKey" warning at bootProvide the key via one of the 5 sources above
HTTP 403 / timeout in the logNetwork / proxy issue; the push domain is derived from the key (<n>.push.ft07.com)
No push after restartConfirm the row id is unique and the package resolves — dsh --profile web --dump-config | grep -A8 serverchan-notify
Too many pushesTurn on notifySubagents: false (default) or trim reasons
Temporarily stopdisabled: 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 are accepted in the canonical nickhelion/dsh-plugins monorepo. Two ground rules:

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

License

MIT

Keywords

deepseek-harness

FAQs

Package last updated on 21 Aug 2026

Related posts