Introduction¶
There are two common approaches to letting models operate remote servers: deploying an agent on the target machine, or giving the agent full shell permissions. The former requires maintaining an extra resident process, while the latter implies that a high-risk command might run on a production machine without any confirmation.
dsh-remote-server offers another combination: it installs nothing on the server, executes commands via your existing SSH client, but every command must pass through a fixed-order approval pipeline—anything not explicitly allowed falls to humans, ending with a refusal if humans are unreachable.
What is this¶
dsh-remote-server is a plugin for DeepSeek Harness (hereinafter DSH) by MRZHUH, licensed under MIT, current version 0.1.1. The philosophy of DSH is “everything is a plugin”; this plugin adds an @ mention capability to the session: input @ to list registered servers, select one to reference along with the message, and the model explicitly writes the target server on every command.
The official one-sentence positioning: In DSH sessions, mention servers via @, execute commands via SSH on them, and place all commands behind a two-tier approval threshold in a fail-closed manner.
Core Features¶
Install Nothing on the Server¶
This is the core design of the plugin and deserves its own section:
- No agent, no daemon, and no inbound ports on the target machine. The plugin drives your own SSH client, so your existing
~/.ssh/configcontinues to take effect—jump hosts, agent forwarding, andknown_hostsrequire no changes. - Authentication is key-only. The
identityFileis simply the path handed to the SSH client; the plugin never reads, copies, or stores key material. Thepasswordfield is rejected rather than stored. - The machine running
dshmust have an OpenSSH client. Ifsshis missing, the plugin will fail during loading and provide the installation command for the corresponding platform, rather than leaving the system in a broken state.
Register Servers¶
There are two paths:
- Add in Settings -> Servers -> Add a server;
- Or write to the
remote-serverssettings namespace (YAML).
remote-servers:
servers:
- alias: web-01
host: 10.0.0.11
user: ops
tags: [prod, web]
description: edge tier - start here
- alias: db-01
host: db-01.internal.example
port: 2222
identityFile: ~/.ssh/id_ed25519_db
alias is the name you type after @ and cannot contain whitespace; configuration items include alias, host, user, tags, description, as well as optional port and identityFile.
You can also import existing configurations: the import function reads ~/.ssh/config (or a path you specify), lists hosts for you to select and register; during a re-scan, it will prompt which hosts are already registered rather than listing disabled duplicates.
If a server rejects your key, the server page will provide a ssh-copy-id command with your username, host, and port pre-filled.
Two Tools and Server Info Page¶
The plugin exposes two tools to the model:
| Tool | Function |
|---|---|
remote_exec |
Run a command on a single registered server, returning stdout, stderr, and exit code |
remote_server_info |
Read collected server information, or re-probe the machine |
Each server has a dedicated info page: reachability, the description you wrote, and the machine’s own data—hostname, OS, CPU, memory, disk, uptime—all collected in a single SSH round trip. Unchecked servers will truthfully display “unchecked” rather than placeholder numbers. The page title also displays the version of the installed plugin package.
Approval Pipeline¶
Every command must pass through a fixed-order pipeline, and the order itself is part of the design:
- Unregistered alias: Directly reject, do not initiate a connection.
- Full access: Under the DSH
danger-full-accessandneverpermission combination, commands for registered servers no longer prompt twice. - High-risk rule set: A deterministic match triggers a forced human decision; the model classifier cannot overturn this.
alwaysAsk: Once set, all commands from this point onward are handed to humans.- Read-only allowlist: Normal calls matching configured prefixes execute immediately.
- Model classifier: Answer
autoorhumanfor the remaining commands. - Human approval: Ask via the DSH approval channel.
Nine high-risk categories force a human decision: recursive deletion, disk and filesystem writes, shutdown and reboot, service stop and restart, user and permission changes, package installation and uninstallation, writing to system paths, privilege escalation, and reading credentials or key paths.
The meaning of fail closed is: any command that cannot be given explicit permission falls to humans; classifier timeout, errors, or vague answers do not count as a pass—the rejection branch is the default path in the code, not the error handling branch.
Enabling Model Auto-Approval¶
Auto-approval is off by default until you specify the model in the configuration— the plugin cannot predict which provider you have deployed in your combination. In the profile’s cordis.patch.yml:
- id: remote-server
config:
classifier:
provider: deepseek
model: deepseek-chat
The provider and model must be set together or not at all; setting only one will fail on load. This step does not involve an API key: the plugin calls via ctx.llm, and credentials are parsed by the harness; the plugin itself touches no keys.
Installation and Enablement¶
Install from npm:
dsh plugin --profile web add dsh-remote-server
Then start dsh web as usual (equivalent to dsh --profile web). --profile specifies which combination to load: a profile is a set of loadable plugins under $DSH_HOME/profiles/, allowing daily environments and clean environments to coexist; web is the set the quickstart defaults to. The published tarball is built, requiring no manual edits or extra licenses.
If the dsh command is not in your PATH, you can run it using npx or install it globally:
npx @deepseek-ai/dsh web
# or
npm install -g @deepseek-ai/dsh
Note to keep the full package name scope: writing just npx dsh will pull an unrelated package and report could not determine executable to run.
Install from source:
dsh plugin --profile web add github:MRZHUH/dsh-remote-server
A git install pulls the source code rather than the build artifact; pnpm needs to run the package’s prepare script to compile it. The first add will fail and print the configuration key to add to pnpm-workspace.yaml (in older pnpm versions this key is called allowBuilds):
onlyBuiltDependencies:
- dsh-remote-server
Allowing this line means allowing the package to execute code on your machine during installation. It is recommended to also use github:MRZHUH/dsh-remote-server#<sha> to pin the commit, avoiding subsequent silent changes to what runs. Installing from npm does not require this permission because the released tarball is already built.
Missing peer warnings (@deepseek-ai/dsh-*, @deepseek-ai/cordis, react) that appear during installation are expected behavior: these peers are provided by the dsh installation itself at runtime and are not in the profile’s node_modules, so the plugin works normally.
Uninstalling only requires one command, and registered servers are preserved:
dsh plugin --profile web remove dsh-remote-server
Configuration Items¶
Two verified configuration items: connectTimeoutMs defaults to 10000, constraining the connection establishment process; execTimeoutMs defaults to 120000. The configuration table in the README is truncated after this; for other configuration items, refer to the original repository text.
Typical Usage¶
After installing the plugin and registering a server, the flow is as follows:
- Input
@in the session and select a server from the list; - Speak your requirements in natural language, referencing them passed along with the message; the model explicitly writes the target server on every command;
- Read-only commands execute immediately; any commands that change state will stop and ask you first.
If you want the classifier to automatically approve some commands, configure the provider and model in cordis.patch.yml as described above; not configuring it keeps the default behavior of requiring human confirmation for all commands.
Applicable Scenarios and Notes¶
Suitable scenarios:
- Developers and operations personnel who already have an SSH system and
~/.ssh/configbut want the model to run remote commands without introducing an agent on the target machine; - Environments that require the default strategy of “read commands execute immediately, state-changing commands must be confirmed by a human”.
A few notes:
- The plugin runs with the permissions of the current dsh process. Check the source code and license before installing (this project is MIT). Installing from source is especially important to understand: allowing the
preparescript is equivalent to allowing the package to execute code on your machine during installation; it is recommended to pin the commit. - The machine running dsh must have an OpenSSH client; if it is missing, the plugin will fail directly upon loading.
- Regarding the release process: GitHub Release tags matching
v<package.json version>trigger.github/workflows/publish.yml, publishing via npm trusted publishing with provenance, and do not use theNPM_TOKENsecret.
Conclusion¶
The value of dsh-remote-server lies in changing the default path of “letting the model touch the server” from execute to reject: no agent installation, no key storage, read commands go through the allowlist and execute immediately, nine high-risk categories force human decision, and the classifier defers to humans when uncertain. If the model and SSH are already inseparable in your workflow, try the steps above.
- Directory page: https://www.skillhub.cn/plugins/MRZHUH/dsh-remote-server
- GitHub: https://github.com/MRZHUH/dsh-remote-server
Note: skillhub.cn is an independent community plugin directory and has no official affiliation with DeepSeek / Hypersphere.