Introduction

The philosophy behind DeepSeek Harness (DSH) is “everything is a plugin.” In agent development, we often need to run unattended long-running tasks, such as overnight builds, model training, or batch rendering.

The dsh-schedule mechanism built into DSH can deliver messages, but it is passive: it delivers a message and leaves the decision to the model. However, if the model process crashes or the quota is exhausted, the built-in mechanism often cannot recover the situation in time.

We need an active mechanism: periodically check whether anyone is still working, and if nobody reports activity, directly execute a shell command to reclaim resources. This is the problem that the dsh-deadman plugin solves.

Plugin Introduction

dsh-deadman is the deadman switch plugin for DeepSeek Harness (DSH), maintained by user 0gl20shk0sbt36.

Its core logic is: after armed, it periodically checks for activity. If nobody “checks in,” it executes the command specified in advance. This is suitable for scenarios such as “the job finishes or crashes, then shut down automatically.”

Installation and Enabling

This plugin requires DSH version 0.2.0-rc.2 (strictly pinned dependency). On the Web or desktop client, enable dsh-deadman on the plugin page after installation.

Install it via CLI (using the web profile as an example):

dsh plugin --profile web add github:0gl20shk0sbt36/dsh-deadman

Uninstall command:

dsh plugin --profile <name> remove dsh-deadman

Note:
1. It only makes sense to install it in a long-running profile (such as web). The scheduler lives inside the dsh process; if it is a headless one-shot process, nobody will perform checks after the process exits.
2. Please review the source code and license before installing.
3. The plugin runs with the permissions of the current dsh process, and the commands executed are fully specified by whoever arms it.

Core Features

The plugin provides three tool commands and slash commands.

Tool Commands

  1. deadman_arm
    - Purpose: Arm. Set the task name, command to execute, first check time, interval, and so on.
    - Mechanism: The first check happens after after_minutes; if checked in, it is rescheduled by interval_minutes; after one successful execution, the task automatically finishes.

  2. deadman_hold
    - Purpose: Check in. Tell the plugin “I am still working,” and skip the current execution.
    - Behavior: Any session can check in (fail-safe semantics).

  3. deadman_disarm
    - Purpose: Disarm. Available only to the arming session or its direct child agents; other sessions must explicitly set force=true, and this will be logged.

Slash Commands

  • /deadman: Arm in the current session.
  • /deadman all: Arm in all sessions.
  • /deadman cancel <name>: Cancel the specified task.

How It Works

The plugin decides whether to execute the command based on “activity” rather than “state.”

  1. Resolve the owner session: First obtain the session. If the session is not open, it will try to recover it to avoid messages falling into a black hole.
  2. Deliver the check-in request: Send a message to the agent, requiring it to choose one of two options: check in or remain silent.
  3. Check loop and decision:
    - If any agent has new events since the last check (session.seq advances) ⇒ it is still progressing, so keep waiting.
    - If all agents show no progress ⇒ start the grace period holdWindowSeconds.
    - If there is a question awaiting a user answer (state === 'open' in the userQuestions projection) ⇒ run a separate timer and release after at most questionBlockSeconds.
    - The total cap from the trigger time is maxHoldMinutes; if reached, always release the hold (fail-open).
  4. Execute the command: After release, execute the command. On success, the task automatically finishes and notifies the owner.

Check-in Channels

  1. Use the deadman_hold tool.
  2. Create a marker file .deadman-hold-<name> in the current working directory.
  3. Create a file named after the task name under the plugin data directory hold/.

Configuration

The configuration is written in the profile’s cordis.patch.yml:

- id: deadman
  config:
    holdWindowSeconds: 60
Key Default Description
holdWindowSeconds 60 After all agents stop progressing, how long to wait before proceeding
checkIntervalSeconds 20 Check interval
maxHoldMinutes 30 Total cap from the trigger time; if reached, always release the hold
questionBlockSeconds 600 Maximum wait time when blocked by an open question awaiting a user answer
onUndeliverable execute Behavior when the owner session is completely undeliverable: execute or skip
progressScope global Scope for the activity check: global (whole machine) or owner (owner only)
serializeCommands false Whether multiple action commands are queued and executed serially
commandTimeoutSeconds 300 Execution timeout for a single action command
dataDir $DSH_HOME/plugins/dsh-deadman Data directory (tasks.json + hold/)

Use Cases and Notes

Use Cases

  • Long-running tasks such as overnight builds, training, and batch rendering.
  • Scenarios where resources must be prevented from being left unclaimed after the model crashes or the quota is exhausted.

Notes

  1. Long-running dependency: The scheduler lives inside the dsh process. Arming in a headless one-shot process means nobody will check after the process exits (unless a long-lived instance later loads it when it starts).
  2. Single-writer assumption: tasks.json is a plain JSON file; concurrent writes from multiple processes can overwrite each other. Do not arm simultaneously in multiple processes.
  3. Permission control: Check-ins have no permission restriction (anyone can stop it), but disarming has permission restrictions.
  4. Data persistence: The data is retained across restarts, but executed task records are stored in tasks.json.

Conclusion

dsh-deadman provides a capability complementary to the built-in dsh-schedule in dsh: it does not rely on the model to handle it, executes commands directly, and includes a “check-in gate” mechanism. It is suitable as the deadman switch for unattended tasks.

Plugin directory: https://www.skillhub.cn/plugins/0gl20shk0sbt36/dsh-timer-task
GitHub: https://github.com/0gl20shk0sbt36/dsh-timer-task