Skip to content

usrme/wishlistlite

Repository files navigation

Wishlist Lite

GitHub go.mod Go version test

The lesser SSH directory (though maybe not so much anymore) ✨

I made this a little while after discovering the canonical Wishlist, but after not getting it to work properly (it wasn't able to connect to any of my defined hosts) I still felt the need for a tool of this sort. This luckily coincided with the time I started learning about Go and after a bit of faffing about I got something to work!

Wishlist Lite - animated GIF demo

Features

  • Ping individual hosts on demand
  • Measure time it takes to connect to a host
  • Store when and what was connected to with a local file
  • Connect to a host interactively

Installation

  • using go install:
go install github.com/usrme/wishlistlite/v2@latest
  • download a binary from the releases page

  • build it yourself (requires Go 1.24+):

git clone https://github.com/usrme/wishlistlite.git
cd wishlistlite
go build

Removal

rm -f "${GOPATH}/bin/wishlistlite"
rm -rf "${GOPATH}/pkg/mod/github.com/usrme/wishlistlite*"

Usage

Execute wishlistlite, which opens up an alternate screen where you can (hopefully) see all of your hosts from your ~/.ssh/config listed, which can then be SSH-ed into by selecting the appropriate one using arrow keys, or filtering for it, and pressing Enter. It then just grabs whatever is next to the Host declaration, precedes it with ssh, runs that executable, and exits wishlistlite leaving you with an SSH session.

It's also possible to press the letter i, which will allow you to supply a host to connect to on an ad-hoc basis. For example inputting user@example.com and pressing Enter will go through the exact process as above. Any of the entries from your SSH configuration are still valid as inputs.

To sort by recently connected to hosts press the letter r, which will read the file ~/.ssh/recent.json, which gets created with the same entries as presented in the default view. After connecting to various hosts that file will be sorted according to which host was connected to recently. Press r again to return to the default view.

To delete entries from the recently connected view press the letter d, which will remove the selected host from the view and immediately save the changes to the ~/.ssh/recent.json file.

To copy a highlighted entry's 'HostName' value to the clipboard press the letter c; to copy its 'Host' value press the capital letter C. This works when viewing configuration entries and the recently connected to hosts.

To open the file that a highlighted entry was read from press the letter o, which suspends the interface and opens the file in the editor set through the VISUAL or EDITOR environment variables (falling back to vi), right on the corresponding Host line. This also works for entries that came from Include-d files and from the recently connected to view, as long as the host is still present in the configuration.

Caveats

Wildcard (*, ?) and negated (!) host patterns are excluded as those aren't hosts that can be connected to directly. The parsing is done line by line while keeping track of each Host block, so there may be edge cases with parsing, but I've tried to cover the most common cases with the included tests.

Before starting the execution there is a verification that is made that the ssh executable exists and that any necessary SSH keys are already loaded into an SSH agent.

The ability to show a stopwatch counting up to the moment a connection is made is achieved through the use of the 'ControlMaster', 'ControlPersist', and 'ControlPath' SSH options. Here is some more information on those options and the GitHub issue behind implementing it. The caveat is in that a socket is being set up in /dev/shm (or /tmp on macOS) that is privileged only to your own user. The socket's file name uses the %C token, a hash of the connection details, so host and user names don't appear in the directory listing.

Here is how the connection flow works by way of showing the system processes:

  • Just Wishlist Lite being open:
systemd(1)───...───wishlistlite(85716)─┬─{wishlistlite}(85717)
                                       ├─{wishlistlite}(85718)
                                       ├─{wishlistlite}(85719)
                                       ├─{wishlistlite}(85720)
                                       ├─{wishlistlite}(85721)
                                       ├─{wishlistlite}(85722)
                                       ├─{wishlistlite}(85723)
                                       ├─{wishlistlite}(85724)
                                       └─{wishlistlite}(85725)
  • Having initiated a connection, which brought up a parent SSH connection with specific SSH options:
systemd(1)───...───wishlistlite(85716)─┬─ssh(85853)───ssh(85854)
                                       ├─{wishlistlite}(85717)
                                       ├─{wishlistlite}(85718)
                                       ├─{wishlistlite}(85719)
                                       ├─{wishlistlite}(85720)
                                       ├─{wishlistlite}(85721)
                                       ├─{wishlistlite}(85722)
                                       ├─{wishlistlite}(85723)
                                       ├─{wishlistlite}(85724)
                                       ├─{wishlistlite}(85725)
                                       ├─{wishlistlite}(85855)
                                       ├─{wishlistlite}(85856)
                                       ├─{wishlistlite}(85857)
                                       └─{wishlistlite}(85858)
  • Being finally connected to a host:
systemd(1)───...───ssh(85716)───ssh(85853)

Note how the original process ID of Wishlist Lite (85716) is now that of the SSH process'. This is happening because of the call to syscall.Exec here, which in turn invokes the 'execve(2) system call', which:

causes the program that is currently being run by the calling process to be replaced with a new program, with newly initialized stack, heap, and (initialized and uninitialized) data segments.

Acknowledgments

Couldn't have been possible without the work of people in Charm.

License

MIT

About

The lesser SSH directory ✨

Topics

Resources

License

Stars

3 stars

Watchers

1 watching

Forks

Contributors

Languages