English version: A Practical Ghostty-Based Terminal Stack.

基于 Ghostty 的现代 macOS 终端方案

终端不是越复杂越好。一个好用的日常终端环境,应该满足四件事:启动快、显示稳定、路径跳转顺手、常用命令可读性更好。最近我把本机终端方案整理成一套可重复安装的组合:

Ghostty + Maple Mono NF CN + zinit + Starship + zoxide + fast-syntax-highlighting + zsh-autosuggestions + fzf + Yazi + eza/ripgrep/fd/bat/btop/duf/httpie

这套方案的目标不是把 shell 配成一个大型框架,而是用少量明确的工具替换旧的 Terminal.app + Oh My Zsh + 直接 source 插件 方案,让交互体验更现代,同时保留历史命令和旧配置的可回滚性。

一张图看整体思路

flowchart LR
  A[Ghostty<br/>GPU 加速终端] --> B[Maple Mono NF CN<br/>CJK 等宽与 Nerd Font 图标]
  B --> C[zsh 启动]
  C --> D[zinit<br/>延迟加载插件]
  D --> E[zsh-autosuggestions<br/>历史建议]
  D --> F[fast-syntax-highlighting<br/>语法高亮]
  C --> G[zoxide<br/>智能 cd]
  C --> H[Starship<br/>跨 shell prompt]
  C --> I[现代 CLI 别名<br/>eza rg fd bat btop duf]
  C --> J[fzf<br/>快捷键与补全]
  C --> K[Yazi<br/>终端文件管理器]

设计上,我把“终端模拟器”“字体渲染”“shell 插件”“prompt”“CLI 工具”拆开处理。每一层只做自己擅长的事,不把所有能力都塞进一个庞大的 zsh 框架里。

从旧方案迁移到新方案

旧方案通常长这样:

flowchart TB
  subgraph Old[旧方案]
    O1[Terminal.app] --> O2[Oh My Zsh]
    O2 --> O3[主题]
    O2 --> O4[直接 source autosuggestions]
    O2 --> O5[直接 source syntax-highlighting]
  end

  subgraph New[新方案]
    N1[Ghostty] --> N2[轻量 zsh]
    N2 --> N3[zinit 延迟加载插件]
    N2 --> N4[Starship prompt]
    N2 --> N5[zoxide + fzf]
    N2 --> N6[现代 CLI 工具]
  end

迁移时不删除 Oh My Zsh,也不删除旧插件。更稳妥的做法是:把旧的加载行注释掉,让它们不再影响启动性能;如果需要回滚,文件和插件仍然在。

工具与插件速览

组件角色核心功能为什么选它
Ghostty终端模拟器GPU/Metal 渲染、原生 macOS 体验、配置文件驱动比系统 Terminal 更现代,配置可迁移
Maple Mono NF CN字体中英文等宽混排、Nerd Font 图标、Powerline 符号单一字体同时覆盖 Latin/CJK/图标,避免 fallback 导致中文大小和字重不一致
zinitzsh 插件管理延迟加载、按需拉取插件、减少启动负担替代 Oh My Zsh 的重框架加载方式
zsh-autosuggestions输入建议基于历史命令给出灰色建议保留熟悉的命令补全体验
fast-syntax-highlighting语法高亮命令、参数、路径高亮比传统高亮方案更快,适合交互 shell
StarshippromptGit 状态、目录、语言版本、命令耗时跨 shell,配置集中,显示稳定
zoxide路径跳转根据访问频率智能跳目录cd 习惯获得 z 的效率
fzf模糊查找Ctrl-R 历史搜索、文件/目录模糊选择高频交互场景提速明显
Yazi终端文件管理器三栏浏览、快速预览、文件操作、退出后回到目标目录在终端里完成 Finder 和 cd 之间的高频文件浏览
ezals 替代图标、Git 状态、树状展示恢复并增强 ll/la/l/lt 等快捷命令
ripgrepgrep 替代高速全文搜索搜索代码和文本更快
fdfind 替代简洁语法、默认忽略无关目录日常查文件更顺手
batcat 替代语法高亮、分页、行号查看文件更可读
btoptop 替代进程、CPU、内存可视化交互式资源监控更直观
dufdf 替代磁盘空间表格化展示比传统 df 更易读
httpieHTTP 客户端可读的 HTTP 请求/响应日常 API 调试比 curl 更友好

常用别名设计

