Customizing zsh — starship prompt, history, aliases, plugins
Turn the macOS default zsh into a productive shell in 30 minutes. starship + history search + autosuggestions + syntax highlighting.
macOS has shipped zsh as the default shell since Catalina, but the out-of-the-box config leaves a lot on the table. Installing all of Oh My Zsh adds weight and slows startup. This guide customizes only what you need — starship prompt, history search, autosuggestions, syntax highlighting, fzf, and five useful aliases.
The audience is people who finished the Mac initial setup and want to polish zsh — including syncing .zshrc to other machines via dotfiles.
TL;DR
- starship — fast, beautiful prompt (lighter than Oh My Zsh)
- zsh-autosuggestions — gray history-based suggestions (fish-style)
- zsh-syntax-highlighting — colorize commands as you type
- fzf shell integration — modern
Ctrl+Rhistory search - Commit
.zshrcto chezmoi via dotfiles so other machines pick it up
Prerequisites
- macOS 14+ + Homebrew (Mac initial setup)
- A Nerd Font-capable terminal — Terminal.app, WezTerm/iTerm2
1. Why the default zsh isn't enough
- No git info in the prompt — branch / dirty state invisible
- Weak history search —
Ctrl+Rexists but there's no fuzzy - Limited autocomplete — Tab works, but no fish-style gray suggestions
- No syntax highlighting — typos only show after you submit
Fixing this pays off every day.
2. starship prompt (5 min)
starship.rs — a fast cross-shell prompt written in Rust. Lighter than Oh My Zsh's powerlevel10k, and startup overhead is near-zero.
2.1 Install
brew install starshipAt the bottom of .zshrc:
eval "$(starship init zsh)"Open a new terminal — applied immediately.
2.2 Nerd Font (for icons)
To see starship's git branch and language icons you need a Nerd Font.
brew install --cask font-jetbrains-mono-nerd-fontChange your terminal's font to JetBrainsMono Nerd Font. (See the WezTerm guide.)
2.3 Tweaks (optional)
~/.config/starship.toml:
# Two-line prompt — info above, input below
add_newline = true
format = """
$directory$git_branch$git_status$nodejs$python$rust$line_break$character"""
[character]
success_symbol = "[➜](bold green)"
error_symbol = "[✗](bold red)"
[directory]
truncation_length = 3
truncate_to_repo = true
[git_branch]
symbol = " "
style = "bold purple"
[git_status]
conflicted = "⚠️ "
ahead = "⇡${count} "
behind = "⇣${count} "
staged = "[+${count}](green) "
modified = "[!${count}](yellow) "
untracked = "[?${count}](red) "The defaults are excellent — start without
starship.toml, then tune what bugs you.
3. History — fix the bad defaults
Add to .zshrc:
# History sizes
HISTSIZE=50000 # lines kept in memory
SAVEHIST=100000 # lines saved to file
HISTFILE="$HOME/.zsh_history"
# Dedupe + immediate save
setopt HIST_IGNORE_ALL_DUPS # drop duplicates
setopt HIST_REDUCE_BLANKS # merge whitespace-only diffs
setopt HIST_VERIFY # don't auto-run `!42`-style expansions
setopt SHARE_HISTORY # all zsh instances share history
setopt INC_APPEND_HISTORY # append to history file immediately
setopt EXTENDED_HISTORY # timestamp + duration
# Up/Down — prefix-match search
autoload -U up-line-or-beginning-search down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search
bindkey "^[[A" up-line-or-beginning-search # Up
bindkey "^[[B" down-line-or-beginning-search # DownEffect: type git c and press ↑ — only past commands starting with git c cycle through.
4. zsh-autosuggestions (3 min)
Fish-style gray suggestions of the next command. Tab or → to accept.
brew install zsh-autosuggestionsAt the bottom of .zshrc:
source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh
# Gray tone (default is too dark)
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=#5f5f5f'
# Skip suggestions on very long commands (perf)
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=80New terminal → type a command → see gray suggestion = OK.
5. zsh-syntax-highlighting (2 min)
Color commands as you type — valid green, invalid red, options yellow, etc.
brew install zsh-syntax-highlightingAt the bottom of .zshrc — must come after zsh-autosuggestions:
source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zshOrder matters:
- autosuggestions
- syntax-highlighting (must be last)
Reversed, both occasionally break.
6. fzf — modern Ctrl+R history search
The default Ctrl+R walks back line by line. fzf gives you fuzzy search + preview.
brew install fzf
$(brew --prefix)/opt/fzf/install --allThe install script adds this to .zshrc:
[ -f ~/.fzf.zsh ] && source ~/.fzf.zshCtrl + R— fuzzy history searchCtrl + T— fuzzy pick a file in the current dir (e.g.,vim <Ctrl+T>)Alt + C— fuzzycd
More: Mac initial setup §3.2.
7. Five useful aliases
.zshrc or a separate ~/.zsh_aliases (recommended):
# git
alias g='git'
alias gs='git status -s'
alias gd='git diff'
alias gco='git checkout'
alias gp='git push'
alias gl='git log --oneline --graph --decorate -20'
# Filesystem (eza — modern ls)
alias ls='eza --git --group-directories-first'
alias ll='eza -l --git --group-directories-first --icons'
alias la='eza -la --git --group-directories-first --icons'
alias tree='eza --tree --level=3'
# Directory navigation
alias ..='cd ..'
alias ...='cd ../..'
# Reload
alias zrl='source ~/.zshrc'
# Editor (VS Code or Cursor)
alias c='code .'Single-letter aliases risk collision.
g(git) andc(code) are fine when intent is clear.
8. Directory jumping — zoxide
Instead of cd /Users/me/projects/myapp, type z myapp and jump in one go. Learns your frequently visited directories.
brew install zoxide.zshrc:
eval "$(zoxide init zsh --cmd cd)" # replace cd itself with zoxideUse cd as usual; zoxide learns. Then cd myapp jumps via partial name.
9. Full .zshrc example
A complete reference combining the above:
# ~/.zshrc
# ─────────────────────────────────────────────
# PATH
# ─────────────────────────────────────────────
export PATH="$HOME/.local/bin:$PATH"
# ─────────────────────────────────────────────
# History
# ─────────────────────────────────────────────
HISTSIZE=50000
SAVEHIST=100000
HISTFILE="$HOME/.zsh_history"
setopt HIST_IGNORE_ALL_DUPS HIST_REDUCE_BLANKS HIST_VERIFY
setopt SHARE_HISTORY INC_APPEND_HISTORY EXTENDED_HISTORY
# Up/Down — prefix search
autoload -U up-line-or-beginning-search down-line-or-beginning-search
zle -N up-line-or-beginning-search
zle -N down-line-or-beginning-search
bindkey "^[[A" up-line-or-beginning-search
bindkey "^[[B" down-line-or-beginning-search
# ─────────────────────────────────────────────
# Aliases
# ─────────────────────────────────────────────
alias g='git'
alias gs='git status -s'
alias gd='git diff'
alias gp='git push'
alias gl='git log --oneline --graph --decorate -20'
alias ls='eza --git --group-directories-first'
alias ll='eza -l --git --group-directories-first --icons'
alias la='eza -la --git --group-directories-first --icons'
alias ..='cd ..'
alias ...='cd ../..'
alias zrl='source ~/.zshrc'
alias c='code .'
# ─────────────────────────────────────────────
# Plugins (order matters)
# ─────────────────────────────────────────────
source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=#5f5f5f'
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=80
source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
# ─────────────────────────────────────────────
# Tools
# ─────────────────────────────────────────────
[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
eval "$(mise activate zsh)" # language version manager — /mac/dev-toolchain
eval "$(zoxide init zsh --cmd cd)"
# ─────────────────────────────────────────────
# Prompt
# ─────────────────────────────────────────────
eval "$(starship init zsh)"10. Verify
# In a new terminal
type starship # /opt/homebrew/bin/starship
ZSH_AUTOSUGGEST_USE_ASYNC=true # autosuggest active
echo $HISTSIZE # 50000
# starship prompt
cd ~/work/myrepo # prompt shows git branch + language icons
# Suggestions
git c # gray suggestion — Tab to accept
# fzf
history | head # type 'git c' then Ctrl+R — fuzzy search11. Troubleshooting
Prompt is full of broken glyphs (▢▢)
Nerd Font missing. Install font-jetbrains-mono-nerd-font via brew and change the terminal font.
command not found: starship
which starshipreturns nothing → is the brew prefix on PATH?- Apple Silicon:
eval "$(/opt/homebrew/bin/brew shellenv)"should be in.zprofile
Slow new-terminal startup (1s+)
- Lazy-load heavy commands (
nvm) from.zshrc - Profile with
zprof: addzmodload zsh/zprofat the top,zprof | head -20at the bottom
autosuggestions don't show
- Order in
.zshrc: syntax-highlighting after autosuggestions ZSH_AUTOSUGGEST_HIGHLIGHT_STYLEmay be too close to the background- Try
unset ZSH_AUTOSUGGEST_HIGHLIGHT_STYLEto use the default
syntax-highlighting flickers right after typing
- Turn off "Render fast" in WezTerm/iTerm2
- Or set
ZSH_HIGHLIGHT_MAXLENGTH=300to disable highlighting on very long lines
zsh: no matches found: *.txt
zsh's globbing is strict by default. Either setopt NULL_GLOB in .zshrc, or escape: \*.txt.
12. What's next
- Mac initial setup — /mac/initial-setup
- Terminal — WezTerm / iTerm2 — /mac/terminal
- dotfiles with chezmoi — /mac/dotfiles — sync
.zshrcacross machines - Language toolchain (mise) — /mac/dev-toolchain
References
Changelog
- 2026-05-16: First draft. starship + history + autosuggestions + syntax-highlighting + fzf + aliases + zoxide + full .zshrc example + six troubleshooting cases.