跳转到正文
Mind in Motion

我的 macOS 终端工作流:工具联动与 Starship 美化

介绍我在 macOS 上使用的现代终端工具、模糊搜索与目录跳转工作流,以及 Zsh 和 Starship 的相关配置。

开发实践4分钟阅读

我在 macOS 上使用 Zsh 作为 Shell,并用一组职责明确的命令行工具完成文件查看、文本搜索、目录跳转、文件管理和 Git 状态展示。常用操作保留了 lscatgrepvim 等熟悉入口,同时获得图标、语法高亮、模糊筛选和文件预览能力。

这套终端环境的重点是工具协作:fd 提供文件列表,fzf 负责交互选择,bat 显示内容预览;zoxide 根据使用频率跳转目录;Yazi 退出后将所在目录同步给当前 Zsh;Starship 统一展示目录、Git 分支和工作区状态。

工具 主要用途 常用入口 相关联动
Neovim 终端文本编辑 nvimvim Zsh 别名
eza 目录列表和树形视图 lslllatree Git 状态、Nerd Font
bat 文件查看和语法高亮 catbat fzf 预览、man 页
ripgrep 递归搜索文件内容 rggrep fd、fzf
fd 按名称查找文件 fd fzf 候选列表
fzf 交互式模糊筛选 fzfCtrl+R/T/F fd、bat、zoxide
zoxide 按使用频率跳转目录 zzi fzf
Yazi 终端文件管理 y Zsh 当前目录
Starship 跨 Shell 提示符 自动加载、starship_use Git、目录和语言环境
Git 版本管理与插件来源管理 gitzplugin-update Starship、Zsh 插件
Homebrew 安装和维护终端程序 brewb1b2 以上命令行工具

这些程序可以分别运行,Zsh 配置负责为它们提供统一入口、快捷键和数据传递关系。

eza 为目录列表增加图标、颜色、文件属性、Git 状态和树形视图。配置保留了常用的 ls 系列命令:

Terminal window
ls # 带图标的简洁列表
ll # 权限、大小、时间和 Git 状态
la # 在 ll 的基础上显示隐藏文件
tree # 树形展示当前目录
tree src # 树形展示 src 目录

对应的别名位于 aliases.zsh

aliases.zsh
alias ls='eza --icons'
alias ll='eza -lh --icons --git'
alias la='eza -lah --icons --git'
alias tree='eza --tree --icons'

--icons 需要终端字体包含相应图标字符,Nerd Font 可以提供完整显示。需要调用 macOS 原生 ls 时使用 command ls

bat 适合直接阅读代码和配置文件。它会识别语言、添加语法高亮、显示行号,并在内容较长时调用分页器。

Terminal window
cat ~/.config/zsh/.zshrc
bat -n src/main.ts
bat -r 40:80 src/main.ts

我将 cat 指向 bat,日常查看文件时可以继续使用熟悉的命令:

aliases.zsh
alias cat='bat'

bat 还承担两项显示任务:

  • fzf 选中文件时,用 bat 在右侧显示前 500 行内容。
  • 查看 man 页时,通过 MANPAGER='bat -l man -p' 提供更清晰的排版。

需要原生输出时可以执行 command cat 文件名

Neovim 负责终端内编辑,vim 作为它的快捷入口:

aliases.zsh
alias vim='nvim'
Terminal window
vim README.md
nvim ~/.config/zsh/starship.toml

默认编辑器保持为 Visual Studio Code:

.zshrc
export EDITOR='code --wait'
export VISUAL='code --wait'

因此,手动输入 vim 会进入 Neovim;Git 等程序读取 EDITORVISUAL 时会打开 VS Code,并等待编辑窗口完成。

ripgrep 使用 rg 命令递归搜索目录,默认遵循 .gitignore,并自动跳过二进制文件。

Terminal window
rg 'STARSHIP_CONFIG'
rg -n 'proxy_' ~/.config/zsh
rg -g '*.md' 'Homebrew' .
rg -l 'zoxide' # 只列出匹配的文件

配置同时提供 grep 入口:

aliases.zsh
alias grep='rg --color=auto'

这个入口接受 ripgrep 的参数规则。脚本需要系统 grep 时可以使用 command grep

