#devops #tui #monitoring #terminal #ssh

app essh

Enterprise SSH client with concurrent sessions, real-time host diagnostics, and a Netwatch-inspired TUI

6 releases

new 0.2.4 Mar 2, 2026
0.2.3 Mar 2, 2026
0.1.0 Feb 28, 2026

#958 in Network programming

MIT license

4MB
9K SLoC

                         ███████╗███████╗███████╗██╗  ██╗
                         ██╔════╝██╔════╝██╔════╝██║  ██║
                         █████╗  ███████╗███████╗███████║
                         ██╔══╝  ╚════██║╚════██║██╔══██║
                         ███████╗███████║███████║██║  ██║
                         ╚══════╝╚══════╝╚══════╝╚═╝  ╚═╝
                          Enterprise SSH Client for the Terminal

crates.io Build Status License: MIT

A pure-Rust SSH client with a rich TUI — concurrent sessions, real-time host monitoring, fleet management, and connection diagnostics. All from your terminal.


✨ Feature Highlights

Feature Description
Pure-Rust SSH Built on russh — no libssh/OpenSSH dependency. Public key, password, & SSH agent auth with TOFU host key verification.
Concurrent Sessions Up to 9 simultaneous SSH sessions with instant Alt+1-9 switching, Alt+/ cycling, and Alt+Tab last-used recall.
Virtual Terminal Full ANSI escape sequence rendering via vt100::Parser — colors, cursor positioning, and alternate screen all work correctly.
Host Monitor Real-time remote htop: CPU sparklines, memory bars, disk usage, network I/O, and top processes — all collected over SSH exec channels (no agent required).
Connection Diagnostics Live RTT, throughput (↑/↓), packet loss, and a 5-tier connection quality score per session. JSONL diagnostic logs for replay.
Fleet Management Tag-based host groups, bulk command execution with parallel fan-out, and SSH config import.
Live Fleet Health Background TCP probes with per-host latency sparklines and colour-coded status (green/yellow/red). Configurable probe interval.
Host Search & Filter Press / to live-filter hosts by name, hostname, tags, or status. Navigate filtered results with /.
Auto-Reconnect Exponential backoff reconnection on disconnect (2s → 30s cap). Scrollback preserved across reconnects. Tab bar shows ● Recon. 2/5.
Session Recording Record terminal I/O to asciicast v2 files. Replay with essh session replay <id> — pause, speed control (0.25×–16×), and quit.
Audit Logging Structured JSON audit trail — connection attempts, auth results, host key events, session lifecycle.
Split-Pane View Alt+s splits terminal + host monitor side-by-side. Adjustable width with Alt+[/Alt+] (20–80% range).
Jump Host / ProxyJump Connect through bastion hosts via jump_host config. SSH-over-SSH using direct-tcpip channels. Status bar shows hop path.
File Transfer Alt+f opens a two-pane file browser. Upload/download via SSH exec channels. Transfer progress bar.
Port Forwarding Alt+p manages local TCP port forwards. Live add/remove with SSH direct-tcpip proxy. Active forwards shown in status bar.
Background Notifications Regex-based alerts when background sessions match patterns (e.g. ERROR, build complete). Yellow ! tab indicator.
Command Palette Ctrl+p opens a fuzzy-matched command palette — jump to hosts, sessions, views, or actions instantly. Multi-word scoring with prefix bonuses.
TUI Dashboard 4-tab dashboard (Sessions, Hosts, Fleet, Config) with a Netwatch-inspired Cyan/Yellow/DarkGray aesthetic.

🎬 Demo

ESSH Demo

7 key views: Dashboard → Session Terminal → Host Monitor → Split-Pane → Command Palette → File Browser → Port Forwarding


🖥️ TUI Preview

Dashboard — Hosts Tab

