Introduction¶
DSH comes with the @deepseek-ai/dsh-schedule set of “automated tasks,” but they are schedule reminders: when the time comes, a message is sent back to the bound session, using that session’s history to continue working. The receipt only indicates “the message entered the inbox,” it does not indicate the model execution is complete, and there is no pause or manual run.
The dsh-routines introduced below (maintainer leinaldo, category “Workflow”) changes the semantics to a task runner: at the scheduled time, it opens a new conversation to run a round; after completion, it has status, duration, steps, and token receipts, and allows reviewing that round of conversation. The goal is to supplement DSH with scheduled tasks, mimicking the behavior of Claude Desktop App’s local scheduled tasks (Routines / CCD scheduled tasks).
What is this¶
One-sentence positioning: A DSH plugin that uses a JSON index to manage scheduled tasks; every trigger creates a new session and runs a round with an independent context.
The actual problem it solves is that the built-in reminder only delivers a message at the scheduled time, so you don’t know if the model actually finished running or how well it did; while dsh-routines treats this round as a genuine execution to track, allowing you to check for failures or timeouts.
Differences from Built-in Automated Tasks¶
| Dimension | @deepseek-ai/dsh-schedule (Built-in) |
dsh-routines (This Plugin) |
|---|---|---|
| Execution Location | Sent back to bound session, reusing history | New session, independent context per round |
| Execution Receipt | Only indicates message entered inbox | Records status/duration/steps/tokens after turn/end |
| Manual Run | None | “Run Now”, does not change schedule |
| Disable/Enable | None | Supported |
| One-time Task | None | Supported, automatically disabled after running |
Since the context is not shared between rounds, the instruction (prompt) in the task must be self-contained—write clearly what needs to be done, do not rely on it reading previous conversations.
Scheduling and Execution Semantics¶
Scheduling capabilities:
- cron: Five fields, local timezone; supports
*,a,a-b,a-b/n, lists, and month/weekday abbreviations. - One-time: ISO timestamp, only future times allowed; automatically disabled after running; tasks not run within 7 days are disabled upon trigger.
- Manual Only: No cron or one-time schedule filled; kept in list for “Run Now” button.
- Heartbeat: Scans immediately on start, then every 60 seconds.
- Catch-up Run: When missed, finds the nearest slot after
max(createTime, 7 days ago, enabledTime)to run; if late by more than 2 minutes, marked asmissed. - Jitter: Cron task dispatch delay =
sha256(taskId) % (min(10, adjacent_interval-1) * 60)seconds. Constant for the same task to avoid simultaneous triggers at the hour. - Retry: Retry at 5/15/30 minutes for session creation or delivery failure, max 3 times; no retry for model round failures.
- Concurrency: Same task runs at most once simultaneously.
The process of running a round:
ctx.sessionController.create({ cwd })creates a new session;cwdis taken from the task config, otherwise the most recent session.- After
resolveAgent, the title is changed to “Task Name · Month-Day Hour:Minute”; session ID is added to the hidden list, filtered out of the left sidebar. - Subscribe to
session/event, dispatch instruction, wait forturn/end: ifreason.kind === "completed", record success; otherwise (error,blocked,aborted,timeout, etc.) record failure and keep reason; if not finished within 45 minutes, treat as timeout failure. - Write run records to index, keeping only the most recent 50 per task.
- If the task was created by a tool inside a conversation and notifications are enabled, send a completion/failure message to the creating session; tasks created by the panel do not create a session, so no message is sent.
Status exists in a single file:
~/.dsh/routines/
scheduled-tasks.json # Task index: name, description, instruction, schedule, run records
Old versions wrote tasks in the body of <taskId>/SKILL.md; when reading the index, they are automatically moved to prompt and the directory is deleted.
Installation and Enablement¶
Install from the plugin market; the index source is provided by the author using GitHub Pages:
https://leinaldo.github.io/dsh-routines/market/index.json
- Open Plugins → Discover → Add Index Source, fill in the URL above.
- Find Scheduled Tasks in the list and click Install.
- Restart DSH; “Scheduled Tasks” appears in the left sidebar.
Local development mode:
~/.dsh/plugins/dsh-routines
- Put the repository directory in
~/.dsh/plugins/dsh-routines. - Add
"dsh-routines": "file:/Users/leinaldo/.dsh/plugins/dsh-routines"todependenciesin~/.dsh/profiles/desktop/package.json(adjust path for your machine). - Add
"dsh-routines"to the end ofdsh.profile.bundlesin the same file. - Run
pnpm installin the profile directory, then restart DSH.
The host code is loaded at startup; changes take effect only after a restart. The client panel reloads with the page refresh.
Typical Usage¶
Operation in Sidebar Panel: “New” fills in name, description, instruction, schedule, working directory; “Run Now” on the card does not change the schedule, only updates lastRunAt; “Disable” only stops automatic dispatching; after disabling, manual runs are also rejected. “Run Records” expand each record with status, time, duration, tokens, summary, and “View Session”; clicking it opens the session for that run—the run session does not appear in the left sidebar list, only accessible from here.
Let the model create tasks directly, without opening the panel first:
| Tool | Function |
|---|---|
routine_create |
Create task: name, prompt required; cron_expression / fire_at / cwd / notify_on_completion optional |
routine_list |
List all tasks, next run time, and instructions |
routine_update |
Only update passed fields; enabled:false to disable |
routine_delete |
Delete task and run records |
routine_run |
Run once immediately, does not change schedule |
When saying “Summarize AI news for me at 12 PM every day” in a conversation, the model chooses between the built-in schedule_* and this plugin based on the tool description. To ensure it uses this plugin, specifically say “use scheduled tasks to create,” or directly say “run on every new conversation.”
HTTP Interface (underlying the panel):
| Method | Path | Description |
|---|---|---|
| GET | /dsh-routines/tasks |
Task list view (including next run, recent status, running indicator) |
| GET | /dsh-routines/task?id= |
Single task (including prompt) and all run records |
| GET | /dsh-routines/defaults |
Default working directory |
| POST | /dsh-routines/tasks/create |
{name, description?, prompt, cronExpression?\|fireAt?, cwd?, notifyOnCompletion?} |
| POST | /dsh-routines/tasks/update |
Same fields + id, also supports enabled, disableJitter |
| POST | /dsh-routines/tasks/delete |
{id}, deletes task file and run records together |
| POST | /dsh-routines/tasks/run |
{id}, run immediately (does not change schedule) |
Applicable Scenarios and Notes¶
Suitable for these situations: You already have an independent task you want to run at a fixed time, and you want each round to have a clean context with a verifiable receipt upon completion; or you want to use a one-time task for a “reminder that stops running when the time comes.”
A few points to note:
- The plugin runs with the current DSH process permissions; before installing, you should read the source code and license (MIT, see
LICENSEin the repo). - Tasks requiring approval will stop at the approval card until timeout is recorded as a failure—there is no unattended approval strategy.
- No system notifications, only completion messages sent to the creating session and panel status; there is no cost field, the DSH host only exposes tokens, not prices.
- Hiding the run session is only done on the web side; the cost is that the list update relies on this client code, so when changing the host’s list implementation, the client code must be updated accordingly.
- The storage root directory only takes
DSH_HOMEor~/.dsh, it does not readctx.baseDir—the latter is often/when GUI starts, causing the panel to always read an empty index.
Summary¶
dsh-routines upgrades DSH’s scheduled actions from “reminder delivery” to “execution tracking,” aligning scheduling semantics, missed runs, and jitter with Claude Routines. The cost is that instructions must be self-contained and a new session is opened every round.
- Directory: https://www.skillhub.cn/plugins/leinaldo/dsh-routines
- GitHub: https://github.com/leinaldo/dsh-routines