Automatically colorize terminal tabs based on the server you are logged into

Behold:

OSX’s iTerm 2, and maybe some other terminal applications, support ANSI control sequence extensions which allow shell to set the color of the terminal tab.

Below is a Python script which

  • Randomizes a color based on the server host name. The same hostname always results to the same color.
  • The color is randomized in HSL color space, so that only the hue component varies and saturation and lightness are locked. This prevents the creation of ugly color combinations like black text on black tab background.

Note: The effect can be also applied on terminal windows  – for those who don’t use tabs.

The effective result is that

  • You learn to identify terminal tabs by the color
  • You can much more faster to switch between tabs, because you can visually pick up the terminal without needing to be able to read the text on it or remember its location in the list

Note: If your puny terminal does not support setting the color of window decorations, you can always set the terminal background color. This is useful e.g. if you want to red background for danger zone ™ when you are logged in as root on the production server 23:00 Friday night.

Note: Naturally you also need to have the script installed on the servers you are ssh’ing into

1. precmd() hook

You can run the script once and the tab color is set. However, if you SSH from the computer to another  and then exit back, the color of the latest server would remain in this case.

This can be avoided by

  1. Calculating the OSC control code sequence needed to set the terminal tab color when the shell starts
  2. Have a precmd() hook (zsh terminology, not sure what other shells use) to reset the tab color every time the shell prompt is displayd

We, me with my friend, are maintaining (yet another) zsh toolkit called ztanesh (github). There  you can find precmd() example codes in 1) 98-server-color and 2) 80-statusbar.

2. rainbow-parade.py

The script code lives on Github. Currently it supports iTerm 2 only and we plan to expand support to Konsole. Patches for other terminals are welcome.

(This probably could be done in pure shell code too, but Python is just so much more fun…)

#!/usr/bin/env python
"""

       Set terminal tab / decoration color by the server name.

       Get a random colour which matches the server name and use it for the tab colour:
       the benefit is that each server gets a distinct color which you do not need
       to configure beforehand.

"""

import socket
import random
import colorsys
import sys

# http://stackoverflow.com/questions/1523427/python-what-is-the-common-header-format
__copyright__ = "Copyright 2012 Mikko Ohtamaa - http://opensourcehacker.com"
__author__ = "Mikko Ohtamaa <mikko@opensourcehacker.com>"
__licence__ = "WTFPL"
__credits__ = ["Antti Haapala"]

USAGE = """
Colorize terminal tab based on the current host name.

Usage: rainbow-parade.py [0-1.0] [0-1.0] # Lightness and saturation values

An iTerm 2 example (recolorize dark grey background and black text):

    rainbow-parade.py 0.7 0.4
"""

def get_random_by_string(s):
    """
    Get always the same 0...1 random number based on an arbitrary string
    """

    # Initialize random gen by server name hash
    random.seed(s)
    return random.random()

def decorate_terminal(color):
    """
    Set terminal tab / decoration color.

    Please note that iTerm 2 / Konsole have different control codes over this.
    Note sure what other terminals support this behavior.

    :param color: tuple of (r, g, b)
    """

    r, g, b = color

    # iTerm 2
    # http://www.iterm2.com/#/section/documentation/escape_codes"
    sys.stdout.write("\033]6;1;bg;red;brightness;%d\a" % int(r * 255))
    sys.stdout.write("\033]6;1;bg;green;brightness;%d\a" % int(g * 255))
    sys.stdout.write("\033]6;1;bg;blue;brightness;%d\a" % int(b * 255))
    sys.stdout.flush()

    # Konsole
    # TODO
    # http://meta.ath0.com/2006/05/24/unix-shell-games-with-kde/

def rainbow_unicorn(lightness, saturation):
    """
    Colorize terminal tab by your server name.

    Create a color in HSL space where lightness and saturation is locked, tune only hue by the server.

    http://games.adultswim.com/robot-unicorn-attack-twitchy-online-game.html
    """

    name = socket.gethostname()

    hue = get_random_by_string(name)

    color = colorsys.hls_to_rgb(hue, lightness, saturation)

    decorate_terminal(color)

def main():
    """
    From Toholampi with love http://www.toholampi.fi/tiedostot/119_yleisesite_englanti_naytto.pdf
    """
    if(len(sys.argv) < 3):
        sys.exit(USAGE)

    lightness = float(sys.argv[1])
    saturation = float(sys.argv[2])

    rainbow_unicorn(lightness, saturation)

if __name__ == "__main__":
    main()

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

12 thoughts on “Automatically colorize terminal tabs based on the server you are logged into

  1. It is applicable for specific terminal applications. How to apply to a specific terminal application is a question left for the reader as an exercise.

  2. Very nice thanks.
    But where do i config the script to be executed on each `ssh hostname` ?

  3. The server sets its own color in a shell prompt code. It depends on the shell you are using on the server. Usually the file is .zshrc, .bashrc etc. depending on the server.

    I am am using this ZSH configuration package https://github.com/miohtama/ztanesh which syncs the ZSH configuration changes across the computers using Github. It already contains this coloring code.

  4. Pingback: Five ZSH tricks to optimize your shell workflow

  5. This has a lot of potential, can you do the same but when someone opened an interactive python session?.

    Thanks!

  6. Yes. Basically you just need to send certain ANSI control code sequence to the terminal. Check ztanesh source code how it does it.

    Please note that the sequence is terminal software specific and not all terminals support this.

  7. I’m using bash and don’t understand this part:

    Calculating the OSC control code sequence needed to set the terminal tab color when the shell starts

    So how do I make my basic color revert back when I exit the ssh session?

    thank you

  8. I figured out the sequence to reset the tab color… it’s still not perfect because Blue as active color is gone but for now it’s ok:

    function ssh {
    echo -e “33]6;1;bg;red;brightness;162\a33]6;1;bg;green;brightness;209\a33]6;1;bg;blue;brightness;147\a”
    command ssh $@
    echo -e “33]6;1;bg;red;brightness;176\a33]6;1;bg;green;brightness;181\a33]6;1;bg;blue;brightness;175\a”
    }

    So that is *all* one needs… no python scripts or anything on the server… for now it colors all the servers the same (green) but that’s good enough for me… Gray: local, Green: remote

  9. I certainly dont understand how to setup this to work when you do ssh something

  10. Arnold:

    put this in your .bash_aliases or .bash_profile if you don’t have .bash_aliases:

    function ssh {
    echo -e “33]6;1;bg;red;brightness;162\a33]6;1;bg;green;brightness;209\a33]6;1;bg;blue;brightness;147\a”
    command ssh $@
    echo -e “33]6;1;bg;red;brightness;176\a33]6;1;bg;green;brightness;181\a33]6;1;bg;blue;brightness;175\a”
    }

    and that’s it…it will work in iTerm

  11. the link to iTerm2 in the first sentence is broken – fix and delete this comment 😉

Leave a Reply

Your email address will not be published. Required fields are marked *