Configuring a Functional and Beautiful Linux Shell

Configuring a Functional and Beautiful Linux Shell

An Everyday Tinkering Series Article


A Linux Shell is a program that takes commands from the keyboard and parses them to the operating system to perform. It is comparable to the Windows CMD. There are different Shell programs, the most popular being the bash: Bourne Again Shell, an enhanced version of the original UNIX program, sh.

BASH takes its name from its developer, Steve Bourne.

My favourite is Zsh: the Z-Shell. Zsh inherits all the great functionality from bash, adds speed improvements, and allows integration of third-party modules to enhance its functionality.

We will configure Zsh on an Ubuntu instance running on Windows Subsystem for Linux (WSL). You can use the same commands for bare metal or virtual Debian-based distros, and with slight modifications, you can utilise them in other distros. I will comment on the commands modification for Fedora (Red Hat) & Manjaro (Arch).

Let's get configuring.


  • Basic shell scripting and Linux configuration knowledge.

  • Configuration knowledge of your favourite shell emulator / Terminal

    I will demonstrate the steps using Windows Terminal Preview. Feel free to use Google and StackOverflow to find out how to install fonts on yours.

  • Ensure your Linux distro has Git and Curl installed. Use the following commands to check:

    :> curl -version

    :> git -v

    In most cases, you will get a response showing the installed versions of Git and Curl.

    If you get an error, install the two packages by running the following commands:

    Debian Distros:

    sudo apt update && sudo apt install curl git

    Arch Distros:

    sudo pacman -S curl git

    RHEL Distros

    sudo dnf curl git

  • Tons of curiosity and a love for tinkering.


Always back up your Linux configuration files before editing them.

The easiest way to do this is to copy them with the extension ".old". In this guide, we will edit the ZSH configuration file named ".zshrc". To create a copy of ".zshrc", run the following command:

:> cp ~/.zshrc ~./zshrc.old

You can copy the new .zsh.old to a pen drive for added safety.

Review all commands before running them and read original project documentation if in doubt of their impact on your systems.

IMPORTANT: Do not attempt these steps on critical production servers at work or school. Do not be the legend who brought down the whole campus network!

The why

Many computing professionals spend a lot of time using their preferred terminal emulator. Configuring it to provide information at a glance can do wonders for productivity. We shall discuss each listed functionality as we install and configure them.

