CLI tool
grafviktor/goto avatar
grafviktor/goto

GOTO turns a shared ssh_config into a browsable, grouped host list

Easy to use terminal SSH manager with advanced features. Binaries included! 😉

533 stars34 forksGoMIT

At a glance

What is it?
GOTO is a Go terminal SSH manager that reads hosts from an OpenSSH config file or a yaml store, groups them and hands the actual connection to the system ssh binary. It suits teams that want one shared host list, and it is wrong for anyone who needs connection features of its own.
Who is it for?
GOTO is worth adopting for a team that already runs plain ssh and wants one shared, grouped host list instead of config files scattered across laptops. It is a poor fit for anyone who needs password prompts, port forwarding or session recording built in, because GOTO deliberately holds no connection logic of its own.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

GOTO organizes hosts and leaves the connection to ssh

GOTO is a terminal SSH manager for people whose server list has outgrown ~/.ssh/config but who do not want to replace the OpenSSH client. The README is explicit that it carries no connection logic of its own; it integrates with the ssh utility expected to be present on the machine. That boundary shapes everything else: GOTO is a browser, picker and editor for host entries, and once you press connect the work is handed to the system ssh binary.

That makes it interesting for teams. The suggested arrangement is to keep SSH configuration centrally on an internal server and share it across a whole department, so that new engineers do not hand-copy host blocks. The program lists hosts, groups them, and can serve a configuration file from a URL.

The project is written in Go and the repository topics list multi-platform, shell, ssh-client, ssh-manager and terminal, which is why single binaries are shipped for macOS, Linux and Windows.

Two storage backends, and only one of them is writable

GOTO reads from exactly two storages. The first is ssh_config, described as a readonly storage type: GOTO loads all hosts from your ~/.ssh/config file, and the README points you at man ssh_config for the format itself. The same section says the application also supports remote ssh_config files, with details in docs/SSH_CONFIG.md.

The second storage type is a yaml file, and this one is writable. Its drawback is stated plainly: it supports less options than ssh_config. The file must be named hosts.yaml and lives in a platform specific user config folder, listed as $XDG_CONFIG_HOME/goto or $HOME/.config/goto on Linux, $HOME/Library/Application Support/goto on Mac, and %AppData%\goto on Windows. The structure is a list of host entries with title, description, address and optional fields:

yaml
- host:
    title: kernel.org
    description: Server 1
    address: 127.0.0.1
- host:
    title: microsoft.com
    description: Server 2
    address: 127.0.0.1
    network_port: 22
    username: satya
    identity_file_path: /home/user/.ssh/id_rsa_microsoft

One consequence shows up later in the README: you can only edit hosts loaded from yaml storage. An entry that came from an ssh_config file is visible and connectable but not editable in place.

Installing the gg binary on macOS, Linux and Windows

The project distributes binaries and packages rather than requiring a compiler toolchain. The manual route is to download the latest version from the Releases section, pick the file that matches your platform, and place the binary in your user's binary path. The binary ships under a platform specific name, so renaming gg-${YOUR_PLATFORM_TYPE} to gg is listed as an optional step. On Linux and macOS the file then needs execution permissions:

bash
  chmod +x gg

Three package routes are documented. Debian and RedHat users can take RPM and DEB packages from the releases section, with the caveat that these packages are not provided for pre-release builds. The Arch Linux AUR package goto-ssh-bin is maintained externally by the open source community. On macOS the Homebrew route goes through a community tap:

bash
brew tap grafviktor/goto
brew install --cask goto-ssh-manager

That install puts the gg binary on the system, and the README shows it being started simply as gg.

First run: pointing GOTO at a shared remote config

GOTO exposes a small set of command line options, and several of them change where configuration comes from. The -f flag points the application at a different home folder, so a scratch configuration is easy to isolate:

bash
  gg -f /tmp/goto

The -s flag defines an alternative SSH configuration file path for the current session, which is the quickest way to try a shared config without touching the per user default:

bash
  gg -s /mnt/nfs_share/ssh/config

A persistent version of the same idea exists. The --set-ssh-config-path option stores the path or url of the configuration, and the README example points at a company repository:

bash
  gg --set-ssh-config-path https://company-repo/devops-team/ssh_config

The -d and -e flags toggle a feature whose only supported value today is ssh_config, and --set-theme changes the color theme. Log verbosity is set with -l and accepts only info, the default, or debug. Three environment variables mirror the same settings: GG_HOME, GG_LOG_LEVEL and GG_SSH_CONFIG_FILE_PATH. A -v flag prints version and configuration details, which is worth running first if something is not resolving as expected.

Grouping hosts and the narrow rule on editing

Hosts are organized into logical groups, and the demo shows them split into categories such as Dev, Beta and Prod, with a shortcut to switch between group sets. The details live in docs/GROUPS.md, while docs/FAQ.md collects additional configuration examples and usage notes.

