nubpaws.dev
Back to Articles
Article

My Oh My Zsh Setup

A walkthrough of my terminal setup using Oh My Zsh, Powerlevel10k, and a handful of plugins that make the command line a joy to use.

March 13, 2026 NubPaws
Zsh Terminal Oh My Zsh Tutorial

Table of Contents

Introduction

I spend most of my day in the terminal. Over time I’ve put together a Zsh setup that I’m pretty happy with - it’s fast, gives me the info I need at a glance, and has a few plugins that I genuinely miss when I’m on a machine that doesn’t have them.

This article goes through the whole thing from scratch. If you want to copy it exactly, you can grab the config files at the bottom. Or just cherry-pick the parts you like.

Installing Zsh and Oh My Zsh

Most Linux distros come with Bash. Zsh is basically a superset of it - better tab completion, better globbing, and a massive plugin ecosystem.

Install it:

sudo apt install zsh

Set it as your default shell and log out and back in:

chsh -s $(which zsh)

Next, install Oh My Zsh. It’s a framework that manages your Zsh config, themes, and plugins:

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

This drops a ~/.oh-my-zsh directory with themes and plugins, and generates a starter ~/.zshrc that we’ll be replacing throughout this guide.

Note:

On macOS, Zsh is already the default shell - skip chsh and go straight to Oh My Zsh.

Theme: Powerlevel10k

Powerlevel10k is the prompt theme I use. It’s fast, shows the current directory, git branch, last command’s exit code, execution time - all the stuff you’d want to see at a glance.

Clone it into Oh My Zsh’s custom themes directory:

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

Set the theme in ~/.zshrc:

ZSH_THEME="powerlevel10k/powerlevel10k"

After restarting your terminal, the p10k configuration wizard launches automatically and walks you through the style options. You can always re-run it with:

p10k configure

The wizard writes everything to ~/.p10k.zsh. My config uses lean style, two lines, disconnected segments, transient prompt (old commands collapse to just ), and 24-hour time. I’ve included my .p10k.zsh for download, but honestly - just run the wizard. It’s more fun to pick your own.

Fonts:

You’ll want a Nerd Font for the icons in the prompt. MesloLGS NF is the go-to - p10k configure will offer to install it for you.

Plugins

Adding plugins in Oh My Zsh means cloning a repo into the custom plugins directory and adding the name to the plugins array. Here are the five I use.

git

Built into Oh My Zsh, no clone needed. Gives you a bunch of aliases (gst for git status, gco for git checkout, etc.) and better git completions. I mostly use it for the completions.

zsh-autosuggestions

This is the one I miss the most on other machines. It shows ghost-text suggestions as you type, pulled from your history. Right arrow to accept, or just keep typing to ignore it.

git clone https://github.com/zsh-users/zsh-autosuggestions \
  ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

Type part of a command, press up arrow, and it cycles through history entries that contain what you typed. Way better than the default behavior which only matches from the start of the line.

git clone https://github.com/zsh-users/zsh-history-substring-search \
  ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-history-substring-search

zsh-autopair

Auto-closes brackets, quotes, and other paired characters. Type ( and you get () with the cursor in between. Small thing, but you notice when it’s gone.

git clone https://github.com/hlissner/zsh-autopair \
  ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autopair

zsh-syntax-highlighting

Colors commands as you type - valid commands in green, errors in red, quoted strings highlighted. You catch typos before you hit enter.

git clone https://github.com/zsh-users/zsh-syntax-highlighting \
  ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
Important:

zsh-syntax-highlighting must be last in the plugins array. It needs to load after everything else to highlight correctly.

Once all plugins are cloned, add them to the plugins array in ~/.zshrc:

plugins=(
  git
  zsh-autosuggestions
  zsh-history-substring-search
  zsh-autopair
  zsh-syntax-highlighting # must be last
)

Then source Oh My Zsh to load everything:

source "$ZSH/oh-my-zsh.sh"

Shell Settings

A few shell-level settings that I’ve found worth having.

Editor

I use Neovim, but not every machine has it, so this falls back to Vim:

if command -v nvim >/dev/null 2>&1; then
  export EDITOR="nvim"
else
  export EDITOR="vim"
fi
export VISUAL="$EDITOR"

History

A generous history with deduplication and cross-session sharing:

HISTFILE="$HOME/.zsh_history"
HISTSIZE=200000
SAVEHIST=200000
setopt HIST_IGNORE_ALL_DUPS HIST_REDUCE_BLANKS INC_APPEND_HISTORY SHARE_HISTORY EXTENDED_GLOB

What the setopt flags do:

  • HIST_IGNORE_ALL_DUPS - If a command already exists in history, the old entry is removed. Keeps things clean.
  • HIST_REDUCE_BLANKS - Strips extra whitespace before saving.
  • INC_APPEND_HISTORY - Writes each command to the history file immediately instead of waiting for the shell to exit. No more losing history when a terminal crashes.
  • SHARE_HISTORY - All terminal sessions share the same history. Run something in one tab, press up in another.
  • EXTENDED_GLOB - Enables advanced globbing with ^, ~, and #.

Safety

Two settings that have saved me from myself more than once:

set -o noclobber
set -o pipefail
  • noclobber - Prevents > from overwriting existing files. If important.txt exists, echo "oops" > important.txt will be refused. Use >| when you actually mean it.
  • pipefail - Makes a pipeline fail if any command in it fails, not just the last one. Without this, bad-cmd | grep foo silently swallows the error from bad-cmd.

Aliases

Nothing groundbreaking here, just stuff I got tired of typing:

# Colorized output
alias ls='ls --color=auto'
alias grep='grep --color=auto'

# Quick clear
alias cls="clear"

# Nuclear Docker cleanup - removes all images, containers, and volumes
alias docker-purge="docker system prune -a --volumes -f"

# System update in one shot
alias update-all="sudo apt-get update -y && sudo apt-get upgrade -y && sudo apt-get autoremove -y"

cls is muscle memory from years of Windows. docker-purge is the “nuke everything and start fresh” button for when Docker has eaten half your disk. update-all is just the apt update + upgrade + autoremove dance in one command.

Key Bindings

The history-substring-search plugin doesn’t bind to the arrow keys on its own, so you need to wire it up:

bindkey '^[[A' history-substring-search-up
bindkey '^[[B' history-substring-search-down

^[[A and ^[[B are the escape sequences for up/down arrows. With this, you type docker, press up, and it cycles through only the history entries containing “docker” instead of your entire history.

The Full Config

Both config files are here if you want to grab them:

Back up what you have, drop these in, and source:

cp ~/.zshrc ~/.zshrc.bak
cp ~/.p10k.zsh ~/.p10k.zsh.bak

curl -o ~/.zshrc https://nubpaws.dev/articles/2026-03-13-my-zsh-setup/.zshrc
curl -o ~/.p10k.zsh https://nubpaws.dev/articles/2026-03-13-my-zsh-setup/.p10k.zsh

source ~/.zshrc

You’ll need Oh My Zsh, Powerlevel10k, and all the plugins installed first - the .zshrc references them and will complain if they’re missing.

Wrapping Up

That’s the whole thing. Zsh, Oh My Zsh, Powerlevel10k, and five plugins. Takes maybe ten minutes to set up from scratch on a new machine, and it’s been my go-to setup for a while now.

If you end up using any of this, I hope it serves you well. Happy hacking!