3D scene: the portico of the Portico logo, an entablature on two columns, its lit arch crossed by a tunnel of rings and a stream of particles.

SSH client · Rust · macOS & Linux

The gateway to your servers.

Portico is a local-first, fast, keyboard-first SSH session manager. One Rust engine, two interfaces: a TUI and a GUI. Your ~/.ssh/config stays the source of truth.

  • {rust:1.90}
  • {unsafe:forbid}
  • {cloud:0}
  • {tui:<100ms}
Scroll to step in

kex curve25519-sha256

Principles

Your setup is the source of truth.

Portico reads ~/.ssh/config, known_hosts, ssh-agent and your keys. It never rewrites your configuration: its own metadata (tags, favourites, groups) lives alongside, in readable TOML. No account, no forced sync, no lock-in.

  1. P.001

    Zero lock-in

    Data in readable, versionable TOML. Delete Portico and your SSH setup has not moved.

  2. P.002

    Keyboard-first

    Every action has a shortcut. The ⌘K palette exposes everything; the mouse is never required.

  3. P.003

    Performance

    The TUI is usable in under 100 ms from cold. No redraw when nothing changes.

  4. P.004

    OpenSSH semantics

    Include, Match, ProxyJump, tokens, authentication order: exactly what OpenSSH does.

0 accounts, cloud or telemetry. Everything works offline.

7 MB of memory at rest for the TUI, with a terminal open.

0.5 s to print 500,000 lines in the TUI terminal.

140 + tests, including an in-process SSH server and real OpenSSH interop.

Interfaces

One engine. Two interfaces.

portico-core does all the work: sessions, authentication, SFTP, tunnels. The TUI lives in your terminal, the GUI in a native window. Same engine, same shortcuts, same themes.

~ portico 92×26
 ╭┴┴╮ PORTICO  │▍Hosts 9                                                           Obsidian 
 ╭──────────────────────────────────────╮ ╭───────────────────────────────────────────────╮ 
 │ ⌕ Search hosts   /                   │ │                                               │ 
 ╰──────────────────────────────────────╯ │  db-prod                                      │ 
 ╭ Hosts ───────────────────────────────╮ │  postgres@10.0.4.12:22                        │ 
 │ ▍● db-prod ★  postgres@10.0.4.12 #pro│ │                                               │ 
 │  ● bastion  ops@bastion.example.com #│ │  ● Disconnected                               │ 
 │  ● web-01  deploy@web-01.internal #pr│ │                                               │ 
 │  ● staging  deploy@staging.example.co│ │   ↵  connect                                  │ 
 │  ● nas ★  admin@nas.home.arpa #home  │ │                                               │ 
 │  ● api-01  deploy@api-01.internal #pr│ │  Jump          bastion → db-prod              │ 
 │  ● gitlab-runner  gitlab-runner@runne│ │  Forward -L    5432 localhost:5432            │ 
 │  ● raspberry  pi@192.168.1.42 #home #│ │  Tags          #prod #db                      │ 
 │  ● homelab-k3s  ubuntu@192.168.1.60 #│ │  Defined in    ~/.ssh/config:12               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 │                                      │ │                                               │ 
 ╰──────────────────────────────────────╯ ╰───────────────────────────────────────────────╯ 
  HOSTS   ↵ connect   / search   d disconnect   t theme   ? help                            

Try it: j / k to move, ↵ to connect, / to search, t for the theme.

Rendering
ratatui 0.30 · crossterm
Emulator
alacritty_terminal · 10,000 lines
Tabs
Ctrl-Space prefix, tmux-style

Three dark themes

This site runs on portico-theme tokens: switch theme and the whole page follows.

Features

The MVP, line by line.

Fourteen features, shipped in phases. Each phase closes with three reviews: security, SSH protocols and design.

  • Shipped 08
  • In progress 02
  • Planned 04
  1. F.001 ~/.ssh/config parsing Shipped

    Host, Match, Include, wildcards, inheritance, tokens and ProxyJump, with OpenSSH first-wins semantics. Custom parser, fully tested.

  2. F.002 Fuzzy search, tags and favourites Shipped

    nucleo matcher (from Helix), smart-case. #tag filters by tag, * by favourite.

  3. F.003 Interactive SSH sessions Shipped

    xterm-256color PTY, tabs, live resize, vim and htop work. Recursive ProxyJump, up to 8 hops.

  4. F.004 SFTP browser and transfers Shipped

    Midnight Commander-style dual panes in the TUI, list and drag-and-drop in the GUI. Progress, cancel, conflict handling.

  5. F.005 Local and remote port forwarding Shipped

    -L and -R, bound to localhost by default. Forwards from ssh_config are offered, never started on their own.

  6. F.006 Strict known_hosts Shipped

    Hashed entries, @cert-authority, @revoked. A changed host key always means a hard refusal.

  7. F.007 Connection status and latency Shipped

    connecting → authenticating → connected, with RTT measured through keepalive@openssh.com. Errors come with an actionable hint.

  8. F.008 Three themes, documented shortcuts Shipped

    Obsidian, Basalt, Travertine Night. Contrast tested: primary text AAA, secondary AA.

  9. F.009 Keys, agent and SSH certificates In progress

    Key and certificate discovery shipped. Agent management and certificate expiry warnings come in phase 3.

  10. F.010 Secrets in the keyring In progress

    macOS Keychain and Linux Secret Service already in use. Encrypted fallback vault (Argon2id, XChaCha20-Poly1305) in phase 3.

  11. F.011 Key generation Planned

    ed25519 by default, RSA 3072+ and ECDSA, with a passphrase. Refuses to overwrite an existing key.

  12. F.012 Public key copy Planned

    The ssh-copy-id equivalent, idempotent, verified by reconnecting with the key.

  13. F.013 Snippets Planned

    Global, per host or per tag, with placeholders. Run in the active tab from the palette.

  14. F.014 Recent sessions and debug panel Planned

    History, editable favourites, per-session connection logs and an “effective config” view à la ssh -G.