fd 根据文件名查找内容,语法简洁,并默认遵循 .gitignore

Terminal window
fd zsh
fd -e md
fd 'config' ~/.config
fd --type d Projects ~

在这套配置中,fd 还负责为 fzf 持续生成候选文件:

fzf.zsh
export FZF_DEFAULT_COMMAND='fd --type f --hidden --strip-cwd-prefix'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"

--hidden 将隐藏文件纳入候选,--strip-cwd-prefix 让显示路径更紧凑。

fzf 接收一组文本候选,并提供实时模糊搜索界面。它既可以独立使用,也可以嵌入其他命令:

Terminal window
fd -e md | fzf
rg -l 'Starship' | fzf
git branch --format='%(refname:short)' | fzf

当前界面使用 60% 终端高度、反向布局和右侧预览区域:

fzf.zsh
export FZF_DEFAULT_OPTS='
--height=60%
--layout=reverse
--border=rounded
--preview-window=right:65%:wrap:border-left
'
export _FZF_PREVIEW_CMD='bat --color=always --style=plain,numbers --line-range=:500 {}'
export FZF_CTRL_T_OPTS="--preview '$_FZF_PREVIEW_CMD'"

Zsh 中最常用的是三组快捷键:

快捷键 候选内容 执行结果
Ctrl+R Zsh 命令历史 将选中的历史命令放回当前命令行
Ctrl+T fd 找到的文件,包含隐藏文件 将选中文件路径插入当前命令行
Ctrl+F fd 找到的文件,过滤隐藏文件 将单个文件路径插入当前命令行

Ctrl+RCtrl+T 来自 fzf --zshCtrl+F 由自定义 ZLE 组件提供。配置先在 fzf.zsh 中注册 _fzf_file_no_hidden,再由 bindings.zsh 完成按键绑定:

bindings.zsh
bindkey -M emacs '^F' _fzf_file_no_hidden

zoxide 会记录访问过的目录,并根据访问频率和最近使用时间计算匹配结果。它适合替代反复输入长路径的操作。

Terminal window
z blog # 跳转到最匹配的常用目录
z Projects # 跳转到名称匹配的目录
zi # 用 fzf 交互选择历史目录

.zshrc 在检测到命令后完成初始化:

.zshrc
eval "$(zoxide init zsh)"

z 负责直接匹配,zi 将 zoxide 的目录数据交给 fzf 选择。使用一段时间后,常用路径会逐步积累,无需手动维护跳转列表。

Yazi 是运行在终端中的文件管理器,支持键盘导航、文件预览和批量操作:

Terminal window
y
y ~/Projects

直接启动的 Yazi 运行在独立进程中,进程切换的目录不会自动改变父级 Shell。y 函数通过 --cwd-file 接收 Yazi 退出时的目录,再由当前 Zsh 执行 cd

aliases.zsh
y() {
local tmp cwd
tmp=$(command mktemp -t yazi-cwd.XXXXXX) || return 1
command yazi "$@" --cwd-file="$tmp"
IFS= read -r -d '' cwd < "$tmp" || true
[[ -n $cwd && $cwd != $PWD && -d $cwd ]] && builtin cd -- "$cwd"
command rm -f -- "$tmp"
}

实际配置还会保留 Yazi 的退出状态,并确保临时文件在异常情况下得到清理。

flowchart LR A["fd<br/>生成文件列表"] --> B["fzf<br/>模糊筛选"] B --> C["bat<br/>内容预览"] D["zoxide<br/>常用目录数据"] --> E["zi / fzf<br/>交互选择"] E --> F["Zsh<br/>切换目录"] G["Yazi<br/>文件管理"] --> H["--cwd-file<br/>写出最终目录"] H --> I["y 函数<br/>更新当前目录"]

第一条链路服务于文件查找,第二条链路服务于历史目录跳转,第三条链路让全屏文件管理器与当前命令行保持目录一致。每个工具只承担一项核心职责,Zsh 负责连接输入与输出。

Starship 根据当前目录和运行环境动态生成提示符。进入 Git 项目时,它会显示分支与文件状态;进入 Node.js、Python、Rust 等项目时,相应语言模块会按检测结果出现。

.zshenv 固定配置文件路径,prompt.zsh 完成初始化:

