Zsh 一键复刻配置
Zsh 一键复刻配置
本文用于在新 macOS 机器上一键复刻本人当前的 zsh 环境。下方第一节是给 Claude Code 的执行提示词,直接复制粘贴即可;之后是配置快照与人工说明。
适用环境:macOS (Apple Silicon),Homebrew 装在
/opt/homebrew,主目录~ = /Users/<you>。 快照时间:2026-05-20,基于 zsh + Oh My Zsh + Powerlevel10k。
1. 给 Claude Code 的一键复刻指令
把下面这段贴给 Claude Code:
请按 ~/Documents/_work/99_code/blogv2/src/content/docs/toolbox/tools/zsh-setup.md
里"安装清单"和"~/.zshrc 全文"两节,在本机复刻我的 zsh 环境。
约束:
- 不要覆盖已存在文件;先把 ~/.zshrc、~/.zshenv、~/.zprofile 备份成 *.bak.<today>
- 顺序:Homebrew → oh-my-zsh → powerlevel10k 主题 → 两个 zsh 插件
→ nvm/node → uv → bun → pnpm → miniforge → 写 ~/.zshrc / ~/.zshenv / ~/.zprofile
- Homebrew 必须用 USTC 镜像(见 ~/.zshrc 中的 HOMEBREW_* 变量),否则首次拉取会卡死
- 把 ~/.zshrc 替换为本文档"~/.zshrc 全文"那一节里的完整内容
- 替换完成后让我自己运行 `p10k configure` 选样式
- 全程只问我一次:是否需要把全部 brew 软件包(leaves + casks)也装回来
2. 配置组件清单
| 组件 | 作用 | 安装方式 |
|---|---|---|
| Homebrew | 包管理(走 USTC 镜像) | 官方一键脚本 |
| Oh My Zsh | zsh 框架 | 官方一键脚本,仓库在 ~/.oh-my-zsh |
| Powerlevel10k | 主题,含 instant prompt | git clone 到 ~/.oh-my-zsh/custom/themes/powerlevel10k |
| zsh-autosuggestions | 历史补全 | git clone 到 ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions |
| zsh-syntax-highlighting | 命令高亮 | git clone 到 ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting |
| nvm | Node 版本管理(lazy load) | 官方脚本到 ~/.nvm,默认 v24 系列 |
| Go | ~/go 作为 GOPATH | brew |
| uv | 替代 pip,配合 miniforge 解释器 | curl -LsSf https://astral.sh/uv/install.sh | sh |
| Bun | JS runtime | curl -fsSL https://bun.sh/install | bash |
| pnpm | 包管理,PNPM_HOME=~/Library/pnpm | brew |
| Miniforge | conda 系 Python | brew cask / 官方安装包;解释器路径 ~/miniforge3/bin/python |
| Fira Code Nerd Font | P10k 图标字体 | brew install --cask font-fira-code-nerd-font |
当前实测版本(用于排错对照)
- Homebrew 5.1.1
- node v24.14.1
- pnpm 11.1.2
- uv 0.8.14
- go 1.24.1 (darwin/arm64)
文件位置
~/.zshrc主配置(见第 4 节全文)~/.zshenv内容:. "$HOME/.cargo/env"~/.zprofile内容:eval "$(/opt/homebrew/bin/brew shellenv)"~/.p10k.zsh由p10k configure生成,体积约 90KB,可选择从旧机带过来
3. 配置里几个”非显然”的设计
把这些写进 .zshrc 是踩过坑后的成品,迁移时不要轻易删:
-
P10k instant prompt 必须在文件最顶 提示符立即显示,其余 zshrc 在后台加载。删掉会拖慢启动 ~300 ms。
-
zstyle ':omz:update' mode disabled+ZSH_DISABLE_COMPFIX=true关掉 omz 自动更新检查、跳过 compfix 审计,启动再省 ~150 ms。 -
Terminal theme-report stripping (
_disable_terminal_theme_reports) Ghostty / Kiro / cmux 这几个终端会发^[?2031l主题查询序列,泄露到 prompt 会让 P10k 报 “console output” 警告。这段 hook 把首屏跳过、之后逐次清理。 -
nvm lazy-load
nvm.sh加载要 2 秒,所以我只在 PATH 里塞 default 版本的 bin。真正调用nvm命令时再 source 真身。99% 场景不会触发。 -
Homebrew USTC 镜像 国内不走镜像
brew update必卡。HOMEBREW_AUTO_UPDATE_SECS=31536000把自动更新拉到一年一次。 -
uv 接管 pip / venv
alias pip='uv pip'和alias venv='uv venv'让肌肉记忆无缝迁移。 -
claude-upgrade辅助函数 pnpm v11 isolated layout 有 bug,装@anthropic-ai/claude-code时install.cjs会写一个 500B 的桩文件,而不是 198M 的真实二进制。这个函数装完后重新跑一次 install.cjs 修复。 -
Kiro 集成 只在
TERM_PROGRAM == kiro时加载,不污染其它终端。
4. ~/.zshrc 全文
直接覆盖到 ~/.zshrc 即可。
# =============================================================================
# Powerlevel10k Instant Prompt — MUST be at the top
# =============================================================================
# Lets the prompt appear immediately while the rest of zshrc loads in background.
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
# =============================================================================
# Oh My Zsh + Powerlevel10k
# =============================================================================
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="powerlevel10k/powerlevel10k"
# Skip omz auto-update check on startup (run `omz update` manually when needed)
zstyle ':omz:update' mode disabled
# Skip compfix audit (we trust our completions; saves ~150 ms)
ZSH_DISABLE_COMPFIX=true
plugins=(
git
zsh-syntax-highlighting
zsh-autosuggestions
)
source $ZSH/oh-my-zsh.sh
# Powerlevel10k user config (created by `p10k configure` wizard).
[[ -f ~/.p10k.zsh ]] && source ~/.p10k.zsh
# =============================================================================
# Terminal theme-report stripping (Ghostty / Kiro / cmux compatibility)
# =============================================================================
typeset -g _DTR_FIRST_DONE=
function _disable_terminal_theme_reports() {
[[ -o interactive ]] || return 0
# Skip the first precmd: it fires inside P10k's instant-prompt capture
# window and the escape would trip the "console output" warning.
if [[ -z $_DTR_FIRST_DONE ]]; then
_DTR_FIRST_DONE=1
return 0
fi
printf '\e[?2031l'
}
function _strip_terminal_theme_report_and_accept_line() {
local compact="$BUFFER"
compact=${compact// /}
compact=${compact//$'\t'/}
compact=${compact//$'\r'/}
compact=${compact//$'\n'/}
if [[ "$compact" =~ '^(\??997;[12]n)+$' ]]; then
BUFFER=""
CURSOR=0
zle redisplay
return 0
fi
zle .accept-line
}
autoload -Uz add-zsh-hook
if [[ -o interactive ]]; then
add-zsh-hook precmd _disable_terminal_theme_reports
zle -N accept-line _strip_terminal_theme_report_and_accept_line
fi
# =============================================================================
# Homebrew (China mirrors via USTC)
# =============================================================================
export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.ustc.edu.cn/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.ustc.edu.cn/homebrew-core.git"
export HOMEBREW_API_DOMAIN="https://mirrors.ustc.edu.cn/api/homebrew/core"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.ustc.edu.cn/homebrew-bottles"
export HOMEBREW_AUTO_UPDATE_SECS=31536000
# =============================================================================
# Node via NVM — lazy-load
# =============================================================================
# Strategy: prepend the default node version's bin to PATH so node/npm/npx
# work instantly. Only when you actually call `nvm` itself does nvm.sh load
# (saves ~2000 ms of startup). 99% of users never call nvm directly.
export NVM_DIR="$HOME/.nvm"
# Resolve default version alias to a concrete version dir
__nvm_default_alias=$(<"$NVM_DIR/alias/default" 2>/dev/null)
if [ -n "$__nvm_default_alias" ]; then
if [[ "$__nvm_default_alias" == v* ]]; then
__nvm_default_version="$__nvm_default_alias"
else
__nvm_default_version=$(ls -1 "$NVM_DIR/versions/node" 2>/dev/null \
| grep "^v${__nvm_default_alias}" | sort -V | tail -1)
fi
if [ -n "$__nvm_default_version" ] \
&& [ -d "$NVM_DIR/versions/node/$__nvm_default_version/bin" ]; then
export PATH="$NVM_DIR/versions/node/$__nvm_default_version/bin:$PATH"
fi
fi
unset __nvm_default_alias __nvm_default_version
# Lazy nvm: first call to `nvm` sources nvm.sh, then re-runs the call
nvm() {
unset -f nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
nvm "$@"
}
# =============================================================================
# Go
# =============================================================================
export GOPATH="$HOME/go"
export PATH="$PATH:$GOPATH/bin"
# =============================================================================
# uv (Python — replaces pip in muscle memory)
# =============================================================================
[ -s "$HOME/.local/bin/env" ] && . "$HOME/.local/bin/env"
alias pip='uv pip'
alias venv='uv venv'
# =============================================================================
# Bun
# =============================================================================
export BUN_INSTALL="$HOME/.bun"
export PATH="$BUN_INSTALL/bin:$PATH"
[ -s "$HOME/.bun/_bun" ] && source "$HOME/.bun/_bun"
# =============================================================================
# Antigravity
# =============================================================================
export PATH="$HOME/.antigravity/antigravity/bin:$PATH"
# =============================================================================
# pnpm
# =============================================================================
export PNPM_HOME="$HOME/Library/pnpm"
case ":$PATH:" in
*":$PNPM_HOME:"*) ;;
*) export PATH="$PNPM_HOME:$PATH" ;;
esac
# =============================================================================
# Kiro IDE shell integration (only when running inside Kiro)
# =============================================================================
[[ "$TERM_PROGRAM" == "kiro" ]] && . "$(kiro --locate-shell-integration-path zsh)"
# =============================================================================
# Miniforge / conda — Python ecosystem
# =============================================================================
export MINIFORGE_HOME="$HOME/miniforge3"
export MINIFORGE_PYTHON="$MINIFORGE_HOME/bin/python"
export PIPX_DEFAULT_PYTHON="$MINIFORGE_PYTHON"
export UV_PYTHON="$MINIFORGE_PYTHON"
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/weigao/miniforge3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/Users/weigao/miniforge3/etc/profile.d/conda.sh" ]; then
. "/Users/weigao/miniforge3/etc/profile.d/conda.sh"
else
export PATH="/Users/weigao/miniforge3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
# =============================================================================
# claude-code upgrade helper
# =============================================================================
# Works around pnpm v11 isolated-layout bug where install.cjs writes a 500B
# stub instead of the 198M native binary. Re-running install.cjs after install
# completes fixes it.
claude-upgrade() {
pnpm i -g @anthropic-ai/claude-code "$@" || return
local installer
installer=$(find ~/Library/pnpm/global -path '*claude-code/install.cjs' 2>/dev/null | head -1)
if [ -n "$installer" ]; then
node "$installer"
fi
command claude --version
}
5. ~/.zshenv 和 ~/.zprofile
# ~/.zshenv
. "$HOME/.cargo/env"
# ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
6. 手动安装命令(Claude Code 失败时备用)
# 1. Homebrew(先 export 镜像变量再装,否则会卡 GitHub)
export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.ustc.edu.cn/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.ustc.edu.cn/homebrew-core.git"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 2. Oh My Zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
# 3. Powerlevel10k + 两个插件
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
git clone https://github.com/zsh-users/zsh-autosuggestions \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
# 4. Nerd Font(P10k 图标)
brew install --cask font-fira-code-nerd-font
# 5. nvm + node
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install --lts && nvm alias default lts/*
# 6. uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# 7. bun
curl -fsSL https://bun.sh/install | bash
# 8. pnpm / go
brew install pnpm go
# 9. miniforge
brew install --cask miniforge
conda init zsh
# 10. 覆盖 ~/.zshrc 为本文档第 4 节内容,然后
exec zsh
p10k configure # 走一遍向导,生成 ~/.p10k.zsh
7. 善后检查清单
-
echo $SHELL是/bin/zsh - 终端用了 Nerd Font(否则 P10k 图标会乱码)
-
which node指向~/.nvm/versions/node/v*/bin/node -
which python指向 conda env,uv --version可用 -
claude-upgrade函数可调用(type claude-upgrade) - 启动时间合理:
time zsh -i -c exit< 300 ms
修改历史1 次提交
- content(ingest): AI 推理系列 4 篇 + Zsh 一键复刻配置xiaocheng··
be9ef88