Open source · free

An SSH client that keeps its vault shut.

Hosts, keys, passwords, two-pane SFTP, port forwarding, serial consoles and mosh — in one window, or one binary. Everything it knows about your servers is encrypted on your own machine.

$tm connect prod-1
bastion — ubuntu-fra
$ tm ls
ID          NAME         ADDRESS          USER  GROUP       TAGS
github.com  github.com   github.com       git
fra1        ubuntu-fra   164.92.231.103   root  production  prod

$ tm run disk --tag prod
✓ ubuntu-fra   1.9s  /dev/vda1  58G  11G  47G  20% /
✓ web-2        2.1s  /dev/sda1  40G  22G  17G  57% /
✗ db-1         timeout after 60s

$ tm tunnel add pg --local 5433 --to localhost:5432 --host fra1
→ 127.0.0.1:5433 → localhost:5432   loopback only
Download · v0.1.0

Pick your machine.

The window is a native macOS app today. Windows and Linux get the command-line tool, which does everything except draw the window — and it is the same vault, the same hosts, the same keys.

macOS App

Apple Silicon. The full window: tabs, SFTP, tunnels, serial, themes.

Bastion.app · 3.6 MB

Also: CLI arm64 · Intel

Windows CLI

The command-line tool. No window yet — see the note below.

tm.exe · x64 · 4.1 MB

Also: ARM64

Linux CLI

The command-line tool, static binary. No window yet.

tm · x86_64 · 4.0 MB

Also: ARM64

macOS will refuse to open it the first time. The app is not signed with an Apple Developer certificate yet, so Gatekeeper calls it damaged. It is not. Right-click the app and choose Open, or run:

xattr -d com.apple.quarantine /Applications/Bastion.app

Why no window on Windows and Linux? The window is built on the system web view — WebView2 on Windows, WebKitGTK on Linux — and neither has been compiled or tested yet. Shipping a build nobody has run would waste your time, so it is not offered until it is.

Checksums: SHA256SUMS · verify with shasum -a 256 -c SHA256SUMS

What it does

Everything a day on other people's servers needs.

Hosts that inherit

Nested groups pass down the user, the key, the jump host and the port. Set it once on production, not on forty machines.

SFTP in two panes

Local on the left, remote on the right. Browse, upload, download, rename, make directories, with progress.

Port forwarding

Local, remote and dynamic SOCKS5. Forwards bind to loopback by default, so a database port does not land on the café wifi.

Snippets across a fleet

Save the command you run everywhere, tick the hosts, run it on all of them at once. Every host reported, failures included.

Serial consoles

USB adapters, with the baud rates that matter first. The one thing a terminal app does that SSH cannot — for the switch that has no network yet.

Real mosh

The actual UDP protocol against mosh-server, not SSH wearing its name. Survives a change of network.

Jump hosts that nest

A bastion, then the box behind it, then the box behind that. Each hop carries its own credentials, and each host key is checked.

A session log you can check

What connected, from where, and when — append-only, and chained so editing it by hand is detectable.

Encrypted where it sits

Hosts, addresses, usernames, tags, snippets and your command history — all encrypted on disk under one master passphrase.

Security

What is protected, and what is not.

A security page that only lists good news is marketing. Here is the whole picture.

ThingWhere it lives
Hosts, addresses, users, tags, snippetsEncrypted on your disk
Saved passwordsEncrypted on your disk
Command historyEncrypted on your disk
Session logEncrypted, and chained
Private keysLeft in ~/.ssh, referenced — never copied
Your master passphraseNever written down. Lose it and the vault is gone.

Argon2id derives a key-encryption key from your passphrase; that wraps a random data key; XChaCha20-Poly1305 encrypts each file with its purpose bound in. Changing the passphrase rewrites one wrapped key, not your data.

master passphrase │ ├─ Argon2id ──▶ key-encryption key │ │ │ └─ unwraps ──▶ data key │ │ └─ never stored ├─▶ vault.enc ├─▶ history.enc └─▶ sessions.enc

Honest limits

The session log is tamper-evident, not tamper-proof. Editing it by hand is caught — each record carries the digest of the one before, and the head digest is kept in the system keychain. But anyone who controls the machine can recompute the whole chain. Real proof needs a head digest held somewhere they do not control.

There is a sync server, and its design is end-to-end encrypted — the server stores ciphertext it has no key for. It is not for sale and not switched on, because the cryptography has not been audited by anyone outside this project. It will stay off until it has.

Install

One binary, no runtime.

macOS & Linux

Unpack and put it on your path.

tar xzf tm-v0.1.0-<os>-<arch>.tar.gz
sudo mv tm /usr/local/bin/
tm --version

Windows

Unzip tm.exe anywhere on your PATH.

tm.exe add --id web1 --address 10.0.0.5 --user root
tm.exe connect web1

Or build it yourself — Go 1.26 and make app on a Mac, go build ./cmd/tm anywhere.