目标:新电脑快速装好开发环境(git、zsh、node/pnpm、python、java、常用工具),并安装 codex/claude/gemini CLI 与 WezTerm(含统一配色/快捷键)。建议先读每段脚本的注释再执行。
wsl --install -d Ubuntu
wsl --update
wsl --set-default-version 2
# 安装完成后,打开“Ubuntu”应用并创建 Linux 用户
# 然后在 Ubuntu 里执行本页的“Ubuntu/Debian”脚本
# 1) install WezTerm
winget install --id Wez.WezTerm -e --source winget
# 2) set your WSL distro name (check with: wsl -l -q)
$WslDistro = "Ubuntu-24.04"
# 3) write WezTerm config
$cfgDir = Join-Path $HOME ".config\wezterm"
New-Item -ItemType Directory -Force -Path $cfgDir | Out-Null
@"
local wezterm = require 'wezterm'
local act = wezterm.action
local config = wezterm.config_builder()
config.default_domain = 'WSL:$WslDistro'
config.front_end = 'WebGpu'
config.webgpu_power_preference = 'HighPerformance'
config.color_scheme = 'Tokyo Night'
config.font = wezterm.font('JetBrains Mono', { weight = 'Regular' })
config.font_size = 13.0
config.line_height = 1.2
config.initial_cols = 160
config.initial_rows = 40
config.window_padding = { left = 12, right = 12, top = 10, bottom = 10 }
config.window_background_opacity = 1.0
config.colors = { background = '#000000' }
config.window_decorations = 'TITLE | RESIZE'
config.adjust_window_size_when_changing_font_size = false
config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = true
config.hide_tab_bar_if_only_one_tab = true
config.tab_max_width = 30
config.scrollback_lines = 10000
config.automatically_reload_config = true
config.disable_default_key_bindings = true
config.mouse_bindings = {
{
event = { Down = { streak = 1, button = 'Right' } },
mods = 'NONE',
action = act.PasteFrom 'Clipboard',
},
}
config.keys = {
{ key = 'phys:C', mods = 'CTRL', action = act.CopyTo 'Clipboard' },
{ key = 'phys:V', mods = 'CTRL', action = act.PasteFrom 'Clipboard' },
{ key = 'phys:C', mods = 'CTRL|SHIFT', action = act.SendKey { key = 'c', mods = 'CTRL' } },
{ key = 't', mods = 'CTRL|SHIFT', action = act.SpawnTab 'CurrentPaneDomain' },
{ key = 'w', mods = 'CTRL|SHIFT', action = act.CloseCurrentTab { confirm = false } },
{ key = '[', mods = 'CTRL|SHIFT', action = act.ActivateTabRelative(-1) },
{ key = ']', mods = 'CTRL|SHIFT', action = act.ActivateTabRelative(1) },
{ key = 'r', mods = 'CTRL|SHIFT', action = act.PromptInputLine {
description = 'Rename tab:',
action = wezterm.action_callback(function(window, _, line)
if line then window:active_tab():set_title(line) end
end),
}},
{ key = 'd', mods = 'CTRL|SHIFT', action = act.SplitHorizontal { domain = 'CurrentPaneDomain' } },
{ key = 'e', mods = 'CTRL|SHIFT', action = act.SplitVertical { domain = 'CurrentPaneDomain' } },
{ key = 'h', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Left' },
{ key = 'l', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Right' },
{ key = 'k', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Up' },
{ key = 'j', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Down' },
{ key = 'f', mods = 'CTRL|SHIFT', action = act.Search 'CurrentSelectionOrEmptyString' },
{ key = 'x', mods = 'CTRL|SHIFT', action = act.ActivateCopyMode },
{ key = '=', mods = 'CTRL', action = act.IncreaseFontSize },
{ key = '-', mods = 'CTRL', action = act.DecreaseFontSize },
{ key = '0', mods = 'CTRL', action = act.ResetFontSize },
{ key = 'n', mods = 'CTRL|SHIFT', action = act.SpawnWindow },
{ key = 'p', mods = 'CTRL|SHIFT', action = act.ActivateCommandPalette },
{ key = 'Enter', mods = 'ALT', action = act.ToggleFullScreen },
}
return config
"@ | Set-Content -Path (Join-Path $cfgDir "wezterm.lua") -Encoding UTF8
@"
local wezterm = require 'wezterm'
return dofile(wezterm.home_dir .. '/.config/wezterm/wezterm.lua')
"@ | Set-Content -Path (Join-Path $HOME ".wezterm.lua") -Encoding UTF8
# 4) restart WezTerm
taskkill /F /IM wezterm-gui.exe 2>$null
Start-Process wezterm-gui.exe
字体建议(在 Windows Terminal 设置里改):JetBrainsMono Nerd Font 或 MesloLGS Nerd Font。
set -euo pipefail
# 0) base packages
sudo apt-get update
sudo apt-get install -y \
git curl wget ca-certificates gnupg \
build-essential unzip zip \
jq ripgrep fzf bat fd-find htop tree \
eza zoxide neovim \
zsh \
python3 python3-pip python3-venv
# GitHub CLI
if ! command -v gh >/dev/null 2>&1; then
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt-get update
sudo apt-get install -y gh
fi
# pipx: apt first, fallback to user install
if ! command -v pipx >/dev/null 2>&1; then
sudo apt-get install -y pipx || python3 -m pip install --user --break-system-packages pipx
fi
# Java: prefer OpenJDK 21, fallback to default-jdk
if apt-cache show openjdk-21-jdk-headless >/dev/null 2>&1; then
sudo apt-get install -y openjdk-21-jdk-headless
else
sudo apt-get install -y default-jdk-headless || true
fi
# 1) nvm (Node.js) - latest LTS
if [ ! -d "$HOME/.nvm" ]; then
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
fi
export NVM_DIR="$HOME/.nvm"
# shellcheck disable=SC1091
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install --lts
nvm use --lts
# 2) pnpm via corepack
corepack enable
corepack prepare pnpm@latest --activate
# 3) sdkman (Java manager) - optional but useful
if [ ! -d "$HOME/.sdkman" ]; then
curl -s "https://get.sdkman.io" | bash
fi
# shellcheck disable=SC1091
[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ] && . "$HOME/.sdkman/bin/sdkman-init.sh"
# Rust toolchain (rustup)
if ! command -v rustc >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
fi
# 4) pipx path
python3 -m pipx ensurepath || true
export PATH="$HOME/.local/bin:$PATH"
# Debian/Ubuntu package names expose bat/fd as batcat/fdfind.
mkdir -p "$HOME/.local/bin"
if command -v batcat >/dev/null 2>&1 && ! command -v bat >/dev/null 2>&1; then
ln -sf "$(command -v batcat)" "$HOME/.local/bin/bat"
fi
if command -v fdfind >/dev/null 2>&1 && ! command -v fd >/dev/null 2>&1; then
ln -sf "$(command -v fdfind)" "$HOME/.local/bin/fd"
fi
# uv (fast Python package manager)
if ! command -v uv >/dev/null 2>&1; then
curl -LsSf https://astral.sh/uv/install.sh | sh
fi
# 5) CLIs (no sudo, under nvm-managed Node)
# OpenAI Codex CLI
npm i -g @openai/codex
# Anthropic Claude Code (standalone installer)
if ! command -v claude >/dev/null 2>&1; then
curl -fsSL https://claude.ai/install.sh | sh
fi
# Google Gemini CLI
npm i -g @google/gemini-cli
npm i -g wrangler
# Python SDKs
python3 -m pip install --user anthropic openai google-genai
# Google Chrome
if ! command -v google-chrome >/dev/null 2>&1; then
curl -fsSL https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /tmp/chrome.deb
sudo dpkg -i /tmp/chrome.deb || sudo apt-get install -f -y
rm -f /tmp/chrome.deb
fi
# Docker
if ! command -v docker >/dev/null 2>&1; then
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER"
fi
# Set zsh as default shell
if [ "$SHELL" != "$(which zsh)" ]; then
chsh -s "$(which zsh)"
fi
# 6) quick check
node -v
npm -v
pnpm -v
gh --version || true
docker --version || true
bat --version || true
uv --version || true
rustc --version || true
codex --version || true
claude --version || true
gemini --version || true
echo "Done. Restart your terminal (or re-source your shell rc)"
set -euo pipefail
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
ZSHRC="$HOME/.zshrc"
START_MARK="# --- terminal-html zsh setup start ---"
END_MARK="# --- terminal-html zsh setup end ---"
# Install oh-my-zsh (non-interactive)
if [ ! -d "$HOME/.oh-my-zsh" ]; then
RUNZSH=no CHSH=no KEEP_ZSHRC=yes \
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
fi
# Plugin directories
mkdir -p "$ZSH_CUSTOM/plugins"
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]; then
git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
fi
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]; then
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
fi
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-completions" ]; then
git clone https://github.com/zsh-users/zsh-completions "$ZSH_CUSTOM/plugins/zsh-completions"
fi
# Prompt + modern shell tools
curl -sS https://starship.rs/install.sh | sh
if ! command -v zoxide >/dev/null 2>&1; then
if apt-cache show zoxide >/dev/null 2>&1; then
sudo apt-get install -y zoxide
else
command -v cargo >/dev/null 2>&1 || sudo apt-get install -y cargo
cargo install zoxide --locked
fi
fi
if ! command -v eza >/dev/null 2>&1; then
if apt-cache show eza >/dev/null 2>&1; then
sudo apt-get install -y eza
else
command -v cargo >/dev/null 2>&1 || sudo apt-get install -y cargo
cargo install eza
fi
fi
touch "$ZSHRC"
if grep -Fq "$START_MARK" "$ZSHRC"; then
sed -i "/$START_MARK/,/$END_MARK/d" "$ZSHRC"
fi
cat >> "$ZSHRC" <<'EOF'
# --- terminal-html zsh setup start ---
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="" # disabled: starship overrides the prompt
# Performance: set before plugins load
ZSH_AUTOSUGGEST_USE_ASYNC=1
ZSH_AUTOSUGGEST_MANUAL_REBIND=1
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20
ZSH_HIGHLIGHT_MAXLENGTH=200
plugins=(
git
sudo
history
zsh-autosuggestions
zsh-syntax-highlighting
zsh-completions
)
source $ZSH/oh-my-zsh.sh
# Avoid XON/XOFF flow control freezing input when Ctrl-S is pressed.
stty -ixon 2>/dev/null
# PATH
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH"
# Aliases
alias ll="eza -la --icons --git 2>/dev/null || ls -la"
alias lt="eza --tree --level=2 --icons 2>/dev/null || tree -L 2"
alias gs="git status"
alias gp="git pull"
alias gd="git diff"
alias gl="git log --oneline --graph --decorate -20"
alias vim="nvim"
alias g="git"
# AI CLI shortcuts
alias cl="claude --dangerously-skip-permissions"
alias co="codex --dangerously-bypass-approvals-and-sandbox"
alias gm="gemini"
# Starship
eval "$(starship init zsh)"
# Zoxide
eval "$(zoxide init zsh)"
# WezTerm shell integration
[ -f "$HOME/.config/wezterm/wezterm-shell.sh" ] && source "$HOME/.config/wezterm/wezterm-shell.sh"
# --- terminal-html zsh setup end ---
EOF
echo "Optional: set your terminal font to a Nerd Font (JetBrainsMono Nerd Font / MesloLGS Nerd Font)."
set -euo pipefail
if ! grep -qiE "(microsoft|wsl)" /proc/version; then
echo "This block is for WSL only."
exit 1
fi
WIN_USER="${WIN_USER:-$(cmd.exe /c "echo %USERNAME%" | tr -d '\r')}"
WSL_DISTRO="${WSL_DISTRO_NAME:-Ubuntu-24.04}"
WIN_HOME="/mnt/c/Users/$WIN_USER"
CFG_DIR="$WIN_HOME/.config/wezterm"
mkdir -p "$CFG_DIR"
cat > "$CFG_DIR/wezterm.lua" <<LUA
local wezterm = require 'wezterm'
local act = wezterm.action
local config = wezterm.config_builder()
config.default_domain = 'WSL:$WSL_DISTRO'
config.front_end = 'WebGpu'
config.webgpu_power_preference = 'HighPerformance'
config.color_scheme = 'Tokyo Night'
config.font = wezterm.font('JetBrains Mono', { weight = 'Regular' })
config.font_size = 13.0
config.line_height = 1.2
config.initial_cols = 160
config.initial_rows = 40
config.window_padding = { left = 12, right = 12, top = 10, bottom = 10 }
config.window_background_opacity = 1.0
config.colors = { background = '#000000' }
config.window_decorations = 'TITLE | RESIZE'
config.adjust_window_size_when_changing_font_size = false
config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = true
config.hide_tab_bar_if_only_one_tab = true
config.tab_max_width = 30
config.scrollback_lines = 10000
config.automatically_reload_config = true
config.disable_default_key_bindings = true
config.mouse_bindings = {
{
event = { Down = { streak = 1, button = 'Right' } },
mods = 'NONE',
action = act.PasteFrom 'Clipboard',
},
}
config.keys = {
{ key = 'phys:C', mods = 'CTRL', action = act.CopyTo 'Clipboard' },
{ key = 'phys:V', mods = 'CTRL', action = act.PasteFrom 'Clipboard' },
{ key = 'phys:C', mods = 'CTRL|SHIFT', action = act.SendKey { key = 'c', mods = 'CTRL' } },
{ key = 't', mods = 'CTRL|SHIFT', action = act.SpawnTab 'CurrentPaneDomain' },
{ key = 'w', mods = 'CTRL|SHIFT', action = act.CloseCurrentTab { confirm = false } },
{ key = '[', mods = 'CTRL|SHIFT', action = act.ActivateTabRelative(-1) },
{ key = ']', mods = 'CTRL|SHIFT', action = act.ActivateTabRelative(1) },
{ key = 'r', mods = 'CTRL|SHIFT', action = act.PromptInputLine {
description = 'Rename tab:',
action = wezterm.action_callback(function(window, _, line)
if line then window:active_tab():set_title(line) end
end),
}},
{ key = 'd', mods = 'CTRL|SHIFT', action = act.SplitHorizontal { domain = 'CurrentPaneDomain' } },
{ key = 'e', mods = 'CTRL|SHIFT', action = act.SplitVertical { domain = 'CurrentPaneDomain' } },
{ key = 'h', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Left' },
{ key = 'l', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Right' },
{ key = 'k', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Up' },
{ key = 'j', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Down' },
{ key = 'f', mods = 'CTRL|SHIFT', action = act.Search 'CurrentSelectionOrEmptyString' },
{ key = 'x', mods = 'CTRL|SHIFT', action = act.ActivateCopyMode },
{ key = '=', mods = 'CTRL', action = act.IncreaseFontSize },
{ key = '-', mods = 'CTRL', action = act.DecreaseFontSize },
{ key = '0', mods = 'CTRL', action = act.ResetFontSize },
{ key = 'n', mods = 'CTRL|SHIFT', action = act.SpawnWindow },
{ key = 'p', mods = 'CTRL|SHIFT', action = act.ActivateCommandPalette },
{ key = 'Enter', mods = 'ALT', action = act.ToggleFullScreen },
}
return config
LUA
cat > "$WIN_HOME/.wezterm.lua" <<'LUA'
local wezterm = require 'wezterm'
return dofile(wezterm.home_dir .. '/.config/wezterm/wezterm.lua')
LUA
echo "WezTerm config written to: $CFG_DIR/wezterm.lua"
echo "Restart WezTerm on Windows to apply changes."
# GitHub CLI
gh auth login
# OpenAI Codex
codex login
# Claude Code (会提示你登录/配置)
claude
# Cloudflare Wrangler
wrangler login
# Gemini CLI
# 运行后根据提示配置(通常需要 Google 登录/或 API key)
gemini
# Git global config
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
git config --global init.defaultBranch main
git config --global pull.rebase false
# Generate SSH key (if none exists)
if [ ! -f "$HOME/.ssh/id_ed25519" ]; then
ssh-keygen -t ed25519 -C "your@email.com" -f "$HOME/.ssh/id_ed25519" -N ""
fi
# Print public key — add this to GitHub > Settings > SSH keys
cat "$HOME/.ssh/id_ed25519.pub"
# Test GitHub SSH connection
ssh -T git@github.com 2>&1 || true
# Only run inside WSL
if ! grep -qiE "(microsoft|wsl)" /proc/version 2>/dev/null; then
echo "Not WSL, skipping."
exit 0
fi
# /etc/wsl.conf — disable auto Windows PATH, enable systemd
sudo tee /etc/wsl.conf > /dev/null <<'CONF'
[interop]
appendWindowsPath = false
[boot]
systemd = true
[automount]
enabled = true
options = "metadata,umask=22,fmask=11"
CONF
# Resolve the current Windows username once, then write concrete paths into .zshrc.
WIN_USER="$(cmd.exe /c "echo %USERNAME%" | tr -d '\r')"
WIN_VSCODE_PATH="/mnt/c/Users/$WIN_USER/AppData/Local/Programs/Microsoft VS Code/bin"
# Add selective Windows paths to .zshrc (if not already present)
if ! grep -q "Selective Windows paths" "$HOME/.zshrc" 2>/dev/null; then
{
printf '\n# Selective Windows paths (appendWindowsPath=false in wsl.conf)\n'
printf 'export PATH="$PATH:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS"\n'
printf 'export PATH="$PATH:%s"\n' "$WIN_VSCODE_PATH"
printf 'export PATH="$PATH:/mnt/c/Program Files/Docker/Docker/resources/bin"\n'
} >> "$HOME/.zshrc"
fi
echo "WSL configured. Run 'wsl --shutdown' in PowerShell, then restart."
set -euo pipefail
# Xcode CLI tools
xcode-select --install || true
# Homebrew
if ! command -v brew >/dev/null 2>&1; then
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
# ensure brew is in PATH for this shell session
if [ -x /opt/homebrew/bin/brew ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [ -x /usr/local/bin/brew ]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
brew update
brew install git jq ripgrep fzf zsh starship python pipx openjdk@21 neovim eza zoxide uv bat fd gh htop tree
# Desktop apps
brew install --cask google-chrome alt-tab docker
python3 -m pipx ensurepath || true
export PATH="$HOME/.local/bin:$PATH"
OPENJDK_PREFIX="$(brew --prefix openjdk@21 2>/dev/null || true)"
[ -n "$OPENJDK_PREFIX" ] && export PATH="$OPENJDK_PREFIX/bin:$PATH"
# Rust toolchain
if ! command -v rustc >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
fi
# Node via nvm
if [ ! -d "$HOME/.nvm" ]; then
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
fi
export NVM_DIR="$HOME/.nvm"
# shellcheck disable=SC1091
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm install --lts
nvm use --lts
corepack enable
corepack prepare pnpm@latest --activate
# CLIs (no sudo)
npm i -g @openai/codex
# Anthropic Claude Code (standalone installer)
if ! command -v claude >/dev/null 2>&1; then
curl -fsSL https://claude.ai/install.sh | sh
fi
npm i -g @google/gemini-cli
npm i -g wrangler
python3 -m pip install --user anthropic openai google-genai
# Set zsh as default shell (macOS default is already zsh, but just in case)
if [ "$SHELL" != "$(which zsh)" ]; then
chsh -s "$(which zsh)"
fi
node -v
npm -v
pnpm -v
python3 --version
java -version
gh --version || true
docker --version || true
uv --version || true
rustc --version || true
codex --version || true
claude --version || true
gemini --version || true
set -euo pipefail
if [ -x /opt/homebrew/bin/brew ]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [ -x /usr/local/bin/brew ]; then
eval "$(/usr/local/bin/brew shellenv)"
fi
brew install --cask wezterm
cat > "$HOME/.wezterm.lua" <<'LUA'
local wezterm = require 'wezterm'
local act = wezterm.action
local config = wezterm.config_builder()
config.front_end = 'WebGpu'
config.webgpu_power_preference = 'HighPerformance'
config.color_scheme = 'Tokyo Night'
config.font = wezterm.font('JetBrains Mono', { weight = 'Regular' })
config.font_size = 13.0
config.line_height = 1.2
config.initial_cols = 160
config.initial_rows = 40
config.window_padding = { left = 12, right = 12, top = 10, bottom = 10 }
config.window_background_opacity = 1.0
config.colors = { background = '#000000' }
config.window_decorations = 'TITLE | RESIZE'
config.adjust_window_size_when_changing_font_size = false
config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = true
config.hide_tab_bar_if_only_one_tab = true
config.tab_max_width = 30
config.scrollback_lines = 10000
config.automatically_reload_config = true
config.disable_default_key_bindings = true
config.mouse_bindings = {
{
event = { Down = { streak = 1, button = 'Right' } },
mods = 'NONE',
action = act.PasteFrom 'Clipboard',
},
}
config.keys = {
{ key = 'phys:C', mods = 'CTRL', action = act.CopyTo 'Clipboard' },
{ key = 'phys:V', mods = 'CTRL', action = act.PasteFrom 'Clipboard' },
{ key = 'phys:C', mods = 'CTRL|SHIFT', action = act.SendKey { key = 'c', mods = 'CTRL' } },
{ key = 't', mods = 'CTRL|SHIFT', action = act.SpawnTab 'CurrentPaneDomain' },
{ key = 'w', mods = 'CTRL|SHIFT', action = act.CloseCurrentTab { confirm = false } },
{ key = '[', mods = 'CTRL|SHIFT', action = act.ActivateTabRelative(-1) },
{ key = ']', mods = 'CTRL|SHIFT', action = act.ActivateTabRelative(1) },
{ key = 'r', mods = 'CTRL|SHIFT', action = act.PromptInputLine {
description = 'Rename tab:',
action = wezterm.action_callback(function(window, _, line)
if line then window:active_tab():set_title(line) end
end),
}},
{ key = 'd', mods = 'CTRL|SHIFT', action = act.SplitHorizontal { domain = 'CurrentPaneDomain' } },
{ key = 'e', mods = 'CTRL|SHIFT', action = act.SplitVertical { domain = 'CurrentPaneDomain' } },
{ key = 'h', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Left' },
{ key = 'l', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Right' },
{ key = 'k', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Up' },
{ key = 'j', mods = 'CTRL|SHIFT', action = act.ActivatePaneDirection 'Down' },
{ key = 'f', mods = 'CTRL|SHIFT', action = act.Search 'CurrentSelectionOrEmptyString' },
{ key = 'x', mods = 'CTRL|SHIFT', action = act.ActivateCopyMode },
{ key = '=', mods = 'CTRL', action = act.IncreaseFontSize },
{ key = '-', mods = 'CTRL', action = act.DecreaseFontSize },
{ key = '0', mods = 'CTRL', action = act.ResetFontSize },
{ key = 'n', mods = 'CTRL|SHIFT', action = act.SpawnWindow },
{ key = 'p', mods = 'CTRL|SHIFT', action = act.ActivateCommandPalette },
{ key = 'Enter', mods = 'ALT', action = act.ToggleFullScreen },
}
return config
LUA
echo "WezTerm configured at $HOME/.wezterm.lua"
echo "Restart WezTerm to apply."
set -euo pipefail
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
ZSHRC="$HOME/.zshrc"
START_MARK="# --- terminal-html zsh setup start ---"
END_MARK="# --- terminal-html zsh setup end ---"
# Install oh-my-zsh (non-interactive)
if [ ! -d "$HOME/.oh-my-zsh" ]; then
RUNZSH=no CHSH=no KEEP_ZSHRC=yes \
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
fi
# Plugin directories
mkdir -p "$ZSH_CUSTOM/plugins"
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]; then
git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
fi
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]; then
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
fi
if [ ! -d "$ZSH_CUSTOM/plugins/zsh-completions" ]; then
git clone https://github.com/zsh-users/zsh-completions "$ZSH_CUSTOM/plugins/zsh-completions"
fi
# Prompt + modern shell tools
if ! command -v starship >/dev/null 2>&1; then
curl -sS https://starship.rs/install.sh | sh
fi
if ! command -v zoxide >/dev/null 2>&1; then
brew install zoxide
fi
if ! command -v eza >/dev/null 2>&1; then
brew install eza
fi
touch "$ZSHRC"
if grep -Fq "$START_MARK" "$ZSHRC"; then
sed -i '' "/$START_MARK/,/$END_MARK/d" "$ZSHRC"
fi
cat >> "$ZSHRC" <<'EOF'
# --- terminal-html zsh setup start ---
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="" # disabled: starship overrides the prompt
# Performance: set before plugins load
ZSH_AUTOSUGGEST_USE_ASYNC=1
ZSH_AUTOSUGGEST_MANUAL_REBIND=1
ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=20
ZSH_HIGHLIGHT_MAXLENGTH=200
plugins=(
git
sudo
history
zsh-autosuggestions
zsh-syntax-highlighting
zsh-completions
)
source $ZSH/oh-my-zsh.sh
# Avoid XON/XOFF flow control freezing input when Ctrl-S is pressed.
stty -ixon 2>/dev/null
# PATH
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH"
# Aliases
alias ll="eza -la --icons --git 2>/dev/null || ls -la"
alias lt="eza --tree --level=2 --icons 2>/dev/null || tree -L 2"
alias gs="git status"
alias gp="git pull"
alias gd="git diff"
alias gl="git log --oneline --graph --decorate -20"
alias vim="nvim"
alias g="git"
# AI CLI shortcuts
alias cl="claude --dangerously-skip-permissions"
alias co="codex --dangerously-bypass-approvals-and-sandbox"
alias gm="gemini"
# Starship
eval "$(starship init zsh)"
# Zoxide
eval "$(zoxide init zsh)"
# WezTerm shell integration
[ -f "$HOME/.config/wezterm/wezterm-shell.sh" ] && source "$HOME/.config/wezterm/wezterm-shell.sh"
# --- terminal-html zsh setup end ---
EOF
echo "Optional: set your terminal font to a Nerd Font (JetBrainsMono Nerd Font / MesloLGS Nerd Font)."
# JetBrains Mono Nerd Font
brew install font-jetbrains-mono-nerd-font
# 然后在 iTerm2 / Terminal 的 Profile 里切换字体
# Git global config
git config --global user.name "Your Name"
git config --global user.email "your@email.com"
git config --global init.defaultBranch main
git config --global pull.rebase false
# Generate SSH key (if none exists)
if [ ! -f "$HOME/.ssh/id_ed25519" ]; then
ssh-keygen -t ed25519 -C "your@email.com" -f "$HOME/.ssh/id_ed25519" -N ""
fi
# Print public key — add this to GitHub > Settings > SSH keys
cat "$HOME/.ssh/id_ed25519.pub"
# Test GitHub SSH connection
ssh -T git@github.com 2>&1 || true
提示:如果你用 zsh,记得把默认 shell 切到 zsh(macOS 通常默认就是 zsh)。
这页把安装命令固化在静态站里,方便复制粘贴;但各 CLI/依赖版本会变化。如果某条命令报错,优先以对应官方文档为准。