ssh-cli
Give any LLM remote SSH power in one memory-safe one-shot binary.
- Read this document in Portuguese (pt-BR).
- Install with
cargo install ssh-cli --lockedfor a lockfile-aligned graph. - Upgrade with
cargo install ssh-cli --locked --force. - Verify with
ssh-cli --version. - Read full history in CHANGELOG.md.
- Integrate agents via docs/AGENTS.md and INTEGRATIONS.md.
- Follow first use in docs/HOW_TO_USE.md.
- Copy recipes from docs/COOKBOOK.md.
- Check platforms in docs/CROSS_PLATFORM.md.
- Migrate from 0.3.3+ in docs/MIGRATION.md (target line 0.3.6).
- Run tests via docs/TESTING.md.
- Consume JSON contracts under docs/schemas/README.md.
- Teach LLMs with skills/ssh-cli-en/SKILL.md.
What is it?
One-shot multi-host SSH CLI for agents
- Ship a single Rust binary with zero Node runtime and zero daemon.
- Operate N VPS hosts from XDG storage without
.envfiles. - Authenticate with password or private key per host.
- Execute
exec,sudo-exec, andsu-execas pure one-shot processes. - Capture stdout and stderr with structured JSON for orchestration.
- Auto-detect locale between
en-USandpt-BR. - Disable telemetry completely in every build.
Why ssh-cli?
Replace long-lived SSH processes with a die-after-run binary
- Avoid resident Node processes that hold sockets open between tasks.
- Cut RAM and CPU waste from long-lived SSH sessions.
- Register multi-host credentials once under XDG with atomic writes.
- Align command packing and dual maxChars semantics with the one-shot agent contract.
- Trust host keys via TOFU known_hosts instead of always-trust.
- Route errors with sysexits codes that agents classify reliably.
Superpowers
Capabilities that make agents productive
- Multi-host CRUD with
vps add|list|show|edit|remove|path|doctor|export|import - One-shot remote execution with
exec,sudo-exec,su-exec - Safe
sudopacking viash -cand shell escape - Private key auth with optional passphrase
- Dual limits
max_command_charsandmax_output_chars - Timeout with best-effort remote abort
- Bounded tunnel via mandatory
--timeout-ms - SCP upload and download
- Health-check latency probe
- Shell completions for bash zsh fish powershell
- Secrets via stdin flags to avoid argv leaks
- Default at-rest encryption (ChaCha20-Poly1305) with auto XDG
secrets.key - Master-key UX:
secrets status|init|reencrypt - TOFU
known_hostsand atomic config writes with flock - Install crypto pins for clean
cargo install --locked(GAP-014)
Quick Start
Install and run the first remote command
|
Installation
Choose the install path that matches your environment
- Prefer crates.io with lockfile:
cargo install ssh-cli --locked(after 0.3.6 is published; until then install from git/path for full features). - Rebuild from a checkout:
cargo install --path . --locked - Do not use install without
--lockedunless you verified the crypto pins resolve cleanly. - Force upgrade after a release:
cargo install ssh-cli --locked --force - Build musl with allocator feature when targeting Alpine:
--features musl-allocator - Require Rust MSRV 1.85.0 or newer
Usage
Register hosts then execute one-shot commands
- Default at-rest encryption (ChaCha20-Poly1305): auto
secrets.keyon first secret write; override viaSSH_CLI_SECRETS_KEY/_FILE/ keyring; manage withssh-cli secrets status|init|reencrypt. Opt-out:SSH_CLI_ALLOW_PLAINTEXT_SECRETS=1(tests only). - Prefer
--password-stdin/--keyover argv secrets. - Add password hosts with
vps add --passwordor--password-stdin. - Add key hosts with
vps add --key ~/.ssh/id_ed25519. - Mark active host with
connect <name>. - Run remote shells with
exec <vps> "<cmd>". - Elevate with
sudo-execorsu-execwhen configured. - Diagnose XDG paths with
vps doctor --json. - Export redacted inventory with
vps export.
Commands
Product surface for humans and agents
| Command | Purpose |
|---|---|
ssh-cli vps add |
Register a host (password or key) |
ssh-cli vps list [--json] |
List hosts with secrets masked |
ssh-cli vps show <name> [--json] |
Show one host masked |
ssh-cli vps edit <name> |
Patch host fields |
ssh-cli vps remove <name> |
Delete host |
ssh-cli vps path |
Print config.toml path |
ssh-cli vps doctor [--json] |
Show XDG layer schema and paths |
ssh-cli vps export |
Export hosts (secrets redacted by default) |
ssh-cli vps import --file |
Import hosts from TOML |
ssh-cli connect <name> |
Write sibling active file |
ssh-cli exec <vps> <cmd> |
One-shot remote command |
ssh-cli sudo-exec <vps> <cmd> |
One-shot sudo with safe packing |
ssh-cli su-exec <vps> <cmd> |
One-shot su - elevation |
| `ssh-cli scp upload | download` |
ssh-cli tunnel ... --timeout-ms N |
Bounded local port forward |
ssh-cli health-check [<vps>] |
Connectivity probe |
| `ssh-cli secrets status | init |
ssh-cli completions <shell> |
Shell completion scripts |
Environment Variables
Overrides allowed for tests and locales
| Variable | Description | Example |
|---|---|---|
SSH_CLI_HOME |
Override base config directory | /tmp/ssh-cli-test |
SSH_CLI_LANG |
Override locale | pt-BR |
SSH_CLI_SECRETS_KEY |
Master key as 64 hex chars (encrypt at rest) | (never log) |
SSH_CLI_SECRETS_KEY_FILE |
Path to file with 64 hex master key | ~/.config/ssh-cli/secrets.key |
SSH_CLI_USE_KEYRING |
Load/store master key in OS keyring | 1 |
SSH_CLI_ALLOW_PLAINTEXT_SECRETS |
Opt-out of default encryption (tests only) | 1 |
NO_COLOR |
Disable ANSI colors | 1 |
CLICOLOR_FORCE |
Force ANSI colors | 1 |
RUST_LOG |
Tracing filter override | debug |
- Prefer CLI flags over environment for production agent runs.
- Never put host passwords in environment variables; use registry + stdin.
- Master-key env vars are for encryption of secrets at rest, not SSH passwords.
Integration Patterns
Wire agents with one-shot subprocesses only
- Invoke
ssh-clias a subprocess with explicit argv. - Prefer
--jsonor--output-format jsonfor machine parsing. - Map non-zero exits with sysexits semantics before retry.
- Store hosts once via
vps addthen callexecper task. - Pass secrets through
--password-stdinwhen argv history is risky. - Read INTEGRATIONS.md for agent-specific notes.
Exit Codes
Sysexits-style codes agents must map before retry
| Code | Meaning |
|---|---|
0 |
Success |
1 |
General runtime error |
64 |
Usage / invalid arguments |
65 |
Data error (JSON/TOML/schema) |
66 |
VPS or input file not found |
73 |
Cannot create config/output |
74 |
IO or SSH connection/timeout |
77 |
Authentication rejected or host-key / sudo policy |
130 |
SIGINT |
143 |
SIGTERM |
- Prefer
--jsonor auto JSON when stdout is not a TTY (--output-formatoverrides). - Retry only on transient IO/timeout (
74), never on auth (77) or usage (64).
Performance
Cold start and memory goals
- Target cold start under 100 ms on modern Linux hosts.
- Keep process memory far below a resident long-lived Node SSH process.
- Die after each command so RAM returns to the OS immediately.
- Avoid long-lived tunnels without
--timeout-ms.
Memory Requirements
Plan capacity for multi-host registries
- Config TOML size grows with host count and path lengths.
- Output buffers respect
max_output_charsper stream. - Known_hosts file grows slowly with unique host:port pairs.
- No embedding model and no Node heap are required.
Troubleshooting FAQ
Fix common install and runtime failures
- Install fails on crypto RC drift: rerun with
--lockedor use release 0.3.6+ pins (scripts/verify_install_resolve.sh). - Auth fails on key-only hosts: set
--keyonvps addor pass--key/--password-stdintoexec. - Auth fails with passphrase keys: use
--key-passphrase-stdin. - Host key changed: confirm legitimacy then rerun with
--replace-host-key. - Command rejected as too long: raise
max_command_charsor shorten the command. - Config has encrypted secrets but no key: run
ssh-cli secrets initor restoresecrets.key/ env master-key. - sudo-exec disabled: remove
--disable-sudoand setdisable_sudo=falseon the host. - macOS Gatekeeper blocks binary: run
xattr -d com.apple.quarantine /path/to/ssh-cli. - Permission denied on config: ensure
chmod 600on the XDGconfig.tomlandsecrets.key.
Contributing
- Read CONTRIBUTING.md before opening a pull request.
- Follow the bilingual documentation framework for every public doc change.
Security
- Read SECURITY.md for private vulnerability reporting.
- Prefer stdin secret flags and key files over argv passwords.
Changelog
- Read version history in CHANGELOG.md.
- Do not paste release notes into this README.
License
- Dual-licensed under MIT or Apache-2.0.
- See LICENSE, LICENSE-MIT, and LICENSE-APACHE.