devAlice
← Mac

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

  1. starship — fast, beautiful prompt (lighter than Oh My Zsh)
  2. zsh-autosuggestions — gray history-based suggestions (fish-style)
  3. zsh-syntax-highlighting — colorize commands as you type
  4. fzf shell integration — modern Ctrl+R history search
  5. Commit .zshrc to chezmoi via dotfiles so other machines pick it up

Prerequisites

1. Why the default zsh isn't enough

  • No git info in the prompt — branch / dirty state invisible
  • Weak history searchCtrl+R exists 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 starship

At 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-font

Change 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  # Down

Effect: 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-autosuggestions

At 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=80

New 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-highlighting

At the bottom of .zshrc — must come after zsh-autosuggestions:

source $(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

Order matters:

  1. autosuggestions
  2. 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 --all

The install script adds this to .zshrc:

[ -f ~/.fzf.zsh ] && source ~/.fzf.zsh
  • Ctrl + R — fuzzy history search
  • Ctrl + T — fuzzy pick a file in the current dir (e.g., vim <Ctrl+T>)
  • Alt + C — fuzzy cd

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) and c (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 zoxide

Use 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 search

11. 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 starship returns 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: add zmodload zsh/zprof at the top, zprof | head -20 at the bottom

autosuggestions don't show

  • Order in .zshrc: syntax-highlighting after autosuggestions
  • ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE may be too close to the background
  • Try unset ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE to use the default

syntax-highlighting flickers right after typing

  • Turn off "Render fast" in WezTerm/iTerm2
  • Or set ZSH_HIGHLIGHT_MAXLENGTH=300 to 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


References

Changelog

  • 2026-05-16: First draft. starship + history + autosuggestions + syntax-highlighting + fzf + aliases + zoxide + full .zshrc example + six troubleshooting cases.

Comments