dsh-scheduler
An autonomous scheduled-task plugin for DeepSeek Harness (DSH), built as a dynamic Cordis plugin. It lets the agent schedule subprocess commands on a cron expression or a fixed interval, records each run's exit code and output tail, and persists everything to a JSON state file so schedules survive plugin restarts.
No npm dependencies. Scheduling runs on the DSH host process (timer service), execution uses the subprocess service.
What it does
| Piece |
Where |
Role |
Host half (host-half.js) |
DSH host process |
1-second tick, cron/everyMs next-run computation, subprocess execution, result capture, JSON persistence |
| State file |
<data dir>/state.json |
Schedules + last run results, restored on plugin (re)start |
schedule_add ──▶ host half ──1s tick──▶ due? ──▶ subprocess spawn ──▶ record exit/output
│
└────────▶ persist state.json
Requirements
- DeepSeek Harness with the dynamic-Cordis extension
- The host process must stay running for tasks to fire (results are read later via
schedule_list)
Install
-
Place this repo somewhere on the machine.
-
In host-half.js, edit the two constants: STATE_PATH (where the JSON state lives) and BASE_CWD (default working directory for scheduled commands, and the writable root the sandbox policy is scoped to).
-
In your DSH session, define the plugin — paste the entire content of host-half.js into code.host (host-only: no Client half, no approval):
cordis_define(plugin: { kind: "new", idPrefix: "sched" },
name: "dsh-scheduler",
purpose: "Autonomous scheduled tasks: cron/everyMs subprocess jobs",
code: { host: <host-half.js> })
cordis_run(pluginId, packageId, mode: "run")
Tools
| Tool |
What it does |
schedule_add |
Add a task: kind: "everyMs" (fixed interval ≥ 1000 ms, optional runImmediately) or kind: "cron" (5 fields: minute hour day-of-month month day-of-week; supports *, */n, a-b, a,b; standard dom/dow OR semantics). argv is the command to run (argv[0] may be a bare name or absolute path), cwd optional. |
schedule_list |
All tasks: spec, enabled, next/last run (ISO), exit code, error, output tail, run count, plus any persistence error. |
schedule_set |
Enable or disable a task. |
schedule_remove |
Delete a task. |
schedule_run |
Run a task now (even when disabled) and wait for the result — handy for testing. |
Cron examples: 0 9 * * 1-5 (weekdays at 09:00), */5 * * * * (every 5 minutes), 0 0 1 * * (first day of each month at midnight).
Privacy & safety
- Local only: commands run on your machine, results stay in the local state file; no telemetry.
- Scheduled commands run with the same sandbox confinement as the session — check
lastError if a command is denied.
- Persistence writes use an explicit
workspace-write policy scoped to BASE_CWD (the dynamic plugin context has no exec, so the sandbox-policy fallback would otherwise default to read-only and silently deny writes).
- No notification channel exists yet: results accumulate in
schedule_list for the agent to read on the next conversation.
Known limitations
- Tasks survive plugin restarts, but not the harness process being down at fire time (missed fires run at the next tick once back up).
- One run per task at a time; a still-running task skips its next fire.
- No HTTP action kind yet — pair with dsh-http or wrap a command (
node -e "fetch(...)") for scheduled network checks.
License
MIT