Skip to content
All posts

SSHM: a terminal SSH manager with Keychain passwords and auto-sudo

Rajesh Govada · · 4 min read
sshpythonmacoscli

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:

  1. SSH into the server and send the password at the login prompt
  2. Wait for the shell prompt (it looks for the user@host:...$ pattern)
  3. Send sudo -i
  4. Send the same password at the sudo prompt
  5. 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

KeyAction
aAdd a new server
eEdit selected server
dDelete selected server
EnterSSH into selected server
cCopy SSH command to clipboard
/Search and filter servers
qQuit

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 security CLI for Keychain and expect for 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.