⏱️ dsh-automations
August 14, 2026 · View on GitHub
Codex-style automations for DeepSeek Harness: let coding work run on its own — triggered by GitHub events, cron schedules, or local file changes — with an agent dispatched per match and results reported back where they matter.
Why
You want unattended work that is more than a reminder:
- A new
bug-labeled GitHub issue should get investigated and fixed without you watching. - Every day at 09:00 the workspace should get an inspection report.
- When a docs directory changes, someone should read the diff and update the project status.
dsh-automations turns each of these into a rule: trigger → template prompt → spawned coding agent → (optional) result posted back to the issue/PR.
Features
| Capability | Description |
|---|---|
| GitHub events | Webhook receiver at POST /api/automations/webhook (issues / pull_request / issue_comment), filterable by event, repository, and label |
| GitHub polling | No public URL? Poll the API instead — per-rule interval (e.g. 1440 = once a day), incremental since cursor, public repos work without a token |
| cron schedules | Standard 5-field expressions (*, */n, a-b, a,b), evaluated every 30 s |
| Local file watch | Recursively poll a directory (default every 60 min), fingerprint compare (size + mtime) detects added/changed/deleted files, dispatches only on real changes; include supports * patterns |
| Working directory | Optional per-rule cwd: the dispatch prefers a live session whose workspace matches, so the child agent inherits the right workspace; {{cwd}} is also injected into the prompt |
| Read-only mode | Per-rule readOnly: the child agent is restricted to read/glob/grep/web_search — safe for inspection/reporting tasks |
| Overlap guard | One active run per rule; a due trigger while running is recorded as skipped (overlap) |
| Report-back | report: true + a GitHub token → the agent's result is posted as a comment on the issue/PR |
| Durable state | Rules, GitHub config, run history, and file fingerprints persist to ~/.dsh/automations.json — nothing is lost on restart |
| Two control planes | Manage from the Automations settings page (GUI) or by asking any agent via the automation_manage tool; a JSON API (/api/automations/*) backs both |
| Run history | Last 100 runs (persisted): trigger source, status, summary, child session id, error |
Install
One command — works on any Windows user (paths are resolved from %USERPROFILE% / %LOCALAPPDATA%, never hard-coded):
powershell -NoProfile -ExecutionPolicy Bypass -File install-automations.ps1
The installer uses the official dsh plugin mechanism when possible:
- Locates the
dshCLI (PATH, then the npx cache, then a running git-clone checkout) andpnpm(PATH, then corepack, thennpm install -g pnpm— user directory, no admin needed). - Packs the package into a tarball (
npm pack) so pnpm copies it into the profile's.pnpmvirtual store — a plainpnpm add <dir>would link the source tree, which breaks runtime imports of@deepseek-ai/*after Node resolves the symlink. - Runs
dsh plugin --profile web add <tarball>; the bundle declaration (dsh.bundle.patch→cordis.patch.yml) makes theautomationsrow mount automatically viadsh.profile.bundles. - Falls back to a manual copy + patch row only when
dsh/pnpmare unavailable (-UseFallbackforces it).
Both deployment styles are supported (npx-launched or git clone source checkout — the module-resolution anchor is the same profiles/node_modules fallback that DSH heals on every boot):
# npx deployment (default; the CLI is auto-detected)
powershell -NoProfile -ExecutionPolicy Bypass -File install-automations.ps1
# git-clone deployment: run from inside the deepseek-harness checkout
powershell -NoProfile -ExecutionPolicy Bypass -File install-automations.ps1 -DshBin pnpm-dsh
# ...or pass the CLI entry directly
powershell -NoProfile -ExecutionPolicy Bypass -File install-automations.ps1 -DshBin C:\path\to\dsh\lib\bin.js
From GitHub once released:
dsh plugin --profile web add github:nbhby/dsh-automations#v0.3.0
Then restart dsh web (close the launcher window, rerun it). Remove with install-automations.ps1 -Remove (or dsh plugin --profile web remove @dsh-external/dsh-automations).
Quick start
- Open Settings → Automations (or ask any agent: "list the automation rules").
- Add a rule: a name, a trigger, and a self-contained template prompt.
- Use Run now once to verify before relying on the schedule.
Example rule
Trigger: Local file change on E:\project\docs, *.md, every 60 min
Template:
Detected {{changeCount}} file change(s) under {{dir}}:
{{changes}}
Analyze the changes: read any new design docs and update the project status
notes accordingly; for code changes, run a targeted check. Working directory: {{cwd}}
Template variables
{{repo}} {{number}} {{title}} {{body}} {{labels}} {{actor}} {{htmlUrl}} {{headRef}} {{baseRef}} {{commentBody}} {{dir}} {{changes}} {{changeCount}} {{cwd}} {{now}} {{date}} {{time}}
({{changes}} is the file-trigger change list, one [added|changed|deleted] relative-path per line.)
GitHub setup
- Token (needed only for comment report-back or private-repo polling): GitHub → Settings → Developer settings → Personal access tokens → generate one with
reposcope (classic) or Issues: Read and write (fine-grained). - Default repo:
owner/nameused by polling rules that do not pin their own. - Webhook (optional, real-time): repo Settings → Webhooks → Payload URL
http://127.0.0.1:3080/api/automations/webhookexposed through a tunnel (ngrok/cloudflared), Content typeapplication/json, events: Issues + Pull requests.
Management API
GET /api/automations/state
POST /api/automations/rule # { name, triggerType: github|cron|file, event?, repo?, label?, poll?, pollIntervalMin?, cron?, dir?, include?, intervalMin?, cwd?, readOnly?, template, report?, timeoutMinutes? }
POST /api/automations/rule/:id/remove
POST /api/automations/rule/:id/toggle # { enabled }
POST /api/automations/rule/:id/run
POST /api/automations/github # { token?, repo? }
POST /api/automations/runs/clear
Safety notes
- A schedule is not permission. Unattended runs are less interactive than a chat. Use
readOnlyfor anything that should not write; the overlap guard and the per-rule timeout bound runaway work. - The child agent's approval policy is the delegation default (
never, fail-closed) — a tool that needs interactive approval fails instead of hanging. - Webhook signature (HMAC) verification is not implemented; keep the endpoint behind a tunnel you trust in local deployments.
- The engine is process-local: the DSH host must be running for triggers to fire.
Development
No build step — plain ESM host + a browser client bundle (web UI). The installer only copies files.
Acknowledgments
- titanwings/dsh-automation — the design of this plugin owes a lot to it: the durable run-history model (definition snapshots, terminal statuses, overlap skipping), the explicit permission boundary for unattended runs (read-only vs workspace-write, fail-closed approval), and the Agent-facing management tools. Both projects independently follow the Codex Scheduled tasks product pattern (fresh agent per run vs. returning to a chat); this plugin extends the trigger model to GitHub events (webhook + polling), cron, and local file changes, and reports results back to GitHub.
- Codex (OpenAI) — the product pattern ("automations") that inspired both projects. Referenced as a pattern only; no code is copied.
License
MIT. Independent community plugin for DeepSeek Harness; "Codex" is referenced only as the product pattern that inspired the design.