.zshenv
export STARSHIP_CONFIG="${STARSHIP_CONFIG:-$ZDOTDIR/starship.toml}"
prompt.zsh
eval "$(starship init zsh)"

当前 starship.toml 保留 Starship 的完整默认模块,并调整四项显示规则:

starship.toml
format = "$all"
add_newline = true
scan_timeout = 100
[username]
show_always = true
disabled = false
[git_status]
format = "\\[ $all_status$ahead_behind\\] "
staged = "A$count "
modified = "M$count "
untracked = "?$count "
deleted = "D$count "
conflicted = "U$count "
  • format = "$all" 按 Starship 默认顺序组合已启用模块。
  • add_newline = true 在命令之间增加留白,让长输出更容易分辨。
  • scan_timeout = 100 将项目文件扫描时间限制为 100 毫秒。
  • show_always = true 始终显示当前用户名。
  • git_status 使用紧凑字母标记工作区状态。

Git 状态符号的含义如下:

显示 含义 示例
A 已加入暂存区 A2
M 已修改、等待暂存 M1
? Git 尚未跟踪 ?3
D 已删除 D1
U 存在合并冲突 U2

例如 [ A2 M1 ?3 ] 表示 2 项已暂存、1 项已修改、3 项尚未跟踪。ahead_behind 继续显示本地分支相对远端的领先或落后状态。

starship_use 用于快速切换当前外观:

Terminal window
starship_use default # 使用 Starship 官方默认外观
starship_use official # 与 default 相同
starship_use pills # 使用 ~/.config/starship_pills.toml

选择 defaultofficial 时,当前配置会保存为 starship.toml.bak;选择 pills 时,预设文件会复制到 STARSHIP_CONFIG 指向的位置。函数最后通过 exec zsh 立即刷新终端。

终端同时加载三个轻量插件:

插件 作用
zsh-completions 扩充命令和参数的 Tab 补全定义
zsh-autosuggestions 根据历史记录显示灰色行内建议
zsh-syntax-highlighting 根据命令有效性和语法结构着色

首次启动时,plugins.zsh 使用 Git 将插件浅克隆到 ~/.config/zsh/plugins/zsh-completions 先加入 FPATH,随后 compinit 生成补全缓存;自动建议和语法高亮在交互模块之后加载。

更新插件使用:

Terminal window
zplugin-update

这个函数遍历插件目录,并对每个 Git 项目执行 git pull --ff-only

配置中还包含一组面向 macOS 日常维护的函数:

函数 用法 执行内容
ip ip 通过 ipip.net 和 cip.cc 查询公网 IP
launch launchlaunch u/a 显示并打开 macOS 启动项目录
b1 b1 执行 brew updatebrew outdated
b2 b2 执行 brew upgradebrew cleanup
proxy_on proxy_on 设置当前 Shell 的 HTTP、HTTPS 和通用代理
proxy_off proxy_off 清除当前 Shell 的代理环境变量
proxy_status proxy_status 检查系统代理、TUN 路由、端口和 Shell 变量
zplugin-update zplugin-update 更新 Git 管理的 Zsh 插件
starship_use <预设> starship_use pills 切换 Starship 外观并重新启动 Zsh

b1 适合先获取最新软件包信息并查看有哪些程序可以更新:

Terminal window
b1

确认后使用 b2 执行升级,并清理旧版本和缓存:

Terminal window
b2

代理地址默认为 http://127.0.0.1:7890。交互式 Zsh 启动时会检查 macOS 系统代理、TUN 路由和本地端口,再根据 PROXY_AUTO_MODE="auto" 更新当前 Shell 的代理变量。

Terminal window
proxy_status # 查看系统、TUN、端口和 Shell 四层状态
proxy_on # 手动写入代理环境变量
proxy_off # 清除代理环境变量

当前 Shell 启动的 Git、Homebrew 和 curl 会继承这些环境变量。

整个启动过程由三个 Zsh 文件和若干功能模块组成:

/etc/zshenv
→ .zshenv:XDG 目录、ZDOTDIR、Starship 路径
→ .zprofile:Homebrew 登录环境
→ .zshrc:历史记录、补全、工具、插件和提示符

.zshrc 中的模块加载顺序如下:

