中文版本:基于 Ghostty 的现代 macOS 终端方案.

A Practical Ghostty-Based Terminal Stack

A good terminal setup should not feel heavy. It should start quickly, render text and icons reliably, preserve command history, make navigation fast, and improve the readability of everyday commands.

The stack I settled on is:

Ghostty + JetBrainsMono Nerd Font + zinit + Starship + zoxide + fast-syntax-highlighting + zsh-autosuggestions + fzf + Yazi + eza/ripgrep/fd/bat/btop/duf/httpie.

The goal is not to build a large shell framework. The goal is to replace a traditional Terminal.app + Oh My Zsh + directly sourced plugins setup with a clearer, faster, reproducible terminal environment.

The Stack At A Glance

flowchart LR
  A[Ghostty<br/>GPU accelerated terminal] --> B[JetBrainsMono Nerd Font<br/>icons and monospace rendering]
  B --> C[zsh startup]
  C --> D[zinit<br/>lazy plugin loading]
  D --> E[zsh-autosuggestions<br/>history-based suggestions]
  D --> F[fast-syntax-highlighting<br/>command highlighting]
  C --> G[zoxide<br/>smart cd]
  C --> H[Starship<br/>cross-shell prompt]
  C --> I[modern CLI aliases<br/>eza rg fd bat btop duf]
  C --> J[fzf<br/>key bindings and completion]
  C --> K[Yazi<br/>terminal file manager]

The key idea is separation of responsibility. The terminal emulator handles rendering. The font handles icons. zsh stays small. zinit loads interactive plugins lazily. Starship owns the prompt. zoxide owns navigation. Modern CLI tools improve the commands used every day.

From The Old Setup To The New Setup

A common old setup looks like this:

flowchart TB
  subgraph Old[Old setup]
    O1[Terminal.app] --> O2[Oh My Zsh]
    O2 --> O3[theme]
    O2 --> O4[directly sourced autosuggestions]
    O2 --> O5[directly sourced syntax highlighting]
  end

  subgraph New[New setup]
    N1[Ghostty] --> N2[lean zsh]
    N2 --> N3[zinit lazy plugins]
    N2 --> N4[Starship prompt]
    N2 --> N5[zoxide + fzf]
    N2 --> N6[modern CLI tools]
  end

The migration does not need to delete Oh My Zsh or old plugins. A safer approach is to comment out the old loading lines so they no longer affect shell startup. The files remain available for rollback.

Tools And Plugins

ComponentRoleCore capabilityWhy it is in the stack
GhosttyTerminal emulatorGPU/Metal rendering, native macOS behavior, file-based configMore modern and reproducible than the stock Terminal setup
JetBrainsMono Nerd FontFontMonospace text, Nerd Font icons, Powerline symbolsKeeps Starship and eza icons rendering correctly
zinitzsh plugin managerLazy loading and plugin managementReplaces heavier framework-style loading
zsh-autosuggestionsInput suggestionsGrey suggestions from shell historyKeeps the familiar history-based workflow
fast-syntax-highlightingSyntax highlightingHighlights commands, arguments, and pathsFast enough for interactive use
StarshipPromptGit status, directory, language versions, command durationCross-shell, compact, and easy to configure
zoxideNavigationFrequency-aware directory jumpingPreserves the cd habit while adding smart jumps
fzfFuzzy finderCtrl-R history search, fuzzy completion, file selectionSpeeds up high-frequency interactive tasks
YaziTerminal file managerThree-pane browsing, previews, file operations, return-to-directory workflowBridges Finder-like browsing and shell navigation inside the terminal
ezals replacementIcons, Git status, tree viewRestores and improves ll/la/l/lt shortcuts
ripgrepgrep replacementFast full-text searchBetter default for code and text search
fdfind replacementSimple syntax and sensible ignoresEasier day-to-day file discovery
batcat replacementSyntax highlighting and pagingMore readable file inspection
btoptop replacementInteractive CPU, memory, and process viewBetter system monitoring
dufdf replacementHuman-friendly disk usage tablesEasier disk inspection
httpieHTTP clientReadable HTTP requests and responsesFriendly API debugging

Alias Design

