devAlice
← Mac

Mac Terminal — iTerm2 vs WezTerm vs Ghostty + zsh + Starship

Three options to replace the default Terminal.app, plus the fastest path to a stable zsh + Starship setup.

macOS's built-in Terminal.app works, but it falls behind the alternatives on splits, search, rendering, and configurability. This guide compares iTerm2 · WezTerm · Ghostty and builds the fastest stable environment (WezTerm + zsh + Starship + four modules).

TL;DR

OptionStrengthsWeaknessesBest for
WezTerm (recommended)Lua config / GPU acceleration / cross-platformLua learning curveSolo devs who like configs as code
iTerm2Most mature / strong search/split/sessionsSettings GUI mazePrioritizes feature richness
GhosttyFast / simple / 1.0 stableNewer, some features missingMinimalists / latest-first

1. Options Compared

iTerm2

The oldest macOS-only terminal. Splits (⌘D), instant replay, search, triggers (text-match actions), session auto-restore — rich feature set.

WezTerm

Written in Rust, configured in Lua, GPU-accelerated, cross-platform (Mac/Linux/Win). Keybindings, themes, multiplexing — all in one Lua file. Reproducible.

Ghostty

1.0 stable in 2024. Fast, GPU-accelerated, minimal config. Fewer features than iTerm2/WezTerm but enough for daily use.

Recommendation: WezTerm

For "manage config as code, restore on a new machine in one shot" scenarios, WezTerm wins decisively. Integrates naturally with dotfiles management. This guide is WezTerm-based.

2. Install WezTerm

brew install --cask wezterm

First launch → default shell is zsh (macOS default). If the screen renders, you're good.

3. WezTerm Config — ~/.config/wezterm/wezterm.lua

mkdir -p ~/.config/wezterm && nvim ~/.config/wezterm/wezterm.lua:

local wezterm = require 'wezterm'
local config = wezterm.config_builder()
 
-- Fonts
config.font = wezterm.font_with_fallback({
  'JetBrainsMono Nerd Font',
  'Hiragino Sans',  -- Korean / Japanese fallback
})
config.font_size = 13.0
 
-- Color scheme
config.color_scheme = 'Catppuccin Mocha'  -- or 'Tokyo Night', 'Dracula'
 
-- Window
config.window_decorations = 'RESIZE'  -- hide titlebar, keep resizable
config.window_padding = { left = 8, right = 8, top = 8, bottom = 8 }
config.window_background_opacity = 0.95
config.macos_window_background_blur = 20
 
-- Tabs
config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = true
config.hide_tab_bar_if_only_one_tab = true
 
-- Shell
config.default_prog = { '/opt/homebrew/bin/zsh', '-l' }  -- brew zsh (newer than macOS default)
 
-- Keybindings
config.keys = {
  -- Splits
  { key = 'd', mods = 'CMD', action = wezterm.action.SplitHorizontal { domain = 'CurrentPaneDomain' } },
  { key = 'D', mods = 'CMD|SHIFT', action = wezterm.action.SplitVertical { domain = 'CurrentPaneDomain' } },
  -- Pane navigation
  { key = 'LeftArrow', mods = 'CMD|OPT', action = wezterm.action.ActivatePaneDirection 'Left' },
  { key = 'RightArrow', mods = 'CMD|OPT', action = wezterm.action.ActivatePaneDirection 'Right' },
  { key = 'UpArrow', mods = 'CMD|OPT', action = wezterm.action.ActivatePaneDirection 'Up' },
  { key = 'DownArrow', mods = 'CMD|OPT', action = wezterm.action.ActivatePaneDirection 'Down' },
  -- Close pane
  { key = 'w', mods = 'CMD', action = wezterm.action.CloseCurrentPane { confirm = true } },
}
 
return config

WezTerm auto-reloads on save. Try ⌘D to confirm splits work.

4. Upgrade zsh

macOS ships an older zsh. brew has newer:

brew install zsh
which -a zsh
# /opt/homebrew/bin/zsh
# /bin/zsh
 
# Change default shell
sudo sh -c "echo /opt/homebrew/bin/zsh >> /etc/shells"
chsh -s /opt/homebrew/bin/zsh

