DEV Community

Cover image for Make Your Tmux Status Line 100% Better With Bash
brandon_wallace
brandon_wallace

Posted on • Updated on

Make Your Tmux Status Line 100% Better With Bash

Did you know that you can easily use Bash to display information on the Tmux status line? Because of that the possibilities of what you can do are almost endless. You can display all sorts of useful information such as:

  • Hostname
  • IP address
  • Netmask
  • Gateway
  • Memory
  • CPU temperature
  • System load
  • Battery meter
  • VPN status
  • Time
  • Date
  • Weather report
  • Git status

In this article I will show you an easy way to add information to your Tmux status line.

Requirements

  • lm-sensors

Here is the default status line.

status-line-original.png

Here is the status line enhanced to show more information.

tmux-status-line-enhanced.png

# Debian/Ubuntu based distributions
$ sudo apt install tmux


# Redhat/Fedora based distributions
$ sudo dnf install tmux
Enter fullscreen mode Exit fullscreen mode

Check your Tmux version. Currently I am using version 3.3a.

$ tmux -V

# Output
tmux 3.3a
Enter fullscreen mode Exit fullscreen mode

If you do not have a .tmux.conf create one in your home directory.

$ touch .tmux.conf
Enter fullscreen mode Exit fullscreen mode

I will start out with a basic .tmux.conf configuration. Edit .tmux.conf and add the following lines.


# .tmux.conf

bind r source-file ~/.tmux.conf \; display-message "RELOADING CONFIGURATION FILE…"

# STATUS LINE
set -g status on
set -g status-interval 1
set -g status-justify centre # Careful! It is spelled "centre" not "center".
set -g status-style fg=white,bg=black

# Highlight the current window.
setw -g window-status-current-style fg=white,bg=red,bright

# LEFT STATUS
set -g status-left-length 100
set -g status-left-style default
set -g status-left " "

# RIGHT STATUS
set -g status-right-length 100
set -g status-right-style default
set -g status-right " "

Enter fullscreen mode Exit fullscreen mode

Status Line Left Side

Tmux has same built in variables that you can use to display information such as #h to display the hostname. View the man page for more information.


$ man tmux

Enter fullscreen mode Exit fullscreen mode

Add #h in between the double quotes


set -g status-left "#h"

Enter fullscreen mode Exit fullscreen mode

You need to reload Tmux to see the changes. To reload Tmux you can type exit then launch Tmux again or you can reload Tmux by press the CTRL+b then r.
After reloading Tmux you will see the hostname of your computer on the status line.

tmux-status-line-hostname-bw.png

Adding the IP address and netmask to Status Line

All we need to do to customize the status line is to add Bash one-liners. To add Bash commands to the command line you only need to place each command inside a hash mark and parenthesis #( <my-command> ).

I use this Bash command to get the IP address of the enp4s0 Ethernet interface.


$ ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}'

# Output

192.168.0.101/26

Enter fullscreen mode Exit fullscreen mode

I can add the command to the Tmux status line by placing it in between the parenthesis like this.


set -g status-left "#h #(ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}')"

Enter fullscreen mode Exit fullscreen mode

tmux-status-line-ip-netmask-bw.png

Adding the CPU Temperature to Status Line

Next I want to add the CPU temperature. To make that work you must use lm-sensors. Install lm-sensors.


# Debian/Ubuntu based distributions
$ sudo apt install lm-sensors


# Redhat/Fedora based distributions
$ sudo dnf install lm_sensors

Enter fullscreen mode Exit fullscreen mode

Enable lm-sensors with this command and follow the prompts.

$ sudo sensors-detect
Enter fullscreen mode Exit fullscreen mode

Run the sensors command to see the output. From the output you will need to figure out which line displays information about the CPU. The line you need might be labeled Tccd1 or CPU. Add the -f argument to the sensors command to see the temperature in Fahrenheit.


$ sensors -f

# Partial Output 

intel-isa-0000
Adapter: ISA adapter
fan1:           0 RPM
CPU:          +96.8°F  
GPU:              N/A  
temp3:        +96.8°F  
temp4:        +32.0°F  
temp5:        +96.8°F  
temp6:        +96.8°F  
temp7:        +96.8°F  
temp8:            N/A  

intel-pci-0400
Adapter: PCI adapter
vddgfx:      794.00 mV 
vddnb:       604.00 mV 
edge:         +95.0°F  
PPT:           3.16 W  

BAT0-acpi-0
Adapter: ACPI interface
in0:          17.27 V  
[....]

Enter fullscreen mode Exit fullscreen mode

Add this code #(sensors -f | awk '/CPU/{printf $2}') to the end of the left status line. This command uses awk to find the row with the text CPU and print the second column.


set -g status-left "#h #(ip addr show enp4s0 | awk '/inet /{printf $2}') #(sensors -f | awk '/CPU/{printf $2}')"

