DSH Plugin Store
Back to home

YOLO-LZL

dsh-ssh-plugin

No description

Stars
0
Language
TypeScript
Created
Aug 14, 2026
Updated
Aug 14, 2026
Other
GitHub repo

Introduction

dsh-ssh-plugin

A DeepSeek Harness plugin that adds the ssh_exec model tool — run commands on a remote Linux server over the system ssh client — plus persisted SSH connections: save connections once, bind them to a workspace, and let ssh_exec use them by default.

  • Key-based auth only (BatchMode=yes) — no password/passphrase prompts, so a missing or unauthorized key fails fast instead of hanging.
  • No remote-shell quoting layer — the remote command travels through ssh stdin to bash -s.
  • Session sandbox aware — runs the client under the calling session's standing policy; danger-full-access runs it unconfined.
  • Recognizes your local ~/.ssh/config — hosts defined there need no manual ssh_connections save; pass the alias as ssh_exec host and ssh resolves it, and ssh_connections list shows them read-only.
  • Dual-face package — the host half registers the ssh-connections settings namespace and the ssh_connections tool; the browser half registers the "SSH Connections" card in Settings → Plugins.
  • All harness services except tools/shell are optional — profiles without settings or workspaceRegistry degrade gracefully (see below).

Install

dsh plugin --profile <name> add dsh-ssh-plugin          # from npm
dsh plugin --profile <name> add github:you/dsh-ssh-plugin   # from git
dsh plugin --profile <name> add ./dsh-ssh-plugin        # from a local checkout

A local checkout must be built first: pnpm install && pnpm bundle (git installs build automatically through prepare).

Then boot with dsh --profile <name>.

The plugin declares the harness packages as peer dependencies; @deepseek-ai/dsh-base (the first bundle of every profile) provides them.

Usage

ssh_exec

The model gains an ssh_exec tool. Ask in natural language (e.g. "ssh to root@10.0.0.5 and show disk usage"), or pass explicit arguments:

ArgRequiredNotes
hostyes*Remote host as [user@]host, e.g. root@10.0.0.5, or any alias defined in ~/.ssh/config.
commandyesBash command(s) run on the remote host via bash -s.
portnoSSH port. Default 22.
key_pathnoAbsolute path to the private key. Omit for ~/.ssh defaults and ssh-agent.
timeout_msnoForeground timeout in ms. Default 30000.
connectionnoLabel of a saved connection; fills in host/port/user/keyPath.

* host is required in the schema, but at execution the effective host resolves as explicit host → explicit connection → workspace default. Explicit port/key_path always win over the resolved connection's values. A host that is a ~/.ssh/config alias is handed to ssh unchanged — ssh applies the config's HostName/User/Port/IdentityFile itself, so no ssh_connections save is needed for config hosts.

ssh_connections

The model also gains an ssh_connections tool for durable connection management (persisted through the harness settings store, so it survives restarts):

  • save — persist a connection (label, host, optional port/user/keyPath). Labels are unique.
  • list — show saved connections plus hosts discovered from the local ~/.ssh/config (read-only; pass the alias as ssh_exec host, no save needed).
  • delete — remove one by label (also unbinds workspaces that pointed at it).
  • use — bind the current workspace to a connection label so ssh_exec may omit host; omit label to clear the workspace default.

SSH config discovery

On every call the plugin reads the local OpenSSH client config (~/.ssh/config, or sshConfigPath when configured) and parses it:

  • Concrete Host aliases become visible to the model in ssh_connections list and are suggested in ssh_exec error messages.
  • Per ssh semantics, the first obtained value wins: global directives and Host * blocks provide defaults, later matching blocks cannot override them. HostName/User/Port/IdentityFile are resolved; Match blocks and Include directives are not expanded — hosts must live in the file itself.
  • Discovery is best-effort: a missing/unreadable config yields an empty list, never an error. Config hosts are never persisted — they exist only in your ~/.ssh/config.

Settings card

With a web profile, Settings → Plugins shows an "SSH Connections" card styled like the built-in plugin cards (Bash/Terminal, Agent loop, Web search): a collapsible card with an unsaved badge and discard/save actions. Edit the same connections list (add/remove rows, save). The card only writes the connections field; workspace bindings are managed by ssh_connections use.

Data model

The ssh-connections settings namespace (schemastery schema, validated for duplicate labels):

{
  connections: [{
    label: string            // unique, non-empty
    host: string             // [user@]host, non-empty
    port?: number            // 1..65535, default 22
    user?: string            // optional; prepended to host when host has no user part
    keyPath?: string         // absolute private-key path; omit for ~/.ssh + ssh-agent
  }],
  workspaceDefaults: { [workspaceId: string]: string }   // workspaceId → label
}

Only key paths are stored — key content never leaves disk (role('secret') is reserved for a future keyContent field).

Configuration

Set row-level defaults in a later patch layer (profile cordis.patch.yml or --patch):

- id: tool-ssh
  name: dsh-ssh-plugin
  config:
    timeoutMs: 30000
    connectTimeout: 15
    sshConfigPath: C:\Users\me\.ssh\config   # optional; defaults to ~/.ssh/config

Degradation matrix

CompositionBehavior
No ctx.settings (e.g. TUI)No namespace, no ssh_connections tool; ssh_exec works with explicit args only.
No ctx.workspaceRegistryuse and the workspace-default resolution report "workspace registry unavailable"; everything else works.
No ~/.ssh/config (or unreadable)ssh_connections list shows saved connections only; ssh_exec suggestions omit config aliases.
Namespace not exposed to the browserThe card renders an "unavailable" placeholder.

Requirements

  • A reachable Linux target with bash and key-based SSH access set up (~/.ssh/authorized_keys).
  • On Windows, a session whose standing sandbox policy is danger-full-access; the restricted token otherwise refuses to start ssh.exe.

Development

pnpm install
pnpm bundle     # tsdown → lib/index.js (host) + lib/client.js (browser bundle)
pnpm types      # tsc --emitDeclarationOnly → lib/types/**/*.d.ts
pnpm test       # vitest (model + wiring)