A modern, interactive terminal UI for managing SSH connections
SSHC transforms your ~/.ssh/config into a searchable, navigable interface — letting you connect to servers, transfer files, and manage hosts without memorizing hostnames or typing lengthy commands.
Built with Go and the Charm ecosystem. Continuation of sshm.
curl -fsSL https://raw.githubusercontent.com/xvertile/sshc/main/install/install.sh | bashHomebrew
brew tap xvertile/sshc && brew install sshcFrom source
go install github.com/xvertile/sshc@latestClean, distraction-free interface with real-time host status
Add, edit, delete, and move SSH hosts through an interactive TUI or CLI.
- Parse
~/.ssh/configautomatically — or specify a custom config with-c - Include directive support with glob patterns and recursive parsing
- Multi-host declarations (
Host server1 server2 server3) - Tags for organizing hosts (
#production,#database) - ProxyJump configuration for bastion/jump host setups
- Custom SSH options per host (RemoteCommand, RequestTTY, etc.)
One-key connect — select a host, press Enter.
- Live status indicators — see which hosts are online before connecting
- Connection history — tracks last login time and connection count
- Sort by recent — quickly access frequently-used hosts
- Retry on failure — connection error view with instant retry option
Upload or download files without leaving the TUI.
- Remote file browser — navigate the remote filesystem to select paths
- Local file picker — native picker integration with TUI fallback
- SCP commands —
sshc cp ./file.txt host:/path/andsshc get host:/file ./ - Recursive transfers — full directory upload/download support
- Transfer history — logs all transfers per host
Upload public keys to remote hosts.
- Select from local keys — browses
~/.ssh/*.pubautomatically - Paste key directly — paste any public key without a local file
- Auto-config update — optionally add IdentityFile to host config after upload
Local, remote, and dynamic forwarding with saved configurations.
- Local forwarding (
-L) — expose remote services locally - Remote forwarding (
-R) — expose local services remotely - Dynamic forwarding (
-D) — SOCKS proxy - History — remembers previous port forward configurations per host
Real-time search across hosts by name, hostname, or tags.
- Multiple output formats — table, JSON, or simple (one per line)
- CLI search —
sshc search prod --tagsfor scripting
Manage K8s pods alongside SSH hosts in a unified interface.
kubectl execintegration with namespace, context, and container selection- Separate config — K8s hosts stored in
~/.config/sshc/k8s.yaml - Tags and organization — same tag system as SSH hosts
Themes, keybindings, and persistent preferences.
- Themes — Default, Nord, Dracula, and more
- Keybindings — customize quit keys, disable ESC for vim users
- Persistent preferences — sort mode, theme, search focus saved to config
sshc Interactive TUI
sshc <host> Connect directly
sshc add [name] Add a new host
sshc edit <host> Edit existing host
sshc search [query] Search hosts (--format json|table|simple)
sshc cp <src> <dst> SCP file transfer
sshc send <host> Upload with file picker
sshc get <host> Download with remote browser
sshc move <host> Move host between config files
sshc update Check for and install updates
Launch without arguments to enter the TUI:
sshcup/down, j/k Navigate hosts
enter Connect to selected host
a Add new host
e Edit selected host
d Delete selected host
m Move host to another config file
f Port forwarding setup
t File transfer
/ Search/filter hosts
s Switch sort mode (name/recent)
n Sort by name
r Sort by recent
tab Cycle filter modes
q Quit
- Green — host is reachable via SSH
- Yellow — currently checking connectivity
- Red — host is unreachable or connection failed
- Gray — status not yet determined
Connect to any configured host without entering the TUI:
sshc production-server
sshc db-staging
sshc web-01All direct connections are tracked in history. Use -c for custom config files:
sshc my-server -c /path/to/custom/ssh_configPress f while a host is selected to open the port forwarding interface.
Local (-L) — forward a local port to a remote host through the SSH connection
ssh -L 15432:localhost:5432 server
# Database on remote localhost:5432 becomes accessible at localhost:15432
Remote (-R) — forward a remote port back to a local service
ssh -R 8080:localhost:3000 server
# Local app on port 3000 becomes accessible from remote host's port 8080
Requirements for external access:
- SSH server config:
GatewayPorts yesin/etc/ssh/sshd_config - Firewall: open the remote port
- Bind address: use
0.0.0.0for external,127.0.0.1for local-only
Dynamic (-D) — create a SOCKS proxy
ssh -D 1080 server
# Configure browser to use localhost:1080 as SOCKS5 proxy
SSHC remembers forwarding configurations per host. Previously used setups appear as suggestions for quick reuse.
Manage Kubernetes pods alongside SSH hosts in a unified interface.
Kubernetes hosts are stored separately in ~/.config/sshc/k8s.yaml:
hosts:
- name: api-pod
namespace: production
context: prod-cluster
container: api
tags:
- production
- api
- name: worker-pod
namespace: staging
context: staging-cluster
tags:
- stagingkubectl execintegration with interactive shell- Namespace, context, and container selection
- Same tag system as SSH hosts
- Appears in the main host list alongside SSH entries
- Connection history tracking
kubectlinstalled and configured- Valid kubeconfig with cluster access
- Appropriate RBAC permissions for
exec
SSHC works directly with your ~/.ssh/config file. Custom configs can be specified with -c:
sshc -c /path/to/configOrganize configurations across multiple files:
# ~/.ssh/config
Include ~/.ssh/conf.d/*
Include work-servers.conf
Host personal
HostName personal.example.com
User me
The move command relocates hosts between included config files.
Built-in fields:
HostName— server addressUser— SSH usernamePort— SSH portIdentityFile— path to private keyProxyJump— jump host for tunnelingTags— custom tags (SSHC extension)
Any valid SSH option can be added through the forms. Enter in command-line format:
-o Compression=yes -o ServerAliveInterval=60
This converts to:
Compression yes
ServerAliveInterval 60
Common options: Compression, ServerAliveInterval, ServerAliveCountMax, StrictHostKeyChecking, UserKnownHostsFile, BatchMode, ConnectTimeout, ControlMaster, ControlPath, ControlPersist, ForwardAgent, LocalForward, RemoteForward, DynamicForward.
Configure in ~/.config/sshc/config.json:
{
"key_bindings": {
"quit_keys": ["q", "ctrl+c"],
"disable_esc_quit": true
}
}Set disable_esc_quit to true if you use vim and accidentally quit with ESC.
~/.config/sshc/
├── config.json # preferences, keybindings
├── history.json # connection history
├── k8s.yaml # kubernetes hosts
└── backups/ # automatic config backups
Backups are created automatically before any configuration change.
macOS / Linux
- Standard config:
~/.ssh/config - XDG Base Directory compliance on Linux
- File permissions enforced (0600 config, 0700 directories)
Windows
- Works with built-in OpenSSH client (Windows 10/11)
- Config location:
%USERPROFILE%\.ssh\config - Compatible with WSL configurations
git clone https://github.com/xvertile/sshc.git
cd sshc
go build -o sshc .
sudo mv sshc /usr/local/bin/- Cobra — CLI framework
- Bubble Tea — TUI framework
- Bubbles — TUI components
- Lip Gloss — styling
- x/crypto/ssh — SSH connectivity
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-feature) - Commit changes (
git commit -m 'Add new feature') - Push to branch (
git push origin feature/new-feature) - Open a Pull Request
MIT — see LICENSE for details.