┌──────────────────────────────────────────────────────────────────────┐
│ ESSH[1] Sessions  [2] Hosts  [3] Fleet  [4] Config  │ ?:Help │ 14:32:07 │
├──────────────────────────────────────────────────────────────────────┤
│ Hosts (4)                                                            │
│                                                                      │
│  Name            Hostname             Port  User     Status          │
│ ─────────────────────────────────────────────────────────────────── │
│» web-prod-1      10.0.1.10            22    deploy   ● Online        │
│  web-prod-2      10.0.1.11            22    deploy   ● Online        │
│  db-primary      10.0.2.10            22    dba      ● Online        │
│  staging-1       10.0.3.5             2222  matt     ○ Unknown       │
│                                                                      │
├──────────────────────────────────────────────────────────────────────┤
│ Enter:Connect  Alt+1-9:Session  a:Add  /:Search  r:Refresh  q:Quit │
└──────────────────────────────────────────────────────────────────────┘

Session View — Active Terminal

┌──────────────────────────────────────────────────────────────────────┐
│ ESSH ── [1] web-prod-1  [2] db-primary  [3] staging-1 ── 14:33:42 │
├──────────────────────────────────────────────────────────────────────┤
│ deploy@web-prod-1:~$ htop                                          │
│                                                                      │
│  (full terminal output — colors, cursor, alternate screen)          │
│                                                                      │
│                                                                      │
│                                                                      │
├──────────────────────────────────────────────────────────────────────┤
│ RTT:12.3ms  ↑1.2KB/s  ↓48.5KB/s  Loss:0.0%  ●Excellent  Up:1h24m │
├──────────────────────────────────────────────────────────────────────┤
│ Alt+←→:Switch  Alt+s:Split  Alt+f:Files  Alt+p:Fwd  Alt+d:Detach  Alt+w:Close│
└──────────────────────────────────────────────────────────────────────┘

Host Monitor — Remote htop (Alt+m)

┌──────────────────────────────────────────────────────────────────────┐
│ ESSH ── [1] web-prod-1  [2] db-primary ────────────── 14:34:18     │
├──────────────────────────────────────────────────────────────────────┤
│ CPU   23.4%  ▁▂▃▃▂▅▃▂▁▂▃▄▅▆▅▃▂▁▂▃▃▂▁▁▂▃▅▆▅▃▂▂▃▃▂▁▂▃▃▂          │
│       ████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 23%                  │
│       Core 0: ██████░░░░░  28%    Core 1: █████░░░░░░  19%          │
│       Core 2: ███████░░░░  31%    Core 3: █████░░░░░░  15%          │
│──────────────────────────────────────────────────────────────────── │
│ MEM   3.2G / 8.0G (40%)  Swap: 0B / 2.0G                          │
│       ▁▁▂▂▂▂▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃▃                  │
│       ████████████████░░░░░░░░░░░░░░░░░░░░░░░░ 40%                  │
│──────────────────────────────────────────────────────────────────── │
│ LOAD  0.82  0.64  0.55    UPTIME  14d 6h 32m                      │
│──────────────────────────────────────────────────────────────────── │
│ DISK  /               12.4G      7.6G ██████████ 62%                │
│       /data           84.2G    115.8G █████░░░░░ 42%                │
│──────────────────────────────────────────────────────────────────── │
│ NET   RX ▁▂▃▂▁▂▃▅▃▂▁ 48.5KB/s   TX ▁▁▁▂▁▁▁▂▁▁▁ 1.2KB/s          │
│──────────────────────────────────────────────────────────────────── │
│ Top Processes (by CPU)                                              │
│  PID     Name                      CPU%    MEM%    RSS              │
│  1842    node                       8.2     3.1    256M             │
│  2104    nginx                      4.1     0.8     64M             │
│  3921    postgres                   3.7     5.2    420M             │
│  1203    containerd                 2.1     1.4    112M             │
├──────────────────────────────────────────────────────────────────────┤
│ Esc:Terminal  s:Sort(→mem)  p:Pause  r:Refresh  ↑↓:Scroll          │
└──────────────────────────────────────────────────────────────────────┘

📦 Installation

From crates.io

cargo install essh

From Source

git clone https://github.com/matthart1983/essh.git
cd essh
cargo build --release
# Binary is at ./target/release/essh

🚀 Quick Start

# Launch the TUI dashboard
essh

# Direct connect to a host
essh connect user@hostname

# Connect with a specific key
essh connect user@hostname -i ~/.ssh/id_ed25519

# Connect with password authentication
essh connect user@hostname --password

# Import hosts from your SSH config
essh hosts import

