前言

一个好用的 Shell 配置,不应该只是“看起来很酷”。它更应该做到三件事:

  1. 启动快:进入终端后立刻可输入命令,而不是等待一堆插件初始化。
  2. 提示准:当前目录、Git 状态、命令执行结果、语言环境等信息一眼可见。
  3. 操作顺手:常用命令短、路径跳转快、补全和历史建议足够智能。

这篇文章记录我的 Zsh 配置思路。整体方案是:Zinit 管理插件,Powerlevel10k 负责提示符,Oh My Zsh 提供成熟插件生态,再配合 eza、yazi 等工具优化日常开发体验

整体结构

我的 Zsh 配置主要由两个文件组成:

~/.zshrc       # 主配置:环境变量、zinit、插件、别名、函数
~/.p10k.zsh    # Powerlevel10k 主题配置

加载顺序大致如下:

启动 Zsh
  |
  v
Powerlevel10k instant prompt
  |
  v
基础环境变量与 Shell options
  |
  v
加载 zinit
  |
  v
加载 OMZ library / Powerlevel10k / 插件
  |
  v
source ~/.p10k.zsh
  |
  v
注册 alias / function / PATH

这种拆分的好处是:.zshrc 保持“启动流程与插件管理”,.p10k.zsh 专注“提示符长什么样”。以后更换主题时,也不会影响插件和别名体系。

用 instant prompt 提升启动体验

配置最顶部是 Powerlevel10k 的 instant prompt:

if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

它的作用是:在完整配置加载完成之前,先显示一个临时 Prompt,让终端看起来“秒开”。

同时我设置了:

typeset -g POWERLEVEL9K_INSTANT_PROMPT=quiet

这样可以减少 instant prompt 对启动时输出内容的干扰。对于需要频繁打开新终端、tmux pane 或远程会话的人来说,这一点体验提升很明显。

基础环境与 Zsh options

path=(~/.local/bin $path)
typeset -x XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"

setopt correct
setopt interactive_comments

这里做了几个基础设定:

配置作用
~/.local/bin 前置到 PATH优先使用用户级安装的命令
XDG_CONFIG_HOME统一配置目录,默认指向 ~/.config
setopt correct命令输错时给出纠正建议
setopt interactive_comments交互式 Shell 中也允许使用 # 注释

interactive_comments 很适合在终端里临时记录命令意图,比如粘贴多行命令时可以保留注释说明。

为什么选择 Zinit

插件管理器我使用的是 Zinit:

ZINIT_HOME="${XDG_DATA_HOME:-${HOME}/.local/share}/zinit/zinit.git"
[[ ! -d "${ZINIT_HOME}" ]] && mkdir -p "$(dirname "${ZINIT_HOME}")"
[[ ! -d "${ZINIT_HOME}/.git" ]] && git clone https://gh-proxy.org/https://github.com/zdharma-continuum/zinit.git "${ZINIT_HOME}"
source "${ZINIT_HOME}/zinit.zsh"

Zinit 的核心价值是:可以精细控制插件加载时机。比如有些插件必须同步加载,有些插件可以延迟 1 秒、2 秒、3 秒再加载;对于启动速度敏感的 Shell 配置来说,这比简单地 source 一堆脚本更可控。

配置里还使用了 GitHub 代理地址,主要是为了在国内网络环境下更稳定地安装 Zinit。你也可以按自己的网络情况替换为官方仓库地址。

先加载 Oh My Zsh 的基础库

我没有直接使用完整的 Oh My Zsh 框架,而是通过 Zinit 按需加载其中的 library 和 plugin。

同步加载的 OMZ library:

for i in theme-and-appearance.zsh git.zsh prompt_info_functions.zsh history.zsh; do
  zinit snippet "OMZL::${i}"
done

延迟加载的 OMZ library:

for i in completion.zsh key-bindings.zsh; do
  zinit ice lucid wait="1"
  zinit snippet "OMZL::${i}"
done

这里的思路是:

类型加载策略原因
theme / git / prompt / history同步加载主题和提示符依赖,越早越好
completion / key-bindings延迟加载对首屏 Prompt 不是硬依赖

补全初始化则交给:

zpcompinit
zpcdreplay