The how

  1. Please install the following Meslo Nerd Fonts and install them.

    1. MesloLGS NF Regular

    2. MesloLGS NF Bold

    3. MesloLGS NF Italic

    4. MesloLGS NF Bold Italic

  2. Set MesloLGS NF as the default font for your preferred terminal emulator. Please use Google for your specific distro and terminal. There are too many combinations to go through them all. In my case, I am using Windows Terminal on an Ubuntu WSL instance. To change the font: Settings > Defaults > Appearance, as shown below.

  3. Install Zsh - Run the following commands, depending on your distro, to install Z-Shell (Zsh).

    Debian Distros:

    :> sudo apt install zsh

    Arch Distros:

    :> sudo pacman -S zsh

    RHEL Distros

    :> sudo dnf zsh

  4. Install Oh-My-Zsh - Oh My Zsh is an open-source, community-driven framework for managing the Zsh configuration. Run the command below to install Oh-My-Zsh and set Zsh as your default shell. Enter your password when requested.

    :> sh -c "$(curl -fsSL"

  5. Confirm that zsh has been set as the default shell in your terminal emulator by running the following command.

    :> echo $SHELL

    The terminal should get a response as shown below.

  6. Hooray, we have successfully installed Zsh and Oh-My-Zsh and set Zsh as the default shell in our terminal. We can now dive into configuring Zsh to be beautiful and functional. To do so, we must edit the zshrc configuration file. As discussed earlier, let us start by creating a backup copy of the zshrc. Note that the dot(.) in front of a file name in Linux means the file is hidden.

    :> cp ~/.zshrc ~./zshrc.backup

    We can now list the files to confirm that our backup file was created.

    :> ls -a

    1. We shall use nano, a small but powerful terminal text editor, to edit the zshrc file.

      :> nano ~/.zshrc

      We shall edit four sections.

      • Change ZSH_THEME to Powerlevel10k - Powerlevel10k is a perfect theme for zsh.

      • Uncomment ZSH_CUSTOM and set it to ~/.zsh_custom. We want to install all Oh-My-Zsh plugins to a different hidden folder to clean our Oh-My-Zsh directory. We should create this folder before proceeding using the command below.

        :> mkdir ~/.zsh_custom

      • Add several essential plugins: git, zsh-completions, zsh-autosuggestions, zsh-syntax-highlighting, z and docker-compose. These are my favourite plugins; it is not wise to put many of them as they can significantly slow your signal. We also need to add FPATH to our .zshrc by adding the line after the plugins.

      • Finally, we should add the ~/.local/bin folder to the path. Most development environments exist in this folder. Adding it to the path means we can quickly call them from the terminal.

        export PATH="~/.local/bin:$PATH"

      • The final .zshr file should look like the code segment shown below. All the code and writings starting with # are commented out and have no effect. It is good practice to keep them.

          # If you come from bash you might have to change your $PATH.
          # export PATH=$HOME/bin:/usr/local/bin:$PATH
          # Path to your oh-my-zsh installation.
          export ZSH="$HOME/.oh-my-zsh"
          # Set name of the theme to load --- if set to "random", it will
          # load a random theme each time oh-my-zsh is loaded, in which case,
          # to know which specific one was loaded, run: echo $RANDOM_THEME
          # See
          # Set list of themes to pick from when loading at random
          # Setting this variable when ZSH_THEME=random will cause zsh to load
          # a theme from this variable instead of looking in $ZSH/themes/
          # If set to an empty array, this variable will have no effect.
          # ZSH_THEME_RANDOM_CANDIDATES=( "robbyrussell" "agnoster" )
          # Uncomment the following line to use case-sensitive completion.
          # CASE_SENSITIVE="true"
          # Uncomment the following line to use hyphen-insensitive completion.
          # Case-sensitive completion must be off. _ and - will be interchangeable.
          # HYPHEN_INSENSITIVE="true"
          # Uncomment one of the following lines to change the auto-update behavior
          # zstyle ':omz:update' mode disabled  # disable automatic updates
          # zstyle ':omz:update' mode auto      # update automatically without asking
          # zstyle ':omz:update' mode reminder  # just remind me to update when it's time
          # Uncomment the following line to change how often to auto-update (in days).
          # zstyle ':omz:update' frequency 13
          # Uncomment the following line if pasting URLs and other text is messed up.
          # DISABLE_MAGIC_FUNCTIONS="true"
          # Uncomment the following line to disable colors in ls.
          # DISABLE_LS_COLORS="true"
          # Uncomment the following line to disable auto-setting terminal title.
          # DISABLE_AUTO_TITLE="true"
          # Uncomment the following line to enable command auto-correction.
          # ENABLE_CORRECTION="true"
          # Uncomment the following line to display red dots whilst waiting for completion.
          # You can also set it to another string to have that shown instead of the default red dots.
          # e.g. COMPLETION_WAITING_DOTS="%F{yellow}waiting...%f"
          # Caution: this setting can cause issues with multiline prompts in zsh < 5.7.1 (see #5765)
          # COMPLETION_WAITING_DOTS="true"
          # Uncomment the following line if you want to disable marking untracked files
          # under VCS as dirty. This makes repository status check for large repositories
          # much, much faster.
          # Uncomment the following line if you want to change the command execution time
          # stamp shown in the history command output.
          # You can set one of the optional three formats:
          # "mm/dd/yyyy"|""|"yyyy-mm-dd"
          # or set a custom format using the strftime function format specifications,
          # see 'man strftime' for details.
          # HIST_STAMPS="mm/dd/yyyy"
          # Would you like to use another custom folder than $ZSH/custom?
          # Which plugins would you like to load?
          # Standard plugins can be found in $ZSH/plugins/
          # Custom plugins may be added to $ZSH_CUSTOM/plugins/
          # Example format: plugins=(rails git textmate ruby lighthouse)
          # Add wisely, as too many plugins slow down shell startup.
          source $ZSH/
          # User configuration
          # export MANPATH="/usr/local/man:$MANPATH"
          # You may need to manually set your language environment
          # export LANG=en_US.UTF-8
          # Preferred editor for local and remote sessions
          # if [[ -n $SSH_CONNECTION ]]; then
          #   export EDITOR='vim'
          # else
          #   export EDITOR='mvim'
          # fi
          # Compilation flags
          # export ARCHFLAGS="-arch x86_64"
          # Set personal aliases, overriding those provided by oh-my-zsh libs,
          # plugins, and themes. Aliases can be placed here, though oh-my-zsh
          # users are encouraged to define aliases within the ZSH_CUSTOM folder.
          # For a full list of active aliases, run `alias`.
          # Example aliases
          # alias zshconfig="mate ~/.zshrc"
          # alias ohmyzsh="mate ~/.oh-my-zsh"
          # Custom PATHS
          export PATH="~/.local/bin:$PATH"
  7. We are done with the setup and configuration. The next step is to restart your terminal. You can also run the command below instead of restarting your terminal:

    :> source ~/.zshrc

    As seen in the screenshot below - the terminal relaunches with errors! Some plugins and themes we configured are not found - can you guess why? We DID NOT install them.

  8. I like doing my configurations this way because it allows me to test that everything works as expected. It is a concept I borrowed from Test Driven Development. The other plugins that do not show any errors are batteries that come with Oh-My-Zsh and do not need further installations.

  9. Let's install the PowerLevel10k theme.

    We use Oh-My-Zsh to fetch the theme files and correctly configure them.

    git clone --depth=1 ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

  10. Let's install the zsh-completions plugin using Oh-My-Zsh.

    git clone ${ZSH_CUSTOM:-${ZSH:-~/.oh-my-zsh}/custom}/plugins/zsh-completions

  11. Let's install the zsh-autosuggestions theme, also using Oh-My-Zsh.