Enter fullscreen mode Exit fullscreen mode

tmux-status-line-cpu-temp-bw.png

Adding Memory to the Status Line

Next, I want to view the amount of memory used, the total memory, and calculate the percentage of memory in use. To do that I use the free command.


# Amount of memory used / total amount of memory
$ free -m -h | awk '/Mem/{printf $3"/"$2}'

# Output

3.3Gi/62Gi

# Calculate percentage of memory used

$ free -m | awk '/Mem/{printf "%.2f%", 100*$3/$2}'

# Output

2.1%

Enter fullscreen mode Exit fullscreen mode

Careful here! To get the memory command to display properly in the Tmux status line requires that certain characters be escaped.
Here I am using the backward slash \ to escape the double quote \", the period \., the percent sign \%, and the forward slash \/.

Before escaping characters:


#(free -m -h | awk '/Mem/{printf $3"/"$2}') #(free -m | awk '/Mem{printf "%.2f%", 100*$2/$3}')"

Enter fullscreen mode Exit fullscreen mode

After escaping characters:


#(free -m -h | awk '/Mem/{printf $3\"\/\"$2}') #(free -m | awk '/Mem{printf \"\%\.2f\%\", 100*$2/$3}')"

Enter fullscreen mode Exit fullscreen mode

The status left should now look like this.


set -g status-left "#h #(ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}') #(sensors | awk '/CPU/{printf $2}') #(free -m -h | awk '/Mem/{printf $3\"\/\"$2}') #(free -m | awk '/Mem{printf \"\%\.2f\%\", 100*$2/$3}')"

Enter fullscreen mode Exit fullscreen mode

tmux-status-line-memory-bw.png

Adding the Battery Level to Status Line

I want to see the battery level and see if it is charging on not. To do that I can check the /sys file system for the battery information.

If your terminal supports unicode characters you can add an unicode characters to the status bar.

I will test to see if the power cable is plugged in and show a lighting bolt icon if it is. I will show the percentage of battery remaining next to the lightning bolt.

If $(cat /sys/class/power_supply/AC/online) is equal to 1 the lightning bolt will display.

Add these lines to the end of the left status line.


#([ $(cat /sys/class/power_supply/AC/online) == 1 ] && printf %s'🗲') 

#( $(cat /sys/class/power_supply/BAT0/capacity)\% )

Enter fullscreen mode Exit fullscreen mode

The left status line should look something like this.


set -g status-left "#h #(ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}') #(sensors | awk '/CPU/{printf $2}') #(free -m -h | awk '/Mem/{printf \$3\"\/\"\$2\}') #(free -m | awk '/Mem{printf 100*$2/$3" %"}') #([ $(cat /sys/class/power_supply/AC/online) == 1 ] && printf %s'🗲') #(cat /sys/class/power_supply/BAT0/capacity)\%"

Enter fullscreen mode Exit fullscreen mode

tmux-status-line-battery-bw.png

Adding the VPN to Status Line

I want to check if the VPN is up and see the IP address assigned to it. Depending on the VPN you use you might have to check the tun0 or ppp0 interface.


ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf $2}'

# Output

10.20.3.45

Enter fullscreen mode Exit fullscreen mode

Add this to the end of the left status line.


#([ ! -z $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf $2}') ] && echo $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf \"VPN \"$2}'))

Enter fullscreen mode Exit fullscreen mode

My status line now looks like this.


set -g status-left "#h #(ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}') #(sensors | awk '/CPU/{printf $2}') #(free -m -h | awk '/Mem/{printf \$3\"\/\"\$2\}') #(free -m | awk '/Mem{printf 100*$2/$3" %"}') #([ $(cat /sys/class/power_supply/AC/online) == 1 ] && printf %s'🗲') #(cat /sys/class/power_supply/BAT0/capacity)\% #([ ! -z $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf $2}') ] && echo $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf \"VPN \"$2}'))"

Enter fullscreen mode Exit fullscreen mode

tmux-status-line-enhanced-bw.png

Status Bar Right Side

Now let’s configure the right side.

I will get the load average using the uptime command.


$ uptime

# Output

02:39:38 up 12:18,  1 user,  load average: 0.20, 0.11, 0.10

Enter fullscreen mode Exit fullscreen mode

The number of columns in the output can change so depending on the time. To get around that problem I use $(NF) to get the last column and tr to remove the colon characters.

Add this to the right status line option with escaped characters in between the double quotes.


set -g status-right "#(uptime | awk '{printf \$(NF-2)\" \"\$(NF-1)\" \"\$(NF)}' | tr -d ',')"

Enter fullscreen mode Exit fullscreen mode

The last thing I will add is the date, time, and timezone using variables to status-right. Tmux uses strftime formatting to display variables. Given that, I can view the date and time using a custom format. Example: %F represents YYYY-mm-dd %T represents HH:MM:SS . See the man page for more information man strftime.

