dsh-ssh-vaultv2.2.0

scientificmaniac/dsh-ssh-vault

安全管理 MIT 最近更新 2026-11-07
1Stars
0Forks
0待解决 Issue
安装命令 dsh plugin --profile web add github:scientificmaniac/dsh-ssh-vault#e7602ef934102c054e8541e12fc0e5ecd3c9276c

介绍

SSH for DeepSeek Harness agents: host address, port, account, password and private key live in an encrypted vault, and the conversation only ever uses an alias. The model never sees a password, and a password never reaches a command line or a remote process list.

标签

dsh-plugin dsh-plugin-desktop dsh-plugins

概述

dsh-ssh-vault

English | 简体中文

SSH for DeepSeek Harness agents: host address, port, account, password and private key live in an encrypted vault, and the conversation only ever uses an alias. The model never sees a password, and a password never reaches a command line or a remote process list.

Overview

Windows only. The vault data key is protected by Windows DPAPI and the SSH_ASKPASS helper is a Windows .cmd wrapper; the plugin declares os: ["win32"] and refuses to start anywhere else rather than storing the key as plaintext.

Three capabilities in one plugin:

  • Model-facing tools — ssh_hosts, ssh_run, ssh_transfer, ssh_probe, so the agent operates remote hosts by alias.
  • Settings UI — add, edit and delete hosts in Settings → SSH Connections, and test reachability. A password entered there travels in an HTTP body, never through the session log.
  • /hosts command — probe hosts and run commands from the conversation without going through the model.

Under the hood it drives the local OpenSSH client (ssh / scp). It does not implement the SSH protocol itself.

Install

From npm. The plugin is published as dsh-ssh-vault; the bare name below resolves against the registry:

dsh plugin --profile desktop install dsh-ssh-vault

To pin a release or install offline, fetch the tarball with npm and hand the file to the same command:

npm pack dsh-ssh-vault        # writes dsh-ssh-vault-<version>.tgz into the current directory
dsh plugin --profile desktop install ./dsh-ssh-vault-<version>.tgz

From a local checkout. The argument is a path, so . works when you are already inside the plugin directory:

# inside the checkout
dsh plugin --profile desktop install .

# or point at it from elsewhere
dsh plugin --profile desktop install ../dsh-ssh-vault

# or install from a packed tarball
dsh plugin --profile desktop install ./dsh-ssh-vault-<version>.tgz

--profile is required. DSH isolates plugins per profile, and one machine can carry several (desktop, cli, …). Omitting it falls back to whichever profile is currently default, which is an easy way to install into the wrong place. Confirm the landing spot with:

dsh plugin --profile desktop list

Restart DSH after installing. Host-side tools and routes are loaded at startup.

This package is Windows only. package.json declares os: ["win32"], so dsh plugin ... install refuses to install it on Linux or macOS; a checkout loaded on another platform refuses to start for the same reason (see Known limitations).

Requirements

ItemRequirement
Node≥ 20
MachineWindows 10 / 11 with the OpenSSH Client enabled (ssh -V prints a version)
PlatformWindows only (win32) — installation and loading are refused on Linux / macOS

Quick start

  1. Install, then restart DSH.
  2. Open Settings → SSH Connections, click "Add connection", fill in alias, address, port, account, and choose password or private-key authentication. Each card carries a health dot that is checked automatically: grey = not checked, yellow = checking, green = reachable, red = unreachable.
  3. Say something in the conversation, for example:
   run uptime on kali

The model calls ssh_run and the result appears as a terminal card.

Do not paste passwords into the conversation. A password entered in Settings goes straight into the encrypted vault and never enters the model context.

Usage

Model-facing tools

