最后活跃于 3 weeks ago

Interactive developer environment bootstrapper for Zsh/Bash with repeatable workstation setup helpers.

修订 9d24e57a773090c3a07f65d441bbcad15da6c99c

README.md 原始文件

Strict Developer Environment Installer

A robust, idempotent, and interactive bash script to bootstrap your macOS, Linux, or WSL development environment.

Unlike standard setup scripts that rely heavily on package managers like Homebrew or Apt (which can introduce bloat, dependency hell, or outdated packages), this script is designed with a "Strict Official Source" philosophy. It dynamically fetches the absolute latest binaries and pre-compiled releases directly from the official maintainers (e.g., GitHub API, Python.org, Amazon).

✨ Key Features

  • Zero-Brew Dependency: By default, it bypasses Homebrew entirely, fetching tools directly from official APIs and release pages (Homebrew is available as an optional install).
  • Idempotent: Safe to run multiple times. It intelligently checks if a tool is already installed before attempting to download it.
  • Dynamic Versioning: Pings official APIs (like GitHub Releases or go.dev/VERSION) to ensure you are downloading the exact latest version at the time of execution.
  • Auto-Path Management: Intelligently injects paths into a dedicated ~/.pathrc (or your .bashrc/.zshrc) without mangling your config files.
  • Architecture Aware: Automatically detects if you are running on Intel (x86_64) or Apple Silicon/ARM (aarch64/arm64) and downloads the correct binaries.

🚀 Usage

You can launch the interactive installer directly from your terminal with a single command:

bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/af1c64c143a44ffbb0a1632dd6a32af1/raw/HEAD/menu.sh)"

Once the menu loads, simply follow the interactive prompts. You can select multiple tools at once by entering space-separated numbers (e.g., 1 3 8 12).

🛠️ Included Tools

Core Runtimes & Managers

  • Build Tools: GCC, Make, Git, Curl, Unzip, and core libraries.
  • Homebrew: (Optional) Installed officially.
  • NVM (Node Version Manager): Includes interactive prompt to install LTS or Latest Node.js immediately.
  • Python 3: Fetches the latest stable .pkg for Mac or compiles strictly from source for Linux.
  • Go: Fetches the latest tarball and installs system-wide to /usr/local/go.
  • SDKMAN: For managing Java, Kotlin, and Gradle.
  • .NET: Installed via Microsoft's official script.

Cloud & Infrastructure

  • Docker: Downloads the official .dmg (macOS) or runs the official get.docker.com script (Linux) with auto-group assignment.
  • AWS CLI: Fetches the official binaries directly from Amazon.
  • Google Cloud CLI (gcloud): Official Google setup script.
  • Firebase CLI: Standalone binary (no Node.js required natively).

Dev Tools & Security

  • GitHub CLI (gh): Downloaded directly from GitHub Releases to /usr/local/bin.
  • Infisical CLI: Downloaded directly from GitHub Releases for secret management.

AI & Agentic Tools

  • Claude Code CLI: Anthropic's official agent.
  • OpenCode: AI agent orchestration.
  • OpenAI Codex CLI: Required NVM/Node.js to run.

⚠️ Important Notes & Troubleshooting

  • Restart Your Shell: After running the script for the first time, you should restart your terminal or run source ~/.bashrc (or ~/.zshrc) to ensure all new PATH variables (like NVM, Go, or .NET) take effect.
  • Docker Permissions (Linux): The script automatically adds your user to the docker group. You will need to log out and log back in for this to take effect.
  • AWS CLI on Linux: Ensure you install Build Tools (Option 1) first if you are on a fresh Linux install, as the AWS installer requires unzip to extract the payload.

Built for developers who want total control over their toolchain.

