Dahao's Personal Website

The Modern Zsh Setup: Plugins, Starship & a Clean Prompt

Zsh ships as the default shell on modern macOS, but out of the box it's barebones — no autocomplete beyond the basics, no colour-coded command feedback, no intelligent history suggestions. With two Homebrew-managed plugins and Starship as your prompt engine, you get a terminal that suggests commands as you type, highlights syntax errors before you run them, and shows rich git/project context without weighing down every prompt render.

What we're installing:

All three are maintained, well-documented, and trivially installed via Homebrew — no plugin manager like Oh My Zsh required.


1. Installing the Plugins with Homebrew

Homebrew installs these as regular formulae and puts the source files under $(brew --prefix)/share/. That path changes based on your architecture — /opt/homebrew on Apple Silicon, /usr/local on Intel — so using $(brew --prefix) in your config keeps everything portable.

brew install zsh-autosuggestions
brew install zsh-syntax-highlighting
brew install starship

After installing, Homebrew usually prints a Caveats section showing the exact source path for the plugin. Using $(brew --prefix) in your config is safer and more portable than hardcoding that path.


2. Adding the Plugins to .zshrc

Plugin source lines must be added at the bottom of your ~/.zshrc. Order matters: zsh-syntax-highlighting must always be the last sourced plugin — it hooks into zsh's line editor at a low level, and loading it before other plugins can break things.

Open your .zshrc:

nano ~/.zshrc
# or: code ~/.zshrc  /  vim ~/.zshrc

Add these lines at the bottom:

# Autosuggestions: ghost-text suggestions from history
source "$(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh"

# Syntax highlighting — MUST be sourced LAST
source "$(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"

Important: zsh-syntax-highlighting must always be the last plugin sourced. If you add more plugins later, keep this one at the very end of your .zshrc.

Accepting autosuggestions

Press (right arrow) or End to accept a full suggestion. Add these optional keybindings for a smoother experience:

# Accept the whole suggestion
bindkey '^F' autosuggest-accept

# Accept just one word of the suggestion
bindkey '^J' forward-word

Customise suggestion colour

The suggestion ghost text defaults to grey. Override it with any ANSI colour code:

# 244 = light grey (default). Try 240 (darker) or 32 (green)
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=244"

3. Setting Up Starship as Your Prompt

Starship automatically detects your current context — git branch, Node version, Python virtualenv, AWS profile, Kubernetes namespace — and shows only what's relevant. Configuration lives in a single TOML file.

Initialise Starship in .zshrc

Add this line before your plugin source lines:

# Starship prompt
eval "$(starship init zsh)"

Install a Nerd Font

Starship uses Nerd Font glyphs for its icons. Without a compatible font, you'll see placeholder boxes. Install via Homebrew Cask:

brew install --cask font-jetbrains-mono-nerd-font

Then set your terminal font to JetBrainsMono Nerd Font in your terminal's preferences.

Create a Starship config

Starship reads from ~/.config/starship.toml. Here's a clean starting config:

# ~/.config/starship.toml

# Remove blank line between prompts (see section 4)
add_newline = false

# Prompt format
format = """
$directory$git_branch$git_status$nodejs$python$rust$package
$character"""

[directory]
style            = "bold cyan"
truncation_length  = 3
truncate_to_repo   = true

[git_branch]
symbol = " "
style  = "bold purple"

[git_status]
conflicted = "⚡"
ahead      = "⇡${count}"
behind     = "⇣${count}"
modified   = "~"
untracked  = "?"
staged     = "+"

[character]
success_symbol = "[❯](bold green)"
error_symbol   = "[❯](bold red)"

[nodejs]
symbol = " "
style  = "bold green"

[python]
symbol = " "

4. Removing the Blank Line Before Each Prompt

By default, Starship inserts an empty line above each prompt to visually separate commands. There are a few ways to remove it.

Set add_newline = false in ~/.config/starship.toml. This is already included in the config above.

add_newline = false

Option B — Suppress it in .zshrc

If you're not using Starship, or want to suppress zsh's own newline behaviour:

# Remove zsh's end-of-line marker (the % sign)
PROMPT_EOL_MARK=''

Option C — Combine both

For maximum compactness, set add_newline = false in starship.toml and add this to .zshrc:

PROMPT_EOL_MARK=''

The % that sometimes appears at the end of command output is zsh's end-of-line marker. Setting PROMPT_EOL_MARK='' hides it for a cleaner look.


5. The Complete .zshrc

Here's a clean, production-ready .zshrc that brings everything together in the correct order.

# ══════════════════════════════════════════════════════════
# ~/.zshrc  —  Modern Zsh Configuration
# ══════════════════════════════════════════════════════════

# ── History ───────────────────────────────────────────────
HISTSIZE=10000
SAVEHIST=10000
HISTFILE=~/.zsh_history
setopt HIST_IGNORE_DUPS
setopt SHARE_HISTORY

# ── Completion ────────────────────────────────────────────
autoload -Uz compinit && compinit
zstyle ':completion:*' menu select
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# ── Useful aliases ────────────────────────────────────────
alias ls='ls --color=auto'
alias ll='ls -lAh'
alias grep='grep --color=auto'

# ── Suppress blank line / EOL marker ──────────────────────
PROMPT_EOL_MARK=''

# ── Starship Prompt ───────────────────────────────────────
# (add_newline = false is set in ~/.config/starship.toml)
eval "$(starship init zsh)"

# ── Autosuggestion colour ─────────────────────────────────
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=244"

# ── Optional keybindings ──────────────────────────────────
bindkey '^F' autosuggest-accept
bindkey '^J' forward-word

# ── Plugins (syntax-highlighting MUST be last) ────────────
source "$(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh"
source "$(brew --prefix)/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"

Apply the changes:

source ~/.zshrc

6. Tips & Common Issues

Verify Homebrew prefix

If sourcing the plugins fails, confirm where Homebrew installed them:

brew --prefix
# Apple Silicon → /opt/homebrew
# Intel Mac     → /usr/local

# Find the plugin file directly
ls "$(brew --prefix)/share/zsh-autosuggestions/"

Starship icons appear as boxes

Your terminal font isn't set to a Nerd Font. In iTerm2: Preferences → Profiles → Text → Font. In Terminal.app: Preferences → Profiles → Text → Change Font. Select any Nerd Font variant.

Explore Starship presets

Starship ships with a library of community presets:

# List available presets
starship preset --list

# Apply one (e.g. Tokyo Night)
starship preset tokyo-night -o ~/.config/starship.toml

# Revert to a blank config
starship preset blank -o ~/.config/starship.toml

Check plugin load time

If your shell feels slow, profile startup time:

time zsh -i -c exit

Starship is extremely fast — typically under 5ms per prompt render. If your shell is slow, the culprit is almost always compinit running without a cache check. Replace compinit with compinit -C to skip the security check on subsequent loads (safe for personal machines).