My Simple GNU Screen Set-up 🧑‍💻 (TMUX Alternative)
Tags: linux, vim, programming, productivity
Published: 2024-07-17 16:36:46

*This article was originally posted on my [ad-free blog](https://aedrielkylejavier.me/articles/2024-07-15_gnu-screen/). For more content, including extra downloadables and resources for this post — feel free to visit my [website](https://aedrielkylejavier.me/).*

&nbsp;

⚠ Now, before anything, I personally wouldn't recommend **switching** to GNU `screen` **if** you already have a `tmux` configuration. I believe `tmux` excels in terms of extensibility, documentation, and community support, with numerous videos and guides available. This blog post is best suited for those who might **not** have a terminal multiplexer setup yet and are looking for something simple, built-in, and somewhat ["suckless"](https://suckless.org/philosophy/) 🧩.

GNU `screen` provides all the necessities of a terminal multiplexer with a few essential features and configurability options sprinkled on top ✨. If you don't foresee the need to heavily *extend* the tool, want to keep your setup straightforward, and aren't interested in creating elaborate configurations for [show](https://www.reddit.com/r/unixporn/), GNU `screen` might be perfect for those long SSH sessions and productive late nights with text editors like Neovim and other CLI tools.

In this post, I'll share my simple GNU Screen setup, which I find more than sufficient for my needs. I hope this post serves as a good starting point for anyone looking to configure a terminal multiplexer 👍.

## The Set-up

I have two concurrent GNU `screen` setups on my machines. One for when I am in a session where the `X11` display server is running (essentially, when using a graphical environment):

[![Image of my GNU screen setup](https://aedrielkylejavier.me/articles/img/gnu-screen-images/0.png)](https://aedrielkylejavier.me/articles/img/gnu-screen-images/0.png)

And another for when I am in a TTY session (a text-based environment without a graphical interface):

[![Image of my GNU screen setup in a TTY](https://aedrielkylejavier.me/articles/img/gnu-screen-images/1.png)](https://aedrielkylejavier.me/articles/img/gnu-screen-images/1.png)

&nbsp;

## The "Top Bar"

The `hardstatus` line consists of a few basic elements:

[![Image of my GNU screen hardstatus line in a TTY](https://aedrielkylejavier.me/articles/img/gnu-screen-images/3.png)](https://aedrielkylejavier.me/articles/img/gnu-screen-images/3.png)

[![Image of my GNU screen hardstatus line in a GUI / X11 Window Manager/ Desktop Environment](https://aedrielkylejavier.me/articles/img/gnu-screen-images/2.png)](https://aedrielkylejavier.me/articles/img/gnu-screen-images/2.png)

* **A** *(Top-left)* — a simple hard-coded `[ GNU screen ]` indicator to signify that you are in an attached session.
* **B** *(Middle-left)* — a horizontal "window buttons list" similar to a taskbar in a panel.
    * The "Active Window" is represented within " `(==` " and " `==)` ".
    * The X11 `screen` config has more *verbose* "window" titles.
* **C** *(Top-right)* — a "textclock" displaying the date, day, and time (only present in the `tty` config).

This setup is meant to be "functionally simple" and not reliant on any [Nerd Fonts](https://www.nerdfonts.com/) or other non-ASCII characters, so you can get up and running with a multiplexer even on a barebones Linux install.

&nbsp;

## Keybindings

My preferred "prefix" key is `Ctrl`+`space` (instead of the default, `Ctrl`+`a`). This prefix key seems to conflict less with known default terminal programs’ keybindings unless it was explicitly set in said tools (e.g., in a VI/Vim/Neovim config). Here are some of my configuration's keybindings based on the common commands presented in the [ArchWiki](https://wiki.archlinux.org/title/GNU_Screen#Common_Commands).

|  Keybind                                |  Action                                                                                      |
|----------------------------------|----------------------------------------------------------------------------------------|
| Ctrl+space &nbsp; &nbsp; "       | toggle window list                                                                     |
| Ctrl+space &nbsp; &nbsp; 1       | open window 1                                                                          |
| Ctrl+space &nbsp; &nbsp; 0       | open window 10                                                                         |
| Ctrl+space &nbsp; &nbsp; ?       | display commands and their defaults                                                    |
| Ctrl+space &nbsp; &nbsp; A       | rename the current window                                                              |
| Ctrl+space &nbsp; &nbsp; Esc     | enter copy mode (use enter to select a range of text)                                  |
| Ctrl+space &nbsp; &nbsp; Q       | close all regions but the current one                                                  |
| Ctrl+space &nbsp; &nbsp; S       | split the current region horizontally into two regions                                 |
| Ctrl+space &nbsp; &nbsp; ]       | paste text                                                                             |
| Ctrl+space &nbsp; &nbsp; a       | send ctrl+a to the current window                                                      |
| Ctrl+space &nbsp; &nbsp; c       | create a new window (with shell)                                                       |
| Ctrl+space &nbsp; &nbsp; d       | detach from the current screen session and leave it running. use `screen -r` to resume |
| Ctrl+space &nbsp; &nbsp; k       | "kill" the current window                                                              |
| Ctrl+space &nbsp; &nbsp; tab     | switch the input focus to the next region                                              |
| Ctrl+space &nbsp; &nbsp; \|      | split the current region vertically into two regions                                   |
| Ctrl+space &nbsp; &nbsp; :       | enter the command prompt of screen                                                     |
| Ctrl+space &nbsp; &nbsp; :quit   | close all windows and close the screen session                                         |
| Ctrl+space &nbsp; &nbsp; :source | reload the screenrc configuration file (can alternatively use /etc/screenrc)           |

&nbsp;

## Replicate My GNU Screen Config 🚀

Due to my VI/Neovim configuration requiring True Color (24-bit) support, I use GNU Screen 5.0.0 (the -git master branch), which finally has the `truecolor` setting. For those who prefer not to compile software and would rather stick with the versions available in the repositories, I also have a similar configuration that works with `screen` versions `<= 4.9.1` (which only support 256 colors). I will share both configurations in this blog post.

## GNU Screen 5.0.0 (-git master branch)

[![Image of my GNU screen setup](https://aedrielkylejavier.me/articles/img/gnu-screen-images/0.png)](https://aedrielkylejavier.me/articles/img/gnu-screen-images/0.png)

### Installation Instructions for GNU Screen `-git`

The following are installation instructions for Linux distributions that have a `-git` GNU `screen` package.

#### Arch Linux (AUR)
```sh
$ paru -S screen-git
```
or
```sh
$ yay -S screen-git
```
or
```sh
# Download screen-git PKGBUILD
$ wget 'https://aur.archlinux.org/cgit/aur.git/snapshot/screen-git.tar.gz'
# Extract Tarball
$ tar -xvf screen-git.tar.gz
# Change Directory to screen-git/
$ cd screen-git/
# Build Package
$ makepkg -si
```

&nbsp;

### Building From Source

The following are build instructions for the `-git` version of GNU `screen`.

#### Install Dependencies for Your Distro

*Ubuntu/Debian*
```sh
$ sudo apt-get update
$ sudo apt-get install -y git autoconf automake libtool make
```

*Fedora*
```sh
$ sudo dnf install -y git autoconf automake libtool make
```

*Gentoo*
```sh
$ sudo emerge dev-vcs/git autoconf automake libtool
```

*Alpine Linux*
```sh
$ sudo apk add git autoconf automake libtool make
```

*OpenSUSE*
```sh
$ sudo zypper install -y git autoconf automake libtool make
```

&nbsp;

##### Clone, Build, and Run GNU `screen`
```sh
# Clone Source
$ git clone https://git.savannah.gnu.org/git/screen.git
# Build GNU Screen
$ ./autogen.sh
$ ./configure --prefix=/usr/local \
              --enable-pam \
              --enable-colors256 \
              --enable-rxvt_osc \
              --enable-use-locale \
              --enable-telnet
$ make
# Optional
$ make install # or place in a PATH= directory
# Run and Test GNU screen
$ ./screen
```

&nbsp;

### Configuration (GNU Screen 5.0.0 `-git`)

`~/.screenrc`

```sh
# This config requires Screen v5 (-git master branch release)
truecolor on
hardstatus off # Puts notifications at the bottom
hardstatus firstline '%{#999999}[ GNU screen ]%{#ffffff} %< %{7}%?%-Lw%?%{1;0}%{#009dff}(== %{#ffffff}%n %h%?(%u)%?%{1;0}%{#009dff} ==)%{7}%?%+Lw%?%?'
altscreen on
bind 0 select 10
bind c screen 1
defscrollback 5000
escape ^@a
maptimeout 0
screen 1
startup_message off
```

or

`~/.screenrc` *(with clock, as found in my TTY config)*:

```sh
# This config requires Screen v5 (-git master branch release)
truecolor on
backtick 0 5 5 "/usr/bin/date" '+%m/%d (%a)'
backtick 1 5 5 "/usr/bin/date" '+%H%M'
hardstatus off # Puts notifications at the bottom
hardstatus firstline '%{#999999}[ GNU screen ]%{#ffffff} %< %{7}%?%-Lw%?%{1;0}%{#009dff}(== %{#ffffff}%n%f%t%?(%u)%?%{1;0}%{#009dff} ==)%{7}%?%+Lw%?%? %= %{#999999}[ %{#999999}%0` %1` ]'
altscreen on
bind 0 select 10
bind c screen 1
defscrollback 5000
escape ^@a
maptimeout 0
screen 1
startup_message off
```

## GNU Screen 4.0.0+ (Stable Release Across Distros)

[![Image of my GNU screen 4.0 partial setup](https://aedrielkylejavier.me/articles/img/gnu-screen-images/4.png)](https://aedrielkylejavier.me/articles/img/gnu-screen-images/4.png)

### Installation Instructions for GNU Screen 4.0.0+

GNU Screen version 4.0.0+ is widely available across various Linux distributions through their respective package managers. Below are the installation commands for some common distributions.

*Debian/Ubuntu*
```sh
$ sudo apt update
$ sudo apt install screen
```

*Fedora*
```sh
$ sudo dnf install screen
```

*Arch Linux*
```sh
$ sudo pacman -S screen
```

*Gentoo*
```sh
$ sudo emerge --ask app-misc/screen
```

*Alpine Linux*
```sh
$ sudo apk add screen
```

*openSUSE*
```sh
$ sudo zypper install screen
```

&nbsp;

After installation, you can run GNU Screen by simply typing `screen` in your terminal.

&nbsp;

### Configuration (GNU Screen 4.0.0+)

`.screenrc`

```sh
attrcolor b ".I"
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
defbce on
backtick 0 5 5 "/usr/bin/date" '+%m/%d (%a)'
backtick 1 5 5 "/usr/bin/date" '+%H%M'
hardstatus alwaysfirstline
hardstatus string '%{= kW}[%{W} GNU screen %{W}]%{W} %< %{kW}%?%-Lw%?%{= kB}(== %{W}%n*%f %t%?(%u)%? %{kB}==)%{= kW}%?%+Lw%?%? %= %{kW}[%{W}%0` %{W}%1`%{kW}]'
altscreen on
bind 0 select 10
bind c screen 1
defscrollback 5000
escape ^@a
maptimeout 0
screen 1
startup_message off
```

## Dynamic `screen` Configuration Based on Session

On my machines, these configs are dynamically loaded based on session. I also follow the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest) by declaring the `SCREENRC=` environment variable, which moves the configuration from `~/.screenrc` to whatever path is specified in the variable.

If you would also like to load individual configs based on whether you're in an X11 or a TTY session, refer to this snippet of my `.config/shell/profile` :

```sh
#!/bin/sh
…
# X11-dependent env variables
if [ -n "$DISPLAY" ] && xhost >/dev/null; then
    setxkbmap -option compose:ralt
    xset r rate 300 50
    export SCREENRC="$XDG_CONFIG_HOME"/screen/screenrc
    export XPROFILE_X11_SPECIFICS=loaded
else # if TTY
    export SCREENRC="$XDG_CONFIG_HOME"/screen/screenrc-if-tty
    export XPROFILE_X11_SPECIFICS=unloaded
    echo "X11 is not running... X11-related settings have been skipped"
fi
```

This file is sourced by my `fish` shell config (via a method similar to what is mentioned in the [ArchWiki](https://wiki.archlinux.org/title/Fish#Source_/etc/profile_on_login)). The file is also symlinked to `.zprofile`, `.profile`, and `.xprofile`/`.xsessionrc` in case I want to go back to using `zsh` or `bash` as my default shell again.

## Changing the "Prefix" Key

If you would like to have a different "prefix" key, you can run `showkey -a` to examine the codes sent by the keyboard and then grab the ASCII output, append an "a", and modify the config like so:

[![Image of screenkey and showkey when pressing Ctrl+\ ](https://aedrielkylejavier.me/articles/img/gnu-screen-images/new-keybind.png)](https://aedrielkylejavier.me/articles/img/gnu-screen-images/new-keybind.png)
*Output while pressing* `Ctrl`+`\`

&nbsp;

**To apply, replace the `escape ^@a` line in the config with:**
```sh
escape ^\a
```

&nbsp;

For more information on this, you can refer to the ArchWiki's "Change The Escape Key" [GNU Screen Article](https://wiki.archlinux.org/title/GNU_Screen#Change_the_escape_key).


&nbsp;

## Wrapping Up 🎁

That's it for my simple GNU Screen setup! While GNU Screen might not be as feature-rich `tmux`, I believe it offers a straightforward and functional alternative for those who prefer simplicity and minimalism with their tools. The configurations shared here should provide a solid foundation to get you started. Feel free to experiment with the configs and make them your own.

Happy hacking, and may your terminal sessions be ever efficient and productive! 🚀

&nbsp;