go install go-ssh
A full-screen TUI (terminal UI) application written in Go for organizing SSH hosts in a tree structure and connecting to them quickly.
- 🎨 Full-screen terminal user interface (TUI)
- 🌳 Tree-based category and host organization
- 📁 Nested categories support
- ⌨️ Keyboard navigation with arrow keys or Vim-style keys
- 🔗 SSH connections via multiple hosts (jump hosts)
- 📜 Sequential command execution for complex connection scenarios
- 🤖 Interactive mode for automatic password entry and command sending
- 📝 YAML-based configuration
- 🏠 Automatic config management under the user home directory
go build -o go-ssh
sudo mv go-ssh /usr/local/bin/or:
go installRun the application:
go-sshOn first run, the config file ~/.go-ssh/config.yaml will be created automatically.
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate up/down |
←/→ or h/l |
Collapse/expand category |
Enter or Space |
Open/close category or connect to host |
e |
Expand all categories |
C (Shift+c) |
Collapse all categories |
p |
Open password manager |
c |
Open config editor |
q or Ctrl+C |
Quit |
Config file path: ~/.go-ssh/config.yaml
Categories can be nested. Each category can contain both subcategories and hosts:
categories:
- name: Production
description: Production environment servers
categories:
- name: Web Servers
description: Frontend web servers
hosts:
- name: Web Server 1
description: Primary web server
command: ssh -t jumphost@bastion "ssh -t deploy@web1 'cd /var/www && exec bash'"
- name: Web Server 2
description: Secondary web server
command: ssh -t jumphost@bastion "ssh -t deploy@web2 'cd /var/www && exec bash'"
- name: Database Servers
description: Database servers
hosts:
- name: MySQL Master
description: Primary MySQL server
command: ssh -t jumphost@bastion "ssh -t dba@mysql-master 'exec bash'"
hosts:
- name: Bastion Host
description: Jump server for production
command: ssh jumphost@bastion
- name: Staging
description: Staging environment
hosts:
- name: Staging Server
description: Staging environment server
command: ssh deploy@staging
- name: Development
description: Development servers
categories:
- name: Local VMs
description: Local virtual machines
hosts:
- name: Dev VM 1
description: Development VM
command: ssh dev@192.168.1.100
hosts:
- name: Dev Server
description: Main development server
command: ssh dev@devserverCategory:
name: Category namedescription: Description (optional)icon: Emoji icon (optional)categories: Subcategories (optional)hosts: Hosts (optional)
Host:
name: Display name of the hostdescription: Host description (optional)command: Single SSH command to run (for simple connections)commands: List of commands to run sequentially (for complex connections)
Note: For a host you should use either
commandorcommands, not both.
Direct connection with a single command:
hosts:
- name: Production Server
description: Main production server
command: ssh user@production.example.comFor multi-hop connections or jump hosts:
hosts:
- name: Inner Server
description: Server behind jump host
commands:
- ssh jumphost@bastion.example.com # Connect to bastion first
- sleep 2 # Wait for connection to establish
- ssh user@internal-server # Then connect to internal server
- name: Complex Setup
description: Multi-step connection
commands:
- echo "Connecting to production..."
- ssh -t jump@gateway "cd /opt/scripts && ./prepare.sh"
- sleep 1
- ssh -t jump@gateway "ssh app@prod-server"How Sequential Commands Work:
- The first SSH command is detected and extended with
-tt(for terminal allocation). - All subsequent commands are embedded as remote commands executed within the first SSH session.
- If the last command is an SSH command, it is run via
execso that the user is attached directly to that session. - Example:
["ssh host1", "sleep 2", "ssh host2"]→ssh -tt host1 'sleep 2; exec ssh host2'
Example Transformation:
commands:
- ssh jumphost@bastion
- sleep 2
- ssh user@internal-serverAutomatically becomes:
ssh -tt jumphost@bastion 'sleep 2; exec ssh user@internal-server'Interactive mode lets the Go app control the SSH connection via a PTY (pseudo-terminal). This allows you to:
- Automatically enter passwords
- Send commands after the connection is established
- Finally hand control back to the user
Special Command Prefixes:
SEND:text– Send text to the terminal (followed by Enter)SENDPASS:id– Send password from password manager (followed by Enter)WAIT:N– Wait N seconds (e.g.,WAIT:5waits 5 seconds)EXPECT:text– Wait until the specified text appears in output (30 second timeout)INTERACT– Give control back to the user
Example 1: Login with Password
hosts:
- name: Server with Password
description: Auto-login with password
commands:
- ssh user@server.com # Start SSH
- WAIT:2 # Wait 2 seconds for password prompt
- SEND:mypassword123 # Send password
- INTERACT # Hand control to userExample 2: Using EXPECT for Dynamic Prompts
hosts:
- name: Server with EXPECT
description: Wait for specific prompts instead of fixed delays
commands:
- ssh user@server.com # Start SSH
- EXPECT:Password: # Wait until "Password:" appears in output
- SEND:mypassword123 # Send password
- EXPECT:$ # Wait until shell prompt appears
- SEND:cd /opt/app # Change directory
- INTERACT # Hand control to user - WAIT:2 # Wait for password prompt
- SEND:mypassword123 # Send password
- INTERACT # Hand control to user
**Example 3: Password + Automatic Commands**
```yaml
hosts:
- name: Auto Setup Server
description: Login and run setup commands
commands:
- ssh user@server.com
- EXPECT:Password: # Wait for password prompt (better than fixed WAIT)
- SEND:mypassword # Send password
- EXPECT:$ # Wait for shell prompt
- SEND:cd /opt/app # Change directory
- SEND:./setup.sh # Run script
- INTERACT # User continues
Example 4: Complex Scenario with Jump Host and Passwords
hosts:
- name: Multi-Hop with Passwords
description: Jump through multiple hosts with passwords
commands:
- ssh jumphost@bastion.com
- EXPECT:Password: # More reliable than WAIT:2
- SEND:bastion_password
- EXPECT:$ # Wait for shell prompt
- SEND:ssh user@internal-server
- EXPECT:Password:
- SEND:internal_password
- INTERACTEXPECT vs WAIT:
WAIT:N– Waits for a fixed number of seconds. Simple but may wait too long or too short depending on network conditions.EXPECT:text– Waits until specific text appears in the output (max 30 seconds). More reliable for dynamic scenarios like waiting for prompts.- Use
EXPECTwhen you need to wait for specific output (like "Password:", prompt symbols "$" or "#") - Use
WAITfor simple delays where timing is predictable
Go-SSH includes a built-in password manager to store your passwords securely. Passwords are encrypted with AES-256-GCM and stored safely on disk.
Open the password manager from the host selector by pressing p.
Note: The legacy
./go-ssh --passwordsflag still works for backward compatibility, but the main way to access it is through thepshortcut on the host selector screen.
On first run, you will be asked to create a master password. This master password protects all stored secrets.
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate through stored passwords |
a |
Add a new password |
e |
Edit the selected password |
d |
Delete the selected password |
Enter or v |
View the selected password |
m |
Change the master password |
q or Esc |
Return to the host selector |
Each password has:
- ID: Unique identifier for the secret (e.g.
prod-db,staging-app) - Description: Description for the secret
- Password: The password to store
To use stored passwords in SSH connections, use the SENDPASS:password_id command:
categories:
- name: Production
hosts:
- name: Database Server
description: Production database with password
commands:
- ssh user@db-server.com
- SENDPASS:prod-db # Send password from password manager
- INTERACT- ✅ AES-256-GCM encryption
- ✅ PBKDF2 key derivation (100,000 iterations)
- ✅ Encryption with a master password
- ✅ Only encrypted data stored on disk
- ✅ File permissions
0600(owner read/write only) - ✅ Passwords are decrypted in memory only when needed
-
Run go-ssh:
./go-ssh
-
Open the password manager by pressing
p. -
Add a new password:
- ID:
prod-web - Description:
Production web server password - Password:
<your-secure-password>
- ID:
-
Use it in your config (or add it via the config editor by pressing
c):- name: Web Server commands: - ssh admin@web-server.com - SENDPASS:prod-web - INTERACT
-
Press
qto return to the host selector, select the host, and enter your master password for automatic login.
Security Note: The password manager uses AES-256 encryption and is designed to be secure, but in production environments you should prefer SSH key authentication whenever possible. Storing plain passwords directly in the YAML config (e.g. via SEND:) is not recommended.
Go-SSH includes a built-in config editor so you can manage hosts and categories without manually editing YAML files.
From the host selector, press c to open the config editor.
| Key | Action |
|---|---|
↑/↓ or j/k |
Navigate the config tree |
←/→ or h/l |
Collapse/expand categories |
a |
Add a category or host under the selection |
e |
Edit the selected category or host |
d |
Delete the selected category or host |
s |
Confirm all changes are saved |
q or Esc |
Return to the host selector |
When you add a new category or host, the editor will ask you to choose a target file:
~/.go-ssh/config.yaml(main config)- Any existing
.yamlfile in~/.go-ssh/conf.d/ - A new file under
~/.go-ssh/conf.d/
This keeps modular configs organized while editing from a single UI.
- The config editor writes YAML files atomically.
- YAML comments in edited files may be lost after saving because the editor re-serializes the structure.
- When multiple
conf.dfiles define a category with the same name, they are merged into a single tree in the UI. Editing that category updates the source file of the first occurrence.
┌─────────────────────────────────────────────────────────────┐
│ 🔐 SSH Host Manager Hosts: 7 │
├─────────────────────────────────────────────────────────────┤
│ ▼ 🔴 Production │
│ ▼ 🌐 Web Servers │
│ ➤ 🖥️ Web Server 1 │
│ 🖥️ Web Server 2 │
│ ▶ 🗄️ Database Servers │
│ 🖥️ Bastion Host │
│ ▶ 🟡 Staging │
│ ▶ 🟢 Development │
├─────────────────────────────────────────────────────────────┤
│ 🖥️ Web Server 1 │
│ Primary web server │
│ │
│ 💻 Command: ssh -t jumphost@bastion "ssh -t deploy@web1..." │
├─────────────────────────────────────────────────────────────┤
│ ↑↓/jk: Navigate ←→/hl: Collapse/Expand Enter: Select │
└─────────────────────────────────────────────────────────────┘
For large configurations, you can split your config into multiple files using the conf.d directory.
All .yaml and .yml files in ~/.go-ssh/conf.d/ are automatically loaded and merged with the main config file. This allows you to organize your hosts by team, environment, or any other criteria.
Categories with the same name across multiple files are merged into a single tree. For example, if conf.d/turkcell-inventum.yaml, conf.d/turkcell-monicat.yaml, and conf.d/turkcell-star.yaml each define a root category named Turkcell, they will appear as one Turkcell category with Inventum, MoniCat, and Star subcategories.
~/.go-ssh/
├── config.yaml # Main config (optional, can be empty)
├── conf.d/
│ ├── production.yaml # Production servers
│ ├── staging.yaml # Staging servers
│ ├── development.yaml # Development servers
│ ├── team-backend.yaml # Backend team servers
│ └── team-frontend.yaml # Frontend team servers
└── README.md # Auto-generated documentation
Main config (~/.go-ssh/config.yaml):
# Can be empty or contain common/shared categories
categories: []conf.d/production.yaml:
categories:
- name: Production
description: Production environment
hosts:
- name: Web Server
description: Production web server
command: ssh user@web.prod.example.comconf.d/staging.yaml:
categories:
- name: Staging
description: Staging environment
hosts:
- name: Staging Server
command: ssh user@staging.example.comAll files are automatically loaded and merged when you run go-ssh.
- 📁 Organization: Split large configs into logical units
- 👥 Team collaboration: Each team can maintain their own config file
- 🔄 Easy updates: Add/remove servers by adding/removing files
- 🚀 No code changes: Works automatically, no setup needed
To run the project:
go run main.goTo build:
go build -o go-ssh- Bubble Tea – TUI framework
- Lipgloss – Styling and layout
- yaml.v3 – YAML parsing
MIT