# Run a command across a host group
essh run web-servers -- uptime

On first launch, ESSH creates ~/.essh/ with a default config.toml. Navigate the Hosts tab, select a host, and press Enter to connect.


⚙️ Configuration

ESSH uses a TOML config file at ~/.essh/config.toml. Initialize or edit it:

essh config init    # Create default config
essh config edit    # Open in $EDITOR
essh config show    # Print current config

Example Configuration

[general]
default_user = "deploy"
default_key = "~/.ssh/id_ed25519"
tofu_policy = "prompt"       # strict | prompt | auto
cache_ttl = "30d"
log_level = "info"

[diagnostics]
enabled = true
display = "status_bar"       # status_bar | overlay | hidden
export_format = "jsonl"
keepalive_interval = 15

[host_monitor]
enabled = true
cpu_interval = 1
memory_interval = 2
process_count = 15
history_samples = 60

[session]
auto_reconnect = true
reconnect_max_retries = 5
max_concurrent = 9
scrollback_lines = 10000
recording = false            # Set true to record sessions as asciicast v2
notification_patterns = []

[fleet]
probe_enabled = true
probe_interval = 60          # Seconds between TCP health probes
probe_timeout = 5            # Seconds before probe timeout
latency_history_samples = 30 # Sparkline data points per host

[security]
min_key_bits = 3072
allowed_ciphers = [
    "chacha20-poly1305@openssh.com",
    "aes256-gcm@openssh.com",
    "aes128-gcm@openssh.com",
]
allowed_kex = [
    "curve25519-sha256",
    "curve25519-sha256@libssh.org",
]

[audit]
enabled = true

# Define hosts
[[hosts]]
name = "web-prod-1"
hostname = "10.0.1.10"
port = 22
user = "deploy"
key = "~/.ssh/deploy_key"

[hosts.tags]
env = "production"
role = "web"

[[hosts]]
name = "db-primary"
hostname = "10.0.2.10"
user = "dba"
jump_host = "web-prod-1"

[hosts.tags]
env = "production"
role = "database"

# Define host groups (matched by tags)
[[host_groups]]
name = "web-servers"

[host_groups.match_tags]
role = "web"

[host_groups.defaults]
user = "deploy"
key = "~/.ssh/deploy_key"

Data Directory Structure

~/.essh/
├── config.toml          # Main configuration
├── cache.db             # SQLite host key & host cache
├── audit.log            # Structured JSON audit log
├── sessions/            # Per-session diagnostic logs (JSONL)
├── recordings/          # Session recordings (if enabled)
└── known_cas/           # Trusted CA certificates

⌨️ Keyboard Reference

Global (all views)

Key Action
? / Alt+h Toggle help overlay
Alt+1Alt+9 Jump to session N
Alt+ / Alt+ Cycle to previous / next session
Alt+Tab Switch to last-used session
Alt+m Toggle host monitor
Alt+d Detach to dashboard
Alt+w Close active session
Alt+r Rename active session
Alt+s Toggle split-pane view
Alt+[ / Alt+] Adjust split-pane width
Alt+f File browser (upload/download)
Alt+p Port forwarding manager
Ctrl+p Command palette (fuzzy finder)

Dashboard

Key Action
14 Switch tab (Sessions / Hosts / Fleet / Config)
j / k / / Navigate host list
Enter Connect to selected host
a Add host
/ Live search/filter hosts
r Refresh host list
d Delete selected host
q / Ctrl+c Quit

Session Terminal

Key Action
(all keys) Forwarded directly to the remote shell

Host Monitor

Key Action
Esc Return to terminal view
s Toggle sort (CPU ↔ Memory)
p Pause metric collection
r Force refresh
/ Scroll process list

📋 CLI Reference

essh                                  Launch TUI dashboard
essh connect <user@host>              Direct SSH connection
  -p, --port <PORT>                     Port (default: 22)
  -i, --identity <FILE>                 Private key file
  --password                            Use password auth

essh hosts list [--tag key=value]     List cached hosts
essh hosts add <hostname>             Add host to cache
  -p, --port <PORT>                     Port (default: 22)
  -n, --name <NAME>                     Display name
  -u, --user <USER>                     Username
  --tag <key=value>                     Tag (repeatable)
