_____ _ |__ /___| |__ / // __| '_ \ / /_\__ \ | | | /____|___/_| |_|

Zsh

Z Shell — the modern shell with powerful interactive features

Zsh 5.9 · macOS default since Catalina · oh-my-zsh ready
Why Switch to Zsh?
Smarter Tab Completion
Zsh completes command flags, git branches, SSH hostnames, Docker container names, and more — with an interactive menu you can arrow-key through.
🔍
Spell Correction
setopt CORRECT catches typos like grpe and asks "Did you mean grep?" before running the wrong command.
🌿
Extended Globbing
Recursive **/*, negation ^*.log, glob qualifiers like *(Om) for sort-by-mtime, and null glob *(N) — no more broken scripts on empty matches.
📜
Better History
Shared history across all terminal sessions, timestamps, deduplication, and per-session append so you never lose commands from parallel windows.
🎨
Prompt Theming
Full PROMPT_SUBST support and a rich theme ecosystem — Powerlevel10k renders git status, language versions, exit codes, and more, all in milliseconds.
🔌
Plugin Ecosystem
oh-my-zsh, Zinit, and Prezto give you hundreds of plugins: autosuggestions, syntax highlighting, fzf integration, and per-tool completions.
📂
Directory Stack
setopt AUTO_PUSHD turns every cd into a push, letting you jump back with cd -2 or ~3 — a permanent nav history.
🔗
Suffix Aliases
alias -s pdf=zathura lets you open files just by typing their name — no open or xdg-open needed.
🍎
macOS Default
Apple switched macOS from Bash 3.2 to Zsh as the default login shell in macOS Catalina (2019) — it's already there, no install needed.
Zsh vs Bash — Feature Comparison
FeatureBashZsh
Tab completionBasicAdvanced (menus, context-aware)
Spelling correction✓ (setopt CORRECT)
Recursive glob **Requires globstarBuilt-in, extended qualifiers
Glob negation✓ (^*.log with EXTENDED_GLOB)
Array indexing0-indexed, sparse1-indexed, slice syntax
Prompt expansionLimitedFull PROMPT_SUBST, RPROMPT
Plugin ecosystemMinimaloh-my-zsh, Zinit, Prezto
Float arithmeticRequires bcBuilt-in (zsh/mathfunc)
History sharingPer-session onlyCross-session with SHARE_HISTORY
Suffix aliases✓ (alias -s ext=app)
Global aliases✓ (expand anywhere in line)
Directory stackManual pushd/popdAUTO_PUSHD, ~1 ~2 expansion
Parameter flagsLimited${(U)(L)(q)(f)(o)(u)…} flags
POSIX compliance✓ defaultemulate sh for compat
Scripting portabilityMore portablePrefer bash for scripts
Quick Reference
Keyboard Shortcuts (emacs mode)
Ctrl+A beginning of line Ctrl+E end of line Ctrl+U kill to beginning Ctrl+K kill to end Ctrl+W kill word backward Alt+. insert last arg of prev cmd Ctrl+R history search (fzf if installed) Ctrl+Z suspend / fg to resume Tab Tab show completion menu
Useful One-Liners
# time a command time cmd # run in background, disowned cmd &! # check exit codes of each pipe stage cmd1 | cmd2; echo ${pipestatus[@]} # repeat command N times repeat 5 cmd # jump to frecent dir (z plugin) z proj
Origin
Who Created Zsh?

Zsh was created by Paul Falstad in 1990 while he was a student at Princeton University. He released the first version (0.1) in late 1990 on the comp.sources.misc Usenet newsgroup.

The name "zsh" comes from Zhong Shao, a Yale professor whose login name was zsh — Falstad thought it made a good shell name. Shao himself had nothing to do with creating the shell.

Falstad later said he wrote Zsh to have a shell "with all the features I wanted" — pulling from csh, ksh, and bash, then adding his own ideas on top.

Shell Family Tree
1971 sh — Thompson shell (Bell Labs) 1979 sh — Bourne shell (replaces Thompson) 1983 csh — C shell (Bill Joy, BSD) 1983 ksh — KornShell (David Korn, AT&T) 1989 bash — Bourne Again Shell (FSF/GNU) 1990 zsh — Z Shell (Paul Falstad) 1993 tcsh — TENEX C Shell update 2003 fish — Friendly Interactive Shell 2019 zsh — becomes macOS default shell
Version Timeline
1990
Zsh 0.1 — Paul Falstad posts first version to comp.sources.misc at Princeton. Features prompt customization, command completion, and spelling correction from day one.
1992
Zsh 2.0 — Richard Coleman takes over maintenance. Adds history sharing between sessions, extended globbing, and associative arrays. Project moves to a public mailing list.
1995
Zsh 2.6 / 3.0 — Zoltan Hidvegi joins as co-maintainer. Module system introduced (zsh/mathfunc, zsh/zle, zsh/complete). ZLE (Zsh Line Editor) becomes a first-class subsystem.
1997
Zsh 3.1 (development) — Peter Stephenson becomes lead. Introduces zstyle for configurable completion, the zcompdump cache, and the completion system (compsys) that still ships today.
2000
Zsh 4.0 — Major completion rewrite. The new compsys (compdef, compctl replacement) ships, giving context-aware completion with zstyle configuration. This is the completion engine still in use.
2003
Zsh 4.2 — Stable release with improved Unicode support, parameter flags, and the prompt theme system formalized. oh-my-zsh-style themes become practical.
2009
oh-my-zsh launched — Robby Russell releases oh-my-zsh on GitHub. Within years it becomes the dominant way to manage Zsh config — 170,000+ GitHub stars today.
2015
Zsh 5.0 — Unicode fully supported, multibyte characters in prompts and completion. zsh/zutil module adds zparseopts for getopts-style flag parsing.
2017
Zsh 5.4 — Pattern matching improvements, new modules, and stability fixes. Zinit (formerly zplugin) emerges as a faster alternative to oh-my-zsh for plugin management.
2019
macOS Catalina — Zsh becomes default — Apple replaces Bash 3.2 (GPLv2) with Zsh 5.7 (MIT) as the default shell for new macOS accounts, instantly making Zsh the most widely distributed interactive shell in the world.
2022
Zsh 5.9 — Current stable release. Continued improvements to completion, Unicode, and the module system. The codebase is now over 30 years old and actively maintained by a small core team.
Today
Standard on macOS, popular on Linux — Zsh ships by default on macOS, is the preferred shell for millions of developers, and is the default in many Docker images and dev containers. oh-my-zsh alone has over 170K GitHub stars.
Zsh Configuration (.zshrc)
Options (setopt)
setopt AUTO_CD # cd by typing dirname setopt CORRECT # spell correction setopt GLOB_DOTS # glob matches dotfiles setopt EXTENDED_GLOB # *, **, ^, (#…) setopt NO_CASE_GLOB # case-insensitive glob setopt HIST_IGNORE_DUPS # no duplicate history setopt SHARE_HISTORY # sync across sessions setopt AUTO_PUSHD # pushd automatically setopt PUSHD_IGNORE_DUPS # no dup dirstack
History Config
HISTFILE=~/.zsh_history HISTSIZE=50000 SAVEHIST=50000 setopt HIST_EXPIRE_DUPS_FIRST setopt HIST_FIND_NO_DUPS setopt INC_APPEND_HISTORY # write immediately # Ctrl+R — interactive history search # !! — repeat last command # !$ — last argument of prev cmd
Completion Setup
autoload -Uz compinit compinit # use menu selection zstyle ':completion:*' menu select # case-insensitive matching zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' # group by category zstyle ':completion:*' group-name '' # colored completion zstyle ':completion:*' list-colors ''
Key Bindings
bindkey -e # emacs mode (default) bindkey -v # vi mode bindkey '^[[A' history-search-backward bindkey '^[[B' history-search-forward bindkey '^[.' insert-last-word bindkey '^U' backward-kill-line
Zsh-Specific Syntax
Extended Globbing
setopt EXTENDED_GLOB ls **/*.py # recursive glob ls ^*.py # negate: not .py files ls *.(py|js) # alternation ls *.py(.) # plain files only ls *.py(Om) # sort by mtime oldest ls *.log(Lm+1) # files > 1MB ls *(/) # directories only ls *(N) # null glob (no error)
Arrays (1-indexed)
arr=(a b c d) echo $arr[1] # a (1-indexed!) echo $arr[-1] # d (last) echo $arr[2,3] # b c (slice) echo ${#arr} # length: 4 echo ${arr:u} # UPPERCASE echo ${(j:,:)arr} # join: a,b,c,d echo ${(s:,:)csv} # split on comma
Parameter Flags
${(U)var} # UPPERCASE ${(L)var} # lowercase ${(C)var} # Capitalize Words ${(q)var} # shell-quote ${(Q)var} # unquote ${(r:10:)var} # right-pad to 10 ${(l:10:)var} # left-pad to 10 ${(f)var} # split by newlines → array ${(o)arr} # sort array ${(u)arr} # unique elements
Aliases
# regular alias alias ll='ls -lah' # global alias (expands anywhere) alias -g G='| grep' alias -g L='| less' alias -g T='| tail -f' dmesg G error # grep errors # suffix alias (open by extension) alias -s pdf=evince alias -s py=python3 doc.pdf # opens in evince
Prompt Customization
autoload -Uz colors && colors setopt PROMPT_SUBST # simple prompt with git branch PROMPT='%F{blue}%~%f $(git branch --show-current 2>/dev/null | sed "s/.*/ [&]/") %F{green}❯%f ' # prompt codes # %~ = cwd %n = user %m = host # %? = exit code %# = $ or # # %F{color}…%f = foreground color
Floating Point
zmodload zsh/mathfunc typeset -F x=3.14 echo $(( x * 2.0 )) # 6.28 echo $(( sqrt(2.0) )) # 1.4142... echo $(( log(M_E) )) # 1.0 (natural log of e)
Functions & Autoload
# define inline mkcd() { mkdir -p "$1" && cd "$1"; } # autoload from fpath fpath=(~/.zfuncs $fpath) autoload -Uz myfunc # lazy-load # hook functions chpwd() { ls -la; } # runs on cd precmd() { } # before prompt preexec() { } # before each cmd
Directory Stack
setopt AUTO_PUSHD setopt PUSHD_IGNORE_DUPS DIRSTACKSIZE=20 dirs -v # show stack cd -2 # go to entry 2 popd # pop top # ~1 ~2 etc expand to stack entries
Oh-My-Zsh Plugins
git
Hundreds of git aliases: gst, gco, gcb, glog, gp, gl, etc.
z
Jump to frecent directories: z proj jumps to your most-used projects dir.
docker
Tab-completion for docker commands, images, containers, and compose.
kubectl
Kubectl completion + k alias. Show current context in prompt.
zsh-autosuggestions
Fish-style greyed-out suggestions from history. Press → to accept.
zsh-syntax-highlighting
Colors commands as you type: green for valid, red for unknown.
fzf
Fuzzy file/history search. Ctrl+R for history, Ctrl+T for files.
nvm
Auto-switch Node version when entering directories with .nvmrc.
sudo
Press Esc twice to prepend sudo to the current command.
web-search
Search from terminal: google zsh tips, ddg bash arrays.
extract
Universal extract: extract file.tar.gz — detects format automatically.
colored-man-pages
Colorizes man pages for much better readability.
Popular Themes & Plugin Managers
Powerlevel10k
# install git clone --depth=1 \ https://github.com/romkatv/powerlevel10k.git \ ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/themes/powerlevel10k # .zshrc ZSH_THEME="powerlevel10k/powerlevel10k" # then: p10k configure
Starship (cross-shell)
# install curl -sS https://starship.rs/install.sh | sh # add to .zshrc eval "$(starship init zsh)" # configure ~/.config/starship.toml # shows git, language, exit code etc
Zinit (fast plugin manager)
# install Zinit bash -c "$(curl -fsSL https://git.io/zinit-install)" # .zshrc zinit light zsh-users/zsh-autosuggestions zinit light zsh-users/zsh-syntax-highlighting zinit ice depth=1 zinit light romkatv/powerlevel10k
zsh — ~/projects/myapp
bck-i-search:
~/projects/myapp main