sshpassx
A drop-in Rust replacement for sshpass with secure password storage via macOS Keychain and 1Password.
Quick Start
# Install
# Store a password once, use it everywhere
# Or pass a password directly (original sshpass style)
Using 1Password instead of macOS Keychain?
Installation
# From crates.io
# Or from source
# Or build manually
# Binary at: target/release/sshpassx
Configuration
Backend Selection
sshpassx supports two password storage backends, controlled by environment variables:
| Variable | Values | Description |
|---|---|---|
SSHPASSX_BACKEND |
op, 1password |
Use 1Password instead of macOS Keychain. Unset = macOS Keychain. |
SSHPASSX_VAULT |
vault name | 1Password vault to use (optional, defaults to personal vault) |
Backward compatibility: The legacy
SSHPASS_RS_BACKENDandSSHPASS_RS_VAULTenvironment variables are still accepted as fallbacks.
macOS Keychain (default) — passwords are stored in the system Keychain, encrypted at rest, protected by your login password.
1Password — passwords are stored as tagged items in your 1Password vault. Requires the 1Password CLI (op) to be installed and authenticated.
On non-macOS platforms, macOS Keychain is unavailable. Set
SSHPASSX_BACKEND=opto use 1Password instead.
1Password Service Account (for automation)
Verbose / Diagnostic Output
Use -v to see which backend is selected, what commands are executed, and how password resolution proceeds:
SSHPASSX: checking SSHPASSX_BACKEND environment variable
SSHPASSX: selected OS keychain backend
SSHPASSX: using keychain with key 'user@host'
SSHPASSX: querying backend for key 'user@host'
SSHPASSX: key 'user@host' found in backend
SSHPASS searching for password prompt using match "assword:"
SSHPASS detected password prompt
SSHPASS sending password
Usage
sshpassx [OPTIONS] <command> [args...]
sshpassx --store <key>
sshpassx --delete <key>
sshpassx --list
sshpassx --help
Password Source Flags
Mutually exclusive — only one per invocation.
| Flag | Description |
|---|---|
-p <password> |
Pass the password directly as an argument |
-f <filename> |
Read the password from a file (first line) |
-d <number> |
Read the password from a file descriptor |
-e |
Read the password from the SSHPASS environment variable |
-k |
Look up the password from the configured backend, auto-deriving the key from the SSH command |
No flag = read password from stdin (original sshpass behavior).
Password Management
Standalone operations — no wrapped command needed.
| Flag | Description |
|---|---|
--store <key> |
Prompt for a password and store it under <key> |
--delete <key> |
Delete the stored entry for <key> |
--list |
List all entries managed by sshpassx |
--key <value> |
Explicit key name for -k (overrides auto-detection) |
Other Flags
| Flag | Default | Description |
|---|---|---|
-P <prompt> |
assword: |
Prompt pattern to match in PTY output |
-v |
off | Verbose mode — diagnostic output to stderr |
-h, --help |
Context-sensitive help (try --store --help, --list --help, -k --help) |
Key Auto-Detection
With -k (no --key), the key is derived from the wrapped command using a two-stage fallback:
-
Direct parsing — extracts
user@hostfrom SSH arguments:ssh user@host→ key =user@hostssh -l user host→ key =user@host
-
SSH config resolution — if direct parsing fails, runs
ssh -G <destination>to resolve aliases:ssh myalias→ resolvesUserandHostNamefrom~/.ssh/config→ key =resolved_user@resolved_hostssh -W %h:%p gw→ resolvesgwalias → key =resolved_user@resolved_host- Propagates
-F <config>if present in the SSH arguments
Use --key <name> to override auto-detection entirely.
If both stages fail, you're prompted interactively.
Examples
Basic Password Passing
# Direct password
# From file
# From environment variable
SSHPASS=hunter2
# From stdin
|
Keychain Workflow
# Store once
# Use everywhere
# Explicit key name
# Manage stored entries
1Password Workflow
# Store in 1Password
# Use from 1Password
# Use a specific vault
SSHPASSX_VAULT=Production
# List / delete
SSH Config Integration
Use sshpassx as a ProxyCommand in ~/.ssh/config to automate password-based jump hosts. Aliases are resolved automatically via ssh -G.
# First, store the jump host password
# ~/.ssh/config
# Jump host that requires keyboard-interactive auth
Host gw
Hostname gateway.example.com
User user
PreferredAuthentications keyboard-interactive
PubkeyAuthentication no
# Internal hosts via the jump host — alias "gw" is auto-resolved
Host internal-server1
HostName 10.0.0.1
User admin
ProxyCommand sshpassx -k ssh -W %h:%p gw
GSSAPIAuthentication no
Host internal-server2
HostName 10.0.0.2
User admin
ProxyCommand sshpassx -k ssh -W %h:%p gw
GSSAPIAuthentication no
How it works: sshpassx runs
ssh -G gwto resolve the alias, extractingUserandHostNamefrom your SSH config to construct the keychain keyuser@gateway.example.com. Use--key <name>to override if needed.
Advanced
# Custom prompt pattern (non-English systems)
# Verbose diagnostics
Exit Codes
| Code | Name | Meaning |
|---|---|---|
| 0 | Success | Command completed successfully |
| 1 | InvalidArguments | Missing required argument |
| 2 | ConflictingArguments | Multiple password sources or bad flags |
| 3 | RuntimeError | PTY, spawn, keychain, or I/O error |
| 4 | ParseError | Could not parse child process output |
| 5 | IncorrectPassword | SSH rejected the password |
| 6 | HostKeyUnknown | Host key not in known_hosts |
| 7 | HostKeyChanged | Host key changed since last connection |
Security
| Property | Original sshpass | sshpassx |
|---|---|---|
Password in args (-p) |
Visible in ps |
Visible in ps (same) |
Password in file (-f) |
Plaintext file | Plaintext file (same) |
Password in env (-e) |
Cleared before exec | Cleared before exec |
| Keychain storage | Not supported | macOS Keychain (encrypted at rest) |
| 1Password storage | Not supported | op CLI (encrypted vault, biometric unlock) |
| In-memory handling | Plain string | SecretString (zeroized on drop) |
Recommendation: avoid -p — the password is visible in ps. Use -k with stored passwords for scripts and automation.
Compatibility
Same as original sshpass
-p,-f,-d,-epassword sources-Pprompt pattern matching-vverbose mode- Exit codes 0–7
- Works with any PTY-based password prompt (
ssh,scp,sftp,rsync, etc.)
New in sshpassx
-k/--key— backend-backed password lookup--store/--delete/--list— password management- 1Password backend via
SSHPASSX_BACKEND=op - Auto-detection of
user@hostfrom SSH arguments - Interactive fallback when key is missing
- Context-sensitive
--help - Cross-platform backend guard (non-macOS → requires 1Password)
Limitations
- macOS Keychain backend is macOS-only. On other platforms, use
SSHPASSX_BACKEND=op. - 1Password backend requires the
opCLI. - No config file — all options via command line and environment variables.