New terminal → echo $ZSH_VERSION → 5.9+ confirms.

5. Starship Prompt

Lighter and faster than oh-my-zsh. Rust single binary:

brew install starship

Append to ~/.zshrc:

eval "$(starship init zsh)"

~/.config/starship.toml:

# Snappy default activation
add_newline = true
format = """
$directory\
$git_branch\
$git_status\
$nodejs\
$python\
$rust\
$cmd_duration\
$line_break\
$character"""
 
[directory]
truncation_length = 3
truncate_to_repo = true
 
[git_status]
disabled = false
ahead = "↑${count} "
behind = "↓${count} "
 
[cmd_duration]
min_time = 2000  # only show for commands >2 seconds
 
[character]
success_symbol = "[➜](bold green)"
error_symbol = "[➜](bold red)"

Reload with . ~/.zshrc or open a new terminal.

6. Four zsh Modules

6.1 zsh-autosuggestions

History-based gray suggestion:

brew install zsh-autosuggestions

~/.zshrc:

source /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh

Accept with .

6.2 zsh-syntax-highlighting

Color commands (invalid = red):

brew install zsh-syntax-highlighting
source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

⚠️ Source syntax-highlighting last in .zshrc for correct behavior.

6.3 fzf — fuzzy finder

brew install fzf
$(brew --prefix)/opt/fzf/install
# yes to all prompts

In a new terminal:

  • Ctrl+R — history search
  • Ctrl+T — file search
  • Alt+C — directory jump

6.4 zoxide — smarter cd

brew install zoxide

~/.zshrc:

eval "$(zoxide init zsh)"
z proj        # jump to a frequently visited project path
zi            # interactive picker

7. Full .zshrc Example

# History
HISTFILE=~/.zsh_history
HISTSIZE=10000
SAVEHIST=10000
setopt SHARE_HISTORY HIST_IGNORE_DUPS HIST_IGNORE_SPACE
 
# Completion
autoload -Uz compinit && compinit
 
# Brew
eval "$(/opt/homebrew/bin/brew shellenv)"
 
# Modules
source /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh
eval "$(zoxide init zsh)"
 
# Aliases
alias ll='ls -lah'
alias gs='git status -sb'
alias gd='git diff'
alias ..='cd ..'
 
# Tools
eval "$(starship init zsh)"
 
# (Must be last)
source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

8. iTerm2 Quick Setup (Alternative)

If you prefer iTerm2 over WezTerm:

brew install --cask iterm2
  • Preferences → Profiles → Default → Text → Font = JetBrainsMono Nerd Font 13pt
  • Window → Transparency 5%, Blur on
  • Keys → Hotkey window — bind a global shortcut like ⌥ Space for floating

iTerm2's killer feature is the Hotkey Window (floating terminal toggle from anywhere). WezTerm can be configured to behave similarly, but iTerm2 gives it out of the box.

Verification

  1. New terminal → Starship prompt shows (with colored cwd / git branch)
  2. Ctrl+R → fzf interactive history search
  3. ls → zsh-syntax-highlighting colors the command
  4. Type part of a previous command → gray autosuggestion → press
  5. z proj → jump to a previously visited project folder
  6. WezTerm ⌘D → split pane → ⌘⌥← to navigate

Troubleshooting

Syntax highlighting shows no color

  • Not sourced last in .zshrc (must come after other modules)
  • WezTerm color_scheme below 256 colors — unlikely; prefer Catppuccin / Tokyo Night

Garbled glyphs in Starship

Nerd Font missing. Check WezTerm's font config + actually install the font (brew install --cask font-jetbrains-mono-nerd-font).

z does nothing

  • zoxide init missing from .zshrc, or .zshrc not reloaded
  • Database is empty at first — do a few cds to train it

WezTerm opens at $HOME by default

Set in config: config.default_cwd = wezterm.home_dir .. '/work', or alias cd to your folder.

chsh didn't change the shell

  • The new shell wasn't added to /etc/shells → chsh fails
  • Log out / log back in, or reboot

References

Changelog

  • 2026-05-12: First draft. Three terminals compared + WezTerm + zsh + Starship + four modules + five troubleshooting cases.

Comments