dsh-plugin-ssh-remote
DiscoveredMulti-host SSH toolbelt for DeepSeek Harness: server registry, /ssh, run/put/get tools, destructive-command guard, secret redaction, audit log
SSH Remote — a DeepSeek Harness plugin
English | Русский
Operate any number of VPS servers over SSH from inside DeepSeek Harness:
a server registry, the /ssh command, ssh_run / ssh_put / ssh_get, four
read-only navigation tools, a destructive-command guard, secret redaction, and an
action log.
Authentication is by key where one is configured, and by a stored password otherwise. The plugin ships no server addresses: you add your own, so one installation works with any number of machines.
Status: 0.1.0, tested against Harness
0.2.1-rc.3and allowed on>=0.2.1-rc.3 <0.3.0(declared inengines.dsh). DSH is a developer preview and breaks compatibility between releases, so pin the Harness version you run.
Published on npm as dsh-plugin-ssh-remote.
Why this one
Most SSH tooling for an agent makes the whole session remote: the shell, the file tools and the editor are replaced by their remote counterparts, and you pick one host per workspace. This plugin is the other shape:
- Several hosts at once.
ssh_runwithhost: "web1", thenhost: "db1", in the same session. Localbash/read/editkeep working on local files. - Zero dependencies. It drives the system
ssh/scpinstead of reimplementing the protocol, so~/.ssh/config,known_hostsand the agent all behave exactly as they do in a terminal. - Guardrails on by default. Catastrophic commands never run, irreversible ones ask first, secrets are cut from output before the model sees it, and every call lands in an audit log.
- Small enough to read. Six source files, no client bundle, no build step.
If you want a full remote workspace — remote file editing, a terminal panel, LSP —
use dsh-ssh,
dsh-remote-ssh or
dsh-ssh-ops instead. They are
larger and solve a different problem.
Install
# from npm
dsh plugin --profile web add dsh-plugin-ssh-remote
# from a local checkout, for development
plugin_manager action=install_bundle target=<absolute path to this folder>
It needs Node >= 22 and DSH >= 0.2.1-rc.3. The package declares engines.dsh,
so dsh plugin add refuses a host outside that range instead of installing
half-way. There is nothing else to install: the plugin drives the ssh and
scp binaries already on the machine, so it pulls in no runtime dependencies.
Then add servers with /ssh sync (import from ~/.ssh/config) or /ssh add.
Quick start
/ssh add # add a server by hand
/ssh pass web1 <pass> # only if no key is installed on that server yet
/ssh test web1 # check the connection
Then just ask the agent: "check disk usage on web1", "tail the nginx error log on web1", "copy ./dist.tar.gz to web1 and unpack it in /srv/app".
Tools
| Tool | What it does | Limits |
|---|---|---|
ssh_run | Run a command, return stdout, stderr and exit code. | Command policy, timeoutMs, tty, detached, logPath. |
ssh_read | Read a file by line window. | offset (1-based), limit ≤ 2000; says when lines continue. |
ssh_ls | List a directory. | 200 entries, long: false for names only. |
ssh_grep | Search file contents. | glob, maxMatches ≤ 1000, binary files skipped. |
ssh_glob | Find files by name. | maxResults ≤ 2000, pattern as in find -name. |
ssh_put / ssh_get | Upload or download one file. | Local path is not sandboxed (see Limits). |
ssh_hosts / ssh_host_add / ssh_host_remove | Manage the registry. | Every change asks for confirmation first. |
/ssh commands
/ssh # list servers; pick one from the list
/ssh web1 # test a server (does NOT change the default)
/ssh default web1 # make a server the default
/ssh status # what is allowed, how login works, which server is default
/ssh add # add a server manually
/ssh sync # import from ~/.ssh/config
/ssh pass web1 <pass> # store a password (only for a server without a key)
/ssh nopass web1 # forget the password
/ssh lock web1 # block every operation with this server
/ssh unlock web1 # allow it again
/ssh remove web1 # drop it from the registry
Configuration
profile-patch-snippet.yml restates every key: a patch replaces the row's
whole config instead of merging, so a profile-level patch must list every key
it wants to keep.
| Key | Default | Meaning |
|---|---|---|
registryPath | $DSH_HOME/ssh-remote-hosts.json | Server registry. |
secretsPath | $DSH_HOME/ssh-remote-secrets.json | Saved passwords. |
auditLogPath | $DSH_HOME/ssh-remote-audit.jsonl | Action log. |
askpassDir | $DSH_HOME/ssh-remote-askpass | Scratch directory for the password helper. |
sshConfigPath | ~/.ssh/config | Source for /ssh sync. |
allowRawHosts | false | Accept an address that is not in the registry (turns the allowlist off). |
sshPath / scpPath | platform default | OpenSSH clients; on Windows %SystemRoot%\System32\OpenSSH\. |
connectTimeoutMs | 10000 | Connection timeout. |
defaultTimeoutMs | 120000 | Default command deadline. |
maxTimeoutMs | 1800000 | Ceiling any timeoutMs is clamped to. |
maxOutputChars | 60000 | Per-stream output ceiling; head and tail are kept. |
commandPolicy | standard | standard asks about irreversible commands; off stops asking (catastrophic ones are still refused). |
multiplex | false | OpenSSH connection sharing; needs a POSIX local endpoint. |
Safety model
- The registry is the allowlist. A connection needs a registered name.
allowRawHostsis off by default, and even when on, an address is never substituted silently. - Host-key checking is never relaxed. Always
StrictHostKeyChecking=yes, including in password mode; a changed key stops the command and asks you to verify the fingerprint yourself. - No interactive prompts. Key auth uses
BatchMode=yes; password auth allows exactly one attempt, so a command can never hang waiting for input. - Catastrophic commands are refused before the process starts.
rm -rf /,mkfs,ddto a device,shutdownand similar are blocked even when wrapped insudo,nohuporsh -c. Irreversible but legitimate commands (rm -rfon an absolute path,apt purge,docker system prune,DROP DATABASE) ask once, with the command, the server and the working directory shown. No answerer means no execution. - Secrets are cut before the model sees them. Private-key blocks, AWS keys,
sk-…, JWTs,password=/token=/api_key=,Authorization: Bearer …and credentials in URLs are replaced withredacted:<kind>, and the report says how many were removed. - Every call is logged. One JSON line per client call in
ssh-remote-audit.jsonl, command already redacted, rotated at 10 MB.
The command policy reads text, it does not evaluate it. rm -rf $(echo /),
find / -delete, or a script uploaded with ssh_put and run afterwards are not
caught. The real boundary is a dedicated server user without sudo; keep
root for manual work.
Limits
- No multiplexing on Windows. Each call is a new connection, which shows up as
latency.
multiplex: trueworks only on a POSIX local endpoint. - Local paths are not sandboxed.
ssh_putcan send any file your user can read. Every transfer is logged, but the local sandbox does not apply. - No terminal, no remote editing, no LSP. These are tools, not a workspace. Use one of the plugins linked above for that.
- No ProxyJump. The registry has no jump-chain support; put the hops in
~/.ssh/configand sync, or connect to the bastion and hop manually. - The registry is per profile. One file per
$DSH_HOME; concurrent writes are serialized inside the plugin, but a manual edit during a run is picked up on the next operation. /ssh syncdoes not expandInclude,Matchor*patterns. Such blocks are listed as skipped rather than guessed.- Editing the installed code needs a Harness restart. Node caches ES modules by URL, so toggling the bundle does not reload changed code.
- The
/sshinterface speaks Russian. Tool descriptions — what the model reads — are English, but the/sshoutput, prompts and picker labels are Russian. An English locale is the next planned change.
Tests
npm install # one dev dependency, @deepseek-ai/schemastery, for the tests
npm test # both suites
node test-args.mjs # argv, failures, command policy, redaction, registry,
# ssh-config parser, passwords, ACL, audit, atomic writes
node test-host.mjs # tools, policy gate, confirmation, /ssh, guard
No network, no real server: the host half runs against a fake subprocess.
node test-live.mjs <name> is the optional live checklist (40 checks) against a
registered server.
License
MIT. Not affiliated with DeepSeek AI.
Comments
Loading…
Similar plugins
SSH session manager for DeepSeek Harness: saved profiles, agent ssh_run, interactive terminals, and SFTP with secrets kept in the DSH credential center.
★ 1
MIT
JavaScript
dsh plugin --profile web add dsh-remote-ssh-toolsby hcyinnn
SSH tools plugin for DeepSeek Harness (dsh): run remote commands and transfer files via OpenSSH. dsh 插件——让 Agent 通过 SSH 在远程主机执行命令、上传/下载文件。
★ 0
MIT
TypeScript
Sep 1, 2026
dsh plugin --profile web add dsh-tool-sshby hehehe1234567894
DeepSeek Harness (DSH) SSH 远程工作插件 — 纯远程模式:多机管理、工作区选择、远程文件读写工具
★ 0
JavaScript
Sep 1, 2026
dsh plugin --profile web add deepseek-harness-sshby CrazyShout
SSH remote workspaces for DeepSeek Harness: browse/read/write remote files, run remote commands, with connection status dots.
★ 13
↓ 75/wk
MIT
TypeScript
Oct 25, 2026
dsh plugin --profile web add dsh-ssh-remoteby hoshinoick811
MobaXterm-style SSH/SFTP tool plugin for DeepSeek Harness (DSH): saved connection profiles, persistent multiplexed sessions, remote command execution, SFTP file transfer, and a web GUI console with fi
★ 4
MIT
JavaScript
Sep 6, 2026
dsh plugin --profile web add dsh-tool-sshby pipipigu
Unified, non-intrusive SSH control center for DeepSeek Harness (DSH)
★ 0
Apache-2.0
TypeScript
Sep 2, 2026
dsh plugin --profile web add @dsh-external/dsh-ssh-control