这样可以配合 Zinit 的补全 replay 机制,让插件延迟加载后仍然能正确注册补全。

Powerlevel10k:两行式 Prompt

主题使用 Powerlevel10k:

zinit ice depth=1
zinit light romkatv/powerlevel10k

[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

depth=1 可以减少 clone 体积,只拉取必要历史。

我的 .p10k.zsh 是通过 p10k configure 生成的 rainbow 风格配置,主要特点是:

项目配置
字体Nerd Font v3
风格powerline + rainbow
Prompt两行式
分隔符angled separators
图标small icons / many icons
显示密度sparse、concise

左侧 Prompt 保留最核心的信息:

POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
  os_icon
  dir
  vcs
  newline
  prompt_char
)

右侧 Prompt 则放一些上下文信息,例如命令状态、执行耗时、后台任务、Python 虚拟环境、Kubernetes context、Terraform workspace、云 CLI profile、时间等。

这种布局的优点是:左边只显示当前操作最常用的信息,右边显示“有就看、没有也不影响”的上下文。两行式 Prompt 也能避免路径太长时挤压命令输入区域。

插件设计:按“必要程度”延迟加载

我的插件并不是一股脑同步加载,而是按使用频率和必要程度分层。

插件加载方式用途
command-not-foundwait=0命令不存在时提示可安装的软件包
colored-man-pageswait=3彩色 man 页面
fast-syntax-highlightingasync命令行语法高亮
zsh-autosuggestionsasync + atload基于历史记录的命令建议
sudowait=2双击 Esc 给当前命令加 sudo
zwait=1根据访问频率跳转目录
gitwait=1Git 常用别名与函数
extractwait=1一条命令解压多种格式
kubectlwait=1Kubernetes 别名、补全与辅助函数

其中最影响交互体验的是两个插件:

zinit light zdharma-continuum/fast-syntax-highlighting
zinit light zsh-users/zsh-autosuggestions
  • fast-syntax-highlighting:输入命令时实时高亮,能提前发现命令、路径、参数是否写错。
  • zsh-autosuggestions:根据历史记录给出灰色建议,按右方向键即可补全。

这两个插件会让命令行从“纯文本输入框”变成“带反馈的交互环境”。

文件列表:eza 优先,ls 兜底

我把常用 ls 系列命令封装成了别名,如果系统安装了 eza,就优先使用 eza

if [[ -n "$(command -v eza)" ]]; then
  DISABLE_LS_COLORS=true
  alias ls='eza --color=auto'
  alias l='eza -lbah --icons=auto'
  alias la='eza -labgh --icons=auto'
  alias ll='eza -lbg --icons=auto'
  alias lt='eza -lTbg --icons=auto'
  alias lsa='eza -lbagR --icons=auto'
  alias lst='eza -lTabgh --icons=auto'
else
  alias ls='ls --color=auto'
  alias l='ls -lah'
  alias la='ls -lAh'
  alias ll='ls -lh'
  alias lsa='ls -lah'
  alias lst='tree -pCsh'
fi

常用别名含义如下:

别名作用
l长列表,显示隐藏文件、人类可读大小、图标
la类似 l,但更适合查看权限和分组信息
ll简洁长列表
lt树状展示目录
lsa递归列出所有文件
lst树状递归展示并包含隐藏文件

这里的关键是“有增强工具就增强,没有就优雅降级”。配置可以在新机器上直接使用,不会因为缺少 eza 导致 Shell 启动失败。

路径跳转与目录历史

alias ...=../..
alias ....=../../..
alias .....=../../../..
alias ......=../../../../..

alias 1='cd -'
alias 2='cd -2'
alias 3='cd -3'
# ...一直到 9

这组别名解决两个常见问题:

  1. 多级返回目录时不用反复输入 cd ../../..
  2. 在多个目录之间来回切换时,可以直接用 19 访问目录栈。

配合 OMZ 的 z 插件,可以覆盖两类跳转场景:

  • 已知相对路径:使用 .......
  • 经常访问的目录:使用 z <keyword>

yazi:退出文件管理器后自动 cd

配置中有一个很实用的 y() 函数:

