目标:新电脑快速装好开发环境(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 \
zsh \
python3 python3-pip python3-venv
# 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"
# 4) pipx path
python3 -m pipx ensurepath || true
export PATH="$HOME/.local/bin:$PATH"
# 5) CLIs (no sudo, under nvm-managed Node)
# OpenAI Codex CLI
npm i -g @openai/codex
# Anthropic Claude Code
npm i -g @anthropic-ai/claude-code
# Google Gemini CLI
npm i -g @google/gemini-cli
# 6) quick check
node -v
npm -v
pnpm -v
codex --version || true
claude --version || true
gemini --version || true
echo "Done. Restart your terminal (or re-source your shell rc)"
set -euo pipefail
# 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
# Install starship prompt
curl -fsSL https://starship.rs/install.sh | sh -s -- -y
# Enable starship in zshrc
if ! rg -q "starship init zsh" "$HOME/.zshrc" 2>/dev/null; then
printf '\n# Prompt\neval "$(starship init zsh)"\n' >> "$HOME/.zshrc"
fi
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."
# OpenAI Codex
codex --login
# Claude Code (会提示你登录/配置)
claude
# Gemini CLI
# 运行后根据提示配置(通常需要 Google 登录/或 API key)
gemini
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
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"
# 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
npm i -g @anthropic-ai/claude-code
npm i -g @google/gemini-cli
node -v
npm -v
pnpm -v
python3 --version
java -version
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."
# JetBrains Mono Nerd Font
brew tap homebrew/cask-fonts
brew install --cask font-jetbrains-mono-nerd-font
# 然后在 iTerm2 / Terminal 的 Profile 里切换字体
提示:如果你用 zsh,记得把默认 shell 切到 zsh(macOS 通常默认就是 zsh)。
这页把安装命令固化在静态站里,方便复制粘贴;但各 CLI/依赖版本会变化。如果某条命令报错,优先以对应官方文档为准。