DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Windows Remote Ssh — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
W

dsh-windows-remote-ssh

Windows Remote Ssh

Control a remote Windows desktop over SSH from DeepSeek Harness: app_list/app_launch, screen_shot, screen_read (UI Automation), and click/type/scroll/key — every mutating action gated by approval, delivered without stealing foreground focus, with stale-observation rejection and process-identity chec

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:pureexe/dsh-windows-remote-ssh#87e20e711dddb87e11790728389995f37cb71047
READMECompatibilityVersions

Description

Control a remote Windows desktop over SSH from DeepSeek Harness: app_list/app_launch, screen_shot, screen_read (UI Automation), and click/type/scroll/key — every mutating action gated by approval, delivered without stealing foreground focus, with stale-observation rejection and process-identity checks. No pre-installed agent required on the target: a single PowerShell helper is bootstrapped over SFTP on first use.

Compatibility and provenance

Windows Remote Ssh is published as dsh-windows-remote-ssh and currently resolves to version 0.1.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
any
Release source
github
Registry updated
9/12/2026

Versions

0.1.0stable
9/12/2026

Related plugins

Loading related plugins…

Latest
0.1.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
any
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/14/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in productivity-workflow.

Acp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseClient Ui Task Board@linxin666/dsh-client-ui-task-boardHost-authoritative task board for the DSH Web GUI with real session execution, Host cron scheduling, and optional cross-platform idle-sleep protection; mounted without DSH source changes.Web All@linxin666/dsh-web-allDSH Web UI 全家桶聚合插件:一键安装全部功能插件(task-board / git-graph / pet / remote-web-ui / web-ui-settings / skin-center / community-plugins / compat shim)。compat 桥接层已并入本包(src/client),无需独立 compat npm 包。Agent Teams@nanmicoder/dsh-agent-teamsAgentTeams for DeepSeek Harness: multi-agent team collaboration (captain, members, tasks with dependencies, messaging) driven by natural language, with a tree monitor in the web GUI

README

dsh-windows-remote-ssh

Control a remote Windows desktop over SSH from DeepSeek Harness. Same tool surface and safety model as the local dsh-click plugin — screenshots, UI Automation reads, click/type/scroll/key, app listing/launch — but every action runs on a Windows box reached over plain SSH instead of a local subprocess. The harness itself can run from Linux, macOS, or Windows; only the target needs to be Windows.

How it works

  • No pre-installed agent on the target. The only thing this plugin assumes on the remote host is a working SSH server (Win32-OpenSSH, built into modern Windows). Everything else — window enumeration, UI Automation, screenshots, input delivery — is done by a single PowerShell script this package ships (native/win32/dsh-windows-remote-ssh-helper.ps1), staged onto the target over SFTP the first time it's needed and re-staged automatically if it ever changes (content-hash compared against a marker file). It uses only classes already in stock Windows (.NET's System.Windows.Automation, System.Drawing, and user32.dll/kernel32.dll P/Invoke) — no Python, no third-party modules, no separate installer.
  • File-based request/response, not stdin/stdout. Each call writes a small JSON request file over SFTP, runs the helper once, and reads a JSON response file back over SFTP. Moving bytes through SFTP rather than piping them through the SSH exec channel's stdin/stdout sidesteps Windows console code-page and UTF-8/UTF-16 encoding pitfalls entirely.
  • Runs in the user's real desktop session, not a hidden one. This is the detail that makes GUI automation over plain SSH actually work: Win32-OpenSSH runs a normal ssh user@host command in a non-interactive Session 0 / window station, completely isolated from the interactive desktop — from there, EnumWindows, UI Automation, and screen capture all come back empty even though the process runs fine. So instead of executing the helper directly, this plugin schedules it as a one-shot Scheduled Task bound to the connected user with the "only when logged on" flag (attaching it to their interactive session), triggers it immediately, and polls for the response file — the standard workaround for driving a Windows GUI over SSH. See Requirements below for what this means for the target account. The scheduled process is launched through a tiny VBScript wrapper (WScript.Shell.Run with a hidden window style), not powershell.exe -WindowStyle Hidden directly — that flag alone still lets a console flash on screen for a moment before it takes effect. Verified empirically: zero window sightings across repeated calls while continuously polling for one.
  • Never steals the user's mouse/keyboard focus. Actions prefer UI Automation invoke/value/scroll patterns; when an element exposes none, they fall back to posted window messages (WM_LBUTTONDOWN/WM_KEYDOWN/etc.) rather than moving the real cursor or bringing the window to the foreground. Bringing a window to the foreground is available only as an explicit, config-gated fallback (focusFallback: 'allow', default off).

Requirements

  • The target account must be a local administrator and must already be logged on interactively (an unlocked console/RDP session) when a tool call runs — the Scheduled Task attaches to that existing session; it does not create one. If nobody is logged on, calls fail with a clear SCHEDULE_FAILED / timeout error rather than hanging.
  • Win32-OpenSSH (sshd) running and reachable on the target.
  • Node.js ^22.19.0 || >=24.0.0 wherever the harness itself runs.

Installation

dsh plugin --profile web add "github:pureexe/dsh-windows-remote-ssh#main"

Then mount it with a profile patch (see cordis.patch.yml for every field, or override at bundle level):

- insert:
    - id: dsh-windows-remote-ssh
      config:
        ssh:
          host: <ip>
          user: <username>
          # Prefer a private key over a password where you can:
          # privateKeyPath: /path/to/id_ed25519
        autoApproveWindows: ['^Notepad']

Connection details may also come from environment variables instead of the profile (handy for CI, and for keeping credentials out of a checked-in patch): SSH_HOST, SSH_PORT (default 22), SSH_USER, SSH_PASSWORD, SSH_KEY_PATH, SSH_KEY_PASSPHRASE. Explicit config.ssh.* fields win over the matching env var when both are set.

