A complete, reproducible terminal setup for macOS developers. Give this to Claude Code (or any AI agent) and say: "Follow this guide to set up my terminal."
- iTerm2 — Feature-rich terminal emulator
- Powerlevel10k — Fast, informative Zsh prompt with git status, language versions, and more
- Catppuccin Mocha — Dark color scheme (easy on the eyes)
- MesloLGS Nerd Font — Monospace font with icons for the prompt
- fzf — Fuzzy finder for history (Ctrl+R), files (Ctrl+T), directories (Alt+C)
- fzf-tab — Fuzzy tab completion with previews
- bat — Syntax-highlighted
catreplacement - eza — Modern
lswith icons, colors, git status - fd — Fast
findreplacement - zoxide — Smart
cdthat learns your directories - fast-syntax-highlighting — Real-time command validation (green = valid, red = typo)
- zsh-autosuggestions — Ghost-text suggestions from history
- macOS (Apple Silicon or Intel)
- Homebrew installed (
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)") - Zsh as default shell (default on macOS since Catalina)
brew install --cask iterm2brew install --cask font-meslo-lg-nerd-font# Skip if already installed (check: ls ~/.oh-my-zsh)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattendedgit clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k# zsh-autosuggestions
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
# fast-syntax-highlighting (better than zsh-syntax-highlighting)
git clone --depth=1 https://github.com/zdharma-continuum/fast-syntax-highlighting \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/fast-syntax-highlighting
# fzf-tab (fuzzy tab completion)
git clone --depth=1 https://github.com/Aloxaf/fzf-tab \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/fzf-tabbrew install fzf bat eza fd zoxidecurl -sL https://raw.githubusercontent.com/catppuccin/iterm/main/colors/catppuccin-mocha.itermcolors \
-o ~/catppuccin-mocha.itermcolorscurl -sL https://iterm2.com/shell_integration/zsh \
-o ~/.iterm2_shell_integration.zshBack up the existing .zshrc, then apply changes:
# Backup existing .zshrc
cp ~/.zshrc ~/.zshrc.backup.$(date +%Y%m%d%H%M%S)Make the following changes in ~/.zshrc:
9a. Set the theme — Find ZSH_THEME= line and change to:
ZSH_THEME="powerlevel10k/powerlevel10k"
9b. Set the plugins — Find plugins=( line and change to:
plugins=(git fzf-tab zsh-autosuggestions fast-syntax-highlighting docker kubectl)
Plugin load order matters: fzf-tab must come BEFORE autosuggestions and fast-syntax-highlighting. Do NOT include both
zsh-syntax-highlightingandfast-syntax-highlighting— they conflict. Do NOT include thezplugin — zoxide replaces it.
9c. Add the following block at the end of .zshrc (before any p10k source line if present):
# fzf shell integration (Ctrl+R history, Ctrl+T files, Alt+C directories)
source <(fzf --zsh)
# zoxide (smarter cd — use 'z' to jump to frecent directories)
eval "$(zoxide init zsh)"
# Modern CLI aliases
alias cat="bat --paging=never"
alias ls="eza --icons --group-directories-first"
alias ll="eza --icons --group-directories-first -la"
alias lt="eza --icons --group-directories-first --tree --level=2"
alias find="fd"
# fzf-tab styling (Catppuccin Mocha colors)
zstyle ':fzf-tab:complete:cd:*' fzf-preview 'eza --icons --group-directories-first -1 --color=always $realpath'
zstyle ':fzf-tab:complete:ls:*' fzf-preview 'eza --icons --group-directories-first -1 --color=always $realpath'
zstyle ':fzf-tab:*' fzf-flags --color=bg+:#313244,bg:#1e1e2e,spinner:#f5e0dc,hl:#f38ba8 --color=fg:#cdd6f4,header:#f38ba8,info:#cba6f7,pointer:#f5e0dc --color=marker:#f5e0dc,fg+:#cdd6f4,prompt:#cba6f7,hl+:#f38ba8
# iTerm2 Shell Integration
test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh"IMPORTANT: iTerm2 must NOT be running when editing the plist. Close iTerm2 completely before running this step.
Run this Python script to configure the iTerm2 Default profile:
#!/usr/bin/env python3
"""Configure iTerm2 profile: font, colors, window, keys."""
import plistlib
import os
plist_path = os.path.expanduser("~/Library/Preferences/com.googlecode.iterm2.plist")
colors_path = os.path.expanduser("~/catppuccin-mocha.itermcolors")
# Read iTerm2 plist
with open(plist_path, 'rb') as f:
plist = plistlib.load(f)
profile = plist["New Bookmarks"][0]
# Font: MesloLGS Nerd Font Mono, 13pt
profile["Normal Font"] = "MesloLGSNerdFontMono-Regular 13"
profile["Non Ascii Font"] = "MesloLGSNerdFontMono-Regular 13"
# Window size
profile["Columns"] = 120
profile["Rows"] = 35
# Transparency + Blur
profile["Transparency"] = 0.08
profile["Blur"] = True
profile["Blur Radius"] = 15.0
# Scrollback
profile["Scrollback Lines"] = 10000
profile["Unlimited Scrollback"] = False
# Terminal type
profile["Terminal Type"] = "xterm-256color"
# Option keys -> Esc+ (enables word jumping with Opt+Arrow)
profile["Option Key Sends"] = 2
profile["Right Option Key Sends"] = 2
# Mouse reporting
profile["Mouse Reporting"] = True
# Apply Catppuccin Mocha colors
if os.path.exists(colors_path):
with open(colors_path, 'rb') as f:
colors = plistlib.load(f)
for key, value in colors.items():
profile[key] = value
print(f"Applied {len(colors)} color settings")
# Write back
with open(plist_path, 'wb') as f:
plistlib.dump(plist, f)
print("iTerm2 profile configured successfully!")Save this as a temp file and run it:
python3 /tmp/configure_iterm2.py- Open iTerm2
- The Powerlevel10k configuration wizard will auto-launch
- Follow the prompts to pick your preferred prompt style
- Recommended choices: Lean or Rainbow style, 2-line prompt, transient prompt ON
In iTerm2:
- Go to Preferences > Profiles > Keys > Key Mappings
- Click Presets... dropdown at bottom
- Select Natural Text Editing
- This enables Cmd+Arrow, Option+Arrow, Option+Delete like native macOS
Run these commands to verify everything is set up:
echo "=== Theme ==="
grep "^ZSH_THEME=" ~/.zshrc
echo "=== Plugins ==="
grep "^plugins=" ~/.zshrc
echo "=== P10k ==="
test -f ~/.p10k.zsh && echo "OK" || echo "MISSING — run: p10k configure"
echo "=== Font ==="
ls ~/Library/Fonts/MesloLGSNerdFontMono-Regular.ttf 2>/dev/null && echo "OK" || echo "MISSING"
echo "=== CLI Tools ==="
fzf --version
bat --version | head -1
eza --version | head -1
fd --version
zoxide --version
echo "=== Plugins Installed ==="
ls ~/.oh-my-zsh/custom/plugins/fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh 2>/dev/null && echo "fast-syntax-highlighting OK" || echo "MISSING"
ls ~/.oh-my-zsh/custom/plugins/fzf-tab/fzf-tab.plugin.zsh 2>/dev/null && echo "fzf-tab OK" || echo "MISSING"
ls ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions/zsh-autosuggestions.plugin.zsh 2>/dev/null && echo "zsh-autosuggestions OK" || echo "MISSING"
echo "=== Shell Integration ==="
test -f ~/.iterm2_shell_integration.zsh && echo "OK" || echo "MISSING"
echo "=== Color Scheme ==="
test -f ~/catppuccin-mocha.itermcolors && echo "OK" || echo "MISSING"All items should show "OK" or display a version number.
For those who want to run everything in one go, here's a single script.
WARNING: This will modify your .zshrc. A backup is created automatically.
#!/bin/bash
set -e
echo "=== nVs Terminal Setup ==="
echo ""
# --- Step 1: iTerm2 ---
if ! brew list --cask iterm2 &>/dev/null; then
echo "[1/10] Installing iTerm2..."
brew install --cask iterm2
else
echo "[1/10] iTerm2 already installed"
fi
# --- Step 2: Nerd Font ---
if ! ls ~/Library/Fonts/MesloLGSNerdFontMono-Regular.ttf &>/dev/null; then
echo "[2/10] Installing MesloLGS Nerd Font..."
brew install --cask font-meslo-lg-nerd-font
else
echo "[2/10] MesloLGS Nerd Font already installed"
fi
# --- Step 3: Oh My Zsh ---
if [ ! -d ~/.oh-my-zsh ]; then
echo "[3/10] Installing Oh My Zsh..."
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
else
echo "[3/10] Oh My Zsh already installed"
fi
# --- Step 4: Powerlevel10k ---
P10K_DIR="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k"
if [ ! -d "$P10K_DIR" ]; then
echo "[4/10] Installing Powerlevel10k..."
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "$P10K_DIR"
else
echo "[4/10] Powerlevel10k already installed"
fi
# --- Step 5: Zsh Plugins ---
echo "[5/10] Installing Zsh plugins..."
CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins"
[ ! -d "$CUSTOM/zsh-autosuggestions" ] && \
git clone --depth=1 https://github.com/zsh-users/zsh-autosuggestions "$CUSTOM/zsh-autosuggestions" || true
[ ! -d "$CUSTOM/fast-syntax-highlighting" ] && \
git clone --depth=1 https://github.com/zdharma-continuum/fast-syntax-highlighting "$CUSTOM/fast-syntax-highlighting" || true
[ ! -d "$CUSTOM/fzf-tab" ] && \
git clone --depth=1 https://github.com/Aloxaf/fzf-tab "$CUSTOM/fzf-tab" || true
# --- Step 6: CLI Tools ---
echo "[6/10] Installing CLI tools..."
brew install fzf bat eza fd zoxide 2>/dev/null || true
# --- Step 7: Catppuccin Color Scheme ---
echo "[7/10] Downloading Catppuccin Mocha..."
curl -sL https://raw.githubusercontent.com/catppuccin/iterm/main/colors/catppuccin-mocha.itermcolors \
-o ~/catppuccin-mocha.itermcolors
# --- Step 8: Shell Integration ---
echo "[8/10] Installing iTerm2 shell integration..."
curl -sL https://iterm2.com/shell_integration/zsh \
-o ~/.iterm2_shell_integration.zsh
# --- Step 9: Configure .zshrc ---
echo "[9/10] Configuring .zshrc..."
cp ~/.zshrc ~/.zshrc.backup.$(date +%Y%m%d%H%M%S)
# Set theme
sed -i '' 's/^ZSH_THEME=.*/ZSH_THEME="powerlevel10k\/powerlevel10k"/' ~/.zshrc
# Set plugins (replace existing plugins line)
sed -i '' 's/^plugins=(.*/plugins=(git fzf-tab zsh-autosuggestions fast-syntax-highlighting docker kubectl)/' ~/.zshrc
# Remove old zsh-syntax-highlighting from plugins if present alongside fast-syntax-highlighting
# (they conflict — fast-syntax-highlighting is the replacement)
# Add new config block if not already present
if ! grep -q "fzf --zsh" ~/.zshrc; then
cat >> ~/.zshrc << 'ZSHEOF'
# --- nVs Terminal Setup additions ---
# fzf shell integration (Ctrl+R history, Ctrl+T files, Alt+C directories)
source <(fzf --zsh)
# zoxide (smarter cd — use 'z' to jump to frecent directories)
eval "$(zoxide init zsh)"
# Modern CLI aliases
alias cat="bat --paging=never"
alias ls="eza --icons --group-directories-first"
alias ll="eza --icons --group-directories-first -la"
alias lt="eza --icons --group-directories-first --tree --level=2"
alias find="fd"
# fzf-tab styling (Catppuccin Mocha colors)
zstyle ':fzf-tab:complete:cd:*' fzf-preview 'eza --icons --group-directories-first -1 --color=always $realpath'
zstyle ':fzf-tab:complete:ls:*' fzf-preview 'eza --icons --group-directories-first -1 --color=always $realpath'
zstyle ':fzf-tab:*' fzf-flags --color=bg+:#313244,bg:#1e1e2e,spinner:#f5e0dc,hl:#f38ba8 --color=fg:#cdd6f4,header:#f38ba8,info:#cba6f7,pointer:#f5e0dc --color=marker:#f5e0dc,fg+:#cdd6f4,prompt:#cba6f7,hl+:#f38ba8
# iTerm2 Shell Integration
test -e "${HOME}/.iterm2_shell_integration.zsh" && source "${HOME}/.iterm2_shell_integration.zsh"
# --- End nVs Terminal Setup ---
ZSHEOF
echo " Added shell config to .zshrc"
else
echo " Shell config already in .zshrc"
fi
# --- Step 10: Configure iTerm2 Profile ---
echo "[10/10] Configuring iTerm2 profile..."
# Only configure if iTerm2 is not running
if pgrep -x iTerm2 > /dev/null; then
echo " WARNING: iTerm2 is running. Close it and re-run this step."
echo " Skipping iTerm2 profile configuration."
else
python3 << 'PYEOF'
import plistlib, os
plist_path = os.path.expanduser("~/Library/Preferences/com.googlecode.iterm2.plist")
colors_path = os.path.expanduser("~/catppuccin-mocha.itermcolors")
if not os.path.exists(plist_path):
print(" iTerm2 plist not found — open iTerm2 once first, then re-run.")
exit(0)
with open(plist_path, 'rb') as f:
plist = plistlib.load(f)
profile = plist["New Bookmarks"][0]
profile["Normal Font"] = "MesloLGSNerdFontMono-Regular 13"
profile["Non Ascii Font"] = "MesloLGSNerdFontMono-Regular 13"
profile["Columns"] = 120
profile["Rows"] = 35
profile["Transparency"] = 0.08
profile["Blur"] = True
profile["Blur Radius"] = 15.0
profile["Scrollback Lines"] = 10000
profile["Unlimited Scrollback"] = False
profile["Terminal Type"] = "xterm-256color"
profile["Option Key Sends"] = 2
profile["Right Option Key Sends"] = 2
profile["Mouse Reporting"] = True
if os.path.exists(colors_path):
with open(colors_path, 'rb') as f:
colors = plistlib.load(f)
for key, value in colors.items():
profile[key] = value
with open(plist_path, 'wb') as f:
plistlib.dump(plist, f)
print(" iTerm2 profile configured!")
PYEOF
fi
echo ""
echo "=== Setup Complete ==="
echo ""
echo "Next steps:"
echo " 1. Open iTerm2 (the P10k wizard will auto-launch)"
echo " 2. Follow the wizard to pick your prompt style"
echo " 3. Go to Preferences > Profiles > Keys > Presets > Natural Text Editing"
echo " 4. Enjoy your new terminal!"Save and run:
bash /path/to/nvs-terminal-setup.shThese cannot be automated and must be done once by the user:
- Open iTerm2 — Powerlevel10k wizard launches automatically, follow prompts
- Natural Text Editing — Preferences > Profiles > Keys > Key Mappings > Presets > Natural Text Editing
- Reconfigure prompt anytime — Run
p10k configure
| Problem | Solution |
|---|---|
| Broken/missing icons in prompt | Font not set — Preferences > Profiles > Text > Change font to "MesloLGS NF" |
Option+Arrow types ∫ instead of jumping |
Set Preferences > Profiles > Keys > Left/Right Option Key > Esc+ |
| Colors reset after opening iTerm2 | iTerm2 overwrites plist on launch — close iTerm2, re-run Step 10 |
zsh-syntax-highlighting and fast-syntax-highlighting conflict |
Remove zsh-syntax-highlighting from plugins, keep only fast-syntax-highlighting |
z command not working |
Make sure eval "$(zoxide init zsh)" is in .zshrc and you've reloaded (source ~/.zshrc) |
| fzf Ctrl+R not working | Make sure source <(fzf --zsh) is in .zshrc |
| Tab completion not fuzzy | Make sure fzf-tab is first in plugins list (before autosuggestions) |
| Slow shell startup | Remove duplicate entries in .zshrc, check with: time zsh -i -c exit |
If you are an AI agent setting this up for a user:
- Check what's already installed before each step — skip if present
- Back up .zshrc before making changes
- Close iTerm2 before editing the plist (Step 10)
- Do NOT include both
zsh-syntax-highlightingandfast-syntax-highlightingin plugins - Do NOT include the
zplugin when using zoxide — they conflict - Plugin order matters:
fzf-tabmust come beforezsh-autosuggestionsandfast-syntax-highlighting - Run the verification checklist after setup to confirm everything works
- Inform the user about the 3 manual steps (P10k wizard, Natural Text Editing, and optional
p10k configure) - The one-shot script is idempotent — safe to run multiple times
- If on a corporate network with SSL issues (Zscaler, etc.), the
curlcommands may need--insecureor the user's CA cert configured
Last updated: 2026-03-04 Tools: iTerm2 + Oh My Zsh + Powerlevel10k + Catppuccin Mocha + fzf + bat + eza + fd + zoxide