better-ssh

Remember your servers, not their arguments.

A thin layer over OpenSSH that stores everything you would otherwise keep in a scratchpad — hosts, jump chains, port forwards, passwords, file transfers, pre/post hooks — and gives you back bssh.

uv tool install git+https://github.com/aa-blinov/better-ssh.git@v0.3.0

Requires Python 3.12+ and an OpenSSH client.

The SSH config-file arms race

If you connect to more than a handful of servers, you've felt this. IPs live in a Notion page. Passwords live in a password manager that you manually paste into the terminal. Jump hosts get re-typed. Port forwards get forgotten between sessions. Your shell history fills up with command fragments you stitched together last time.

~/.ssh/config helps — until you need more than what ssh_config can express: a password that stays encrypted on disk, port forwards attached to the server (not per invocation), or a local aws sso login that has to run before every connect.

Before / after

Today

$ # which server was that again?
$ # let me open 1Password…
$ ssh -J bastion_ops \
    deploy@prod-db.internal \
    -p 2222 \
    -i ~/.ssh/work_ed25519 \
    -L 5432:localhost:5432
# paste password from clipboard
# it's always a login shell for this one

With better-ssh

$ bssh prod-db
Password copied to clipboard.
SSH: ssh -p 2222 -L 5432:localhost:5432
  -J deploy@bastion:22
  -i /home/u/.ssh/work_ed25519
  deploy@prod-db.internal
# paste, done.

Same OpenSSH under the hood. better-ssh just stores what you'd otherwise keep in your head.

What you get

Interactive picker

Fuzzy search across names, tags, and hosts. Recent connections bubble to the top. Pin the ones you hit daily.

Encrypted password clipboard

Optional Fernet encryption keyed to your SSH private key (PBKDF2-HMAC-SHA256, per-installation salt). Copied to clipboard on connect, never injected into the process list.

Jump-host chains baked in

--jump bastion once, and bssh rebuilds the full -J chain on every connect. Multi-hop bastions, cycle detection, and cascade cleanup on removal all handled.

Port forwards as server profile

-L, -R, and dynamic SOCKS -D stored per-server. No more -hunting for the forward spec you built last week.

Parallel command broadcast

bssh exec "uptime" prod runs concurrently across every matched host with per-host colored output and an aggregated pass/fail summary. Scales to low hundreds.

Pre- and post-connect hooks

Bring a VPN up before each connect. Mount sshfs and unmount on exit. Refresh an AWS SSO token. Local shell, runs around ssh itself.

SSH config round-trip

bssh isc imports your existing ~/.ssh/config via ssh -G. bssh esc writes it back out as Host blocks other tooling can read.

Scripts-friendly by design

Every destructive op has a non-interactive flag (--yes, --force, --skip). Exit codes match Unix convention. Output stays terminal-width friendly.

File transfer, batteries included

bssh put and bssh get for one-shot transfers. bssh sftp drops into an interactive session when you need to browse first. Jump chain, port, key — all inherited from the server profile, nothing retyped.

Who is this for?

If you have three servers and your muscle memory already covers them, ssh is still the right tool. No shame in it.

Get started

Install (wheel from the latest release):

uv tool install git+https://github.com/aa-blinov/better-ssh.git@v0.3.0

Import what you already have and go:

$ bssh isc                    # imports ~/.ssh/config
$ bssh                        # interactive picker
$ bssh prod-db                # direct connect when the query is unique
$ bssh exec "uptime" prod     # one command, every matching host

Full reference — every command, every flag, every edge case — lives in the README.