Supplying the SSH target: two options

There are two ways to tell this plugin which Windows machine to control, and they can be mixed — a configured default, plus per-call overrides for the odd exception.

1. Configure ssh.host/ssh.user/ssh.password (or ssh.privateKeyPath) once, as shown above — recommended. The target and its credentials never appear in the model's context and never get written to the harness's own tool-call session logs. Every tool call just omits ssh entirely and uses this default. This is the right choice for a fixed, known target (your own desktop, a lab VM, a CI runner).

2. Leave config.ssh unset and let the model supply a target per call. Every entry-point tool (screen_shot, screen_read, app_list, app_launch) accepts an optional ssh argument — host, port, user, and either password or privateKeyPath — that the model fills in from whatever you tell it in chat ("connect to 10.0.0.12 as admin, password hunter2"). No config edit needed, which is handy when the target varies conversation to conversation or isn't known ahead of time. The tradeoff: that host/user/password is now part of the conversation — it flows through the model's context like any other tool argument and gets captured by the harness's own tool-call logging, the same way any other tool call's arguments are. If you can, prefer option 1, or at least a privateKeyPath in chat instead of a raw password, so the secret itself lives on disk rather than in the transcript.

If host/user are given (in chat, or in config.ssh) but neither password nor privateKeyPath is, the plugin falls back to the default SSH identity on the machine running the harness — ~/.ssh/id_ed25519, id_ecdsa, then id_rsa, the same lookup order the plain ssh CLI uses — before failing with "requires either a password or a privateKeyPath". This is what lets "connect to 10.0.0.12 as pakkapon" work with no credential in the call at all, as long as that machine's default key is already authorized on the target.

click/type/scroll/key never need an ssh argument either way — they replay against whatever host the basedOn observation they cite came from, so a single conversation can safely juggle more than one remote machine without an action ever landing on the wrong one.

With no config.ssh default and no per-call ssh argument, a call fails immediately with a clear error asking for one or the other — it never silently guesses or hangs.

Tools

ToolRead-onlyApprovalPurpose
screen_shot✅—Capture a window/screen as an image attachment (or text-only description with imageMode: 'text')
screen_read✅—UI Automation accessibility tree + pixel-location hints
app_list✅—Enumerate running applications and their windows
clickYesClick an element (by id) or a coordinate
typeYesType text into an editable element, with rollback on failure
scrollYesScroll an element or the window
keyYesSend a key combination (e.g. Ctrl+S)
app_launchYesLaunch an application by name or path

screen_shot/screen_read/app_list/app_launch each accept an optional ssh argument (see Supplying the SSH target above) for deployments with no configured default. click/type/scroll/key never take one — they replay against whichever host their cited basedOn observation came from.

Every mutating action (click/type/scroll/key/app_launch) must cite a basedOn observation returned by screen_shot/screen_read. Before acting, the plugin re-observes the window over SSH and refuses if the window identity, its accessibility tree, or (when staleCheckPixels is on) its pixels changed since that observation — so the model can't act on a screen it no longer has an accurate picture of. It also captures the target process's identity before and after the action and refuses if it changed mid-flight.

Configuration

All fields live under one Config object (Schemastery-validated; invalid values fail the profile load loudly, not at call time). See the fully commented cordis.patch.yml for the complete list and defaults: ssh.*, requireApproval, autoApproveWindows, auditSessionEvents, focusFallback, imageMode, connectTimeoutMs, helperTimeoutMs, maxScreenshotSide, staleCheckPixels, maxObservationAgeMs, maxCachedObservations, maxElements, maxTreeDepth, maxTextLength, rollbackEnabled.

Development

npm install
npm run typecheck
npm run build          # tsdown -> lib/
npm run test:unit      # pure logic, no network
npm run test:e2e       # live, against a real remote Windows host - see below

Running the live integration suite

SSH_HOST=<ip> SSH_USER=<username> SSH_PASSWORD=<password> \
  npm run test:e2e

The suite is skipped (not failed) when SSH_HOST/SSH_USER and a credential aren't set. It exercises the SSH + PowerShell-helper path directly against a real target:

  1. Establishes the SSH connection and enumerates windows.
  2. Lists running applications and launches notepad.exe.
  3. Reads the UI Automation element tree of the new Notepad window.
  4. Types text into Notepad's edit control.
  5. Captures a screenshot of the window.
  6. Connects with no configured default at all, passing host/user/ password directly to resolveSshTarget — the same path a model-supplied per-call ssh argument takes.

It cleans up the Notepad process it launches in afterAll.

Design notes / why not paramiko or asyncssh

The reference plugin format for DeepSeek Harness (see dsh-click) is a TypeScript module running inside the harness's own Node/cordis process — there is no Python runtime in that picture to host paramiko/asyncssh. This plugin uses ssh2, the equivalent mature, widely-used SSH2 client for Node: persistent connections, exec channels, and SFTP, all from the same process the rest of the plugin runs in.

Safety boundaries

  1. Freshness — every action cites a basedOn observation; identity, tree, and (optionally) pixel-hash comparison refuse a stale action.
  2. Approval — mutating actions request approval through @deepseek-ai/dsh-user-approval by default; autoApproveWindows regexes skip the ask for matched windows but remain freshness-checked and audited.
  3. Process identity — PID and executable path are verified immediately before and after every action.
  4. Audit — every observation and action is logged as dsh-windows-remote-ssh/observed / dsh-windows-remote-ssh/action session events (sanitized: credential-shaped text is redacted before it ever reaches a log or the model).

License

MIT