Architecture

Event-driven, end to end.

The engine publishes events on a control plane. Terminal bytes travel on dedicated, bounded channels. A slow UI never slows a session down.

Fig. 02 · Engine and interfaces

Security

No secret in clear text. Ever.

Secure by design, checked by an audit agent at the end of every phase: every critical and high finding was fixed before moving on.

Portico’s blocking alert: host key changed for staging, expected and received fingerprints, the ssh-keygen -R command, a single Close button.
Real capture · GUI · Obsidian
  • S.01

    System keyring

    Passwords and passphrases in Keychain or Secret Service, bound to the host’s verified identity.

  • S.02

    Changed key = refusal

    Even with StrictHostKeyChecking no. No “accept” button: the exact ssh-keygen -R command is shown.

  • S.03

    No SHA-1

    ssh-rsa removed from host key algorithms. aws-lc-rs crypto backend, no libssh2 in C.

  • S.04

    Sanitised paste

    ESC and C1 controls stripped before reaching the terminal. A paste never answers a host key dialog.

  • S.05

    Clean logs

    No secret and no terminal content in logs or events. Debug output is redacted.

  • S.06

    Strict Rust

    forbid(unsafe_code), zero unwrap outside tests, clippy pedantic with no warning.

Keyboard

Hands stay on the keys.

One grammar for the TUI and the GUI. Press the keys: the shortcuts light up.

Hosts

  • j k Move down / up
  • / Fuzzy search, #tag, *
  • ↵ Connect
  • d Disconnect
  • f Files (SFTP)
  • p Tunnels
  • t Switch theme
  • ? Help

Terminal · TUI

  • Ctrl Space Command prefix
  • ␣ n New tab, same host
  • ␣ w Close tab
  • ␣ 1…9 Go to tab n
  • ⇧ PgUp Scrollback

GUI · ⌘ / Ctrl-Shift

  • ⌘ K Command palette
  • ⌘ T New tab
  • ⌘ W Close tab
  • ⌘ ⇧ F Files beside the terminal
  • ⌘ 1…9 Tab n

Tip: the t key switches this site’s theme, just like in Portico.

All shortcuts

Roadmap

Shipped in phases, checked at every step.

  1. Phase 00

    Shipped

    Foundations

    Workspace, strict lints, ssh_config parser, inventory, themes, TUI and GUI shells.

  2. Phase 01

    Shipped

    Interactive sessions

    Transport, known_hosts, OpenSSH-order auth, ProxyJump, PTY and terminals in both UIs.

  3. Phase 02

    Shipped

    SFTP and tunnels

    File browsers, streamed transfers, -L and -R forwarding, Tunnels panel.

  4. Phase 03

    In progress

    Keys, secrets, snippets

    Generation, copy-id, agent, encrypted fallback vault, snippets with placeholders.

  5. Phase 04

    Planned

    MVP polish

    Recents, favourites, debug panel, configurable shortcuts, .dmg, .deb and AppImage packages.

After that

  • SOCKS5 (-D)
  • Split panes
  • asciicast recording
  • Optional local sync
  • Windows
  • Mosh
  • Termius import

Install

Build it tonight.

Portico is under active development. Until the signed packages of phase 4, build it from source with Rust 1.90+.

~/src bash
  1. 01 · Clone
    git clone https://github.com/fs0ciety7000/Portico && cd Portico
  2. 02 · TUI
    cargo run --release -p portico-tui
  3. 03 · GUI
    cd apps/portico-gui && pnpm install && pnpm tauri dev

Linux: the GUI needs libwebkit2gtk-4.1-dev. Licensed MIT OR Apache-2.0.

Questions

Before you start.

Q.001 Does Portico modify my ~/.ssh/config?

No, never. Portico reads it. Its own metadata lives in hosts.toml. The only writes to ~/.ssh are known_hosts additions after you agree, and keys you ask it to generate.

Q.002 Do I need an account or an Internet connection?

No. No account, no remote service, no telemetry. Portico works entirely offline.

Q.003 Why both a TUI and a GUI?

Because some people live in tmux and others in windows. The engine is the same: identical behaviour, security and shortcuts.

Q.004 What about Windows?

macOS and Linux first. Windows is on the post-MVP roadmap.

Q.005 How does Portico compare to Termius?

Portico is open, local and subscription-free. It respects your OpenSSH configuration instead of replacing it, and a Termius import is planned after the MVP.

Q.006 What is the licence?

MIT OR Apache-2.0, at your option.