不给模型乱来的机会:命令不走模型不花 token,AI 的每次改动按风险分级确认,改文件先备份、改防火墙先设连通性保险。
Translation pending
Developer toolsJavaScript · ShellGitHub @AIcivilizationOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
VPS & SSH manager plugin for DeepSeek Harness (DSH): zero-token /vps- commands, an in-conversation web terminal, and AI server ops with risk-tiered confirmation. 在 DSH 里像 SSH 一样无感地用 VPS:零 token 命令、对话内终端、AI 分级确认运维。
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗Use your VPS inside DeepSeek Harness as seamlessly as over SSH: curated zero-token commands, plus the AI in the conversation can operate the server.
在 DSH 中和 SSH 一样无感地使用 VPS,除了精选的部分常用命令之外,使用时还能让对话中的大模型对 VPS 进行操作。
English · 简体中文
Install: search for dsh-vps-manager in the DSH plugin market and click install; or quit DSH completely and run the line below in a terminal (for command-line dsh web, replace desktop with web; see Install). Then open DSH and add a machine under Settings → VPS Manager.
dsh plugin --profile desktop add dsh-vps-manager
Manage your VPS from DeepSeek Harness (DSH): check server status with commands that skip the model and cost no tokens, tell the AI what to do and let it work on the server, see how the server is doing on one page, open a real terminal or move files in the conversation when you want to do it yourself, and handle common installs and maintenance with recipes.
It works with DSH on Windows, macOS and Linux, in both DSH Desktop and command-line dsh web, and several computers (home, office) can manage the same server at the same time.
You enter the password once when adding a machine; from then on everything uses SSH key login and shares one execution mechanism: operations that change things run as remote tasks and keep going if the connection drops; changes on the same machine run one at a time; config files are backed up before they are edited; an automatic restore is set up on the server before firewall or SSH changes; and every run is written to an audit log.
Want DSH itself running on your VPS? See the sister project dsh-vps: one command on the VPS installs stock DSH behind a login page with automatic HTTPS, reachable from any browser, with settings, API keys and the plugin market all working, and new DSH releases upgraded with one click in the page. The two work together: install this plugin in the DSH on your VPS and manage that server right from the conversation.
| Capability | What it does |
|---|---|
| Zero-token commands | 22 /vps- commands: check status, install software, reboot and wait for the machine to come back, without touching the model |
| VPS mode | One click in the conversation header and that conversation operates the server; each conversation has its own binding, so one window can work on the server while another keeps working on local code |
| Real connection state | Header squares: grey not selected · yellow connecting · green connected · red unreachable, with the reason and a retry button |
| Terminal in the conversation | A real terminal (xterm.js over ssh -tt) where menu scripts, top and vim work; red / yellow / green buttons to end, minimize and maximize; nothing lost when you minimize or switch conversations, and it reconnects after a drop |
| Status in the conversation | One page for how the server is doing: rule-judged "needs attention" items first (failed services, full disks, expiring certificates, pending security updates), then ring meters, disks, services, containers, ports, firewall and more; click Interpret for a few sentences from DSH's default model. Expand it into DSH's right sidebar to keep it open beside the chat, refreshing every minute while visible, and pick any of your machines to look at |
| Files in the conversation | A file browser for the server: drag in to upload, right-click to download, double-click to edit, deletes go to a trash you can restore from; backups before overwriting or editing; right-click "let the AI look at this file" |
| AI on the server | 5 tools with risk-tiered confirmation: read-only runs automatically, changes ask you, dangerous commands ask again; levels can be set per machine, group or globally |
| Three safeguards | Files are backed up before editing and restored if validation fails; a connectivity safety net before firewall and SSH changes; long operations run as remote tasks that survive disconnects |
| Commands that fit the system | A health check finds the OS, package manager, init system, privilege, running services and containers, and the model is told to write commands for that machine |
| Recipe library | 29 repeatable recipes (7 install · 6 configure · 16 query); anything the AI gets working can be saved as a recipe in one sentence |
| Settings page | Add a machine with one form (enter the password once, the key is put in place for you, the password is not stored), import from , baseline configuration, terminal settings, uninstall |
| Look things up | Talk to the AI | Install and maintain with recipes | |
|---|---|---|---|
| How | Commands like /vps-sysinfo | "Install nginx on this machine and reverse-proxy a.com to port 3000" | /vps-install <recipe id> shows the plan, /vps-yes runs it |
| Uses the model | No | Yes | No |
| Cost | Zero tokens | Normal token use | Zero tokens |
| Scope | Fixed read-only queries | Anything SSH can do, with confirmations by risk level | 29 recipes that are safe to run again |
dsh websudo that asks for a password is not supportedroot or to have passwordless sudo; read-only queries do not| Windows | macOS | Linux | |
|---|---|---|---|
| SSH client | The built-in "OpenSSH Client". Usually already installed on Windows 10 / 11; otherwise add it under Settings → System → Optional features | Built in | Built in; otherwise install openssh-client |
| Speed | The Windows build of OpenSSH has no connection sharing, so each command opens its own connection, a fraction of a second more | One shared connection, tens of milliseconds | One shared connection, tens of milliseconds |
| Copying in the terminal | Select text, then Ctrl+C (with nothing selected, Ctrl+C interrupts) | ⌘C | Select text, then Ctrl+C |
~ in data locations | Your user folder, C:\Users\yourname | Home directory | Home directory |
| How it is verified | On every push, GitHub's Windows 2022 and 2025 machines go through the full flow against a real server | The author's daily machine | On every push, the full flow against a real server; every 6 hours, a compatibility check against the latest DSH |
Everything works the same on all three: commands, the AI, the terminal, the Files page, recipes, the settings page and uninstall.
Interface language follows DSH: pick English or 中文 under DSH Settings → General → Language, and the plugin's settings page, conversation header, terminal and Files panel switch at once; server errors and hints, /vps- command output, and recipe names and plans use the same language. Those are the two languages DSH ships today; with another language pack installed, the plugin shows English or Chinese according to the pack's declared fallback.
Plugin market: search for dsh-vps-manager in DSH's plugin market (dshmarket) and click install. Works in both DSH Desktop and dsh web.
Command line: quit DSH completely first, then run the line for your DSH:
# Official DeepSeek Harness desktop app
dsh plugin --profile desktop add dsh-vps-manager
# Command-line dsh web
dsh plugin --profile web add dsh-vps-manager
dsh command: install it from the app menu, "Manage dsh command…". A dsh installed from npm cannot change the desktop app's plugins.--profile must come before add. Since DSH 0.2.0, leaving it out fails with required option '--profile <name>' not specified.For the latest code on GitHub (possibly newer than the release on npm), use github:AIcivilization/dsh-vps-manager as the package name instead.
Open DSH afterwards. Plugins are loaded when DSH starts. What changed in each version is listed under Releases.
To uninstall, open DSH Settings → VPS Manager, scroll to the bottom and click "Uninstall…" (see Settings page). You can also quit DSH completely, run dsh plugin --profile desktop remove dsh-vps-manager in a terminal (--profile web for dsh web) and reopen DSH; that removes only the plugin and keeps the machine list, keys, SSH configuration and audit log.
Open DSH Settings → VPS Manager → "+ Add machine". It is one form:
Click Save and connect:
~/.ssh/dsh_vps_ed25519 (your existing keys are left alone)~/.ssh/authorized_keys on the server (skipped if it is already there)~/.ssh/config.d/dsh-vps.conf, one Include line is added at the very top of ~/.ssh/config (backed up first to ~/.ssh/config.dsh-bak), and the machine is reached with the key and gets a health checkThe password is used once and never stored: it goes only into the environment of that single ssh process and reaches ssh through SSH_ASKPASS. It is not written to any file, log or audit record, and every later connection uses the key. Adding with a password only works on the computer running DSH, so the password never crosses the network.
A wrong password, a server that refuses password logins, or a changed fingerprint is explained right in the form. For a key-only server, expand "No password?" under the form: paste the public key into your provider's "SSH keys" page, or run a one-line command on a server you can already log in to, then click "The public key is in place, connect".
Machines already defined in ~/.ssh/config can be taken over with "Import from ~/.ssh/config". The plugin never rewrites what you wrote in ~/.ssh/config.
On Windows the paths are the same, with ~ meaning your user folder (for example C:\Users\yourname).
DSH on Windows, a Mac and Linux can each have the plugin installed and manage the same server at the same time:
authorized_keys gets one line per computer, commented dsh-vps-manager@computer-name, so you can tell them apartThe conversation header has a VPS switch: the word VPS, then the terminal button >_, then one small square per machine. Each square shows its number (1 for the first machine, 2 for the second, and so on), matching the numbers on the settings page.
A square's colour is the real connection state, not just whether it is selected:
A live check runs when you turn the switch on, open the conversation, or come back to the DSH window (tens of milliseconds over the shared connection, a fraction of a second on Windows). Every command, AI tool call and terminal connection also records whether it reached the server, and the square follows
Click a square: this conversation enters VPS mode. From then on /vps- commands act on that machine, and the plugin tells the model which machine this conversation operates on, what system it runs (package manager, init system, privilege), which program holds ports 80/443, which services and containers are running, plus a few rules it must follow (never guess names, handle systemd services only through systemctl, never turn a failed lookup into a restart or reinstall). The model writes commands for that system, and knows what you mean by "this machine" or "the server"
In VPS mode the model cannot use local bash: a call is refused with a pointer to the VPS tools, so the model does not investigate server problems on your own computer. Reading files, searching and similar tools are unaffected
Click it again: VPS mode ends, the square turns grey, and local bash is available again. With nothing bound there is no default machine at all: commands do not run, and the AI must name the machine it operates on
Each conversation can be bound to one machine at a time. A binding only applies to its own conversation: one window can operate the server in VPS mode while another keeps working on local code, without affecting each other
The same from the keyboard: /vps-use <alias> binds, /vps-use off unbinds
A machine that has never had a health check gets one in the background when the switch is turned on, so the model receives its system details
Nothing is shown below the input box, except a single line in three cases: a task is running on the machine, the machine is unreachable, or its disk is at least 85% full.
The >_ button right after VPS in the conversation header is the terminal. Once a machine is bound, click it and a real terminal opens below the input box, working just like an SSH session (with only one machine you can click it before binding, and it binds that machine for you):
top, htop, vim, docker exec -it, mysql and other programs that need keystrokes all work, as do Ctrl+C, arrow keys and CJK text. To copy: ⌘C on a Mac; on Windows and Linux, select text and press Ctrl+C (with nothing selected, Ctrl+C interrupts as usual)>_ button in the header is still a switch: not open → open; open → minimize; minimized → restore. While minimized it shows a small green dot/vps-sh when you want the AI to see its outputSettings (DSH Settings → VPS Manager → 界面 / Interface): colour scheme (follow system / dark / light, where follow system matches DSH's appearance), font size (11–20), how long to keep the terminal after a disconnect (5 minutes / 10 minutes / 30 minutes / 1 hour), and whether other devices may open it.
It works in both DSH Desktop and dsh web: the connection follows the page address (an https page automatically uses an encrypted connection). Every connection must pass three checks: DSH's own sign-in check, an origin that is the DSH page itself, and the plugin token embedded in that page. On top of that, by default the terminal only opens on the computer running DSH: when you reach dsh web through a LAN address or a reverse proxy, first tick "允许从其他设备打开 VPS 终端" (allow opening the VPS terminal from other devices) under DSH Settings → VPS Manager → Interface. The terminal is full control of the server, so only turn this on for access paths you trust.
No native module has to be compiled on your machine: the pseudo-terminal on the server is requested with ssh -tt, and window-size changes are applied over a second SSH connection. The terminal display is xterm.js (MIT licensed, bundled with the plugin and loaded the first time you open a terminal).
The terminal panel's title bar has a Terminal | Files | Status switch. Files is a file browser for the server this conversation is bound to:
/etc, /var/log, root, trash) and a clickable path on top; click the empty part of the path to type one (~ means home). Columns sort, and files starting with . are hidden until you turn on "show hidden files"~/.cache/dsh-vps/backups/ on the server, and keeps its mode and owner. New files get 644 and new folders 755, so web servers can read them. An upload that breaks off halfway leaves the original untouched.tar.gz as it downloads. Download managers installed on your computer (IDM, Folx and the like) do not get in the waysshd_config, firewall rules) are flagged at the top~/.cache/dsh-vps/trash) you can restore from; deleting permanently or emptying the trash asks again. Top-level system directories (/etc, /usr and the like) cannot be deletedcds there)The terminal panel's third tab, Status, shows on one page how the server bound to this conversation is doing:
$DSH_HOME/vps-manager/status/), so reopening the tab shows them at once; each of your computers keeps its ownWhile the Status tab is showing, the button with a divided square, left of the panel's three dots, opens the same page in DSH's right sidebar (the column Files and document previews use). It sits beside the conversation, stays open while you chat, and comes back after you switch conversations or reload; it is also listed on the right sidebar's start page as VPS status.
The first card on the Status tab is Network. Click Start check-up (about 30 seconds, no tokens) and it tells you, one line each, whether things actually work; the numbers are under Details:
$DSH_HOME/vps-manager/net/, one file per check, kept for 90 days); /vps-netcheck shows the same in the conversationThe Speed card measures from your own computer, with your broadband plan as 100% (enter it once in the card, for example 1000).
$DSH_HOME/vps-manager/speed/, 90 days)The Compare servers card is for choosing a VPS provider. Enter a few candidates as IPs, domains or a provider's Looking Glass address (click + to add a row, up to 10); they are tested directly from your computer (not through your proxy), side by side:
+AI on the cards: the Network, Speed, Compare servers, Ports, Firewall and Security cards have a blue-violet +AI at the right of their title row. Clicking it sends that card's findings and key numbers to the conversation as one message; the AI answers there, and you can follow up or let it act. Only the findings go, not the raw data or your home broadband IP; it is hidden while the right sidebar shows another machine. The whole-page interpretation is still the AI interpretation at the top
Commands skip the model and cost no tokens. DSH folds a command's result down to one line, so the first line of every result is the conclusion.
Two rules:
/vps-yes on its own.Commands you type are shared with the AI: DSH itself never passes command results to the model. The plugin keeps your last few /vps-sh commands and their output (tokens, passwords and private keys masked first) and attaches them the next time you talk to the AI, so you can investigate yourself and then just ask "why did that fail?". Prefix --private to keep a command out of it.
| Command | What it does |
|---|---|
/vps-help | Every command and how to use it |
/vps-yes | Confirms the plan you just saw: a reboot, an install, or a dangerous command that was held. Only for the current conversation, valid for 5 minutes, runs once |
| Command | What it does |
|---|---|
/vps-sysinfo | OS, CPU, memory, disk, load, public IP |
/vps-disk | Mounts, inodes, largest directories (the scan has a time limit) |
/vps-ports | Listening ports and the processes behind them |
/vps-services | Running and failed services |
/vps-net | Network interfaces, cumulative traffic, connection count |
/vps-docker | Containers and disk usage |
/vps-ping | Hostname, OS, load, uptime |
/vps-netcheck | Network check-up: reachable from China, whether ChatGPT and other AI and streaming services work, how clean the IP is (about 30 seconds; see Network check-up) |
/vps-logs <service> | The last 100 log lines of a service |
/vps-q <recipe id> | Runs any query recipe, e.g. ip-info, top-procs, cron-list, cert-expiry, firewall-status, updates, login-history |
/vps-sh <command> | Runs a command on the machine and shows the output in the conversation: the directory you cd into is remembered within the conversation; commands that keep refreshing or page (top, tail -f, journalctl -f, less, watch) are turned into one-shot output, and things that cannot work here (vim, interactive shells) point you to the terminal; commands judged dangerous are held until you send /vps-yes. Prefix --bg to run in the background, --private to keep this output away from the AI |
| Command | What it does |
|---|---|
/vps-list | Registered machines and their status; ★ marks the one bound to the current conversation |
/vps-use <alias> | Binds the current conversation to a machine; /vps-use off removes the binding |
/vps-probe | Runs the health check again: OS, init system, package manager, privilege, CPU, memory, disk |
/vps-reboot | Checks before rebooting: why a reboot is needed (kernel or libc updates waiting), whether now is a safe time (it refuses while the package manager is installing or a plugin task is running), which containers will stop, and whether they will start again by themselves. /vps-yes reboots, waits for the machine to come back, and reports the kernel change, containers and failed services. If the machine is still unreachable after 5 minutes, it tells you to check your provider's console |
| Command | What it does |
|---|---|
/vps-recipes | The recipe list, grouped into installs, configuration and queries |
/vps-install <recipe id> [key=value …] | Shows the plan: detection result, parameters and their defaults, steps, and the script itself. /vps-yes runs it |
/vps-tasks | Remote tasks on the machine |
/vps-task <task id> [--stop] | A task's state and log; add --stop to terminate it |
| Command | What it does |
|---|---|
/vps-doctor | Plugin and DSH versions (and whether this DSH version is verified), registration status of each part, the machine bound to the current conversation, a connectivity test, recent errors and runs; ends with a pre-filled feedback link |
The plugin registers 5 tools for the model, plus a set of operating rules (the vps-operator skill, which the model reads when it needs to):
| Tool | What it does |
|---|---|
vps_hosts | Lists registered machines |
vps_exec | Runs a script on a machine |
vps_write_file | Writes a remote file: backs it up first and restores it if validation fails |
vps_task | Remote tasks: list, status, log, terminate |
vps_recipe | Recipes: list, show, run, and save what was just done as a recipe |
Before any script runs, the plugin decides its risk level. The level the model declares can only raise the result, never lower it.
| Level | Examples |
|---|---|
| Read-only | df -h, systemctl status, docker ps, journalctl |
| Change | apt-get install, sed -i, systemctl restart, writing files |
| Dangerous | rm -rf, mkfs, firewall changes (ufw, iptables), passwd, reboot, killing processes (kill, pkill, killall), curl … | sh |
Whether a confirmation dialog appears depends on the machine's confirmation level (machine > group > global):
| Level | Read-only | Change | Dangerous |
|---|---|---|---|
| Careful (default) | Automatic | Ask | Ask |
| Relaxed | Automatic | Automatic | Ask |
| Fully automatic | Automatic | Automatic | Automatic |
| No approval UI available | Automatic | Refused | Refused |
vps_write_file copies the original to ~/.cache/dsh-vps/backups/ on the server, writes atomically (an existing file keeps its mode and owner), runs the validation command you give it (such as nginx -t), and restores the original if validation fails29 built-in recipes, each safe to run again:
Install and configuration recipes have four parts:
docker info rather than docker --versionA recipe that is already in its target state skips the install and goes straight to verification.
Pass parameters as key=value. The plan lists every parameter with its default:
/vps-install setup-swap size_mb=4096
/vps-yes
detect and verify; the plugin checks that no password or key slipped in, then saves it as $DSH_HOME/vps-manager/recipes/my-<id>.ymlYour own recipes get a my- id prefix and cannot replace built-in ones. To change one, save it again under the same id; to delete one, delete its file.
Your own recipes are treated as untrusted: their risk level is the stricter of what the recipe declares and what the plugin's static analysis finds, and the first run after a recipe is added or changed asks for confirmation at least at the "change" level.
DSH Settings → VPS Manager, all point-and-click, never through the model:
Update (top right, next to the version number): when a new version is released on GitHub, the button turns into Update to vX.Y.Z with a note linking to what's new. Clicking it hands the install to DSH's own plugin manager (the same one DSH's Plugins page uses: it runs pnpm under a lock and restores your profile if anything fails). Quit DSH completely and reopen it to run the new version. If npm hasn't caught up with GitHub yet, the button waits; if the install fails, the reason and the dsh plugin add command to run yourself are shown. The check is cached for 6 hours; the button checks again on demand
Machine list: number (matching the squares in the conversation header), address, privilege, group, note; one-click connectivity test
Add machine, and Import from ~/.ssh/config
Per-machine settings: alias, address, port, user, jump host, public key placement, host fingerprint, confirmation level, removal
Basics: fill in the state you want (timezone, swap size, BBR, automatic security updates, fail2ban, common CLI tools). On save, only the items that differ from the current state are run, each as a remote task with progress shown
Global settings: default confirmation level, safety-net duration, and whether changes may be made from the settings page when DSH's web server is open to the local network
Interface: colour scheme (follow system / dark / light), font size, how long to keep the terminal after a disconnect, and whether the terminal may be opened from other devices (off by default)
Use DSH on your phone or tablet too: a two-line note about the sister project dsh-vps, which installs DSH on your VPS so a phone or tablet browser can reach it; it links to GitHub and mentions searching dsh-vps in the plugin marketplace. If dsh-vps is already installed, the note says so and points to "VPS Deploy" in the settings sidebar
Feedback and suggestions: "report a problem" and "suggest" open a pre-filled GitHub issue; the diagnostics (plugin and DSH versions, registration status of each part, recent errors, masked) stay folded away until you click "diagnostics"
The settings page's backend only accepts same-origin JSON requests carrying a token generated at random each time DSH starts. It offers no arbitrary command execution and cannot write arbitrary files. When DSH's web server is bound to 0.0.0.0, operations that change a server are turned off by default.
/vps- commands and the AI tools share one execution engine. Scripts reach the server on SSH's standard input and are written to a file before they run, so no outside data is ever spliced into the remote command line~/.cache/dsh-vps/ on the server, with a lock, and keep going after a disconnect; you can reattach and read the log at any timessh -tt, and the browser reaches the plugin over a WebSocket; if the connection drops, the session is kept for a while and the missed output is replayed on reconnect| Location | Contents |
|---|---|
$DSH_HOME/vps-manager/hosts.yml | Machines, groups, confirmation levels (safe to edit by hand) |
$DSH_HOME/vps-manager/state.json | Health check results and which machine each conversation is bound to |
$DSH_HOME/vps-manager/status/ | The last look from the Status tab and its AI reading, one file per machine |
$DSH_HOME/vps-manager/recipes/ | Your own recipes |
$DSH_HOME/vps-manager/audit/ | Audit log: one JSON line per run (source, machine, action, level, result), one file per month, kept for 6 months |
~/.ssh/config.d/dsh-vps.conf | SSH connection settings maintained by the plugin |
~/.ssh/dsh_vps_ed25519 | The dedicated key the plugin generates |
~/.cache/dsh-vps/ on the server | Remote task directories, logs, file backups, trash (shared by all your computers) |
$DSH_HOME defaults to ~/.dsh; on Windows ~ is your user folder (C:\Users\yourname).
The plugin never reads private key contents. The password you enter when adding a machine is used for that one login only; it is never written to a file or stored.
/vps-doctor in DSH, or click Settings → VPS Manager → 反馈问题 (report a problem). It opens a GitHub issue pre-filled with the plugin version, DSH version and diagnostics for you to review and edit before submitting. Diagnostics are masked and contain no machine addresses; the plugin never uploads anything by itself/vps-doctor say soErrors the plugin runs into itself (registration failures, backend errors, interface errors) are kept locally under $DSH_HOME/vps-manager/logs/, masked, for 3 months.
| File | Purpose |
|---|---|
lib/index.js | Plugin entry: registers tools, commands, the skill, VPS mode, settings routes and the terminal |
lib/commands.js | The 22 /vps- commands |
lib/tools.js | The 5 tools for the model |
lib/risk.js · lib/safety.js | Risk classification, tiered confirmation, connectivity safety net |
lib/engine.js · lib/payload.js · lib/prelude.sh | Execution engine: payloads, remote tasks, the cross-distro prelude |
lib/actions.js · lib/task.js · lib/files.js | Health checks, runs, remote tasks, file edits (backup + validation + restore) |
lib/recipes.js · lib/recipe-store.js · recipes/ | Loading, running and saving recipes; the 29 built-in recipes |
lib/vps-mode.js · lib/skills/vps-operator.md | VPS mode and the operating rules for the model |
lib/terminal-server.js · lib/vendor/xterm/ | The in-conversation terminal (server side) and the bundled xterm.js |
lib/terminal.js | The /vps-sh mini terminal: remembered directory, interactive-command rewriting, masking |
lib/reach.js | Connection checks (the colour of the header squares) |
lib/health.js · lib/verified-dsh.json | Self-diagnostics: registration results, DSH version verification, local error log, feedback link |
scripts/compat-smoke.mjs · scripts/install-dsh.sh · .github/workflows/dsh-compat.yml | Compatibility check: install the plugin, boot a real DSH web app and check each part, against DSH's three release channels every 6 hours. If a fresh DSH release is still missing packages on npm, the install is retried every 10 minutes, up to 4 times, so it doesn't raise a false alarm |
lib/client.js | Interface: header switch, terminal panel (terminal, files, status), notices below the input box, settings page |
npm install
npm test
339 tests, no real server needed: a local sh -s stands in for the remote sshd, covering the payload protocol, remote tasks, locking, backup and restore, risk classification, VPS mode, uninstall, commands, the settings-page backend, the terminal connection (authentication, local-only access, input and output, window size, keeping and resuming after a disconnect, cleanup), the status collection script and rules, and UI rendering. On a machine with DSH Desktop installed, tool definitions, return values, skill fields and approval outcomes are also checked against DSH's own dsh-tools, dsh-skill and dsh-user-approval, along with whether the notice the plugin adds to a conversation is accepted by the host's session format.
On every push, GitHub's Windows machines (2022 and 2025, with the OpenSSH that ships with Windows) and a Linux machine also each connect to a real sshd and follow the same path a user does: add a machine with a password, run commands, run a remote task, upload, download and edit on the Files page, open the terminal and resize it, and revoke the key on uninstall.
Bundled third-party code: lib/vendor/xterm/ contains xterm.js 6.0.0 and addon-fit 0.11.0, MIT licensed, copyright the xterm.js authors; see lib/vendor/xterm/LICENSE.
~/.ssh/config| Three platforms, both kinds of DSH | Windows, macOS, Linux; DSH Desktop and dsh web. Terminal connections pass DSH's sign-in check, a same-origin check and the plugin token, and open only on the local computer by default |
| Several computers, one server | Each computer has its own key; changes queue on the server and say which computer is making them; trash, backups and task records are shared; uninstalling revokes only that computer's key |
| English / 中文 | The interface follows the language set in DSH and switches instantly, without a reload; server messages, /vps- command output and recipe names follow too |
| Light install | No native modules (no node-pty to compile); the only runtime dependencies are ws and yaml |
Data location
Uninstall: tick what to do, confirm, and see the result of each step. The plugin itself is removed last: in the official DeepSeek Harness app through DSH's own plugin manager (the settings page disappears as it goes; quit and reopen DSH for a clean start), on the old DSH Desktop through its own service with a one-click restart; elsewhere you get the terminal command to run
Include line the plugin added at the top of ~/.ssh/config is removed and config.d/dsh-vps.conf is renamed as a backup, so both can be restored~/.cache/dsh-vps on the servers (machines with a running task are skipped, and so are machines another computer's plugin also manages, because that directory is shared)authorized_keys, after a backup; other computers' keys are left alone). If that key is your only way into a server, you will be locked outServer-side items run first, because once the local configuration and key are gone the servers can no longer be reached. Only the first two items are ticked by default
lib/status.js | The Status tab: the read-only collection script, rules, local cache and AI interpretation |
lib/netcheck.js | The Network card (network check-up): read-only checks on the VPS, reachability from China (Globalping), rules |
lib/speedtest.js | The Speed and Compare servers cards: proxy and direct speeds measured on this computer, the temporary speed-test service on the VPS, candidate comparison |
lib/update.js | The settings page's Update button: latest release on GitHub and npm, install through DSH's plugin manager |
lib/routes.js | Settings page backend |
lib/config.js · lib/onboarding.js · lib/ssh.js | Machine list, SSH configuration, adding machines, ssh arguments |
lib/reboot.js · lib/uninstall.js · lib/audit.js | Reboot and wait for the machine, uninstall, audit log |
test/ | 339 tests |
scripts/windows-e2e.mjs · .github/workflows/platform-e2e.yml | Cross-platform run against a real sshd on GitHub's Windows and Linux machines: adding a machine, running commands, the Files page, the Status page, the terminal, uninstalling |