My Z shell setup
I've been a Fish shell user for years. It was my shell of choice on my Linux systems until I purchased my MacBook Pro, when I switched to Z shell.
As a fairly new Z shell user, I thought it might be good for me to document how I install and configure it, so that I can replicate my setup on new servers etc.
Install
I run Debian on my servers, so adjust this command if you use a different Linux distro. I've included git and curl as Git is required to clone the Z shell scripts and curl is referenced in my .zshrc file.
sudo apt update
sudo apt install zsh git curl
Clone zsh scripts from GitHub
Run the following commands to create a directory to hold the zsh scripts before cloning them from GitHub:
mkdir -p ~/.zsh
git clone https://github.com/sindresorhus/pure.git ~/.zsh/pure
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-history-substring-search ~/.zsh/zsh-history-substring-search
git clone https://github.com/lukechilds/zsh-better-npm-completion ~/.zsh/zsh-better-npm-completion
Create the .zshrc file
The .zshrc file is used to configure the shell session and make use of the above scripts. Run the command:
nano ~/.zshrc
And paste in the following:
# --- STARTUP SYSTEM INFO (Linux interactive shells only) ---
if [[ -o interactive && "$(uname -s)" == "Linux" ]]; then
echo
# Header
print -P "%F{cyan}=== System Info ===%f"
# Core info
print -P "Host: %F{green}%m%f"
print -P "User: %F{green}%n%f"
print -P "Uptime: %F{green}$(uptime -p)%f"
print -P "Kernel: %F{green}$(uname -r)%f"
# OS info (safe fallback if file missing)
if [[ -r /etc/os-release ]]; then
os=$(awk -F= '/^PRETTY_NAME=/ {gsub(/"/,"",$2); print $2}' /etc/os-release)
print -P "OS: %F{green}$os%f"
fi
# RAM usage
ram=$(free | awk '/^Mem:/ {used=$3; total=$2; pct=int(used/total*100); printf "%.1f/%.1fG (%d%%%%)", used/1024/1024, total/1024/1024, pct}')
print -P "RAM: %F{green}$ram%f"
# Root disk usage (cleaner parsing)
disk=$(df -h / | awk 'NR==2 {print $3 "/" $2 " (" $5 "%)"}')
print -P "Disk: %F{green}$disk%f"
# Inode usage
inode=$(df -i / | awk 'NR==2 {gsub(/%/,"",$5); print $3 "/" $2 " (" $5 "%%)"}')
print -P "Inodes: %F{green}$inode%f"
echo
fi
# --- PATH CUSTOMISATION ---
# Ensure ~/bin is at the front of PATH (and avoid duplicates)
typeset -U path
path=(~/bin $path)
# --- HISTORY SETTINGS ---
# File location and size limits for command history
HISTFILE=~/.zsh_history
HISTSIZE=5000 # commands kept in memory
SAVEHIST=5000 # commands saved to file
# Share history across all terminal sessions in real time
setopt SHARE_HISTORY
# Skip saving duplicate consecutive commands
setopt HIST_IGNORE_DUPS
# --- PURE PROMPT SETUP ---
# Add Pure prompt functions to fpath if installed, then enable Pure theme
if [[ -d "$HOME/.zsh/pure" ]]; then
fpath+=("$HOME/.zsh/pure")
autoload -U promptinit; promptinit
prompt pure
fi
# --- COMPLETION SETTINGS ---
# Enable Zsh's programmable completion system
autoload -Uz compinit && compinit
# Make completion case-insensitive (e.g. "doc" → "Documents")
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
# --- SSH HOST COMPLETION ---
# Populate SSH/SCP completion from ~/.ssh/config (ignore wildcard entries)
if [ -f ~/.ssh/config ]; then
h=($(grep -i "^Host " ~/.ssh/config | grep -v "*" | awk '{print $2}'))
zstyle ':completion:*:*:ssh:*:hosts' hosts $h
zstyle ':completion:*:*:scp:*:hosts' hosts $h
fi
# --- COMPLETION UI TWEAKS ---
# Enable interactive selection menu and improve descriptions
zstyle ':completion:*:*:ssh:*' menu select
zstyle ':completion:*' verbose yes
zstyle ':completion:*:descriptions' format '%B--- %d ---%b'
# --- NPM COMPLETION ---
# Load enhanced npm completion if available
[[ -f ~/.zsh/zsh-better-npm-completion/zsh-better-npm-completion.plugin.zsh ]] && \
source ~/.zsh/zsh-better-npm-completion/zsh-better-npm-completion.plugin.zsh
# --- HISTORY SUBSTRING SEARCH ---
# Allows up/down arrows to search history by current input
if [[ -f ~/.zsh/zsh-history-substring-search/zsh-history-substring-search.zsh ]]; then
source ~/.zsh/zsh-history-substring-search/zsh-history-substring-search.zsh
# Bind arrow keys (terminfo first, fallback sequences if needed)
bindkey "$terminfo[kcuu1]" history-substring-search-up
bindkey "$terminfo[kcud1]" history-substring-search-down
bindkey '^[[A' history-substring-search-up
bindkey '^[[B' history-substring-search-down
fi
# --- AUTOSUGGESTIONS ---
# Fish-style inline suggestions based on history
if [[ -f ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh ]]; then
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
# Subtle grey suggestion text
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
# Accept suggestion with right arrow
bindkey '^[[C' autosuggest-accept
fi
# ---------------
# --- ALIASES ---
# ---------------
# --- Git helpers ---
alias gs='git status'
alias gd='git diff'
alias ga='git add'
alias gc='git commit'
alias gcm='git commit -m'
alias gl='git log --oneline --graph --decorate'
alias gp='git pull'
alias gps='git push'
alias gb='git branch'
alias gco='git checkout'
# File list helpers
alias ls='ls --color=auto'
alias ll='ls -lh --color=auto'
alias la='ls -lah --color=auto'
# --- OS-SPECIFIC HELPERS ---
case "$(uname -s)" in
Darwin)
# macOS
alias ports='lsof -iTCP -sTCP:LISTEN -n -P'
alias localip="ipconfig getifaddr en0"
;;
Linux)
# Linux
alias ports='ss -tulpen'
alias localip='hostname -I'
;;
esac
# Public IPv4 address
alias myip='curl -4 ifconfig.me && echo'
Set Z shell as the default shell
Enter the following command to set Z shell as your default shell:
chsh -s $(which zsh)
Note: you'll be prompted for your user password to confirm the change.