ToolPurposeTypical phrasing
ssh_hostsManage the vault (list / show / add / update / remove)"which hosts do I have", "change kali's note"
ssh_runRun a command on a host, return stdout and stderr"check disk usage on kali"
ssh_transferUpload or download a file (scp), optionally with sudo"copy this file to /tmp on kali"
ssh_probeReachability self-check that also records capability metadata"is kali still reachable"
ssh_tunnelMaintain local port forwards (ssh -L)"map kali's 8787 to local 18787"

Conventions for ssh_run:

  • Explicit shell wrapping. POSIX targets run through bash --norc -c '<command>': the command is parsed exactly once by bash and cannot be reinterpreted by the remote login shell (fish/zsh). login_shell: true switches to bash -lc when you need the PATH that your profile defines. The returned remoteShell states what was actually used. --norc is not cosmetic: RHEL/CentOS builds of bash carry the SSH_SOURCE_BASHRC patch, so a non-interactive bash inside an SSH session still sources ~/.bashrc; one failing source line there puts noise on the stderr of every command and derails failure diagnosis.
  • Command arrays. command_array: ["find", ".", "-name", "*.log"] quotes each element, so the remote shell performs no word splitting, globbing or variable expansion — the double-shell quoting trap disappears.
  • Working directory. workdir: "/srv/app" runs the command in that directory: a cd (POSIX) or Set-Location (PowerShell) is prepended to the same script, and with sudo it happens inside the elevated context, so root-only directories work. A failed cd aborts the command instead of silently running in the login directory. cmd targets reject workdir with an explanation: Windows sshd wraps the whole command in another cmd.exe /c "...", which tears the quotes out of a quoted cd — write cd /D <dir> && <command> into the command yourself there.
  • Three sudo forms. sudo: true picks one automatically; sudo: "wrap" runs the whole command as sudo -n bash -c '...'; sudo: "script" writes a temporary script and runs it as root, so heredocs, pipelines, background jobs and multi-line flows never deform at the privilege boundary — the script is deleted right after, and the password reaches sudo -S through a base64 pipe, invisible to either command line and to the remote ps; sudo: "prime" only pre-warms the cache while the command keeps writing its own sudo. The password always comes from the vault. Once elevated, do not write sudo inside the command again.
  • Error classification. A failure carries one category label (connection / auth / sudo / remote command / truncated output); sudo failures are further split into "needs a password / not in sudoers / no sudo" with the exact fix.
  • A command that kills its own session is named as such. The whole command travels as the shell's own argument, so a pkill -f pattern also appears in the cmdline of the shell carrying it. A negative local exit code used to surface as 4294967295; it now renders as [exit code: -1], is classified as a connection-layer failure, names the raw value, and suggests pkill -x or running a script file instead. The risk is also warned about before the command runs.
  • Large output on disk. Past the cap, the response keeps the beginning and the end, prints how many characters were omitted in the middle, and writes the full stream under outputs/ in the vault directory with the absolute path attached.

ssh_transfer adds four things to scp: sudo: true moves root-only files (remote temporary staging plus cleanup); normalize_eol: true converts CRLF to LF before uploading, so a script written on Windows does not fail with $'r': command not found (binaries are detected and skipped); mode / owner / preserve_mode set remote permissions and ownership; and recursive copies are content-based by default — flatten (default true) puts the source directory's contents into the target directory, merging when it already exists, so src/ → /root/app lands in /root/app/* rather than /root/app/src/* and no cp -f src/* . && rm -rf src cleanup is needed. Pass flatten: false for raw scp nesting.

ssh_tunnel reads the remote sshd -T forwarding policy before opening a tunnel: with AllowTcpForwarding no it hands back a paste-ready Match User <user> snippet that allows LocalForwarding (rather than globally enabling it) plus the PermitOpen explanation, instead of making you hit administratively prohibited. It manages the tunnel lifecycle (local port precheck, drop events, exponential-backoff reconnect, cleanup on unload) and returns the local addresses.

Where to see the result: calls to ssh_run, ssh_probe, ssh_transfer and ssh_tunnel render as a terminal card — a header with "host · command" and a state dot, above a scrollable monospace output area. The dot is blue while running, grey on success, red on failure (including a non-zero exit code).

