DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-reaper

1

dsh-reaper

Manifest valid

Find and reclaim the orphan dev servers and watchers an agent session left behind.

hasBundlePatch

dsh-reaper

Reclaim the ports your agent forgot to give back.

An agent starts vite, next dev, a watcher, a tunnel. The turn ends. The session ends. The process does not — it keeps holding 5173, and the next run dies with EADDRINUSE while you go hunting through Task Manager for a node.exe you cannot identify.

dsh-reaper inventories every listening endpoint on the machine, attributes each holder to this session, shows you exactly what it would kill, and only then — when you say confirm: true — reclaims the ports.

$ /reap

dsh-reaper · win32 · 2026-10-16T10:57:26.626Z
workspace: E:\work\shop-frontend

51 listening endpoint(s) · 432 process(es) · 3 reclaimable

 5173  tcp  agent-spawned  pid   8899   18m  node.exe
      node E:\work\shop-frontend\node_modules\.bin\vite --host
 3001  tcp  workspace      pid   9120   42m  node.exe
      node E:\work\shop-frontend\server.js
 3306  tcp  system         pid   9168  9h29m  mysqld.exe
      ↳ port 3306 is a well-known service port
19387  tcp  protected      pid  11664   2h9m  DeepSeek Harness.exe
      ↳ holds the harness process tree

Why it is not just "kill by port"

Port tools tell you what holds a port. The hard part is deciding whether you are allowed to kill it, and that answer depends on facts a port number does not carry:

  • Did this process descend from the harness that is running the scan? Killing it takes down the session.
  • Is it the machine's own infrastructure — mysqld on 3306, nginx on 80?
  • Is it a leftover dev server with no session tie at all?
  • Is it something the user explicitly said to leave alone?

dsh-reaper answers that per endpoint and grades the result, so a --all sweep can be safe:

verdictmeaningauto-selected by all: true
agent-spawneddescends from the harness host process✅
workspacecommand line names the current workspace✅
dev-serverlooks like a dev server, watcher or tunnel❌
unattributedlistening, but nothing ties it to this session❌
systemOS process, or holds a well-known service port❌
protectedmatched neverKill / protectPorts, or holds the harness tree❌

Two rules make that table trustworthy:

  1. The harness never kills itself. The scan walks up from its own pid and refuses the whole ancestor chain, plus the process tree it is running inside.
  2. Infrastructure is not "unattributed". A holder of a well-known service port is graded system — the same hands-off grade as an OS process — so all: true never reaches it, and its note says left alone rather than hinting at an override.

Safety properties

Reaping is destructive, so the defaults are conservative and the refusals are absolute:

  • Nothing is signalled without confirm: true. The default call computes the plan and returns it.
  • The plan is the full descendant closure. Killing an npm run dev shim without its child leaves the port held — the exact failure this plugin exists to prevent. Descendants are ordered deepest-first so children die before their parents.
  • Refusals cannot be overridden by naming a pid. The harness process tree, pid 0–4, neverKill matches and protectPorts holders are refused even when passed explicitly, with the reason reported.
  • SIGTERM first, SIGKILL only if you ask. force: true escalates, and even then survivors are reported rather than hidden.
  • The result is verified, not assumed. After signalling, the plugin re-probes each freed port and reports ports confirmed free or ports still held.

Install

dsh plugin add https://github.com/11111353535/dsh-reaper

From a checkout instead of a git host, pass the absolute path:

dsh plugin add /absolute/path/to/dsh-reaper

The package declares no dsh-* peer dependency on purpose: it imports only node:* plus @deepseek-ai/dsh-tools, which the harness resolves from its own installation. Nothing is bundled that could shadow the host's copy.

To tune it per profile, add a config block to the row the installer inserted in ~/.dsh/profiles/<profile>/cordis.patch.yml:

- insert:
    - id: reaper
      name: 'dsh-reaper'
      config:
        neverKill: ['my-precious-daemon']
        protectPorts: [80, 443, 19387]
        includeUdp: false
        graceMs: 3000
        scanTimeoutMs: 20000
keydefaultmeaning
neverKill[]Process-name or command-line substrings that must never be signalled.
protectPorts[]Ports whose holder is refused even when named explicitly. The harness's own web port is added automatically.
includeUdpfalseAlso enumerate UDP endpoints. Off by default: dev servers are TCP.
graceMs3000How long SIGTERM gets before the process is reported as surviving.
scanTimeoutMs20000Wall-clock ceiling for one system enumeration.

Tools

reaper_scan

