⏱️ 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

CapabilityDescription
GitHub eventsWebhook receiver at POST /api/automations/webhook (issues / pull_request / issue_comment), filterable by event, repository, and label
GitHub pollingNo 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 schedulesStandard 5-field expressions (*, */n, a-b, a,b), evaluated every 30 s
Local file watchRecursively 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 directoryOptional 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 modePer-rule readOnly: the child agent is restricted to read/glob/grep/web_search — safe for inspection/reporting tasks
Overlap guardOne active run per rule; a due trigger while running is recorded as skipped (overlap)
Report-backreport: true + a GitHub token → the agent's result is posted as a comment on the issue/PR
Durable stateRules, GitHub config, run history, and file fingerprints persist to ~/.dsh/automations.json — nothing is lost on restart
Two control planesManage from the Automations settings page (GUI) or by asking any agent via the automation_manage tool; a JSON API (/api/automations/*) backs both
Run historyLast 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:

  1. Locates the dsh CLI (PATH, then the npx cache, then a running git-clone checkout) and pnpm (PATH, then corepack, then npm install -g pnpm — user directory, no admin needed).
  2. Packs the package into a tarball (npm pack) so pnpm copies it into the profile's .pnpm virtual store — a plain pnpm add <dir> would link the source tree, which breaks runtime imports of @deepseek-ai/* after Node resolves the symlink.
  3. Runs dsh plugin --profile web add <tarball>; the bundle declaration (dsh.bundle.patchcordis.patch.yml) makes the automations row mount automatically via dsh.profile.bundles.
  4. Falls back to a manual copy + patch row only when dsh/pnpm are unavailable (-UseFallback forces 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

  1. Open Settings → Automations (or ask any agent: "list the automation rules").
  2. Add a rule: a name, a trigger, and a self-contained template prompt.
  3. 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 repo scope (classic) or Issues: Read and write (fine-grained).
  • Default repo: owner/name used 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/webhook exposed through a tunnel (ngrok/cloudflared), Content type application/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 readOnly for 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.