Settings UI

Settings → SSH Connections provides:

  • A host list with a health dot per card; hover for detail
  • Add / edit / delete connections (the alias is editable, credentials move with it)
  • A "Test connection" button per card, whose result also drives the dot
  • "Open in file manager" for the vault directory
  • Password and private-key authentication; a key can be uploaded whole and is written into the vault with its permissions tightened

Language

Everything the plugin shows follows the language chosen in Settings → General → Language; there is no separate switch here.

  • The settings page and the in-conversation SSH cards get their copy from the host's locale service, so they change the moment the language does.
  • /hosts output, transport diagnostics, Settings-API errors, vault errors and background-job status are generated on the Host; they read the same persisted preference (locale.preference) and follow later changes, falling back to the request's Accept-Language only when nothing was ever chosen.
  • Model-facing definitions stay English: tool names, descriptions and parameter schemas belong to the model interface, not to the UI.

The /hosts command

Start a line with / in the composer and the command runs without going through the model.

/hosts                    list every host, grouped into online / offline
/hosts kali               probe one
/hosts kali,win10         probe several (either comma form works)
/hosts kali; apt update   run a command on kali
/hosts kali,win10; uptime run on every reachable host
  • Separators accept both ASCII and full-width forms: , and ,, ; and ;
  • If the text after the semicolon reads as natural language (e.g. "check the disk"), the command does not run it and tells you to send that sentence to the conversation instead — command output never reaches the model, so such requests cannot go through the command
  • Output renders as two cards: reachability and command execution, each with its own state dot
  • Picking /hosts from the / menu only claims it: the composer shows the command token with its hint. Press Enter again to run it bare (list hosts), or type alias; shell command as its arguments. To go back to a normal prompt instead, delete the command token — until then, whatever you type is the command's argument
  • Before the first message the result appears above the composer. DSH treats a transcript containing only command rows as an inactive view, so a bare /hosts in a brand-new conversation used to look like "nothing happened" until you sent a message. The plugin now mirrors the /hosts cards (running state included) in the composer dock while the session is still blank; once the first message exists the transcript takes over, so nothing is duplicated
  • A bare call probes only when the health cache is cold, in parallel and with a 4s budget, so it answers within seconds even when several hosts are unreachable

Architecture

Two halves

This is a Host + Client plugin; the two halves load through different mechanisms:

HalfEntryLoading
Hostindex.jsCordis plugin, inserted into the Loader through cordis.patch.yml
Clientclient.jsBrowser module, declared via dsh.client in package.json and injected into the page by the host

The Host half carries every sensitive operation: vault encryption, driving the local ssh client, web routes, and the registration of commands and tools. The Client half only renders and collects form input; it never executes a command.

Data flow

flowchart TB
    subgraph entry [Entry points]
        chat[Conversation / model tool call]
        settings[Settings form]
        cmd["/hosts command"]
    end

    subgraph host [Host half — index.js]
        resolve[Resolve alias → read credentials → build ssh args]
        vault[(Vault<br/>AES-256-GCM ciphertext)]
        api["Web routes /ssh-vault/*"]
        exec[Spawn local ssh / scp]
    end

    subgraph client [Client half — client.js]
        toolcard[Tool terminal card]
        cmdcard["/hosts double card"]
        form[Connection form]
    end

    proxy[Remote host]

    chat --> resolve
    cmd --> resolve
    settings -->|POST JSON| api
    form -->|same-origin, document-relative| api
    api --> vault
    resolve --> vault
    resolve --> exec
    exec -->|stdout / stderr| toolcard
    exec -->|stdout / stderr| cmdcard
    exec <--> proxy

