A better shell with oh-my-zsh
❓ Abstract
Not So Basic: Devenv is a series of tutorials where we aim to have a nice, productive and portable environment that take the best of both worlds between Linux and windows.
In this second tutorial "A better shell with oh-my-zsh" we do the groundwork using:
- Zsh: a Linux shell with extended capabilities (command-line completion, command history, theming and much more...).
- Oh My Zsh: a framework for managing Zsh configurations and theming.
- Powerlevel10k: A quick, flexible and powerful theme for Zsh.
📝 Overview
To complete this tutorial, you need to:
- Install Zsh and Oh My Zsh
- Install and configure Powerlevel10k
Zsh and Oh My Zsh
Zsh
First you need to run the following commands to install zsh:
sudo apt update
sudo apt install zsh
Oh My Zsh
Now you need to install Oh My Zsh.
Run the following command to install Oh My Zsh:
sh -c "$(curl -fsSLk https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
Change the default shell
The default shell is the shell used when you start your terminal, to use zsh with the configuration we just set up, run:
chsh -s $(which zsh)
Now run exit
, it will close your current terminal, then open it again, you should be using zsh with your current theme.
A look on the default configuration.
You can find the default configuration file is in your home folder: ~/.zshrc
If you open it, you can see that most of it is commented.
A short version can be summarized as:
# Path to your oh-my-zsh installation.
export ZSH="$HOME/.oh-my-zsh"
# Set name of the theme
ZSH_THEME="robbyrussel"
# Plugins
plugins=(git)
#import parent settings
source $ZSH/oh-my-zsh.sh
Themes can add new features and nice display improvements.
Powerlevel10k
Install
Powerlevel10k is a full-featured theme for Zsh.
This theme offers the possibility to customize the style of your shell using many elements based on a font that includes icons.
Nerd fonts contains all the icons you need to have a good experience with the tool. You can check the features offered on the official nerd fonts website, select the font you prefer from the download page, or use the cheat sheet to search for an icon.
We will use FiraCode Nerd Font Mono in this tutorial because it is a monospaced programming font including typographic ligatures and well rendered by most of the terminals.
Install the recommended font on Windows
Download FiraCode Nerd Font, then follow the manual font installation instructions for your terminal.
Install the recommended font on Linux
Create a fonts
directory in ~/.local/share
mkdir -p ~/.local/share/fonts
Then you can download FiraCode Nerd Font
:
wget https://github.com/ryanoasis/nerd-fonts/raw/refs/heads/master/patched-fonts/FiraCode/Bold/FiraCodeNerdFontMono-Bold.ttf -P ~/.local/share/fonts
wget https://github.com/ryanoasis/nerd-fonts/raw/refs/heads/master/patched-fonts/FiraCode/Light/FiraCodeNerdFontMono-Light.ttf -P ~/.local/share/fonts
wget https://github.com/ryanoasis/nerd-fonts/raw/refs/heads/master/patched-fonts/FiraCode/Medium/FiraCodeNerdFontMono-Medium.ttf -P ~/.local/share/fonts
wget https://github.com/ryanoasis/nerd-fonts/raw/refs/heads/master/patched-fonts/FiraCode/Regular/FiraCodeNerdFontMono-Regular.ttf -P ~/.local/share/fonts
wget https://github.com/ryanoasis/nerd-fonts/raw/refs/heads/master/patched-fonts/FiraCode/Retina/FiraCodeNerdFontMono-Retina.ttf -P ~/.local/share/fonts
wget https://github.com/ryanoasis/nerd-fonts/raw/refs/heads/master/patched-fonts/FiraCode/SemiBold/FiraCodeNerdFontMono-SemiBold.ttf -P ~/.local/share/fonts
Finally, you can follow the manual font installation instructions for your terminal.
Install powerlevel10k as a Oh-my-zsh theme
Verify that git is present on your distribution:
git --version
If git is not installed on your distribution, follow these instructions to install it, then run:
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
Set ZSH_THEME="powerlevel10k/powerlevel10k"
in ~/.zshrc
sed -i 's/ZSH_THEME="[^"]*/ZSH_THEME="powerlevel10k\/powerlevel10k/g' .zshrc
Configure
Using the configuration wizard
When you exit
and go back to your shell, you will be prompted by Powerlevel10k configuration wizard, follows the instructions to set up the configuration of your choice.
If you want to start again the configuration wizard, run:
p10k configure
Manual advanced configuration
The configuration wizard is a nice starting point to quickly get a good-looking shell, but there is much more parameters you can fine-tune.
Here is an example of the result you can get at the end by following the Customization examples, which are taken from our p10k configuration file:
We will be glad to see the result of your own configuration, feel free to post a screenshot in the comments section!
You can use vim
to explore and edit p10k configuration file, run the following command to install vim:
sudo apt install vim
Here are some basic vim commands:
-
i
to enter insert mode -
escape
to exit insert mode -
/
to enter a search term -
enter
to perform search -
n
to find the next occurrence orN
to find the previous occurrence -
escape
to exit insert mode, then:wq
andenter
to save the file and quit vim -
escape
to exit insert mode, then:q!
andenter
to quit vim without saving - Read Getting started with Vim to learn the basics of this powerful cli file editor
Open p10k configuration file with vim:
vim ~/.p10k.zsh
Customization examples
Switch a prompt segment from a side to another
For this example we will add the context user@hostname
on the left prompt side and the vcs (git) segment to the right side.
Left prompt segments
- Add
context
, not active by default on a local session, but we will change that later - Remove
vcs
to display it with right prompt segments ```bash=
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
...
context # user@hostname
...
)
###### Right prompt segments
- Remove
context
since it is now displayed with left prompt segments
- Add
vcs
- Add contextual information about tools. Only displayed when installed and referenced by content of the current directory: Node.js, dotnet, PHP, Laravel, package
- Add information about hardware on the next line
```bash=
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
=========================[ Line #1 ]=========================
vcs # git status
...
node_version # node.js version
dotnet_version # .NET version (https://dotnet.microsoft.com)
...
php_version # php version (https://www.php.net/)
laravel_version # laravel php framework version (https://laravel.com/)
...
package # name@version from package.json (https://docs.npmjs.com/files/package.json)
...
=========================[ Line #2 ]=========================
...
load # CPU load
ram # free RAM
disk_usage # disk usage
swap # used swap
battery # internal battery
wifi # wifi speed
...
)
Change common colors
If your terminal support hexColors, you can override with the format var='hexCode'
In this example we:
- Update some prompt segment background color
- Update the color of prompt char displayed on the left following the previous command execution result
- Update current directory colors
- Update exit code of the last command
- Update direnv status ```bash=
...
typeset -g POWERLEVEL9K_BACKGROUND='#232323'
...
typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_DIR_FOREGROUND='#92b7d4'
...
typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND='#44637a'
...
typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND='#6fa0c6'
...
typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_COLOR='#6fa0c6'
...
typeset -g POWERLEVEL9K_VCS_LOADING_VISUAL_IDENTIFIER_COLOR='#6fa0c6'
...
typeset -g POWERLEVEL9K_STATUS_OK_FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_STATUS_OK_PIPE_FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_STATUS_ERROR_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_STATUS_ERROR_SIGNAL_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_STATUS_ERROR_PIPE_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_DIRENV_FOREGROUND='#6fa0c6'
...
Define VCS icons
You can override icons with the format var='charCode'
We create our own icons variables for the stashed/conflicted/staged/unstaged states.
In this example we:
- Update untracked icon to replace default
?
with a ghost from available font icons
- Add a stash icon to replace default
*
with an archive from available font icons
- Add a conflicted icon to replace default
~
with a skull from available font icons
- Add a staged icon to replace default
+
with a filled star from available font icons
- Add an unstaged icon to replace default
!
with an empty star from available font icons
```bash=
...
Change the value of this parameter to show a different untracked file icon.
typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='\uf79f '
Change the value of this parameter to show a different stashed file icon.
typeset -g POWERLEVEL9K_VCS_STASHES_ICON='\uf187 '
Change the value of this parameter to show a different conflicted file icon.
typeset -g POWERLEVEL9K_VCS_CONFLICTED_ICON='\ufb8a '
Change the value of this parameter to show a different staged file icon.
typeset -g POWERLEVEL9K_VCS_STAGED_ICON='\uf005 '
Change the value of this parameter to show a different unstaged file icon.
typeset -g POWERLEVEL9K_VCS_UNSTAGED_ICON='\uf006 '
...
Change VCS colors and icons
We will edit the my_git_formatter() original function
- Update git status color ```bash=
...
function my_git_formatter() {
...
if (( $1 )); then
...
local clean='%F{#6fa0c6}' # blue foreground
local modified='%F{#e8c273}' # yellow foreground
local untracked='%F{#e1874d}' # orange foreground
local conflicted='%F{#d55555}' # red foreground
...
}
- Update git status constants to use the previously defined icons variables (later in function)
```bash=
...
function my_git_formatter() {
...
(( VCS_STATUS_STASHES )) && res+=" ${clean}${(g::)POWERLEVEL9K_VCS_STATUS_STASHES_ICON}${VCS_STATUS_STASHES}"
...
(( VCS_STATUS_NUM_CONFLICTED )) && res+=" ${conflicted}${(g::)POWERLEVEL9K_VCS_CONFLICTED_ICON}${VCS_STATUS_NUM_CONFLICTED}"
...
(( VCS_STATUS_NUM_STAGED )) && res+=" ${modified}${(g::)POWERLEVEL9K_VCS_STAGED_ICON}${VCS_STATUS_NUM_STAGED}"
...
(( VCS_STATUS_NUM_UNSTAGED )) && res+=" ${modified}${(g::)POWERLEVEL9K_VCS_UNSTAGED_ICON}${VCS_STATUS_NUM_UNSTAGED}"
...
}
Package version format
- Update current node package version format
package-name:package-version
...
typeset -g POWERLEVEL9K_PACKAGE_CONTENT_EXPANSION='${P9K_PACKAGE_NAME//\%/%%}:${P9K_PACKAGE_VERSION//\%/%%}'
...
Hardware colors and configuration
- Update disk usage colors
- Update disk usage levels thresholds
- Update disk usage display on warning
- Update free ram color
- Update used swap color
- Update CPU load colors
- Update battery colors
- Update wifi colors
- Update time colors ```bash=
...
typeset -g POWERLEVEL9K_DISK_USAGE_NORMAL_FOREGROUND='#97b882'
typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_FOREGROUND='#e1874d'
typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL=80
typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_LEVEL=90
...
typeset -g POWERLEVEL9K_DISK_USAGE_ONLY_WARNING=true
...
typeset -g POWERLEVEL9K_RAM_FOREGROUND='#af7ca4'
...
typeset -g POWERLEVEL9K_SWAP_FOREGROUND='#e1874d'
...
typeset -g POWERLEVEL9K_LOAD_NORMAL_FOREGROUND='#9090c0'
...
typeset -g POWERLEVEL9K_LOAD_WARNING_FOREGROUND='#e1874d'
...
typeset -g POWERLEVEL9K_LOAD_CRITICAL_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_BATTERY_LOW_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_BATTERY_{CHARGING,CHARGED}_FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_BATTERY_DISCONNECTED_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_WIFI_FOREGROUND='#9fbfb4'
...
typeset -g POWERLEVEL9K_TIME_FOREGROUND='#76a394'
...
Context colors
- Update context colors
- Update context display to be always shown by commenting the relevant line
```bash=
...
typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND='#db6e51'
...
typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND='#d55555'
...
typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND='#e8c273'
...
typeset -g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_{CONTENT,VISUAL_IDENTIFIER}_EXPANSION=
...
Development tools colors
- Update tools colors Node.js, nvm, package, Rust, dotnet, Java, Scala, PHP, Laravel, PostgreSQL ```bash=
...
typeset -g POWERLEVEL9K_ASDF_NODEJS_FOREGROUND='#97b882'
...
typeset -g POWERLEVEL9K_ASDF_RUST_FOREGROUND='#e4917a'
...
typeset -g POWERLEVEL9K_ASDF_DOTNET_CORE_FOREGROUND='#b0b0d2'
...
typeset -g POWERLEVEL9K_ASDF_JAVA_FOREGROUND='#e8a478'
...
typeset -g POWERLEVEL9K_ASDF_POSTGRES_FOREGROUND='#c29cba'
...
typeset -g POWERLEVEL9K_ASDF_PHP_FOREGROUND='#92b7d4'
...
typeset -g POWERLEVEL9K_NODENV_FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_NVM_FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_NODEENV_FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_NODE_VERSION_FOREGROUND='#7ca661'
...
typeset -g POWERLEVEL9K_DOTNET_VERSION_FOREGROUND='#9090c0'
...
typeset -g POWERLEVEL9K_PHP_VERSION_FOREGROUND='#af7ca4'
...
typeset -g POWERLEVEL9K_LARAVEL_VERSION_FOREGROUND='#db6e51'
...
typeset -g POWERLEVEL9K_JAVA_VERSION_FOREGROUND='#e1874d'
...
typeset -g POWERLEVEL9K_PACKAGE_FOREGROUND='#97b882'
...
typeset -g POWERLEVEL9K_JENV_FOREGROUND='#e1874d'
...
typeset -g POWERLEVEL9K_PHPENV_FOREGROUND='#af7ca4'
...
typeset -g POWERLEVEL9K_SCALAENV_FOREGROUND='#e8a478'
Change cloud tools colors
- Update Terraform, Kubernetes, aws and Azure colors
```bash=
...
typeset -g POWERLEVEL9K_TERRAFORM_OTHER_FOREGROUND='#727299'
...
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND='#5a82a1'
...
typeset -g POWERLEVEL9K_AWS_DEFAULT_FOREGROUND='#ba7040'
...
typeset -g POWERLEVEL9K_AWS_EB_ENV_FOREGROUND='#ba7040'
...
typeset -g POWERLEVEL9K_AZURE_FOREGROUND='#92b7d4'
Next article
In the next article Improve your experience using git cli we will focus on customizing git.
Top comments (2)
Fantastic article, helped me a lot with my oh-my-zsh journey on WSL2. Thanks!
Happy to help, thank you for your kind comment :D