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.

I think the right level of zsh customization is "just enough to stop noticing the shell." Not because minimal is always better, but rather because every plugin and framework you add is something that can break on zsh upgrades, macOS updates, or new machines. Because the goal is a shell that's invisibly good, not impressively configured.

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.


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.

Keep reading