Three invariants hold across that chain:

  1. A password never reaches a command line — local ssh receives it through SSH_ASKPASS; remote sudo is primed over stdin
  2. Only ciphertext touches disk — AES-256-GCM, with the data key protected by Windows DPAPI (or, optionally, derived from a master passphrase via scrypt)
  3. ~/.ssh is never touched — known_hosts points into the vault directory and HashKnownHosts is enabled

Configuration

The plugin has no user-configurable options. config: {} in cordis.patch.yml is an empty object, and the Loader entry id is fixed as ssh-vault.

Behaviour is shaped by the following:

ItemNotes
Vault directoryDefaults to $DSH_HOME/ssh-vault; DSH_HOME is decided by DSH
Key protectiondpapi (Windows DPAPI, the default) or passphrase (scrypt-derived key, no key material on disk). file stores the key as plaintext and is an explicit opt-in only
Timeoutsssh_run defaults to 120s, adjustable, capped at 30 minutes; commands inside /hosts are fixed at 120s
Health checksSettings page and /hosts probe with a 15s timeout; the background sweep refreshes every 5 minutes

API and extension points

Host-side services are reached through ctx.inject as optional dependencies; a missing service does not fail the plugin, it just disables that capability.

Model tools (ctx.tools.register)

ToolKey parameters
ssh_hostsaction required (list / show / add / update / remove); reveal controls whether address and account are masked
ssh_runhost, command required; optional sudo, timeoutMs, workdir, run_in_background, wait_for, bindAddress
ssh_transferhost, direction, local, remote required; optional recursive and flatten (default true)
ssh_probehost required; optional timeoutMs, bindAddress

The three terminal-style tools also register presentCall / presentResult hooks, but the current DSH version has no consumer for them; presentation is handled by the slots below.

Client slots (ctx.slots.register)

SlotKeyEffect
settings.sectionid: ssh-vault, order: 20, labelThe "SSH Connections" page in the settings panel
tool.call.toolviewssh_run, ssh_probe, ssh_transferRenders those tool calls as terminal cards
conversation.chat.commandviewhostsRenders /hosts output as two terminal cards

The tool.call.toolview key space is open; none of these three names were taken, so no built-in UI is shadowed.

All three registrations also carry locale: 'ssh-vault' — the namespace registered with the host's locale service — which is what makes the rendered cards re-render and re-read their copy when the language changes.

Human command (ctx.commands.register)

CommandNotes
/hostsProbe hosts / run a command on them. Form: alias[,alias][; shell command]

The command's description and input.hint are re-registered only when the interface language changes. The disposer returned by commands.register destroys the current definition, so replacing it while the user is typing arguments strips the composer of its command context (backspace stops working, and the UI needs a restart). That is why registration is never driven by timers or health results; a locale switch is a deliberate Settings action with nothing being typed, making it the one safe moment to swap the definition.

HTTP routes (ctx.webServer.register)

Mounted at /ssh-vault (kind: 'prefix', no trailing slash). POST only, JSON in and out, with an envelope of { ok: true, value } or { ok: false, error }.

PathEffect
/ssh-vault/listHost list (address and account masked, no passwords)
/ssh-vault/saveCreate / update / rename
/ssh-vault/removeDelete
/ssh-vault/testReachability probe
/ssh-vault/revealReturn unmasked address and account
/ssh-vault/openVaultOpen the vault directory in the system file manager

openVault accepts no path argument at all — it can only open the plugin's own vault directory.

Every request crosses the Host Connection trust fence before the handler looks at the method, the body or the vault: it calls ctx.connection.requestRejection(req), the same Host/Origin check and browser-session authentication used by /api. A rejected request gets 401 / 403 and never reaches the vault, so a DNS-rebinding or cross-site call cannot read host data or trigger a probe.

About ctx.systemPrompt.section

This plugin does not use that extension point. Every tool carries its own description, and no section is injected into the system prompt, so prompt length and ordering are unaffected.

Lifecycle