function y() {
  local tmp cwd
  tmp="$(mktemp -t yazi-cwd.XXXXXX)"
  yazi "$@" --cwd-file="$tmp"
  cwd="$(cat -- "$tmp")"
  if [[ -n "$cwd" && "$cwd" != "$PWD" ]]; then
    builtin cd -- "$cwd"
  fi
  rm -f -- "$tmp"
}

普通文件管理器的问题是:你在里面进入了某个目录,但退出后 Shell 仍然停留在原目录。这个函数通过 --cwd-file 记录 yazi 退出时所在目录,然后让当前 Shell 自动 cd 过去。

实际体验就是:

y
# 在 yazi 中进入目标目录
# 退出 yazi 后,Shell 自动切换到那个目录

这比在终端里反复 cdls、再 cd 要顺手很多。

Git、解压、sudo 与搜索

除了视觉和补全,我还保留了一些非常实用的小别名:

alias _='sudo '
alias gc1='git clone --recursive --depth=1'
alias md='mkdir -p'
alias rd='rmdir'
alias afind='ack -il'
alias grep='grep --color=auto'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
别名用途
_快速给命令加 sudo 前缀
gc1浅克隆并递归拉取子模块
md创建多级目录
rd删除空目录
afindack 搜索包含关键词的文件
grep 系列默认开启彩色输出

此外 OMZ 的 extract 插件也很省心:不需要记住 tar.gzzipxzbz2 等格式分别怎么解压,统一用 extract 即可。

代理开关:为国内网络环境准备

alias proxy-on='export http_proxy=http://127.0.0.1:7890 https_proxy=http://127.0.0.1:7890'
alias proxy-off='unset http_proxy https_proxy'

这两个别名适合临时让命令行工具走本地代理,例如拉取 GitHub 仓库、安装依赖、访问国外 API 等。

proxy-on
# 执行需要代理的命令
proxy-off

我没有把代理永久写进环境变量,因为那样容易影响内网服务、容器网络和一些只需要直连的命令。按需开启更可控。

依赖清单

这套配置推荐安装的依赖如下:

依赖必需用途
zshShell 本体
git安装 zinit、拉取插件
zinit插件管理器
powerlevel10kPrompt 主题
Nerd Font正确显示图标和 powerline 符号
eza可选更现代的 ls 替代品
tree可选eza 不存在时作为树状列表兜底
ack可选afind 搜索别名
yazi可选终端文件管理器
kubectl可选Kubernetes 补全与别名
command-not-found可选命令不存在时提示安装包
最小安装只需要:zshgit、Nerd Font。其他工具可以按需补齐。

可复用的安装步骤

如果要在新机器上复用这套配置,可以按这个流程:

# 1. 安装基础依赖
sudo apt update
sudo apt install -y zsh git

# 2. 可选增强工具
sudo apt install -y tree ack

# 3. 安装 eza / yazi 等增强工具
# 不同发行版包名可能不同,可按实际系统调整

# 4. 放置配置文件
cp .zshrc ~/.zshrc
cp .p10k.zsh ~/.p10k.zsh

# 5. 切换默认 Shell
chsh -s "$(command -v zsh)"

首次进入 Zsh 时,配置会自动安装 Zinit,并通过 Zinit 拉取 Powerlevel10k 和插件。

我的取舍

这套配置没有追求“插件越多越好”,而是围绕日常使用做了几个取舍:

  1. 不完整引入 Oh My Zsh:只按需加载 OMZ library 和 plugin,减少框架开销。
  2. Prompt 信息分层:左侧保留目录与 Git,右侧显示环境上下文。
  3. 增强工具必须有 fallbackeza 不存在就退回 ls,避免新机器启动失败。
  4. 代理手动开关:避免代理污染所有命令。
  5. 插件延迟加载:把首屏可交互时间放在第一优先级。

总结

我的 Zsh 配置可以概括为:

  • Zinit:负责插件安装、延迟加载和补全 replay。
  • Powerlevel10k:提供高信息密度、低干扰的两行 Prompt。
  • OMZ snippets:按需复用 Oh My Zsh 的成熟插件生态。
  • eza / yazi / z / autosuggestions:提升文件浏览、目录跳转和命令输入效率。

终端配置是一个长期迭代的系统。最好的配置不是最复杂的配置,而是能让你在每天打开终端时少想一步、少敲几个字、少等几百毫秒的配置。