Install
Inside DeepSeek Harness, with dsh-market
dsh plugin --profile web add dshmarket
Or from the command line
dsh plugin --profile web add dsh-task-dispatcher
Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.
README
Use TickTick (滴答清单) as DSH's daily task dispatcher: a cordis timer pulls today's due tasks from the configured source list (default 5️⃣AI; point it at In progress to dispatch from the "doing" list), writes them to today's task file, and notifies via WeChat (ClawBot), flomo, or macOS (configurable). The agent reads the file, works through the items, and writes results back to TickTick with ticktick_complete.
Reuses the already-installed
dsh-ticktickplugin (its data layer + OAuth credentials in~/.dsh/dsh-ticktick.json) — no duplicate configuration.
Features
- Interval dispatch: cordis
ctx.intervalpolls every minute and dispatches when the configured interval (minutes) has elapsed; 0 disables the timer;dispatcher_rundispatches manually anytime. - Task source: default the
5️⃣AIlist (set it toIn progressto dispatch from the "doing" list;projectName/projectIdconfigurable);dueMode=todaypulls due-today/overdue + undated,dueMode=allpulls all incomplete. - Today task file: writes a Markdown checklist (default
~/.dsh/dsh-task-dispatcher/today-tasks.md). - Execution-result receipts (
notifyResult, on by default): every auto-executed task pushes a SHORT outcome message (OK/FAIL+ title + a one-line result, or the failure reason such as a worker timeout) as soon as its worker settles, plus a compact batch tally when a pass runs more than one task - a run reports back by itself instead of relying on the worker callingdispatcher_report. The summary is the worker's stdout final answer (progress/reasoning go to stderr), stripped of ANSI and theDONEmarker and capped at 220 characters. - Notify on change only:
notifyWechat(WeChat, relayed through the local DSH-WeChatClawBot gateway; the recipient is auto-detected) +notifyFlomo(reuses~/.dsh/dsh-flomo.json) +notifyMac(osascript); a repeated pull with no new tasks stays silent. - WeChat notifications (ClawBot): the plugin POSTs the text to the local gateway
/send(defaulthttp://127.0.0.1:51235), which relays it to the WeChat account that scanned the QR code. The plugin never talks to WeChat directly and stores no WeChat credentials. The recipient defaults to theuserIdrecorded in the ClawBot state dir (~/.dsh-wechat, override withDSH_WECHAT_HOME) underaccounts/<botId>.json, or can be set explicitly withwechatTo; long bodies are split into 1200-character chunks. An unavailable channel only marks that channel as failed — it never fails the dispatch. - Auto-execute (autoExecute): when on, each pulled task runs in its own
dsh --profile headlesssession (serial, one task per session); success writes back to TickTick viaticktick_complete; failed tasks wait out the retry cooldown. - Worker timeout (workerTimeoutMinutes): each auto-execute worker is SIGKILLed after this many minutes (default 30, range 1–1440), configurable via
dispatcher_config/ the settings panel. It used to be a hardcoded 10 minutes, which killed long-but-healthy tasks and reported them as failures. - Cheap mode (
cheapMode, off by default): when on, auto-execution only starts during DeepSeek's off-peak (discounted) hours; during peak it queues tasks to the next off-peak start (cheapStrategy=wait) or skips the round (skip). The gate sits strictly before a worker is spawned — pull cadence, filtering and serial execution are untouched; off means 100% legacy behaviour. Official schedule (peak/off-peak pricing since 2026-08-17): peak = Mon–Fri 09:00–12:00 and 14:00–18:00 Beijing time; everything else is off-peak (~half price). The windows are not hardcoded:cheapPreset(official-2026/legacy-utcold UTC 16:30–00:30 /custom) +peakWindows+cheapTimezone. Queued tasks andnextCheapStartAtare persisted, so a DSH restart loses nothing;dispatcher_runhonours cheap mode by default and acceptsignoreCheapMode: trueto bypass it. Notifications distinguish “queued for the HH:MM off-peak window” from a normal run. - Worker workspace (workerWorkspaceId): the auto-execute worker session runs in the user's home dir by default; set a DSH workspace id and the worker spawns with cwd = that workspace's directory, so files are written there and the produced session shows up under that workspace in the GUI sidebar. The settings panel provides a workspace dropdown (list read from
~/.dsh/storages/workspace.json); empty = home dir. - Deferred-sync panel (agent -> TickTick): the settings page configures the write-back path directly - silence threshold (
idleMinutes), per-session top-level cap, and the launchd check interval - and shows the queue, the whole-harness idle time, timer state and the last flush result. Buttons: save thresholds, flush now, force flush, reload timer. The control plane only reads the queue file and drives the script/timer; the writing itself stays in the standalone script + launchd, so a flush still happens while DSH is closed, and no write logic is duplicated between the two halves. Routes:GET /api/dsh-task-dispatcher/deferred,POST .../deferred/{config,flush,timer}. - Agent tools:
dispatcher_status/dispatcher_config/dispatcher_run/dispatcher_report+ a Web settings panel.
Compatibility
Requires DeepSeek Harness ≥ 0.1.5-rc.1 (declared as dsh.engines.dsh in the package manifest, so the DSH plugin marketplace can report it) and is verified against 0.1.5-rc.1. This build carries the DSH 0.1.5 adaptations: the strict tool-result contract (lossless-JSON snapshot, additionalProperties: false schema validation, and output.render returning ContentBlock[]) plus executable resolution that survives a launchd-started host whose PATH is only /usr/bin:/bin. Since this version the peerDependencies range explicitly declares compatibility with DSH 0.2.0-rc.2 (^0.2.0-rc.2 is now included), so no compatibility warning appears on 0.2.0-rc.2. No functional change.
Install
The shape is install → restart → confirm it loaded. Every step states the expected result, so you can tell success from failure.
- Install the plugin: run
dsh plugin --profile web add dsh-task-dispatcherin a terminal. Expected: the command exits cleanly anddsh-task-dispatchershows up in the dependencies of~/.dsh/profiles/web/package.json. - Restart DSH: restart
dsh web(sidebar “restart”, or re-run the same start command). Expected: the GUI comes back with no plugin-loading errors in the startup output.
📷 【Screenshot slot 2】proves the plugin actually installed How to capture: in the terminal, stop right after step 1's command finishes (or on the DSH startup lines after the restart); crop: the terminal window Redact: local absolute paths, your username, any token To fill in: save the shot to
docs/images/dsh-task-dispatcher-01-installed.png, then replace this whole block with
- Confirm it loaded: ask the agent to run
dispatcher_status(or check that “Task dispatcher” appears on the settings page). Expected: output starts with插件状态:已启用/ status “enabled” and lists the source list, pull interval and notification channels.
Enable & configure
- Open the settings page: DSH Web → Settings → expand the “Task dispatcher” card. Expected: you see the master switch, pull interval, task source, notification channels and auto-execute blocks.
📷 【Screenshot slot 4】proves where the settings live (the step people get stuck on) How to capture: Settings → stop on the top half of the expanded “Task dispatcher” card (master switch + pull interval + source list) Redact: workspace paths / list names if they carry personal information To fill in: save the shot to
docs/images/dsh-task-dispatcher-02-settings.png, then replace this whole block with
- Adjust what you need: set the task source (default
5️⃣AI; useIn progressto dispatch from the “doing” list), the pull interval (0 disables the timer), the notification channels (WeChat ClawBot / flomo / macOS; WeChat is off unless you switch it on) and auto-execute (each task then runs in its own headless session). Expected: the status line refreshes after saving anddispatcher_statusreports the same values. - Turn on cheap mode (optional; the headline of this release): in the same card, tick “省钱模式(自动执行只在 DeepSeek 空闲时段开跑)” (off by default), then pick the preset (default “official, Mon–Fri 09–12 / 14–18 peak”), the strategy (default “wait for off-peak”, or skip) and the tail margin (set it to your worker timeout, e.g.
15/30). Expected: a peak-window editor appears, and the status line shows “current window / next run / queued tasks”.
📷 【Screenshot slot 6】proves cheap mode is configured correctly How to capture: Settings → “Task dispatcher” → stop on the fully expanded cheap-mode area (toggle + preset + strategy + tail margin + window table) Redact: none (just keep the workspace path at the top out of frame) To fill in: save the shot to
docs/images/dsh-task-dispatcher-03-cheap-mode.png, then replace this whole block with
Verify it works
- Trigger one dispatch: ask the agent to run
dispatcher_run, or press pull now in the panel; to “run once right now even in peak”, press “省钱模式(高峰也马上执行,仅本次)”. Expected: today's task file~/.dsh/dsh-task-dispatcher/today-tasks.mdgains items (the agent reads it and works through them), and you get one notification when the task set changed. - Look at the result: run
dispatcher_status, or read the status line in the panel. Expected: “last pull: · items”; with cheap mode on during peak you also see “queued: N” and “next run: ” — tasks held back for the next off-peak window is exactly what cheap mode looks like.
📷 【Screenshot slot 8】proves it is actually in use (the most important one) How to capture: after one dispatch, stop on the panel status line, or on the “last pull / queued / next run” lines of
dispatcher_status; crop: just that card or that terminal output Redact: real task titles, local paths, WeChat display name — use a throwaway test task To fill in: save the shot todocs/images/dsh-task-dispatcher-04-in-use.png, then replace this whole block with
Current release: v0.6.0 (CHANGELOG · Releases · npm).
Dev
pnpm install
pnpm build && node tests/smoke.mjs
License
MIT
Comments
Comments live in GitHub Discussions. Sign in with GitHub to post or react.