传统命令新工具配置意图
lseza --icons=auto --group-directories-first保持习惯,增强显示
lleza -lh --icons=auto --group-directories-first --git恢复长列表快捷键,显示 Git 状态
laeza -lah --icons=auto --group-directories-first --git显示隐藏文件
leza -1 --icons=auto --group-directories-first单列快速浏览
lteza --tree --level=2 --icons=auto --group-directories-first二级树状结构
catbat默认获得语法高亮
greprg默认高速搜索
findfd默认更简洁的文件查找
topbtop默认使用现代资源监控
dfduf默认使用易读磁盘视图
yyazi --cwd-file 包装函数快速打开终端文件管理器,退出后把当前 shell 切到最后所在目录
yyy 兼容别名保留早期 wrapper 名称,行为与 y 一致

这些别名都应该做成“命令存在才启用”。这样在一台新机器上即使某个工具暂时安装失败,shell 仍然能正常启动。

这里有一个细节容易被误解:Yazi 退出后想让“父级 shell”自动 cd 到最后所在目录,不能只写 alias y="yazi"。原因是子进程无法直接修改父 shell 的当前目录。更稳妥的做法是用官方推荐的 --cwd-file 思路写一个很薄的 y() 函数:Yazi 退出时把目录写入临时文件,函数读出后再在当前 shell 里 cd。为了避免嵌套打开 Yazi,嵌套检测也应该放在函数内部,而不是在 .zshrc 顶层写 [[ -n "$YAZI_LEVEL" ]] && exit

Yazi 的预览能力依赖一组小工具:ffmpegthumbnailer 用于视频缩略图,sevenzip 用于压缩包,poppler 用于 PDF,imagemagick 用于图片处理,jq 用于 JSON。把这些依赖放进安装脚本后,新机器打开 Yazi 时不会只得到一个空壳文件列表。

fzf、fd、bat 与 eza 的闭环联动

fzf 的体验不只来自快捷键本身,更来自默认数据源和预览命令。当前配置把 fd 作为文件/目录扫描入口,把 bat 用作文件预览,把 eza --tree 用作目录预览:

export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix --hidden --follow --exclude .git'
export FZF_CTRL_T_COMMAND='fd --strip-cwd-prefix --hidden --follow --exclude .git'
export FZF_ALT_C_COMMAND='fd --type d --strip-cwd-prefix --hidden --follow --exclude .git'
export FZF_DEFAULT_OPTS="--ansi --preview 'if [ -d {} ]; then eza --tree --level=2 --icons=auto --group-directories-first {}; elif command -v bat >/dev/null 2>&1; then bat --style=numbers --color=always --line-range :500 {}; else sed -n \"1,500p\" {}; fi'"

这些变量要放在 source <(fzf --zsh) 之前。实际加载 fzf 时仍然要用 [[ -t 0 && -o zle ]] 做交互 shell 保护,避免自动化脚本或非交互命令被 fzf/ZLE 初始化噪声影响。

历史命令必须保留

迁移 shell 时最容易被忽略的是历史命令。我的做法是显式保留原有 ~/.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

这样打开新的 Ghostty 窗口后,原来的历史命令仍然可以被 zsh、fzf 和 zsh-autosuggestions 继续使用。

为什么不用继续堆 Oh My Zsh

Oh My Zsh 的优点是开箱即用,缺点是它经常把主题、插件、补全和框架行为绑在一起。长期使用后,启动路径会变得不透明:到底是哪段脚本慢、哪个插件影响粘贴、哪段配置覆盖了补全行为,都不容易定位。

这套新方案的思路是:

目标做法
提高启动性能用 zinit 延迟加载交互插件
保持 prompt 可维护用 Starship 统一 prompt 配置
保持历史命令继续使用 ~/.zsh_history
保留回滚能力注释旧配置,不删除旧目录
降低自动化噪声fzf 和 zinit 交互插件只在真实 TTY 中加载
提升日常命令可读性用现代 CLI 工具接管传统命令

推荐 Ghostty 主题

Ghostty 的主题名必须来自 ghostty +list-themes,否则应用会在启动时报配置错误。我的偏好顺序是:

优先级主题风格
1TokyoNight Night接近 Tokyo Night,深色、克制、适合长时间编码
2TokyoNight Storm同属 Tokyo Night 系列,对比略有差异
3Terminal Basic Dark更接近系统 Terminal 的经典深色体验

当前默认使用:

theme = "TokyoNight Night"

配置完成后一定要验证:

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

可重复执行的安装原则