Add that to the end of the right status line.


set -g status-right "#(uptime | awk '{printf \$(NF-2)\" \"\$(NF-1)\" \"\$(NF)}' | tr -d ',') %F %T %Z"

Enter fullscreen mode Exit fullscreen mode

Adding a Bash Script

If you needed to configure more complicated code than what could fit on one line you can make a separate Bash file and add it like this.


set -g status-right "#( example.sh )"

Enter fullscreen mode Exit fullscreen mode

$ cat example.sh

#!/bin/bash
# example.sh

# Get the IP address dynamically
function get_ip_address() {
    mapfile -t iface_arr < <(echo $(ls /sys/class/net/))
    for iface in $iface_arr; do 
        if [ "$(cat /sys/class/net/$iface/operstate)" == "up" ]; then
            printf "    %s\n" "${iface^^}: $(ip addr show $iface | awk '/inet /{printf $2}')"; 
        fi
    done
}

get_ip_address

Enter fullscreen mode Exit fullscreen mode

Adding Color

Run this code in your terminal to see what colors you have available.


#!/bin/bash

for num in {0..255}; do  
    printf "%s\033[38;5;${num}mcolour${num}\033[0m \t"; 

    if [ $(expr $((num+1)) % 8) -eq 0 ]; then
        printf "\n"
    fi
done

Enter fullscreen mode Exit fullscreen mode

tmux-colour-chart.png

Now you can add color to your status line. Add foreground colors by setting a #[fg=<colourN>] or #[bg=<colourN>] variable to the color of your choice.
fg= is for the foreground color bg= is to set the background color in between square brackets. Use #[default] to back to the default colors.


set -g status-left "#[fg=colour220] #h #[fg=colour47] #(ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}') #[colour27] #(sensors -f | awk '/CPU/{printf $2}') #[default]"

Enter fullscreen mode Exit fullscreen mode

tmux-status-line-color.png

The status lines can get quite long. If you do not like long lines use the backslash to break it up.


set -g status-left "#[fg=colour220]#h\
#[fg=colour196] #(ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}')\
#[fg=colour39] #(sensors | awk '/CPU/{printf $2}')\
#[fg=colour40] #(free -m -h | awk '/Mem/{printf \$3\"\/\"\$2\}')\
#[fg=colour128] #(free -m | awk '/Mem{printf 100*$2/$3" %"}')\
#[fg=colour202] #([ $(cat /sys/class/power_supply/AC/online) == 1 ] && printf %s'🗲') #(cat /sys/class/power_supply/BAT0/capacity)\%\
#[fg=colour7] #([ ! -z $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf $2}') ] && echo $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf \"VPN \"$2}'))\
#[default]"

Enter fullscreen mode Exit fullscreen mode

Complete Status Line Configuration


# .tmux.conf

bind r source-file ~/.tmux.conf \; display-message "RELOADING CONFIGURATION FILE…"

# STATUS LINE
set -g status on
set -g status-interval 1
set -g status-justify centre # Careful! It is spelled "centre" not "center".
set -g status-style fg=white,bg=black

# Highlight the current window.
setw -g window-status-current-style fg=white,bg=red,bright

# LEFT STATUS
set -g status-left-length 100
set -g status-left-style default
set -g status-left "#[fg=colour220]#h\
#[fg=colour196] #(ip addr | grep -e 'state UP' -A 2 | awk '/inet /{printf $2}')\
#[fg=colour39] #(sensors | awk '/CPU/{printf $2}')\
#[fg=colour40] #(free -m -h | awk '/Mem/{printf \$3\"\/\"\$2\}')\
#[fg=colour128] #(free -m | awk '/Mem{printf 100*$2/$3" %"}')\
#[fg=colour202] #([ $(cat /sys/class/power_supply/AC/online) == 1 ] && printf %s'🗲') #(cat /sys/class/power_supply/BAT0/capacity)\%\
#[fg=colour7] #([ ! -z $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf $2}') ] && echo $(ip a | egrep 'ppp0|tun0' -A 2 | awk '/inet /{printf \"VPN \"$2}'))\
#[default]"

# RIGHT STATUS
set -g status-right-length 100
set -g status-right-style default
set -g status-right "#[fg=colour39] #(uptime | awk '{printf \$(NF-2)\" \"\$(NF-1)\" \"\$(NF)}' | tr -d ',')\
#[fg=colour40] %F\
#[fg=colour128] %T\
#[fg=colour202] %Z\
#[default]"

Enter fullscreen mode Exit fullscreen mode

Conclusion

You can now easily have a Bash display useful information on the Tmux status line. I hope you learned something new and enjoyed reading this article.

Follow me on Dev.to and Github.

Feel free to leave comments, questions, and suggestions.

Oldest comments (1)

Collapse
 
cainnz profile image
cainnz

Hi, if I want to remove the [0] which command should I use?