git clone ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

  1. Finally, we install zsh-syntax-highlighting using Oh-My-Zsh.

git clone ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

  1. We have completed the configuration of our terminal. In the next stage, we shall customise PowerLevel10K.

### Customising PowerLevel10K

PowerLevel10K comes with many options we can customise to suit our requirements. In the video below, I configure a few essential options. Read through the documentation and play around to find your suite of options.

The sound Effect in the video above is by royalty_free_music from Pixabay

Customising Aliases

In Linux, aliases are used to create shortcuts for commands. They are most commonly used to shorten long or complex commands. Aliases also create shortcuts for files, directories, and programs. Aliases are made using the alias command and stored in the user's profile or the system-wide configuration file.

Some examples are shown below:

alias c='clear';
#Updater alias#
function apt-updater {
        sudo apt-get update &&
        sudo apt-get dist-upgrade -Vy &&
        sudo apt-get autoremove -y &&
        sudo apt-get autoclean &&
        sudo apt-get clean

In the example above, I have defined two aliases

  • alias c='clear': This allows me to type c only instead of clear to remove all texts in my terminal.

  • I have also created a function called apt-updater, which allows me to run five commands by just typing "apt-updater" instead of the five commands.

Oh-My-Zsh allows us to create a file in the ~/.zsh_custom folder. We will name it example. zsh and list our aliases. I have put comments to explain the function of each alias.

# custom ~/.bash_aliases
alias c='clear';
#Updater alias#
function apt-updater {
        sudo apt-get update &&
        sudo apt-get dist-upgrade -Vy &&
        sudo apt-get autoremove -y &&
        sudo apt-get autoclean &&
        sudo apt-get clean
#Install Software#
alias install='sudo apt install';
#Make directory#
alias mkdir='mkdir -pv';
#Colourise grep#
alias grep='grep --color=auto';
alias egrep='egrep --color=auto';
alias fgrep='fgrep --color=auto';
#Compare diff outputs#
alias diff='colordiff';
#Show open ports#
alias ports='netstat -tulanp';
#Do not delete / or prompt if deleting more than 3 files at a time #
alias rm='rm -I --preserve-root'
#Confirmation #
alias mv='mv -i';
alias cp='cp -i';
alias ln='ln -i';
#Parenting changing perms on / #
alias chown='chown --preserve-root';
alias chmod='chmod --preserve-root';
alias chgrp='chgrp --preserve-root';
#Become root #
alias root='sudo -i';
alias su='sudo -i';
#Reboot / halt / poweroff
alias reboot='sudo /sbin/reboot'
alias poweroff='sudo /sbin/poweroff'
alias halt='sudo /sbin/halt'
alias shutdown='sudo /sbin/shutdown'
#This one saved by butt so many times#
alias wget='wget -c';
alias checkupdate='sudo apt update';
# use color
alias ls="ls --color=auto"
alias dir="dir --color=auto"
alias grep="grep --color=auto"
alias dmesg='dmesg --color'
# extended listing
alias ll='ls -halF'
alias la='ls -A'
alias l='ls -CF'
# ensure remove confirmations
alias rm='rm -i'
# human readable df
alias df='df -h'
# ignore common typos
alias naon='nano'

That marks the end of this rather long post, but I hope you have fun trying the steps out and learn a lot from finding solutions to the problems you run into.

Please post your shiny new terminals in the comment sections when you succeed!

This article is part of the Everyday Tinkering series. Look out for more in the same vein.

Thank you for reading, and until next time, keep coding!

Did you find this article valuable?

Support Brian Koech by becoming a sponsor. Any amount is appreciated!