menu.sh 原始文件
1#!/usr/bin/env bash
2set -u
3
4# =============================
5# COLORS & LOGGING
6# =============================
7GREEN="\033[0;32m"
8RED="\033[0;31m"
9YELLOW="\033[1;33m"
10BLUE="\033[0;34m"
11NC="\033[0m"
12
13log() { echo -e "${GREEN}$*${NC}"; }
14warn() { echo -e "${YELLOW}$*${NC}"; }
15err() { echo -e "${RED}$*${NC}"; }
16info() { echo -e "${BLUE}$*${NC}"; }
17
18# =============================
19# HELPERS & SYSTEM DETECTION
20# =============================
21require_cmd() { command -v "$1" >/dev/null 2>&1; }
22
23add_to_path_config() {
24 local label=$1
25 local path_line=$2
26 local target_file="${3:-$HOME/.pathrc}"
27
28 if [[ -f "$target_file" ]]; then
29 if ! grep -q "$label" "$target_file"; then
30 echo -e "\n# $label\n$path_line" >> "$target_file"
31 log "Added $label to $target_file"
32 fi
33 else
34 echo -e "\n# $label\n$path_line" >> "$HOME/.bashrc"
35 [[ -f "$HOME/.zshrc" ]] && echo -e "\n# $label\n$path_line" >> "$HOME/.zshrc"
36 log "Added $label to shell profiles."
37 fi
38}
39
40detect_os_arch() {
41 ARCH=$(uname -m)
42 case "$ARCH" in
43 x86_64|amd64) SYS_ARCH="amd64"; MAC_ARCH="x86_64"; AWS_ARCH="x86_64" ;;
44 aarch64|arm64) SYS_ARCH="arm64"; MAC_ARCH="arm64"; AWS_ARCH="aarch64" ;;
45 *) err "Unsupported architecture: $ARCH"; exit 1 ;;
46 esac
47
48 if [[ "$OSTYPE" == "darwin"* ]]; then
49 OS="macOS"
50 OS_LOWER="darwin"
51 elif grep -qi microsoft /proc/version 2>/dev/null; then
52 OS="WSL"
53 OS_LOWER="linux"
54 elif [[ -f /etc/os-release ]]; then
55 . /etc/os-release
56 [[ "$ID" == "ubuntu" || "$ID_LIKE" == *"ubuntu"* ]] && OS="Ubuntu" || OS="Linux"
57 OS_LOWER="linux"
58 else
59 OS="Unknown"
60 OS_LOWER="unknown"
61 fi
62 log "Detected: $OS ($ARCH)"
63}
64
65detect_os_arch
66
67# =============================
68# CORE RUNTIMES & MANAGERS
69# =============================
70
71install_build_tools() {
72 log "Installing Build Essentials & Core Dependencies..."
73 case "$OS" in
74 Ubuntu|WSL) sudo apt-get update && sudo apt-get install -y build-essential curl wget git jq unzip libssl-dev zlib1g-dev libffi-dev libsqlite3-dev ;;
75 macOS) xcode-select --install || warn "Xcode tools already installed" ;;
76 *) warn "Manual installation required for $OS." ;;
77 esac
78}
79
80install_brew() {
81 if require_cmd brew; then warn "Homebrew already installed"; return; fi
82 log "Installing Homebrew from Official Source..."
83 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
84
85 if [[ "$OS_LOWER" == "linux" ]]; then
86 add_to_path_config "HOMEBREW" 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
87 elif [[ "$MAC_ARCH" == "arm64" ]]; then
88 add_to_path_config "HOMEBREW" 'eval "$(/opt/homebrew/bin/brew shellenv)"'
89 else
90 add_to_path_config "HOMEBREW" 'eval "$(/usr/local/bin/brew shellenv)"'
91 fi
92}
93
94install_nvm() {
95 export NVM_DIR="$HOME/.nvm"
96
97 if [ -d "$NVM_DIR" ]; then
98 warn "NVM is already installed."
99 else
100 log "Installing NVM..."
101 curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
102 fi
103
104 # Load NVM for the current session to ensure the 'nvm' command is available immediately
105 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
106
107 echo -e "\n${YELLOW}Which version of Node.js would you like to install?${NC}"
108 echo " 1) LTS (Long Term Support - Recommended for stability)"
109 echo " 2) Latest (Current features - Recommended for testing new APIs)"
110 echo " 3) Skip installing Node.js right now"
111 read -p "Select (1/2/3): " node_choice
112
113 case "$node_choice" in
114 2)
115 log "Installing Latest Node.js..."
116 nvm install node
117 nvm alias default node
118 nvm use node
119 ;;
120 3)
121 log "Skipping Node.js installation."
122 ;;
123 *)
124 log "Installing Latest LTS Node.js..."
125 nvm install --lts
126 nvm alias default 'lts/*'
127 nvm use --lts
128 ;;
129 esac
130}
131
132install_python() {
133 log "Fetching latest Python 3 version from official API..."
134 LATEST_PY=$(curl -s https://api.github.com/repos/python/cpython/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
135 [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
136
137 log "Installing Python $LATEST_PY directly from Python.org..."
138 if [[ "$OS" == "macOS" ]]; then
139 PKG_URL="https://www.python.org/ftp/python/${LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
140 curl -fsSL -o /tmp/python.pkg "$PKG_URL"
141 sudo installer -pkg /tmp/python.pkg -target /
142 rm /tmp/python.pkg
143 else
144 SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
145 curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
146 cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
147 ./configure --enable-optimizations
148 sudo make altinstall
149
150 PY_MINOR=$(echo "$LATEST_PY" | cut -d. -f1,2)
151 log "Symlinking python${PY_MINOR} to python3..."
152 sudo ln -sf /usr/local/bin/python${PY_MINOR} /usr/local/bin/python3
153 sudo ln -sf /usr/local/bin/pip${PY_MINOR} /usr/local/bin/pip3
154
155 cd ~ && sudo rm -rf /tmp/Python*
156 fi
157}
158
159install_go() {
160 log "Fetching latest Go version from official source..."
161 LATEST_GO=$(curl -sL https://go.dev/VERSION?m=text | head -n 1)
162 TAR_FILE="${LATEST_GO}.${OS_LOWER}-${SYS_ARCH}.tar.gz"
163
164 log "Downloading $TAR_FILE..."
165 curl -fsSL -o /tmp/go.tar.gz "https://go.dev/dl/$TAR_FILE"
166
167 log "Installing to /usr/local/go..."
168 sudo rm -rf /usr/local/go
169 sudo tar -C /usr/local -xzf /tmp/go.tar.gz
170 rm /tmp/go.tar.gz
171 add_to_path_config "GO_BIN" 'export PATH="$PATH:/usr/local/go/bin"'
172}
173
174install_sdkman() {
175 if [ -d "$HOME/.sdkman" ]; then warn "SDKMAN already exists"; return; fi
176 log "Installing SDKMAN..."
177 curl -s "https://get.sdkman.io" | bash
178}
179
180install_dotnet() {
181 log "Installing .NET from official script..."
182 curl -fsSL https://dot.net/v1/dotnet-install.sh | bash
183 add_to_path_config "DOTNET_TOOLS" 'export PATH="$PATH:$HOME/.dotnet/tools"'
184}
185
186# =============================
187# CLOUD & INFRASTRUCTURE
188# =============================
189
190install_docker() {
191 if require_cmd docker; then log "Docker exists"; return; fi
192 log "Installing Docker from official source..."
193
194 if [[ "$OS" == "macOS" ]]; then
195 [[ "$SYS_ARCH" == "arm64" ]] && DOCKER_MAC_ARCH="arm64" || DOCKER_MAC_ARCH="amd64"
196 DMG_URL="https://desktop.docker.com/mac/main/${DOCKER_MAC_ARCH}/Docker.dmg"
197 curl -fsSL -o /tmp/Docker.dmg "$DMG_URL"
198 hdiutil attach /tmp/Docker.dmg -nobrowse -mountpoint /Volumes/Docker
199 sudo cp -a /Volumes/Docker/Docker.app /Applications/
200 hdiutil detach /Volumes/Docker
201 rm /tmp/Docker.dmg
202
203 # macOS Post-install: Launch Docker to start the daemon process
204 log "Starting Docker Desktop..."
205 open /Applications/Docker.app
206 log "Please complete the setup in the Docker Desktop UI."
207 else
208 # Linux install
209 curl -fsSL https://get.docker.com | sudo sh
210
211 # Linux Post-install: Add user to group
212 sudo usermod -aG docker "$USER"
213
214 # Linux Post-install: Enable and start Docker services on boot
215 if command -v systemctl >/dev/null 2>&1; then
216 sudo systemctl enable --now docker.service
217 sudo systemctl enable --now containerd.service
218 fi
219
220 log "Added $USER to the docker group."
221 log "CRITICAL: To apply group changes immediately without logging out, run: newgrp docker"
222 fi
223}
224
225install_aws() {
226 if require_cmd aws; then warn "AWS CLI exists"; return; fi
227 log "Installing AWS CLI directly from Amazon..."
228
229 if [[ "$OS" == "macOS" ]]; then
230 curl -fsSL -o /tmp/AWSCLIV2.pkg "https://awscli.amazonaws.com/AWSCLIV2.pkg"
231 sudo installer -pkg /tmp/AWSCLIV2.pkg -target /
232 rm /tmp/AWSCLIV2.pkg
233 else
234 if ! require_cmd unzip; then
235 err "unzip is required. Please install 'Build Tools' (Option 1) first."
236 return 1
237 fi
238 curl -fsSL -o /tmp/awscliv2.zip "https://awscli.amazonaws.com/awscli-exe-linux-${AWS_ARCH}.zip"
239 cd /tmp && unzip -q awscliv2.zip && sudo ./aws/install
240 rm -rf /tmp/awscliv2.zip /tmp/aws
241 fi
242}
243
244install_gcloud() {
245 if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
246 log "Installing Google Cloud CLI..."
247 curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
248 add_to_path_config "GCLOUD" 'source "$HOME/google-cloud-sdk/path.bash.inc"'
249}
250
251install_firebase() {
252 if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
253 log "Installing Standalone Firebase CLI..."
254 curl -sL https://firebase.tools | bash
255}
256
257# =============================
258# DEV TOOLS & SECURITY
259# =============================
260
261install_gh() {
262 if require_cmd gh; then warn "GitHub CLI exists"; return; fi
263 log "Fetching latest GitHub CLI version..."
264 LATEST_GH=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
265 TAR_NAME="gh_${LATEST_GH}_${OS_LOWER}_${SYS_ARCH}"
266
267 curl -fsSL -o /tmp/gh.tar.gz "https://github.com/cli/cli/releases/download/v${LATEST_GH}/${TAR_NAME}.tar.gz"
268 tar -xzf /tmp/gh.tar.gz -C /tmp
269 sudo mv "/tmp/${TAR_NAME}/bin/gh" /usr/local/bin/
270 sudo rm -rf "/tmp/${TAR_NAME}" /tmp/gh.tar.gz
271}
272
273install_infisical() {
274 if require_cmd infisical; then warn "Infisical exists"; return; fi
275 log "Fetching latest Infisical binary from GitHub Releases..."
276 LATEST_INF=$(curl -s https://api.github.com/repos/Infisical/infisical-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
277 TAR_FILE="infisical_${LATEST_INF}_${OS_LOWER}_${SYS_ARCH}.tar.gz"
278
279 curl -fsSL -o /tmp/infisical.tar.gz "https://github.com/Infisical/infisical-cli/releases/download/v${LATEST_INF}/${TAR_FILE}"
280 tar -xzf /tmp/infisical.tar.gz -C /tmp
281 sudo mv /tmp/infisical /usr/local/bin/
282 rm /tmp/infisical.tar.gz
283}
284
285# =============================
286# AI & AGENTIC TOOLS
287# =============================
288
289install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | bash; }
290install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | bash; }
291
292install_codex() {
293 log "Installing @openai/codex..."
294 if ! require_cmd npm; then err "Node.js/NPM is required. Install NVM (3) first."; return 1; fi
295 npm i -g @openai/codex
296}
297
298# =============================
299# MENU LOGIC
300# =============================
301show_menu() {
302 clear
303 echo -e "${BLUE}==================================================${NC}"
304 echo -e "${GREEN} DEVELOPER ENVIRONMENT INSTALLER (Strict) ${NC}"
305 echo -e "${BLUE}==================================================${NC}"
306 echo -e "${YELLOW}--- Core Runtimes & Managers ---${NC}"
307 echo " 1) Build Tools (GCC/Make)"
308 echo " 2) Homebrew (Optional)"
309 echo " 3) NVM (Node.js)"
310 echo " 4) Python 3 (Official API)"
311 echo " 5) Go (Official -> /usr/local)"
312 echo " 6) SDKMAN (Java/Kotlin)"
313 echo " 7) .NET (Official Script)"
314 echo -e "${YELLOW}--- Cloud & Infrastructure ---${NC}"
315 echo " 8) Docker (Official DMG/sh)"
316 echo " 9) AWS CLI (Official Bin)"
317 echo " 10) Google Cloud CLI (gcloud)"
318 echo " 11) Firebase CLI (Standalone)"
319 echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
320 echo " 12) GitHub CLI (Official Bin)"
321 echo " 13) Infisical (Official Bin)"
322 echo -e "${YELLOW}--- AI & Agentic Tools ---${NC}"
323 echo " 14) Claude Code CLI"
324 echo " 15) OpenCode (opencode.ai)"
325 echo " 16) OpenAI Codex CLI"
326 echo -e "${BLUE}==================================================${NC}"
327 echo " 99) Quit"
328 echo -e "${BLUE}==================================================${NC}"
329}
330
331while true; do
332 show_menu
333 read -p "Select options (space-separated): " input
334 for choice in $input; do
335 case "$choice" in
336 1) install_build_tools ;;
337 2) install_brew ;;
338 3) install_nvm ;;
339 4) install_python ;;
340 5) install_go ;;
341 6) install_sdkman ;;
342 7) install_dotnet ;;
343 8) install_docker ;;
344 9) install_aws ;;
345 10) install_gcloud ;;
346 11) install_firebase ;;
347 12) install_gh ;;
348 13) install_infisical ;;
349 14) install_claude ;;
350 15) install_opencode ;;
351 16) install_codex ;;
352 99) log "Exiting..."; exit 0 ;;
353 *) warn "Option $choice not valid." ;;
354 esac
355 done
356 read -p "Press Enter to continue..."
357done