Read-only inventory. Signals nothing. Grades every listening endpoint and returns the full scan.

argumenttypemeaning
includeUdpbooleanAlso enumerate UDP endpoints.
workspacestringWorkspace root used for attribution. Defaults to the session workspace.

reaper_reap

Compute a plan and, only with confirm: true, execute it.

argumenttypemeaning
pidsinteger[]Explicit root pids. Their descendants are included automatically.
portsinteger[]Reap whatever holds these ports.
allbooleanAlso select every endpoint confidently attributable to this session (agent-spawned and workspace only).
forcebooleanEscalate to SIGKILL for processes that ignore SIGTERM.
confirmbooleanActually signal the plan. Defaults to false.

reaper_free_port

Reclaim one specific port. If the port is already free it says so and does nothing; if the holder cannot be attributed or is protected, it reports why instead of guessing.

argumenttypemeaning
portinteger (required)The TCP port to reclaim.
forcebooleanEscalate to SIGKILL if SIGTERM is ignored.
confirmbooleanActually signal the holder. Defaults to false.

Slash command

/reap                  # inventory
/reap --all            # preview everything confidently attributable to this session
/reap --all --confirm  # and actually do it
/reap 5173             # preview reclaiming one port
/reap 5173 3001 --confirm --force

How the scan works

platformendpointsprocess table
WindowsGet-NetTCPConnection -State Listen (+ Get-NetUDPEndpoint)Get-CimInstance Win32_Process
Windows (fallback)netstat -anotasklist /FO CSV /NH
Linuxss -H -ltnpps -eo pid=,ppid=,comm=,etimes=,args=
macOSlsof -nP -iTCP -sTCP:LISTEN -Fpcnps

Every probe is best-effort: a missing binary or a failed command degrades that one source and is reported in degraded: ... at the end of the scan. A scan that falls back to netstat still works — it just loses command lines, and therefore attribution gets weaker, which the report tells you.

One process listening on both :: and 0.0.0.0 is one problem, not two: dual-stack bindings are collapsed into a single row per protocol/port/pid, with every address kept in addresses.

Development

npm test          # 42 unit tests, no harness needed
npm run test:live # a real read-only scan of this machine
npm run setup:deps

lib/ is plain ESM JavaScript with no build step, and the unit tests cover the parsers against recorded fixtures — Windows and BSD netstat tables, ss, lsof, ps, tasklist, the classifier, the plan builder, and the renderers. test:live covers what fixtures cannot: that the real enumeration works on the host you are on. It signals nothing.

setup:deps links the three host packages lib/ imports (cordis, dsh-tools, schemastery) into a local node_modules so a bare checkout can run the tests. Set DSH_HOST_NODE_MODULES if the harness is not in a standard location.

License

MIT

Comments

Loading…

Similar plugins

dsh-plugin-watchdog

by davidgereb

Restart your ongoing agent sessions once on server restart in DeepSeek Harness.

Manifest valid

★ 0

MIT

JavaScript

Aug 15, 2026

dsh plugin --profile web add dsh-plugin-watchdog

by 1622352030

Session-stall watchdog for DeepSeek Harness: releases a hung turn in place instead of restarting the app.

Tools & CapabilitiesDevelopment & InfrastructureManifest valid

★ 0

MIT

JavaScript

Sep 24, 2026

dsh plugin --profile web add dsh-session-rescue

by flandre2233

Auto-resumes DSH turns interrupted by a host restart

Tools & CapabilitiesDevelopment & InfrastructureSessions & MessagesManifest valid

★ 1

↓ 352/wk

MIT

JavaScript

Sep 24, 2026

dsh plugin --profile web add dsh-recovery-resume

by squirrel20

Unattended scheduled jobs for the DeepSeek Harness (dsh): agent/command tasks on cron schedules

Workflow & AutomationManifest valid

★ 4

↓ 87/wk

MIT

JavaScript

Sep 21, 2026

dsh plugin --profile web add dsh-cron

by wjackiedev

Archived-session manager for the DeepSeek Harness Web GUI — restore and permanently delete session logs.

Development & InfrastructureTerminal & ClientsManifest valid

★ 1

↓ 3.2k/wk

MIT

JavaScript

Sep 20, 2026

dsh plugin --profile web add dsh-session-manager

by andrepontesmelo

DSH plugin: spawns one live session per ready Wayfinder task and draws the dependency map in the chat GUI

Terminal & ClientsSessions & MessagesManifest valid

★ 0

MIT

JavaScript

Sep 29, 2026

dsh plugin --profile web add dsh-wayfinder-ui