Startup

  1. The Loader reads cordis.patch.yml and inserts the entry with id: ssh-vault
  2. The host imports index.js and calls apply(ctx, config)
  3. apply opens the vault, registers the four tools, and — where the services exist — the web routes, the /hosts command and the background health timer. It also subscribes to the host settings document so it can read the interface language and follow later switches
  4. The Client half is injected into the page per the dsh.client declaration, and its apply registers the three slots and its ssh-vault dictionary with the locale service

Unload and resource reclamation

Async resources are wrapped in ctx.effect, and Cordis runs the returned cleanups in reverse order on teardown:

  • Tool and command disposers (including the locale-switched command definition)
  • Web route disposers
  • The settings-document subscription and its startup retry timers
  • The health sweep's setTimeout / setInterval
  • The vault handle
  • The client's locale dictionary and slot registrations

Vault data survives uninstall and is available again after reinstall.

Hot update

The two halves behave differently, and this is easy to get wrong:

ChangeTakes effect by
client.js and slot renderingReinstall the bundle, then reload the page
index.js / lib/**Restart DSH; reinstalling does not replace an already-loaded module generation
package.json versionThe version shown in Settings is read from this file by the Host

Do not infer that the browser has new code from an unchanged slot id — slot registration reflects the host side, not the module actually running in the page.

Known limitations

Platform and authentication

  • Windows only. The data key is protected by Windows DPAPI and the SSH_ASKPASS helper is a Windows .cmd; the repository therefore declares os: ["win32"]. There is no Linux/macOS mode: running the code there would have to fall back to a plaintext key.json, so the plugin refuses to load instead. SSH still targets Linux/Unix hosts remotely — the restriction is on the machine running DSH.
  • dpapi is the default key protection; passphrase is available (a master passphrase, with the key derived through scrypt). file stores the key as plaintext and must be chosen explicitly; it is not a fallback.
  • The Settings UI supports only password and private-key authentication. The agent auth type can be set through ssh_hosts add, but the form cannot enter or edit it
  • Remote shells supported: bash / sh / cmd / powershell, and one host may declare several. The Settings form's "Remote shell" field takes a comma-separated list such as powershell,cmd: the same Windows host can run structured PowerShell commands and the older tools that only cmd understands. Each call selects one with its shell parameter (ssh_run, ssh_probe, ssh_transfer and ssh_tunnel all honour it), defaulting to the first; an explicitly requested shell that was not declared is rejected rather than silently swapped. The three sudo forms apply to POSIX shells only; on cmd / powershell targets sudo: true fails loudly instead of silently degrading
  • The sudo form follows the target's actual state; it is not a style choice. wrap needs sudo -n to work already (root or NOPASSWD); with a password it goes through script, which needs that account's sudo password in the vault (sudoPassword, falling back to the login password). The automatic choice made by sudo: true consults the most recent ssh_probe result
  • The command line on a cmd target cannot contain non-ASCII characters. cmd parses the command line ssh hands it using the system code page, and chcp 65001 only affects output produced afterwards, so CJK text in the command itself is already folded to ? before it runs. Use a PowerShell target for CJK, or encode the payload as ASCII (PowerShell's -EncodedCommand). On PowerShell targets the plugin pins the output encoding to UTF-8, so CJK round-trips correctly
  • cmd targets always run as cmd.exe /Q /D /C <script>. Without /C, cmd enters interactive mode and mixes the Windows banner and the DESKTOP-xxx C:...> prompt into stdout; /D disables AutoRun and /Q disables echo

Concurrency

  • Connections to one host are serialised in-process. Every call opens a fresh SSH connection, and a burst of them — especially concurrent scp — trips sshd's connection limits and accumulates failed-auth counters toward an account lock. Background jobs are exempt from the queue so a long task does not block that host for everything else.
  • Every call opens a fresh SSH connection; there is no reuse. The Windows OpenSSH client does not support ControlMaster / ControlPersist: -G echoes those options happily, but an actual connection fails with getsockname failed: Not a socket. So each call re-handshakes, which is exactly why the per-host serialisation queue exists. If you truly need multiplexing, point the plugin at a Linux ssh client that has Unix domain sockets (e.g. one inside WSL).
  • The vault has no cross-process lock. Two DSH instances (different profiles pointing at the same vault directory) writing at the same time means the later write wins
  • Within one profile, writes from several sessions serialize on the event loop, but frequent concurrent edits of the same host are still not advisable

Account lockout

Windows OpenSSH disconnects a locked account outright instead of returning Permission denied, so a locked account looks like a network problem: the port answers, the banner arrives, then the connection is reset. If "port open, banner fine, still cannot connect" shows up, check the account before chasing the firewall — net user <account> on Windows, faillock --user <account> on Linux. Locking the management account also kills key-based login, so keep a second administrative path available when experimenting with lockout policy. ssh_run warns before commands that change account state.

Host keys

StrictHostKeyChecking=accept-new is used: the first connection is trusted automatically, and any later fingerprint change is refused. There is no separate fingerprint-verification flow, so judging whether a first-time target is trustworthy is up to the operator.

Output and timeouts

  • ssh_run caps a single result at 200000 characters; past that the response keeps the beginning and the end, marks how many characters were omitted in the middle, and writes the full stream under outputs/ in the vault directory with the absolute path attached
  • Each command inside /hosts echoes at most 40 lines
  • Commands inside /hosts have a fixed 120s timeout that is not configurable
  • Foreground tool calls have no streaming output: the result appears in one piece when the command ends. To watch a long job, use run_in_background, whose output lands in a job card

Interface

  • The navigation icon next to "SSH Connections" is drawn by the host from the section id. The settings.section registration accepts only id / order / label, so a plugin cannot supply its own icon
  • Command arguments have no candidate-list mechanism (CommandInputDescriptor carries only hint and attachments), so /hosts cannot offer alias completion
  • A command with an input hint is claimed, not executed, when picked from the / menu: this is DSH behaviour and the plugin cannot bypass it. The hint (localized) explains that a second Enter runs the command bare
  • DSH does not treat a transcript made only of command rows as an active view. /hosts compensates with the composer-dock mirror described above; the built-in rule still applies to other plugins' commands
  • The interface language is read from the shared host settings, so with several browsers attached to one host the most recently written preference wins; DSH Desktop is a single-user surface, where this is the intended behaviour

Open questions

Not verified in detail; check the source or upstream docs before relying on them:

  • Whether DSH exposes a structured field for command results, which would replace the textual section markers (─── 连接状态:ok ───) used today
  • Whether the host will connect a consumer to presentCall / presentResult in a future version

Security boundary

What it touches

CategoryAccessedDetail
FilesystemYesThe vault directory (vault.json, key.json, known_hosts, uploaded key copies) and any private-key path you supply; never ~/.ssh
NetworkYesOutbound SSH through the local ssh / scp processes; loopback HTTP routes (same origin, behind the Host Connection trust fence)
TerminalYesSpawns the local OpenSSH client; openVault launches the system file manager
External APIsNoNo third-party service is contacted
User dataYesHost address, port, account, password, private key, note, tags

Password handling

  • Local SSH: passed through SSH_ASKPASS, never on the command line or in a process list
  • Remote sudo: primed over stdin, never on the remote command line or in ps
  • On disk: only AES-256-GCM ciphertext; the data key is protected by DPAPI or a scrypt-derived key
  • Model context: a password never appears in tool arguments or results; one entered in Settings travels in an HTTP body and stays out of the session log
  • credentialRef: when a host points at an entry in the Harness credential store, the password is read at connect time and never passes through this plugin

Trust boundary

The web routes ride on the DSH web server and ask the Host Connection service for a rejection first (the same Host/Origin fence and browser-session authentication as /api). The plugin adds no authentication of its own beyond that, so do not expose the DSH web port to an untrusted network.

Reporting a vulnerability

See SECURITY.md.

FAQ

"SSH Connections" is missing from Settings after installing. Check you installed into the right profile: dsh plugin --profile <name> list. Then restart DSH — the client bundle is injected at page bootstrap, so a page reload alone is not enough.

A tool call reports a missing route, or Settings says the host is still running old code. The host code was updated but the process was not restarted. Restart DSH.

The health dot stays red although the host answers ping. The dot tests the SSH port 22, not ICMP. Check that sshd is running, that a firewall allows the port, and that the address stored in the vault is still current.

A connection test reports "connection not established within 15000ms". Again a network-layer signal: the address changed, a firewall is blocking, or the machine is up without sshd. It is unrelated to login credentials.

A word gets a red squiggle while typing /hosts. That is why the command is named hosts: the composer is a Lexical editor whose plain text nodes are subject to browser spellcheck, and hosts is a dictionary word while ssh is not.

/hosts kali,win10 says "not found". Check the alias spelling against the vault; it is case-sensitive. Run /hosts with no arguments to list the valid aliases.

A private key upload is rejected. Three common causes: a .pub public key was chosen, a PuTTY .ppk was chosen (convert it with puttygen first), or the file has no BEGIN … PRIVATE KEY header.

Output from several hosts runs together. Use the /hosts host; command form; the output splits into a reachability card and a command card.

I switched DSH to English but some plugin text is still Chinese. From 1.15.0 the whole surface follows the DSH language. After upgrading, reload the page once (client half) and restart DSH once (host half) to load the new code; after that, switching the language in Settings applies immediately, no reload needed. Model-facing tool definitions stay English by design.

Does it work on Linux or macOS? No. The data key is protected by Windows DPAPI and the SSH_ASKPASS helper is a Windows .cmd; any non-Windows path would have to store the key as plaintext, so the plugin refuses to load there. package.json declares os: ["win32"] and installation is rejected elsewhere. The remote hosts can of course be Linux/Unix — only the machine running DSH must be Windows.

Client code changed but the interface did not. Reload the page. Host-side changes need a DSH restart.

Contributing

See CONTRIBUTING.md. The hard rules: zero runtime dependencies (Node built-ins only on the Host side; only the host-provided react on the Client side), no real credentials or addresses in the repo, and a password must never reach a command line or the session log.

npm test            # host-free regression suite
npm run test:live   # end-to-end cases against real hosts

License

MIT

Cheat sheet: start · use · stop · uninstall

# Install (profile required)
dsh plugin --profile desktop install dsh-ssh-vault
dsh plugin --profile desktop install .        # from inside a local checkout

# Confirm where it landed
dsh plugin --profile desktop list

# Reinstall to refresh the installed copy
dsh plugin --profile desktop remove dsh-ssh-vault
dsh plugin --profile desktop install dsh-ssh-vault

# Uninstall
dsh plugin --profile desktop remove dsh-ssh-vault

Starting and stopping are handled by the DSH process itself: the plugin loads when DSH starts and unloads when DSH exits. It has no separate process and no resident background service.

Uninstalling does not delete the vault. Data stays in $DSH_HOME/ssh-vault and is usable again after reinstall; delete that directory by hand to remove it entirely.

Everyday reference:

Settings → SSH Connections        manage hosts, test reachability, open the vault directory
/hosts                            list hosts and their online state
/hosts kali                       probe one host
/hosts kali,win10; uptime         run a command on several
(just talk)                       let the model pick hosts and call the tools

星级评价

1.5 按 GitHub Stars 换算的社区热度,非用户打分
Stars1
Forks0
待解决 Issue0
最近更新2026-11-07

基本信息

作者scientificmaniac
版本2.2.0
开源许可MIT
默认分支main
入库时间2026-11-07

插件信息来自公开 GitHub 仓库与 SkillHub,版权归原作者所有;安装前请自行审查仓库代码。