essh hosts remove <hostname>          Remove host from cache
essh hosts import [path]              Import from SSH config
essh hosts health [--group <name>]    Run TCP health checks

essh keys list                        List cached keys
essh keys add <path> [-n name]        Add a private key
essh keys remove <name>               Remove a key

essh session list                     List session recordings
essh session replay <id>              Replay recorded session (asciicast)
                                        Space:pause  +/-:speed  q:quit

essh diag <session_id>                Show session diagnostics

essh run <group> -- <command>         Execute across a host group

essh config init                      Initialize default config
essh config edit                      Open config in $EDITOR
essh config show                      Print current config

essh audit tail [-l lines]            Show recent audit entries

🔐 Security

  • TOFU Host Key Verification — Three policies: strict (reject unknown), prompt (ask user), auto (trust on first use). Host key fingerprints are cached in SQLite.
  • Configurable Cipher Suites — Restrict allowed ciphers, key exchange algorithms, and MACs.
  • Minimum Key Strength — Enforce minimum key bit length (default: 3072).
  • Structured Audit Trail — Every connection attempt, auth result, and host key event is logged as structured JSON.

🏗️ Architecture & Tech Stack

Layer Crate Purpose
SSH Protocol russh, russh-keys Pure-Rust SSH2 client implementation
TUI Framework ratatui, crossterm Terminal UI rendering and input
Terminal Emulation vt100 Virtual terminal with ANSI escape parsing
Database rusqlite (bundled) Host key cache, host/key management
Async Runtime tokio Async I/O, task spawning, timers
CLI clap (derive) Command-line argument parsing
Serialization serde, serde_json, toml Config, audit logs, diagnostics
Crypto sha2, base64 Fingerprint hashing
Utilities chrono, uuid, dirs, thiserror, anyhow Time, IDs, paths, errors
Pattern Matching regex Background notification pattern matching

Module Structure

src/
├── main.rs              # Entry point, TUI event loop, CLI dispatch, auto-reconnect
├── cli/                 # Clap command definitions
├── config/              # TOML config parsing & defaults (incl. [fleet] section)
├── ssh/                 # russh client, auth (key/password/agent), host key verification
├── session/             # Session state, VirtualTerminal (vt100), SessionManager
├── tui/                 # TUI views
│   ├── dashboard.rs     # Dashboard with 4 tabs, host search/filter bar
│   ├── session_view.rs  # Terminal renderer, tab bar, status bar
│   ├── host_monitor.rs  # CPU/MEM/Disk/Net/Process panels
│   ├── filebrowser_view.rs  # Two-pane file browser UI
│   ├── portfwd_view.rs      # Port forwarding manager panel
│   ├── help.rs          # Help overlay popup
│   ├── command_palette.rs  # Fuzzy-matched command palette (Ctrl+P)
│   └── widgets.rs       # Sparklines, bar gauges, formatters
├── filetransfer/        # Two-pane file browser, upload/download via SSH exec
├── fleet/               # Live fleet health — background TCP probes, latency tracking
├── notify/              # Background activity notification matching (regex)
├── portfwd/             # Port forwarding manager, local TCP proxy
├── recording/           # Session recording (asciicast v2) & replay
├── monitor/             # Remote host metric collection
│   ├── collector.rs     # SSH exec-based metric gathering
│   ├── parser.rs        # /proc & command output parsing
│   └── history.rs       # Sparkline ring buffers
├── diagnostics/         # Connection quality engine, JSONL logging
├── cache/               # SQLite host key & host/key CRUD
├── audit/               # Structured JSON audit logger
└── event.rs             # Async event handler (keys, ticks, SSH data)

🤝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Make your changes with tests (cargo test)
  4. Ensure formatting (cargo fmt) and lints pass (cargo clippy)
  5. Open a pull request

Building & Testing

cargo build              # Debug build
cargo build --release    # Release build
cargo test               # Run all tests (154 tests)
cargo clippy             # Lint checks
cargo fmt --check        # Format check

📄 License

MIT — see LICENSE for details.


Built with 🦀 Rust — inspired by the Netwatch aesthetic

Dependencies

~115–155MB
~3M SLoC