这套配置适合沉淀成一个幂等脚本。脚本应该做到:

  1. 检查 macOS 与 Homebrew。
  2. 安装 Ghostty、Maple Mono NF CN、zinit、Starship、zoxide、Yazi 和现代 CLI 工具。
  3. 注释旧 Oh My Zsh 与旧插件加载行,而不是删除它们。
  4. 用 marker block 管理 ~/.zshrc,重复执行时替换块而不是追加重复配置。
  5. 写入 Ghostty、Starship 与 Yazi 配置。
  6. 在 source fzf 前写入 fdbateza 预览联动变量。
  7. prime 一次 zinit 插件,让首次打开终端时不再等待克隆。
  8. 运行 zsh -n ~/.zshrcghostty +validate-config
flowchart TD
  A[运行安装脚本] --> B{Homebrew 可用?}
  B -- 否 --> C[提示先安装 Homebrew]
  B -- 是 --> D[安装 formulae 与 casks]
  D --> E[备份并更新 zshrc]
  E --> F[写入 Ghostty 配置]
  F --> G[写入 Starship 与 Yazi 配置]
  G --> H[预热 zinit 插件]
  H --> I[验证 zsh、Yazi 与 Ghostty 配置]
  I --> J[打开新的 Ghostty 窗口]

Ghostty 与配套工具快速上手指南

这一节集中列出日常最高频的配置命令、快捷键和工具用法,方便以后直接查阅。

Ghostty

当前字体配置使用 Maple Mono NF CN,中英文与图标会保持一致的等宽基线:

font-family = "Maple Mono NF CN"

常用命令:

# 校验配置
ghostty +validate-config --config-file="$HOME/.config/ghostty/config"

# 让已打开的 Ghostty 窗口热加载新配置
ghostty +reload-config

# 查看 Ghostty 能识别的字体族
ghostty +list-fonts | rg -i "Maple Mono NF CN"

# 查看可用主题,主题名必须来自这个列表
ghostty +list-themes

zsh 插件

  • zsh-autosuggestions:命令输入时出现灰色历史建议,按 RightEnd 接受;继续输入即可忽略。
  • fast-syntax-highlighting:无需额外操作,命令、参数、路径会在输入时自动 高亮。

Starship

Prompt 由 Starship 渲染,Git 状态、目录、语言版本和命令耗时都集中在这里:

starship --version
cat ~/.config/starship.toml

zoxide

当前 shell 把 zoxide 初始化为 --cmd cd,所以直接使用 cd 就会获得智能跳转:

cd projects
cd mobile-workspace
cd -

# 显式查询 zoxide 数据库
zoxide query <keyword>

fzf

快捷键用途
Ctrl-R搜索 shell 历史(Atuin 启用时由 Atuin 接管)
Ctrl-T模糊选择文件
Alt-C模糊跳转目录
**<TAB>调用 fzf 完成 shell 补全

当前配置使用 fd 作为数据源,文件预览使用 bat,目录预览使用 eza --tree

Yazi

y 打开 Yazi(yy 是兼容别名)。退出后,y() 函数会把当前 shell 切换到 Yazi 最后所在的目录。

按键作用
h返回上级目录
l进入目录或打开文件
j / k向下 / 向上移动
Enter打开选中项
Space切换选择
y复制(yank)选中项
d删除选中项
p粘贴
r重命名
a新建文件
/搜索
n / N下一个 / 上一个搜索结果
~返回用户主目录
q退出

在 Yazi 内按 ~F1 可以查看完整帮助和全部键位。

Atuin

atuin search <keyword>
atuin stats
atuin history
atuin daemon status

Atuin 启用后,Ctrl-R 打开的是 Atuin 的历史搜索界面。

现代 CLI 别名

ll          # eza 长列表,显示 Git 状态
la          # eza 长列表,包含隐藏文件
lt          # eza 两级树状视图
rg PATTERN  # ripgrep 全文搜索
fd NAME     # fd 文件搜索
bat FILE    # bat 语法高亮查看文件
btop        # 交互式资源监控
duf         # 易读磁盘使用视图
http GET https://example.com

这套方案的收益

最终得到的是一个更清晰的终端栈:

  • 终端显示由 Ghostty 与 Maple Mono NF CN 负责,中文、英文和图标保持统一等宽。
  • zsh 只保留必要的 shell 行为。
  • 插件由 zinit 延迟加载。
  • prompt 交给 Starship。
  • 路径跳转交给 zoxide。
  • 终端文件浏览和预览交给 Yazi。
  • 搜索、列表、查看、监控、HTTP 调试交给更现代的 CLI 工具。
  • 旧配置保留但不再参与启动。

这不是“把终端配得更花”,而是把常用交互路径拆清楚:哪里负责渲染,哪里负责补全,哪里负责搜索,哪里负责提示,哪里负责可读性。拆清楚之后,配置更容易迁移,也更容易维护。

继续阅读