A better Gopher client in pure Bash
improved gmi2txt.sh
improved list2map.sh a bit
Improved gmi2map logic


browse  log 



You can also use your local clone with git send-email.

#Bopher-NG: A better Gopher browser in pure Bash

“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.”

― Antoine de Saint-Exupéry, Airman's Odyssey

#What is it?

Bopher-NG is an ambitious attempt to write a full-featured Gopher client/browser in under 350 SLOC of pure Bash code. It started off as a really crude and unoptimized prototype developed right in this blog post for educational purposes.

Improvements over the original Bopher from that post:

  • mouse support (where possible)
  • smoother rendering and scrolling
  • better edge-case stability (e.g. on macOS where using file descriptor 3 actually crashes everything)
  • better Gophermap processing according to the RFC1436
  • an actual text reflow when viewing plaintext documents with no hard wrapping
  • multi-level navigation history (although you can only go back)
  • status bar with currently opened resource name
  • ability to accept gopher:// URLs from the command line
  • ability to save the URL to the currently viewed resource into the stash text file
  • optional clipboard support when stashing (only if you set BOPHER_CLIP envvar)
  • ability to force-download pages instead of viewing regardless of their type
  • ability to display 8-type Gophermap entries as telnet:// URIs (not opening anything for security reasons)

"Pure Bash" means any external commands must only be used if absolutely required. For now, Bopher-NG only depends on three external commands (all POSIX-compliant):

  • cat (to handle possibly binary data read from the socket)
  • stty (to fetch current terminal size in rows and columns)
  • date (to shape entry timestamps when stashing links)

This Bopher-NG repo also contains a set of useful tools (also written in pure Bash) to ease authoring and publishing your own Gopher content. See the Bopher Tools README for more information.

#Which Bash versions are supported?

Bopher-NG was only tested on Bash 5.1, but should support any version from 4.2 and up.

#How to start Bopher-NG?

Just run it specifying all the necessary components of the Gopher resource:

bopher-ng.sh host[ port][ selector][ type]

Or, you can just specify a valid gopher:// URL:

bopher-ng.sh gopher://host[:port]/[type][selector]

E.g. running bopher-ng.sh gopher://texto-plano.xyz:70/0comandos.txt is the same as bopher-ng.sh texto-plano.xyz 70 comandos.txt 0 and will open the same document.

In both cases, only the host is required. If everything else is omitted, the port will default to 70, the selector will default to / and the resource type will default to 1.

Also, your selectors now can have a %09[search] part, so you can specify your search queries directly on start and also save them later.

#How to browse Onion nodes with Bopher-NG?

Besides having Tor itself up and running, you also need to have the torsocks wrapper installed:

torsocks bash bopher-ng.sh gopher://[some-address].onion

#Will there be any Gopher-TLS support?

No. Besides the ambiguity problem, it will also introduce huge external dependencies. Use .onion services instead whenever possible.

#How to control Bopher-NG?

  • Scrolling: Up/Down arrow keys, k/j keys or mouse scroll wheel (if supported)
  • Page scrolling: PgUp/PgDn keys or h/l keys
  • Link navigation (keyboard): s - focus on the next link, w - focus on the previous link, Enter/Space - visit the focused link (or download if it points to a binary file), d - force-download the contents of the link
  • Link navigation (mouse, if supported): left click on the link - focus and visit (or download if it points to a binary file), middle click - focus and force-download the contents
  • Go back: b or right mouse click anywhere (if supported)
  • Refresh the page: r
  • Stash the link to the currently open resource: S (shift+s)
  • Toggle mouse support (always on when starting): m
  • Quit the browser: q

Link stash is a viable and interoperable alternative to both bookmarks and clipboard that can be implemented with pure Bash. Essentially, it's an append-only text file at a fixed location (~/.bopher-links.txt by default) where the user can instruct Bopher-NG to save the link to the currently viewed resource. For your convenience, links are stashed with a UTC-based timestamp and in the gopher:// format, so they can be copied from the file later and used in other browsers. As of now, every stash file line is a valid Gophermap line, so can easily share your findings on the Gopherspace whenever you want.

You can override the BOPHER_LINKSTASH environment variable to change the location and name of this file if you need to.

#What about the "normal" system clipboard?

This functionality is too OS/environment-specific and thus can't be built into Bopher-NG. Since April 2023, however, Bopher-NG supports copying the current URL to the OS/env clipboard at the same time as stashing, if and only if you set the BOPHER_CLIP environment variable before invocation. This variable must be set to a valid command that performs copying the standard input to the system clipboard. If you plan on using it constantly, I suggest to add one of the following values to your ~/.profile, ~/.bash_profile or ~/.bashrc:

  • for Linux + X11 GUI: export BOPHER_CLIP='xsel -bi'
  • for Linux + Wayland (with wl-clipboard package): export BOPHER_CLIP=wl-copy
  • for macOS: export BOPHER_CLIP=pbcopy
  • for GNU Screen environment (on any OS): export BOPHER_CLIP='xargs -0 screen -X register .'

Even then, this functionality isn't guaranteed to work on any system. Please verify by yourselves how your operating environment handles the clipboard and adjust this variable accordingly.

#Where do the downloads go?

By default, they go to your current working directory, i.e. the directory you are running this script from. To override this with a fixed path, set the BOPHER_DLDIR environment variable.

#Which platforms is the mouse supported on?

Bopher-NG's mouse input is supported on any terminals that support the 1000 and 1006 mouse reporting modes. This includes but is not limited to:

  • Linux GUI terminal emulators (xterm, Konsole, urxvt, any VTE-based terminal emulator);
  • Linux bare terminals via GPM + LCXterm (sorry, I don't know why no one implemented it in GPM itself in 23 years);
  • macOS Terminal;
  • OpenGL-based xterm-compatible terminal emulators like WezTerm, Kitty, Alacritty etc.

Note that, unlike clipboard, this support is required at the client side only. For instance, you can safely run bopher-ng.sh on any compatible Bash version in an SSH session on your terminal and still be able to use mouse there.

If you don't want to use mouse capture (for instance, to be able to select and copy things with the terminal app itself), you can temporarily turn off mouse support (and then turn it back on) using the m key.

#What is the license on this?

Fully public domain.