最後活躍 3 weeks ago

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

修訂 b0c4c9b6fa988d7b3099d0ada8583cb819ae8d80

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
249 # Use the dot operator which is more POSIX compliant
250 add_to_path_config "GCLOUD" '[ -f "$HOME/google-cloud-sdk/path.bash.inc" ] && . "$HOME/google-cloud-sdk/path.bash.inc"'
251}
252
253install_firebase() {
254 if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
255 log "Installing Firebase CLI via NPM to ensure ARM64 compatibility..."
256
257 # Check if npm exists, if not, try to load nvm or warn user
258 if ! require_cmd npm; then
259 err "NPM not found. Please install NVM (Option 3) first."
260 return 1
261 fi
262
263 npm install -g firebase-tools
264}
265
266# =============================
267# DEV TOOLS & SECURITY
268# =============================
269
270install_gh() {
271 if require_cmd gh; then warn "GitHub CLI exists"; return; fi
272 log "Fetching latest GitHub CLI version..."
273 LATEST_GH=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
274 TAR_NAME="gh_${LATEST_GH}_${OS_LOWER}_${SYS_ARCH}"
275
276 curl -fsSL -o /tmp/gh.tar.gz "https://github.com/cli/cli/releases/download/v${LATEST_GH}/${TAR_NAME}.tar.gz"
277 tar -xzf /tmp/gh.tar.gz -C /tmp
278 sudo mv "/tmp/${TAR_NAME}/bin/gh" /usr/local/bin/
279 sudo rm -rf "/tmp/${TAR_NAME}" /tmp/gh.tar.gz
280}
281
282install_infisical() {
283 if require_cmd infisical; then warn "Infisical CLI exists"; return; fi
284 log "Installing Infisical CLI via NPM..."
285
286 if ! require_cmd npm; then
287 err "NPM not found. Please install NVM (Option 3) first."
288 return 1
289 fi
290
291 npm install -g @infisical/cli
292}
293
294# =============================
295# AI & AGENTIC TOOLS
296# =============================
297
298install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | bash; }
299install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | bash; }
300
301install_codex() {
302 log "Installing @openai/codex..."
303 if ! require_cmd npm; then err "Node.js/NPM is required. Install NVM (3) first."; return 1; fi
304 npm i -g @openai/codex
305}
306
307# =============================
308# MENU LOGIC
309# =============================
310show_menu() {
311 clear
312 echo -e "${BLUE}==================================================${NC}"
313 echo -e "${GREEN} DEVELOPER ENVIRONMENT INSTALLER (Strict) ${NC}"
314 echo -e "${BLUE}==================================================${NC}"
315 echo -e "${YELLOW}--- Core Runtimes & Managers ---${NC}"
316 echo " 1) Build Tools (GCC/Make)"
317 echo " 2) Homebrew (Optional)"
318 echo " 3) NVM (Node.js)"
319 echo " 4) Python 3 (Official API)"
320 echo " 5) Go (Official -> /usr/local)"
321 echo " 6) SDKMAN (Java/Kotlin)"
322 echo " 7) .NET (Official Script)"
323 echo -e "${YELLOW}--- Cloud & Infrastructure ---${NC}"
324 echo " 8) Docker (Official DMG/sh)"
325 echo " 9) AWS CLI (Official Bin)"
326 echo " 10) Google Cloud CLI (gcloud)"
327 echo " 11) Firebase CLI (NPM/ARM64 Safe)"
328 echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
329 echo " 12) GitHub CLI (Official Bin)"
330 echo " 13) Infisical (Official Bin)"
331 echo -e "${YELLOW}--- AI & Agentic Tools ---${NC}"
332 echo " 14) Claude Code CLI"
333 echo " 15) OpenCode (opencode.ai)"
334 echo " 16) OpenAI Codex CLI"
335 echo -e "${BLUE}==================================================${NC}"
336 echo " 99) Quit"
337 echo -e "${BLUE}==================================================${NC}"
338}
339
340while true; do
341 show_menu
342 read -p "Select options (space-separated): " input
343 for choice in $input; do
344 case "$choice" in
345 1) install_build_tools ;;
346 2) install_brew ;;
347 3) install_nvm ;;
348 4) install_python ;;
349 5) install_go ;;
350 6) install_sdkman ;;
351 7) install_dotnet ;;
352 8) install_docker ;;
353 9) install_aws ;;
354 10) install_gcloud ;;
355 11) install_firebase ;;
356 12) install_gh ;;
357 13) install_infisical ;;
358 14) install_claude ;;
359 15) install_opencode ;;
360 16) install_codex ;;
361 99) log "Exiting..."; exit 0 ;;
362 *) warn "Option $choice not valid." ;;
363 esac
364 done
365 read -p "Press Enter to continue..."
366done