Traditional commandReplacementIntent
lseza --icons=auto --group-directories-firstKeep the habit, improve output
lleza -lh --icons=auto --group-directories-first --gitLong listing with Git status
laeza -lah --icons=auto --group-directories-first --gitInclude hidden files
leza -1 --icons=auto --group-directories-firstFast one-column listing
lteza --tree --level=2 --icons=auto --group-directories-firstShallow tree view
catbatSyntax-highlighted reading by default
greprgFaster text search
findfdSimpler file search
topbtopModern resource monitor
dfdufReadable disk usage
yyaziOpen the terminal file manager quickly
yywrapper around yazi --cwd-fileChange the current shell to Yazi’s final directory after exit

These aliases should be conditional. If a tool is missing on a new machine, the shell should still start.

Yazi previews work best with a few supporting tools: ffmpegthumbnailer for video thumbnails, sevenzip for archives, poppler for PDFs, imagemagick for image processing, and jq for JSON. Installing them with the terminal stack keeps Yazi useful immediately on a fresh machine.

Preserve History

Command history is part of the working environment. A terminal migration should not lose it. The setup keeps using the existing ~/.zsh_history:

export HISTFILE="${HISTFILE:-$HOME/.zsh_history}"
export HISTSIZE=100000
export SAVEHIST=100000
setopt APPEND_HISTORY
setopt EXTENDED_HISTORY
setopt INC_APPEND_HISTORY
setopt SHARE_HISTORY
setopt HIST_IGNORE_DUPS
setopt HIST_REDUCE_BLANKS
setopt HIST_VERIFY

After opening a new Ghostty window, the old history remains available to zsh, fzf, and zsh-autosuggestions.

Why Not Keep Adding To Oh My Zsh

Oh My Zsh is excellent for getting started. Over time, however, it can make the startup path harder to reason about. Themes, plugins, completion behavior, paste behavior, and framework defaults can become entangled.

This stack takes a narrower approach:

GoalApproach
Faster startupLazy-load interactive plugins with zinit
Maintainable promptUse Starship for prompt rendering
History preservationKeep ~/.zsh_history as the history file
Rollback safetyComment old config instead of deleting it
Cleaner automationLoad TTY-only integrations only in real terminals
Better daily commandsReplace legacy commands with modern CLI tools

Theme Preferences

Ghostty theme names must come from ghostty +list-themes. Invalid names fail config loading. My preferred dark themes are:

PriorityThemeStyle
1TokyoNight NightDeep Tokyo Night style, calm and suitable for long coding sessions
2TokyoNight StormSimilar family with slightly different contrast
3Terminal Basic DarkCloser to the classic macOS Terminal dark look

The current default is:

theme = "TokyoNight Night"

Always validate after changing it:

ghostty +validate-config --config-file="$HOME/.config/ghostty/config"

Idempotent Installation

This setup works best as a repeatable installer. The installer should:

  1. Check macOS and Homebrew.
  2. Install Ghostty, Nerd Font, zinit, Starship, zoxide, fzf, Yazi, and modern CLI tools.
  3. Comment legacy Oh My Zsh and direct plugin loading lines instead of deleting them.
  4. Manage ~/.zshrc with marker blocks so reruns replace the block instead of appending duplicates.
  5. Write Ghostty, Starship, and Yazi configs.
  6. Prime zinit plugins once so the first real terminal does not wait on cloning.
  7. Validate ~/.zshrc and Ghostty config.
flowchart TD
  A[Run installer] --> B{Homebrew available?}
  B -- No --> C[Ask user to install Homebrew]
  B -- Yes --> D[Install formulae and casks]
  D --> E[Backup and update zshrc]
  E --> F[Write Ghostty config]
  F --> G[Write Starship and Yazi configs]
  G --> H[Prime zinit plugins]
  H --> I[Validate zsh, Yazi, and Ghostty config]
  I --> J[Open a new Ghostty window]

Why This Setup Works

The result is a clean terminal stack:

  • Ghostty and Nerd Font handle rendering.
  • zsh keeps only essential shell behavior.
  • zinit handles lazy plugin loading.
  • Starship handles the prompt.
  • zoxide handles navigation.
  • fzf handles fuzzy interaction.
  • Yazi handles terminal-native file browsing and previews.
  • Modern CLI tools handle readable listings, search, file inspection, resource monitoring, disk usage, and HTTP debugging.
  • Old config remains available but no longer participates in startup.

This is not about making the terminal flashy. It is about making the interaction path explicit: rendering, completion, search, prompt, navigation, and command readability each have a clear owner. That makes the environment easier to migrate, debug, and maintain.

继续阅读