
Fast terminal UI for your SSH hosts: fuzzy-search and connect in two keystrokes, dual-pane SFTP file transfer, and background port forwarding. Keeps its own host database and generates the ssh command — never edits ~/.ssh/config.
Fuzzy-search your SSH hosts and connect in two keystrokes.
sshelf keeps its own host list, builds the ssh command for you, and then gets out of the
way. It hands the terminal to real OpenSSH and never touches ~/.ssh/config.

macOS and Linux, x86_64 and arm64. The prebuilt packages need no Rust toolchain. At runtime sshelf wants OpenSSH 8.4+, which is where password auto-supply comes from.
Homebrew (macOS or Linux):
brew install max-rh/tap/sshelf
Shell installer (prebuilt binary, picks your platform):
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-rh/sshelf/releases/latest/download/sshelf-installer.sh | sh
Debian/Ubuntu: grab the .deb from the
latest release, then
sudo apt install ./sshelf_*_amd64.deb (or *_arm64.deb).
Fedora / RHEL / Rocky / openSUSE: grab the .rpm (static build, works on any RPM
distro) from the latest release, then
sudo dnf install ./sshelf-*.x86_64.rpm (or .aarch64.rpm).
Gentoo: community-maintained overlay (unofficial, thanks to @masterwolf-git). Run
eselect repository enable masterwolf && emerge --sync && emerge --ask app-admin/sshelf.
Cargo (from crates.io; needs Rust 1.88+):
cargo install sshelf.
Shell tab-completion ships with every package. Open a new shell after installing. On Linux,
secrets use a pure-Rust Secret Service backend (no libdbus/OpenSSL build deps).
Full details and completions setup: Install guide.
I run a couple of dozen machines (a homelab, some VPSes, a few boxes behind a bastion), and
I kept typing ssh -J bastion -i ~/.ssh/some-key -p 2222 user@host from memory or grepping my
shell history for it. Every SSH manager I tried wanted either to own ~/.ssh/config or to
give me an account and sync my hosts through someone's server. I didn't want either. I wanted
a launcher that keeps its own list, builds the command, and gets out of the way. And a place
to keep the passwords for the handful of hosts that can't use keys, without ever putting them
in a file. So I built it.
Type to filter. Enter connects. Your most-used hosts float to the top on their own
(frecency: usage count, decayed by recency), and tag:prod / site:homelab narrow the list
further. Ctrl-y copies the command it built instead of running it. From the shell,
sshelf prod-web connects by name and sshelf - reconnects to the last host, both without
opening the TUI.

exec()s into your sshsshelf builds the argv from the host record, tears its own UI down, and then replaces itself
with OpenSSH. There is no wrapper between you and the session: a real TTY, your ssh, your
config-free flags. When the session ends you're back at your shell, not in a menu. The
command it runs is exactly the one Ctrl-y shows you.
How the command is built.
Ctrl-t opens your files on the left and the host's on the right, over a single authenticated
connection. Space marks, Ctrl-a marks everything the filter shows, Ctrl-s sends the
whole set either way, F7 makes a directory. A name the destination already has is skipped,
never overwritten.

Ctrl-f opens a Local, Remote, or SOCKS tunnel that keeps running after you quit sshelf,
and after you close the terminal. F4 lists every one of them across all hosts and stops the
one you pick. They're tracked by pid and reconciled against the processes that are really
running, so nothing lingers in a list after it dies. No daemon, no supervisor.

Set tmux = "window" or "pane" and Enter opens the host in a new tmux window (named after
the host) or a new pane instead of replacing sshelf. End the session and the picker is still
sitting there, still running.

F3 manages sites: a site groups hosts and can carry a shared bastion, user, port, and key
that its members inherit at connect time, filling in only the fields a host leaves unset. Tags
are free-form labels you filter on. Both show up in the list, and an inherited bastion shows
up in the command sshelf builds.

sshpassFor the hosts that can't use keys, sshelf stores the password in your OS keyring (or an
age-encrypted vault on a headless box) and supplies it through SSH_ASKPASS when ssh asks.
The helper is told which secret it is holding, so a password host answers a password prompt
and a key host answers only its own key's passphrase prompt. A server that asks for the other
one gets nothing, and a key host is connected with PreferredAuthentications=publickey so it
cannot be asked in the first place. The password is never in a file, never in ps, never on a
command line. Hosts that also want a verification code get a prompt for it before
the connection starts. Passwords, keys & 2FA
· Security.