plugins.zsh → compinit → aliases.zsh → fzf.zsh → bindings.zsh
→ zoxide 与 bat man pager → 自动建议 → 语法高亮
→ prompt.zsh → local.zsh

这个顺序保证补全定义先于 compinit,fzf 组件先于快捷键,语法高亮接近插件加载末尾,本机覆盖配置最后生效。

文件 负责内容
.zshenv XDG 目录、配置目录和 Starship 配置路径
.zprofile Apple Silicon 与 Intel Mac 的 Homebrew 环境
.zshrc 历史记录、补全系统和模块加载顺序
aliases.zsh 命令别名、Yazi 包装和辅助函数
fzf.zsh fd 候选、fzf 界面和 bat 预览
bindings.zsh 自定义 ZLE 快捷键
plugins.zsh Zsh 插件安装、加载和更新
prompt.zsh Starship 初始化与预设切换
starship.toml 提示符模块和 Git 状态格式
local.example.zsh 本机开发环境模板
local.zsh 当前电脑专用设置

命令历史保存在 ~/.local/state/zsh/history,补全缓存保存在 ~/.cache/zsh/zcompdump。这两类运行数据与可迁移配置分开存放。

Cargo、JetBrains Toolbox、OrbStack、Bun、Conda 和 Proto 与具体电脑上的安装状态相关。公开的 local.example.zsh 提供带注释的示例,初始化时复制为 local.zsh

Terminal window
cp "$HOME/.config/zsh/local.example.zsh" \
"$HOME/.config/zsh/local.zsh"

随后只需取消当前电脑实际使用部分的注释:

环境 模板中的接入方式
Cargo 读取 ~/.cargo/env
JetBrains Toolbox 将 Toolbox scripts 目录加入 PATH
OrbStack 读取 ~/.orbstack/shell/init.zsh
Bun ~/.bun/bin 加入 PATH
Conda 从 Miniconda 生成 Zsh hook
Proto 将 shims 和 bin 目录加入 PATH

local.zsh 位于模块加载末尾,并由 .gitignore 排除。每台电脑可以保留各自的开发环境路径和私人设置。

先按照 Homebrew 官方文档完成安装,再执行:

Terminal window
brew install git neovim eza bat fd fzf zoxide starship ripgrep yazi

终端字体建议选用 Nerd Font,以便 eza 和 Starship 完整显示图标。

Terminal window
mkdir -p "$HOME/.config"
git clone https://github.com/yznn007/zsh.git "$HOME/.config/zsh"

已有 Zsh 配置时,先将原文件移动到备份目录,再逐项合并个人设置。

编辑 macOS 的系统级入口:

Terminal window
sudo nano /etc/zshenv

加入以下内容:

/etc/zshenv
if [[ -z "$XDG_CONFIG_HOME" ]]; then
export XDG_CONFIG_HOME="$HOME/.config"
fi
if [[ -d "$XDG_CONFIG_HOME/zsh" ]]; then
export ZDOTDIR="$XDG_CONFIG_HOME/zsh"
fi

启动新的登录 Shell:

Terminal window
exec /bin/zsh -l

首次启动会自动下载三个 Zsh 插件。

Terminal window
cp "$HOME/.config/zsh/local.example.zsh" \
"$HOME/.config/zsh/local.zsh"

编辑 local.zsh,启用当前电脑需要的 Cargo、Bun、Conda、Proto、Toolbox 或 OrbStack 配置。只使用通用终端工具时可以省略这一步。

Terminal window
print -r -- "ZDOTDIR=$ZDOTDIR"
print -r -- "STARSHIP_CONFIG=$STARSHIP_CONFIG"
command -v nvim eza bat rg fd fzf zoxide yazi starship
alias vim ls ll la tree cat grep
whence -w y z zi ip launch b1 b2
bindkey '^R'
bindkey '^T'
bindkey '^F'

ZDOTDIR 应显示 ~/.config/zsh 对应的完整路径,工具检查应返回各命令位置,别名、函数和快捷键应显示当前定义。

拉取最新配置:

Terminal window
git -C "$HOME/.config/zsh" pull --ff-only

更新 Zsh 插件:

Terminal window
zplugin-update

配置更新后启动新的登录 Shell:

Terminal window
exec /bin/zsh -l

© yznn007. 保留所有权利。