SSHM: a terminal SSH manager with Keychain passwords and auto-sudo
I manage a handful of servers across client environments. Some use key auth, some use passwords, and most of the time I need root access once I’m in. The workflow was always the same: scroll through terminal history for the right ssh command, type the password, then sudo -i and type it again.
I built SSHM to skip all of that. It’s a terminal app that stores server credentials, keeps passwords in macOS Keychain, and optionally elevates to root automatically after login. One keypress to connect.
Install
Install via pipx (recommended):
pipx install sshm-terminal
If you don’t have pipx:
brew install pipx && pipx ensurepath
Optional: install sshpass for cleaner password handling:
brew install esolitos/ipa/sshpass
Without sshpass, the app falls back to macOS built-in expect, which works fine.
Add a server
Launch the TUI:
sshm
Press a to open the add form. Fill in the fields:
Name: Production API
Host / IP: 192.168.1.50
Port: 2222
User: deploy
Group: production
Password: ••••••••
SSH Key Path: (leave empty if using password)
☑ Auto sudo (elevate to root)
Press ctrl+s to save. The password goes straight into macOS Keychain. The server metadata (name, host, user, port, group) is stored in ~/.sshm/servers.json with no secrets in it.
Connect
Select the server with arrow keys and press Enter. That’s it.
If you checked “Auto sudo,” the app will SSH in, wait for the shell prompt, run sudo -i, handle the password prompt, and drop you into a root shell. You don’t type the password at all.
How the password security works
Passwords never touch disk as plaintext. Here’s what happens under the hood:
Storage: the security CLI writes passwords to macOS Keychain with a service tag of sshm. You can verify this yourself in Keychain Access.app by searching for “sshm.”
# This is what SSHM runs internally to store a password
security add-generic-password -a sshm -s <server-id> -w <password>
# And to retrieve it
security find-generic-password -a sshm -s <server-id> -w
During connection: when sshpass is available, the password is passed through an environment variable (SSHPASS), which never hits a file. When falling back to expect, the password is written to a temp file with 0400 permissions (owner-read only), the expect script reads it, deletes the file immediately, then handles the SSH prompt. The temp file is cleaned up in a finally block so it gets removed even if the connection fails.
Auto-sudo in detail
The auto-sudo feature chains two expect sequences in a single script:
- SSH into the server and send the password at the login prompt
- Wait for the shell prompt (it looks for the
user@host:...$pattern) - Send
sudo -i - Send the same password at the sudo prompt
- Hand control to you with
interact
This assumes the SSH user has sudo privileges and that the sudo password matches the SSH password. That’s the common setup for most cloud VMs where you log in as a service user and escalate.
Keyboard shortcuts
| Key | Action |
|---|---|
a | Add a new server |
e | Edit selected server |
d | Delete selected server |
Enter | SSH into selected server |
c | Copy SSH command to clipboard |
/ | Search and filter servers |
q | Quit |
The search filters across name, host, user, and group. Useful when you have 20+ servers and need to find one fast.
Use SSH keys instead of passwords
Leave the Password field empty when adding a server and fill in the SSH Key Path:
SSH Key Path: ~/.ssh/id_rsa
The app will use ssh -i ~/.ssh/id_rsa when connecting. No expect scripts, no sshpass, just a standard key-authenticated SSH session.
Quick list from the terminal
List saved servers without opening the TUI:
sshm list
NAME HOST USER PORT GROUP
──────────── ──────────── ───── ──── ──────────
Production API 192.168.1.50 deploy 2222 production
Staging DB 10.0.1.20 ubuntu 22 staging
Requirements
- macOS (uses the
securityCLI for Keychain andexpectfor password automation) - Python 3.10+
This is macOS-only because the password storage depends on the system Keychain. On Linux, you’d need a different secrets backend (like secret-tool or pass), which I haven’t built yet.
Uninstall
pipx uninstall sshm-terminal
rm -rf ~/.sshm
Passwords stored in Keychain can be removed via Keychain Access.app. Search for “sshm” and delete the entries.