Editing is deliberately narrow. A host entry can be adjusted before the connection is made, for example changing an address on the fly, and the demo folder records this as edit_and_connect. The rule that keeps it consistent is stated in the same README section: only hosts loaded from yaml storage can be edited. Anything that came from an ssh_config file is shown and can be connected to, but its address stays as configured.

The demo directory also records the tool combined with tmux, a key copy shortcut, a proxy creation flow, a duplicate existing record flow, and a fuzzy search through the host database. That fuzzy match comes from the sahilm/fuzzy dependency in go.mod, and the terminal interface itself is built on the charm.land bubbletea, bubbles and lipgloss packages.

The Include directive that works in ssh but not in GOTO

The most useful feature for shared team configuration is the SSH Include directive, and it is also where the documented sharp edge sits. The README describes Include as a way to build an access hierarchy, for example a root configuration used by one team with leaf configurations distributed across departments, and points at docs/SSH_CONFIG.md for the details.

There is a concrete failure here. If an ssh_config uses the Include directive with a double asterisk, meaning a recursive glob across subfolders, GOTO cannot locate those files. The workaround given is to enumerate each folder separately with its own Include line, using the specific glob for each directory:

code
  Include .../conf.d/folder1/*.conf

The recursive pattern that OpenSSH itself understands is not supported here, so a config that works with plain ssh may need rewriting before it works under GOTO. That difference only surfaces after a team has already standardized on a shared config, which is exactly the deployment scenario GOTO is built for.

Two Windows specific failure modes to plan around

The Windows notes are specific and worth reading before deploying this to a mixed platform team. First, the application may not start on Windows if the terminal is set to use the legacy console. The documented workarounds are to disable legacy console mode, or to run the terminal session manually and start the application from inside it.

Second, copying an SSH public key to a remote host with the t shortcut can fail when the remote host does not yet have a ~/.ssh directory. The instruction is to log in to the remote host, create the directory by hand, set the permissions with chmod 700 ~/.ssh, and retry the key copy.

Neither issue is fatal, but both push work back onto the operator, and both are platform specific in a way the Linux and macOS instructions are not. A team standardizing on this tool needs to know that a Windows engineer may need extra steps that a macOS engineer never sees.

Recent releases, MIT licence and a dependency list built for terminal UI

The repository is not archived, and the last push was on 2026-10-20, so the tree is being worked on. Releases are named in the v1.x series: v1.6.1 on 2026-06-08, v1.6.0 on 2026-05-31, and v1.5.1 on 2026-01-21. The Makefile carries a BUILD_VERSION of v1.7.0 and a commented replace directive pointing the termview dependency at a local path, which fits the pattern of shipping binaries instead of expecting a Go toolchain on the user machine.

The licence is MIT, and the repository includes a LICENSE file at its root along with CONTRIBUTING.md and CHANGELOG.md. Vendoring the binary into an internal distribution is therefore straightforward in licensing terms, though the project does not publish separate guidance on how teams should package it. The dependency list is mostly terminal interface work: charm.land bubbletea v2, bubbles v2 and lipgloss v2, plus caarlos0/env for environment parsing, gopkg.in/yaml.v2 for the yaml storage and atotto/clipboard for clipboard handling. The module targets go 1.25.0.

Editorial conclusion

GOTO is worth adopting for a team that already runs plain ssh and wants one shared, grouped host list instead of config files scattered across laptops. It is a poor fit for anyone who needs password prompts, port forwarding or session recording built in, because GOTO deliberately holds no connection logic of its own. Before adopting, check that your shared ssh_config does not use a recursive Include glob, confirm that any host you intend to edit lives in hosts.yaml rather than in ssh_config, and run gg -v to see which configuration paths the binary actually resolved.

Frequently asked questions

How do I install GOTO on macOS?

The README documents a Homebrew community tap, with brew tap grafviktor/goto followed by brew install --cask goto-ssh-manager, which installs the gg binary on the system. A manual download from the Releases section is also supported.

Where does GOTO store hosts in yaml format?

The writable yaml storage is a file named hosts.yaml in a platform specific user config folder: $XDG_CONFIG_HOME/goto or $HOME/.config/goto on Linux, $HOME/Library/Application Support/goto on Mac, and %AppData%\goto on Windows.

Can I edit a host in GOTO that came from my ~/.ssh/config?

No. The README states that you can only edit hosts loaded from yaml storage, so entries read from an ssh_config file are connectable but not editable in place.

Does GOTO replace the OpenSSH client?

No, it integrates with the ssh utility that should already be installed on your system. The README says it does not include any connection logic of its own.

Official sources

  1. grafviktor/goto on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/grafviktor-goto.svg)](https://hysenlabs.com/projects/grafviktor-goto)

Was this useful?