Last active 3 weeks ago

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

weehong revised this gist 1 month ago. Go to revision

1 file changed, 24 insertions, 24 deletions

menu.sh

@@ -10,10 +10,10 @@ YELLOW="\033[1;33m"
10 10 BLUE="\033[0;34m"
11 11 NC="\033[0m"
12 12
13 - log() { echo -e "${GREEN}â–¶ $*${NC}"; }
14 - warn() { echo -e "${YELLOW}âš $*${NC}"; }
15 - err() { echo -e "${RED}✖ $*${NC}"; }
16 - info() { echo -e "${BLUE}ℹ $*${NC}"; }
13 + log() { echo -e "${GREEN}▶ $*${NC}"; }
14 + warn() { echo -e "${YELLOW}⚠ $*${NC}"; }
15 + err() { echo -e "${RED}✖ $*${NC}"; }
16 + info() { echo -e "${BLUE}ℹ $*${NC}"; }
17 17
18 18 # =============================
19 19 # HELPERS & SYSTEM DETECTION
@@ -98,7 +98,7 @@ install_nvm() {
98 98 warn "NVM is already installed."
99 99 else
100 100 log "Installing NVM..."
101 - curl -fsSL [https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh](https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh) | bash
101 + curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
102 102 fi
103 103
104 104 # Load NVM for the current session to ensure the 'nvm' command is available immediately
@@ -131,17 +131,17 @@ install_nvm() {
131 131
132 132 install_python() {
133 133 log "Fetching latest Python 3 version from official API..."
134 - LATEST_PY=$(curl -s [https://api.github.com/repos/python/cpython/releases/latest](https://api.github.com/repos/python/cpython/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
134 + LATEST_PY=$(curl -s https://api.github.com/repos/python/cpython/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
135 135 [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
136 136
137 137 log "Installing Python $LATEST_PY directly from Python.org..."
138 138 if [[ "$OS" == "macOS" ]]; then
139 - PKG_URL="[https://www.python.org/ftp/python/$](https://www.python.org/ftp/python/$){LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
139 + PKG_URL="https://www.python.org/ftp/python/${LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
140 140 curl -fsSL -o /tmp/python.pkg "$PKG_URL"
141 141 sudo installer -pkg /tmp/python.pkg -target /
142 142 rm /tmp/python.pkg
143 143 else
144 - SRC_URL="[https://www.python.org/ftp/python/$](https://www.python.org/ftp/python/$){LATEST_PY}/Python-${LATEST_PY}.tgz"
144 + SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
145 145 curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
146 146 cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
147 147 ./configure --enable-optimizations
@@ -158,11 +158,11 @@ install_python() {
158 158
159 159 install_go() {
160 160 log "Fetching latest Go version from official source..."
161 - LATEST_GO=$(curl -sL [https://go.dev/VERSION?m=text](https://go.dev/VERSION?m=text) | head -n 1)
161 + LATEST_GO=$(curl -sL https://go.dev/VERSION?m=text | head -n 1)
162 162 TAR_FILE="${LATEST_GO}.${OS_LOWER}-${SYS_ARCH}.tar.gz"
163 163
164 164 log "Downloading $TAR_FILE..."
165 - curl -fsSL -o /tmp/go.tar.gz "[https://go.dev/dl/$TAR_FILE](https://go.dev/dl/$TAR_FILE)"
165 + curl -fsSL -o /tmp/go.tar.gz "https://go.dev/dl/$TAR_FILE"
166 166
167 167 log "Installing to /usr/local/go..."
168 168 sudo rm -rf /usr/local/go
@@ -174,12 +174,12 @@ install_go() {
174 174 install_sdkman() {
175 175 if [ -d "$HOME/.sdkman" ]; then warn "SDKMAN already exists"; return; fi
176 176 log "Installing SDKMAN..."
177 - curl -s "[https://get.sdkman.io](https://get.sdkman.io)" | bash
177 + curl -s "https://get.sdkman.io" | bash
178 178 }
179 179
180 180 install_dotnet() {
181 181 log "Installing .NET from official script..."
182 - curl -fsSL [https://dot.net/v1/dotnet-install.sh](https://dot.net/v1/dotnet-install.sh) | bash
182 + curl -fsSL https://dot.net/v1/dotnet-install.sh | bash
183 183 add_to_path_config "DOTNET_TOOLS" 'export PATH="$PATH:$HOME/.dotnet/tools"'
184 184 }
185 185
@@ -193,14 +193,14 @@ install_docker() {
193 193
194 194 if [[ "$OS" == "macOS" ]]; then
195 195 [[ "$SYS_ARCH" == "arm64" ]] && DOCKER_MAC_ARCH="arm64" || DOCKER_MAC_ARCH="amd64"
196 - DMG_URL="[https://desktop.docker.com/mac/main/$](https://desktop.docker.com/mac/main/$){DOCKER_MAC_ARCH}/Docker.dmg"
196 + DMG_URL="https://desktop.docker.com/mac/main/${DOCKER_MAC_ARCH}/Docker.dmg"
197 197 curl -fsSL -o /tmp/Docker.dmg "$DMG_URL"
198 198 hdiutil attach /tmp/Docker.dmg -nobrowse -mountpoint /Volumes/Docker
199 199 sudo cp -a /Volumes/Docker/Docker.app /Applications/
200 200 hdiutil detach /Volumes/Docker
201 201 rm /tmp/Docker.dmg
202 202 else
203 - curl -fsSL [https://get.docker.com](https://get.docker.com) | sudo sh
203 + curl -fsSL https://get.docker.com | sudo sh
204 204 sudo usermod -aG docker "$USER"
205 205 log "Added $USER to docker group. You may need to logout/login."
206 206 fi
@@ -211,7 +211,7 @@ install_aws() {
211 211 log "Installing AWS CLI directly from Amazon..."
212 212
213 213 if [[ "$OS" == "macOS" ]]; then
214 - curl -fsSL -o /tmp/AWSCLIV2.pkg "[https://awscli.amazonaws.com/AWSCLIV2.pkg](https://awscli.amazonaws.com/AWSCLIV2.pkg)"
214 + curl -fsSL -o /tmp/AWSCLIV2.pkg "https://awscli.amazonaws.com/AWSCLIV2.pkg"
215 215 sudo installer -pkg /tmp/AWSCLIV2.pkg -target /
216 216 rm /tmp/AWSCLIV2.pkg
217 217 else
@@ -219,7 +219,7 @@ install_aws() {
219 219 err "unzip is required. Please install 'Build Tools' (Option 1) first."
220 220 return 1
221 221 fi
222 - curl -fsSL -o /tmp/awscliv2.zip "[https://awscli.amazonaws.com/awscli-exe-linux-$](https://awscli.amazonaws.com/awscli-exe-linux-$){AWS_ARCH}.zip"
222 + curl -fsSL -o /tmp/awscliv2.zip "https://awscli.amazonaws.com/awscli-exe-linux-${AWS_ARCH}.zip"
223 223 cd /tmp && unzip -q awscliv2.zip && sudo ./aws/install
224 224 rm -rf /tmp/awscliv2.zip /tmp/aws
225 225 fi
@@ -228,14 +228,14 @@ install_aws() {
228 228 install_gcloud() {
229 229 if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
230 230 log "Installing Google Cloud CLI..."
231 - curl -fsSL [https://sdk.cloud.google.com](https://sdk.cloud.google.com) | bash -s -- --disable-prompts
231 + curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
232 232 add_to_path_config "GCLOUD" 'source "$HOME/google-cloud-sdk/path.bash.inc"'
233 233 }
234 234
235 235 install_firebase() {
236 236 if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
237 237 log "Installing Standalone Firebase CLI..."
238 - curl -sL [https://firebase.tools](https://firebase.tools) | bash
238 + curl -sL https://firebase.tools | bash
239 239 }
240 240
241 241 # =============================
@@ -245,10 +245,10 @@ install_firebase() {
245 245 install_gh() {
246 246 if require_cmd gh; then warn "GitHub CLI exists"; return; fi
247 247 log "Fetching latest GitHub CLI version..."
248 - LATEST_GH=$(curl -s [https://api.github.com/repos/cli/cli/releases/latest](https://api.github.com/repos/cli/cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
248 + LATEST_GH=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
249 249 TAR_NAME="gh_${LATEST_GH}_${OS_LOWER}_${SYS_ARCH}"
250 250
251 - curl -fsSL -o /tmp/gh.tar.gz "[https://github.com/cli/cli/releases/download/v$](https://github.com/cli/cli/releases/download/v$){LATEST_GH}/${TAR_NAME}.tar.gz"
251 + curl -fsSL -o /tmp/gh.tar.gz "https://github.com/cli/cli/releases/download/v${LATEST_GH}/${TAR_NAME}.tar.gz"
252 252 tar -xzf /tmp/gh.tar.gz -C /tmp
253 253 sudo mv "/tmp/${TAR_NAME}/bin/gh" /usr/local/bin/
254 254 sudo rm -rf "/tmp/${TAR_NAME}" /tmp/gh.tar.gz
@@ -257,10 +257,10 @@ install_gh() {
257 257 install_infisical() {
258 258 if require_cmd infisical; then warn "Infisical exists"; return; fi
259 259 log "Fetching latest Infisical binary from GitHub Releases..."
260 - LATEST_INF=$(curl -s [https://api.github.com/repos/Infisical/infisical-cli/releases/latest](https://api.github.com/repos/Infisical/infisical-cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
260 + LATEST_INF=$(curl -s https://api.github.com/repos/Infisical/infisical-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
261 261 TAR_FILE="infisical_${LATEST_INF}_${OS_LOWER}_${SYS_ARCH}.tar.gz"
262 262
263 - curl -fsSL -o /tmp/infisical.tar.gz "[https://github.com/Infisical/infisical-cli/releases/download/v$](https://github.com/Infisical/infisical-cli/releases/download/v$){LATEST_INF}/${TAR_FILE}"
263 + curl -fsSL -o /tmp/infisical.tar.gz "https://github.com/Infisical/infisical-cli/releases/download/v${LATEST_INF}/${TAR_FILE}"
264 264 tar -xzf /tmp/infisical.tar.gz -C /tmp
265 265 sudo mv /tmp/infisical /usr/local/bin/
266 266 rm /tmp/infisical.tar.gz
@@ -270,8 +270,8 @@ install_infisical() {
270 270 # AI & AGENTIC TOOLS
271 271 # =============================
272 272
273 - install_claude() { log "Installing Claude Code..."; curl -fsSL [https://claude.ai/install.sh](https://claude.ai/install.sh) | bash; }
274 - install_opencode() { log "Installing OpenCode..."; curl -fsSL [https://opencode.ai/install](https://opencode.ai/install) | bash; }
273 + install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | bash; }
274 + install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | bash; }
275 275
276 276 install_codex() {
277 277 log "Installing OpenAI Codex CLI..."

weehong revised this gist 1 month ago. Go to revision

1 file changed, 8 insertions, 15 deletions

menu.sh

@@ -80,7 +80,7 @@ install_build_tools() {
80 80 install_brew() {
81 81 if require_cmd brew; then warn "Homebrew already installed"; return; fi
82 82 log "Installing Homebrew from Official Source..."
83 - /bin/bash -c "$(curl -fsSL [https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh](https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh))"
83 + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
84 84
85 85 if [[ "$OS_LOWER" == "linux" ]]; then
86 86 add_to_path_config "HOMEBREW" 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
@@ -288,24 +288,17 @@ show_menu() {
288 288 echo -e "${GREEN} DEVELOPER ENVIRONMENT INSTALLER (Strict) ${NC}"
289 289 echo -e "${BLUE}==================================================${NC}"
290 290 echo -e "${YELLOW}--- Core Runtimes & Managers ---${NC}"
291 - echo " 1) Build Tools (GCC/Make)"
292 - echo " 2) Homebrew (Optional)"
293 - echo " 3) NVM (Node.js)"
294 - echo " 4) Python 3 (Official API)"
295 - echo " 5) Go (Official -> /usr/local)"
296 - echo " 6) SDKMAN (Java/Kotlin)"
291 + echo " 1) Build Tools (GCC/Make) 2) Homebrew (Optional)"
292 + echo " 3) NVM (Node.js) 4) Python 3 (Official API)"
293 + echo " 5) Go (Official -> /usr/local) 6) SDKMAN (Java/Kotlin)"
297 294 echo " 7) .NET (Official Script)"
298 295 echo -e "${YELLOW}--- Cloud & Infrastructure ---${NC}"
299 - echo " 8) Docker (Official DMG/sh)"
300 - echo " 9) AWS CLI (Official Bin)"
301 - echo " 10) Google Cloud CLI (gcloud)"
302 - echo " 11) Firebase CLI (Standalone)"
296 + echo " 8) Docker (Official DMG/sh) 9) AWS CLI (Official Bin)"
297 + echo " 10) Google Cloud CLI (gcloud) 11) Firebase CLI (Standalone)"
303 298 echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
304 - echo " 12) GitHub CLI (Official Bin)"
305 - echo " 13) Infisical (Official Bin)"
299 + echo " 12) GitHub CLI (Official Bin) 13) Infisical (Official Bin)"
306 300 echo -e "${YELLOW}--- AI & Agentic Tools ---${NC}"
307 - echo " 14) Claude Code CLI"
308 - echo " 15) OpenCode (opencode.ai)"
301 + echo " 14) Claude Code CLI 15) OpenCode (opencode.ai)"
309 302 echo " 16) OpenAI Codex CLI"
310 303 echo -e "${BLUE}==================================================${NC}"
311 304 echo " 99) Quit"

weehong revised this gist 1 month ago. Go to revision

1 file changed, 39 insertions, 32 deletions

menu.sh

@@ -10,10 +10,10 @@ YELLOW="\033[1;33m"
10 10 BLUE="\033[0;34m"
11 11 NC="\033[0m"
12 12
13 - log() { echo -e "${GREEN}▶ $*${NC}"; }
14 - warn() { echo -e "${YELLOW}⚠ $*${NC}"; }
15 - err() { echo -e "${RED}✖ $*${NC}"; }
16 - info() { echo -e "${BLUE}ℹ $*${NC}"; }
13 + log() { echo -e "${GREEN}â–¶ $*${NC}"; }
14 + warn() { echo -e "${YELLOW}âš $*${NC}"; }
15 + err() { echo -e "${RED}✖ $*${NC}"; }
16 + info() { echo -e "${BLUE}ℹ $*${NC}"; }
17 17
18 18 # =============================
19 19 # HELPERS & SYSTEM DETECTION
@@ -80,7 +80,7 @@ install_build_tools() {
80 80 install_brew() {
81 81 if require_cmd brew; then warn "Homebrew already installed"; return; fi
82 82 log "Installing Homebrew from Official Source..."
83 - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
83 + /bin/bash -c "$(curl -fsSL [https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh](https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh))"
84 84
85 85 if [[ "$OS_LOWER" == "linux" ]]; then
86 86 add_to_path_config "HOMEBREW" 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
@@ -98,7 +98,7 @@ install_nvm() {
98 98 warn "NVM is already installed."
99 99 else
100 100 log "Installing NVM..."
101 - curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
101 + curl -fsSL [https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh](https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh) | bash
102 102 fi
103 103
104 104 # Load NVM for the current session to ensure the 'nvm' command is available immediately
@@ -131,17 +131,17 @@ install_nvm() {
131 131
132 132 install_python() {
133 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/')
134 + LATEST_PY=$(curl -s [https://api.github.com/repos/python/cpython/releases/latest](https://api.github.com/repos/python/cpython/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
135 135 [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
136 136
137 137 log "Installing Python $LATEST_PY directly from Python.org..."
138 138 if [[ "$OS" == "macOS" ]]; then
139 - PKG_URL="https://www.python.org/ftp/python/${LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
139 + PKG_URL="[https://www.python.org/ftp/python/$](https://www.python.org/ftp/python/$){LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
140 140 curl -fsSL -o /tmp/python.pkg "$PKG_URL"
141 141 sudo installer -pkg /tmp/python.pkg -target /
142 142 rm /tmp/python.pkg
143 143 else
144 - SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
144 + SRC_URL="[https://www.python.org/ftp/python/$](https://www.python.org/ftp/python/$){LATEST_PY}/Python-${LATEST_PY}.tgz"
145 145 curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
146 146 cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
147 147 ./configure --enable-optimizations
@@ -158,11 +158,11 @@ install_python() {
158 158
159 159 install_go() {
160 160 log "Fetching latest Go version from official source..."
161 - LATEST_GO=$(curl -sL https://go.dev/VERSION?m=text | head -n 1)
161 + LATEST_GO=$(curl -sL [https://go.dev/VERSION?m=text](https://go.dev/VERSION?m=text) | head -n 1)
162 162 TAR_FILE="${LATEST_GO}.${OS_LOWER}-${SYS_ARCH}.tar.gz"
163 163
164 164 log "Downloading $TAR_FILE..."
165 - curl -fsSL -o /tmp/go.tar.gz "https://go.dev/dl/$TAR_FILE"
165 + curl -fsSL -o /tmp/go.tar.gz "[https://go.dev/dl/$TAR_FILE](https://go.dev/dl/$TAR_FILE)"
166 166
167 167 log "Installing to /usr/local/go..."
168 168 sudo rm -rf /usr/local/go
@@ -174,12 +174,12 @@ install_go() {
174 174 install_sdkman() {
175 175 if [ -d "$HOME/.sdkman" ]; then warn "SDKMAN already exists"; return; fi
176 176 log "Installing SDKMAN..."
177 - curl -s "https://get.sdkman.io" | bash
177 + curl -s "[https://get.sdkman.io](https://get.sdkman.io)" | bash
178 178 }
179 179
180 180 install_dotnet() {
181 181 log "Installing .NET from official script..."
182 - curl -fsSL https://dot.net/v1/dotnet-install.sh | bash
182 + curl -fsSL [https://dot.net/v1/dotnet-install.sh](https://dot.net/v1/dotnet-install.sh) | bash
183 183 add_to_path_config "DOTNET_TOOLS" 'export PATH="$PATH:$HOME/.dotnet/tools"'
184 184 }
185 185
@@ -193,14 +193,14 @@ install_docker() {
193 193
194 194 if [[ "$OS" == "macOS" ]]; then
195 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"
196 + DMG_URL="[https://desktop.docker.com/mac/main/$](https://desktop.docker.com/mac/main/$){DOCKER_MAC_ARCH}/Docker.dmg"
197 197 curl -fsSL -o /tmp/Docker.dmg "$DMG_URL"
198 198 hdiutil attach /tmp/Docker.dmg -nobrowse -mountpoint /Volumes/Docker
199 199 sudo cp -a /Volumes/Docker/Docker.app /Applications/
200 200 hdiutil detach /Volumes/Docker
201 201 rm /tmp/Docker.dmg
202 202 else
203 - curl -fsSL https://get.docker.com | sudo sh
203 + curl -fsSL [https://get.docker.com](https://get.docker.com) | sudo sh
204 204 sudo usermod -aG docker "$USER"
205 205 log "Added $USER to docker group. You may need to logout/login."
206 206 fi
@@ -211,7 +211,7 @@ install_aws() {
211 211 log "Installing AWS CLI directly from Amazon..."
212 212
213 213 if [[ "$OS" == "macOS" ]]; then
214 - curl -fsSL -o /tmp/AWSCLIV2.pkg "https://awscli.amazonaws.com/AWSCLIV2.pkg"
214 + curl -fsSL -o /tmp/AWSCLIV2.pkg "[https://awscli.amazonaws.com/AWSCLIV2.pkg](https://awscli.amazonaws.com/AWSCLIV2.pkg)"
215 215 sudo installer -pkg /tmp/AWSCLIV2.pkg -target /
216 216 rm /tmp/AWSCLIV2.pkg
217 217 else
@@ -219,7 +219,7 @@ install_aws() {
219 219 err "unzip is required. Please install 'Build Tools' (Option 1) first."
220 220 return 1
221 221 fi
222 - curl -fsSL -o /tmp/awscliv2.zip "https://awscli.amazonaws.com/awscli-exe-linux-${AWS_ARCH}.zip"
222 + curl -fsSL -o /tmp/awscliv2.zip "[https://awscli.amazonaws.com/awscli-exe-linux-$](https://awscli.amazonaws.com/awscli-exe-linux-$){AWS_ARCH}.zip"
223 223 cd /tmp && unzip -q awscliv2.zip && sudo ./aws/install
224 224 rm -rf /tmp/awscliv2.zip /tmp/aws
225 225 fi
@@ -228,14 +228,14 @@ install_aws() {
228 228 install_gcloud() {
229 229 if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
230 230 log "Installing Google Cloud CLI..."
231 - curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
231 + curl -fsSL [https://sdk.cloud.google.com](https://sdk.cloud.google.com) | bash -s -- --disable-prompts
232 232 add_to_path_config "GCLOUD" 'source "$HOME/google-cloud-sdk/path.bash.inc"'
233 233 }
234 234
235 235 install_firebase() {
236 236 if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
237 237 log "Installing Standalone Firebase CLI..."
238 - curl -sL https://firebase.tools | bash
238 + curl -sL [https://firebase.tools](https://firebase.tools) | bash
239 239 }
240 240
241 241 # =============================
@@ -245,10 +245,10 @@ install_firebase() {
245 245 install_gh() {
246 246 if require_cmd gh; then warn "GitHub CLI exists"; return; fi
247 247 log "Fetching latest GitHub CLI version..."
248 - LATEST_GH=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
248 + LATEST_GH=$(curl -s [https://api.github.com/repos/cli/cli/releases/latest](https://api.github.com/repos/cli/cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
249 249 TAR_NAME="gh_${LATEST_GH}_${OS_LOWER}_${SYS_ARCH}"
250 250
251 - curl -fsSL -o /tmp/gh.tar.gz "https://github.com/cli/cli/releases/download/v${LATEST_GH}/${TAR_NAME}.tar.gz"
251 + curl -fsSL -o /tmp/gh.tar.gz "[https://github.com/cli/cli/releases/download/v$](https://github.com/cli/cli/releases/download/v$){LATEST_GH}/${TAR_NAME}.tar.gz"
252 252 tar -xzf /tmp/gh.tar.gz -C /tmp
253 253 sudo mv "/tmp/${TAR_NAME}/bin/gh" /usr/local/bin/
254 254 sudo rm -rf "/tmp/${TAR_NAME}" /tmp/gh.tar.gz
@@ -257,10 +257,10 @@ install_gh() {
257 257 install_infisical() {
258 258 if require_cmd infisical; then warn "Infisical exists"; return; fi
259 259 log "Fetching latest Infisical binary from GitHub Releases..."
260 - LATEST_INF=$(curl -s https://api.github.com/repos/Infisical/infisical-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
260 + LATEST_INF=$(curl -s [https://api.github.com/repos/Infisical/infisical-cli/releases/latest](https://api.github.com/repos/Infisical/infisical-cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
261 261 TAR_FILE="infisical_${LATEST_INF}_${OS_LOWER}_${SYS_ARCH}.tar.gz"
262 262
263 - curl -fsSL -o /tmp/infisical.tar.gz "https://github.com/Infisical/infisical-cli/releases/download/v${LATEST_INF}/${TAR_FILE}"
263 + curl -fsSL -o /tmp/infisical.tar.gz "[https://github.com/Infisical/infisical-cli/releases/download/v$](https://github.com/Infisical/infisical-cli/releases/download/v$){LATEST_INF}/${TAR_FILE}"
264 264 tar -xzf /tmp/infisical.tar.gz -C /tmp
265 265 sudo mv /tmp/infisical /usr/local/bin/
266 266 rm /tmp/infisical.tar.gz
@@ -270,8 +270,8 @@ install_infisical() {
270 270 # AI & AGENTIC TOOLS
271 271 # =============================
272 272
273 - install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | bash; }
274 - install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | bash; }
273 + install_claude() { log "Installing Claude Code..."; curl -fsSL [https://claude.ai/install.sh](https://claude.ai/install.sh) | bash; }
274 + install_opencode() { log "Installing OpenCode..."; curl -fsSL [https://opencode.ai/install](https://opencode.ai/install) | bash; }
275 275
276 276 install_codex() {
277 277 log "Installing OpenAI Codex CLI..."
@@ -288,17 +288,24 @@ show_menu() {
288 288 echo -e "${GREEN} DEVELOPER ENVIRONMENT INSTALLER (Strict) ${NC}"
289 289 echo -e "${BLUE}==================================================${NC}"
290 290 echo -e "${YELLOW}--- Core Runtimes & Managers ---${NC}"
291 - echo " 1) Build Tools (GCC/Make) 2) Homebrew (Optional)"
292 - echo " 3) NVM (Node.js) 4) Python 3 (Official API)"
293 - echo " 5) Go (Official -> /usr/local) 6) SDKMAN (Java/Kotlin)"
291 + echo " 1) Build Tools (GCC/Make)"
292 + echo " 2) Homebrew (Optional)"
293 + echo " 3) NVM (Node.js)"
294 + echo " 4) Python 3 (Official API)"
295 + echo " 5) Go (Official -> /usr/local)"
296 + echo " 6) SDKMAN (Java/Kotlin)"
294 297 echo " 7) .NET (Official Script)"
295 298 echo -e "${YELLOW}--- Cloud & Infrastructure ---${NC}"
296 - echo " 8) Docker (Official DMG/sh) 9) AWS CLI (Official Bin)"
297 - echo " 10) Google Cloud CLI (gcloud) 11) Firebase CLI (Standalone)"
299 + echo " 8) Docker (Official DMG/sh)"
300 + echo " 9) AWS CLI (Official Bin)"
301 + echo " 10) Google Cloud CLI (gcloud)"
302 + echo " 11) Firebase CLI (Standalone)"
298 303 echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
299 - echo " 12) GitHub CLI (Official Bin) 13) Infisical (Official Bin)"
304 + echo " 12) GitHub CLI (Official Bin)"
305 + echo " 13) Infisical (Official Bin)"
300 306 echo -e "${YELLOW}--- AI & Agentic Tools ---${NC}"
301 - echo " 14) Claude Code CLI 15) OpenCode (opencode.ai)"
307 + echo " 14) Claude Code CLI"
308 + echo " 15) OpenCode (opencode.ai)"
302 309 echo " 16) OpenAI Codex CLI"
303 310 echo -e "${BLUE}==================================================${NC}"
304 311 echo " 99) Quit"

weehong revised this gist 1 month ago. Go to revision

1 file changed, 21 insertions, 21 deletions

menu.sh

@@ -80,7 +80,7 @@ install_build_tools() {
80 80 install_brew() {
81 81 if require_cmd brew; then warn "Homebrew already installed"; return; fi
82 82 log "Installing Homebrew from Official Source..."
83 - /bin/bash -c "$(curl -fsSL [https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh](https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh))"
83 + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
84 84
85 85 if [[ "$OS_LOWER" == "linux" ]]; then
86 86 add_to_path_config "HOMEBREW" 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"'
@@ -98,7 +98,7 @@ install_nvm() {
98 98 warn "NVM is already installed."
99 99 else
100 100 log "Installing NVM..."
101 - curl -fsSL [https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh](https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh) | bash
101 + curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
102 102 fi
103 103
104 104 # Load NVM for the current session to ensure the 'nvm' command is available immediately
@@ -131,17 +131,17 @@ install_nvm() {
131 131
132 132 install_python() {
133 133 log "Fetching latest Python 3 version from official API..."
134 - LATEST_PY=$(curl -s [https://api.github.com/repos/python/cpython/releases/latest](https://api.github.com/repos/python/cpython/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
134 + LATEST_PY=$(curl -s https://api.github.com/repos/python/cpython/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
135 135 [[ -z "$LATEST_PY" ]] && LATEST_PY="3.12.3"
136 136
137 137 log "Installing Python $LATEST_PY directly from Python.org..."
138 138 if [[ "$OS" == "macOS" ]]; then
139 - PKG_URL="[https://www.python.org/ftp/python/$](https://www.python.org/ftp/python/$){LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
139 + PKG_URL="https://www.python.org/ftp/python/${LATEST_PY}/python-${LATEST_PY}-macos11.pkg"
140 140 curl -fsSL -o /tmp/python.pkg "$PKG_URL"
141 141 sudo installer -pkg /tmp/python.pkg -target /
142 142 rm /tmp/python.pkg
143 143 else
144 - SRC_URL="[https://www.python.org/ftp/python/$](https://www.python.org/ftp/python/$){LATEST_PY}/Python-${LATEST_PY}.tgz"
144 + SRC_URL="https://www.python.org/ftp/python/${LATEST_PY}/Python-${LATEST_PY}.tgz"
145 145 curl -fsSL -o /tmp/Python.tgz "$SRC_URL"
146 146 cd /tmp && tar -xzf Python.tgz && cd "Python-${LATEST_PY}"
147 147 ./configure --enable-optimizations
@@ -158,11 +158,11 @@ install_python() {
158 158
159 159 install_go() {
160 160 log "Fetching latest Go version from official source..."
161 - LATEST_GO=$(curl -sL [https://go.dev/VERSION?m=text](https://go.dev/VERSION?m=text) | head -n 1)
161 + LATEST_GO=$(curl -sL https://go.dev/VERSION?m=text | head -n 1)
162 162 TAR_FILE="${LATEST_GO}.${OS_LOWER}-${SYS_ARCH}.tar.gz"
163 163
164 164 log "Downloading $TAR_FILE..."
165 - curl -fsSL -o /tmp/go.tar.gz "[https://go.dev/dl/$TAR_FILE](https://go.dev/dl/$TAR_FILE)"
165 + curl -fsSL -o /tmp/go.tar.gz "https://go.dev/dl/$TAR_FILE"
166 166
167 167 log "Installing to /usr/local/go..."
168 168 sudo rm -rf /usr/local/go
@@ -174,12 +174,12 @@ install_go() {
174 174 install_sdkman() {
175 175 if [ -d "$HOME/.sdkman" ]; then warn "SDKMAN already exists"; return; fi
176 176 log "Installing SDKMAN..."
177 - curl -s "[https://get.sdkman.io](https://get.sdkman.io)" | bash
177 + curl -s "https://get.sdkman.io" | bash
178 178 }
179 179
180 180 install_dotnet() {
181 181 log "Installing .NET from official script..."
182 - curl -fsSL [https://dot.net/v1/dotnet-install.sh](https://dot.net/v1/dotnet-install.sh) | bash
182 + curl -fsSL https://dot.net/v1/dotnet-install.sh | bash
183 183 add_to_path_config "DOTNET_TOOLS" 'export PATH="$PATH:$HOME/.dotnet/tools"'
184 184 }
185 185
@@ -193,14 +193,14 @@ install_docker() {
193 193
194 194 if [[ "$OS" == "macOS" ]]; then
195 195 [[ "$SYS_ARCH" == "arm64" ]] && DOCKER_MAC_ARCH="arm64" || DOCKER_MAC_ARCH="amd64"
196 - DMG_URL="[https://desktop.docker.com/mac/main/$](https://desktop.docker.com/mac/main/$){DOCKER_MAC_ARCH}/Docker.dmg"
196 + DMG_URL="https://desktop.docker.com/mac/main/${DOCKER_MAC_ARCH}/Docker.dmg"
197 197 curl -fsSL -o /tmp/Docker.dmg "$DMG_URL"
198 198 hdiutil attach /tmp/Docker.dmg -nobrowse -mountpoint /Volumes/Docker
199 199 sudo cp -a /Volumes/Docker/Docker.app /Applications/
200 200 hdiutil detach /Volumes/Docker
201 201 rm /tmp/Docker.dmg
202 202 else
203 - curl -fsSL [https://get.docker.com](https://get.docker.com) | sudo sh
203 + curl -fsSL https://get.docker.com | sudo sh
204 204 sudo usermod -aG docker "$USER"
205 205 log "Added $USER to docker group. You may need to logout/login."
206 206 fi
@@ -211,7 +211,7 @@ install_aws() {
211 211 log "Installing AWS CLI directly from Amazon..."
212 212
213 213 if [[ "$OS" == "macOS" ]]; then
214 - curl -fsSL -o /tmp/AWSCLIV2.pkg "[https://awscli.amazonaws.com/AWSCLIV2.pkg](https://awscli.amazonaws.com/AWSCLIV2.pkg)"
214 + curl -fsSL -o /tmp/AWSCLIV2.pkg "https://awscli.amazonaws.com/AWSCLIV2.pkg"
215 215 sudo installer -pkg /tmp/AWSCLIV2.pkg -target /
216 216 rm /tmp/AWSCLIV2.pkg
217 217 else
@@ -219,7 +219,7 @@ install_aws() {
219 219 err "unzip is required. Please install 'Build Tools' (Option 1) first."
220 220 return 1
221 221 fi
222 - curl -fsSL -o /tmp/awscliv2.zip "[https://awscli.amazonaws.com/awscli-exe-linux-$](https://awscli.amazonaws.com/awscli-exe-linux-$){AWS_ARCH}.zip"
222 + curl -fsSL -o /tmp/awscliv2.zip "https://awscli.amazonaws.com/awscli-exe-linux-${AWS_ARCH}.zip"
223 223 cd /tmp && unzip -q awscliv2.zip && sudo ./aws/install
224 224 rm -rf /tmp/awscliv2.zip /tmp/aws
225 225 fi
@@ -228,14 +228,14 @@ install_aws() {
228 228 install_gcloud() {
229 229 if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
230 230 log "Installing Google Cloud CLI..."
231 - curl -fsSL [https://sdk.cloud.google.com](https://sdk.cloud.google.com) | bash -s -- --disable-prompts
231 + curl -fsSL https://sdk.cloud.google.com | bash -s -- --disable-prompts
232 232 add_to_path_config "GCLOUD" 'source "$HOME/google-cloud-sdk/path.bash.inc"'
233 233 }
234 234
235 235 install_firebase() {
236 236 if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
237 237 log "Installing Standalone Firebase CLI..."
238 - curl -sL [https://firebase.tools](https://firebase.tools) | bash
238 + curl -sL https://firebase.tools | bash
239 239 }
240 240
241 241 # =============================
@@ -245,10 +245,10 @@ install_firebase() {
245 245 install_gh() {
246 246 if require_cmd gh; then warn "GitHub CLI exists"; return; fi
247 247 log "Fetching latest GitHub CLI version..."
248 - LATEST_GH=$(curl -s [https://api.github.com/repos/cli/cli/releases/latest](https://api.github.com/repos/cli/cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
248 + LATEST_GH=$(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
249 249 TAR_NAME="gh_${LATEST_GH}_${OS_LOWER}_${SYS_ARCH}"
250 250
251 - curl -fsSL -o /tmp/gh.tar.gz "[https://github.com/cli/cli/releases/download/v$](https://github.com/cli/cli/releases/download/v$){LATEST_GH}/${TAR_NAME}.tar.gz"
251 + curl -fsSL -o /tmp/gh.tar.gz "https://github.com/cli/cli/releases/download/v${LATEST_GH}/${TAR_NAME}.tar.gz"
252 252 tar -xzf /tmp/gh.tar.gz -C /tmp
253 253 sudo mv "/tmp/${TAR_NAME}/bin/gh" /usr/local/bin/
254 254 sudo rm -rf "/tmp/${TAR_NAME}" /tmp/gh.tar.gz
@@ -257,10 +257,10 @@ install_gh() {
257 257 install_infisical() {
258 258 if require_cmd infisical; then warn "Infisical exists"; return; fi
259 259 log "Fetching latest Infisical binary from GitHub Releases..."
260 - LATEST_INF=$(curl -s [https://api.github.com/repos/Infisical/infisical-cli/releases/latest](https://api.github.com/repos/Infisical/infisical-cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
260 + LATEST_INF=$(curl -s https://api.github.com/repos/Infisical/infisical-cli/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
261 261 TAR_FILE="infisical_${LATEST_INF}_${OS_LOWER}_${SYS_ARCH}.tar.gz"
262 262
263 - curl -fsSL -o /tmp/infisical.tar.gz "[https://github.com/Infisical/infisical-cli/releases/download/v$](https://github.com/Infisical/infisical-cli/releases/download/v$){LATEST_INF}/${TAR_FILE}"
263 + curl -fsSL -o /tmp/infisical.tar.gz "https://github.com/Infisical/infisical-cli/releases/download/v${LATEST_INF}/${TAR_FILE}"
264 264 tar -xzf /tmp/infisical.tar.gz -C /tmp
265 265 sudo mv /tmp/infisical /usr/local/bin/
266 266 rm /tmp/infisical.tar.gz
@@ -270,8 +270,8 @@ install_infisical() {
270 270 # AI & AGENTIC TOOLS
271 271 # =============================
272 272
273 - install_claude() { log "Installing Claude Code..."; curl -fsSL [https://claude.ai/install.sh](https://claude.ai/install.sh) | bash; }
274 - install_opencode() { log "Installing OpenCode..."; curl -fsSL [https://opencode.ai/install](https://opencode.ai/install) | bash; }
273 + install_claude() { log "Installing Claude Code..."; curl -fsSL https://claude.ai/install.sh | bash; }
274 + install_opencode() { log "Installing OpenCode..."; curl -fsSL https://opencode.ai/install | bash; }
275 275
276 276 install_codex() {
277 277 log "Installing OpenAI Codex CLI..."

weehong revised this gist 1 month ago. Go to revision

1 file changed, 5 insertions, 13 deletions

README.md

@@ -14,21 +14,13 @@ Unlike standard setup scripts that rely heavily on package managers like Homebre
14 14
15 15 ## 🚀 Usage
16 16
17 - 1. **Download the script:**
18 - Save the script to your machine as `install.sh`.
17 + You can launch the interactive installer directly from your terminal with a single command:
19 18
20 - 2. **Make it executable:**
21 - ```bash
22 - chmod +x install.sh
23 - ```
19 + ```bash
20 + bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/af1c64c143a44ffbb0a1632dd6a32af1/raw/HEAD/menu.sh)"
21 + ```
24 22
25 - 3. **Run the installer:**
26 - ```bash
27 - ./install.sh
28 - ```
29 -
30 - 4. **Follow the interactive menu:**
31 - You can select multiple tools at once by entering space-separated numbers (e.g., `1 3 8 12`).
23 + 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`).
32 24
33 25 ## 🛠️ Included Tools
34 26

weehong revised this gist 1 month ago. Go to revision

2 files changed, 400 insertions

README.md(file created)

@@ -0,0 +1,66 @@
1 + # Strict Developer Environment Installer
2 +
3 + A robust, idempotent, and interactive bash script to bootstrap your macOS, Linux, or WSL development environment.
4 +
5 + 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).
6 +
7 + ## ✨ Key Features
8 +
9 + * **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).
10 + * **Idempotent:** Safe to run multiple times. It intelligently checks if a tool is already installed before attempting to download it.
11 + * **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.
12 + * **Auto-Path Management:** Intelligently injects paths into a dedicated `~/.pathrc` (or your `.bashrc`/`.zshrc`) without mangling your config files.
13 + * **Architecture Aware:** Automatically detects if you are running on Intel (`x86_64`) or Apple Silicon/ARM (`aarch64`/`arm64`) and downloads the correct binaries.
14 +
15 + ## 🚀 Usage
16 +
17 + 1. **Download the script:**
18 + Save the script to your machine as `install.sh`.
19 +
20 + 2. **Make it executable:**
21 + ```bash
22 + chmod +x install.sh
23 + ```
24 +
25 + 3. **Run the installer:**
26 + ```bash
27 + ./install.sh
28 + ```
29 +
30 + 4. **Follow the interactive menu:**
31 + You can select multiple tools at once by entering space-separated numbers (e.g., `1 3 8 12`).
32 +
33 + ## 🛠️ Included Tools
34 +
35 + ### Core Runtimes & Managers
36 + * **Build Tools:** GCC, Make, Git, Curl, Unzip, and core libraries.
37 + * **Homebrew:** (Optional) Installed officially.
38 + * **NVM (Node Version Manager):** Includes interactive prompt to install LTS or Latest Node.js immediately.
39 + * **Python 3:** Fetches the latest stable `.pkg` for Mac or compiles strictly from source for Linux.
40 + * **Go:** Fetches the latest tarball and installs system-wide to `/usr/local/go`.
41 + * **SDKMAN:** For managing Java, Kotlin, and Gradle.
42 + * **.NET:** Installed via Microsoft's official script.
43 +
44 + ### Cloud & Infrastructure
45 + * **Docker:** Downloads the official `.dmg` (macOS) or runs the official `get.docker.com` script (Linux) with auto-group assignment.
46 + * **AWS CLI:** Fetches the official binaries directly from Amazon.
47 + * **Google Cloud CLI (gcloud):** Official Google setup script.
48 + * **Firebase CLI:** Standalone binary (no Node.js required natively).
49 +
50 + ### Dev Tools & Security
51 + * **GitHub CLI (gh):** Downloaded directly from GitHub Releases to `/usr/local/bin`.
52 + * **Infisical CLI:** Downloaded directly from GitHub Releases for secret management.
53 +
54 + ### AI & Agentic Tools
55 + * **Claude Code CLI:** Anthropic's official agent.
56 + * **OpenCode:** AI agent orchestration.
57 + * **OpenAI Codex CLI:** Required NVM/Node.js to run.
58 +
59 + ## ⚠️ Important Notes & Troubleshooting
60 +
61 + * **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.
62 + * **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.
63 + * **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.
64 +
65 + ---
66 + *Built for developers who want total control over their toolchain.*

menu.sh(file created)

@@ -0,0 +1,334 @@
1 + #!/usr/bin/env bash
2 + set -u
3 +
4 + # =============================
5 + # COLORS & LOGGING
6 + # =============================
7 + GREEN="\033[0;32m"
8 + RED="\033[0;31m"
9 + YELLOW="\033[1;33m"
10 + BLUE="\033[0;34m"
11 + NC="\033[0m"
12 +
13 + log() { echo -e "${GREEN}▶ $*${NC}"; }
14 + warn() { echo -e "${YELLOW}⚠ $*${NC}"; }
15 + err() { echo -e "${RED}✖ $*${NC}"; }
16 + info() { echo -e "${BLUE}ℹ $*${NC}"; }
17 +
18 + # =============================
19 + # HELPERS & SYSTEM DETECTION
20 + # =============================
21 + require_cmd() { command -v "$1" >/dev/null 2>&1; }
22 +
23 + add_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 +
40 + detect_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 +
65 + detect_os_arch
66 +
67 + # =============================
68 + # CORE RUNTIMES & MANAGERS
69 + # =============================
70 +
71 + install_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 +
80 + install_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](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 +
94 + install_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](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 +
132 + install_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](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/$](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/$](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 +
159 + install_go() {
160 + log "Fetching latest Go version from official source..."
161 + LATEST_GO=$(curl -sL [https://go.dev/VERSION?m=text](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](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 +
174 + install_sdkman() {
175 + if [ -d "$HOME/.sdkman" ]; then warn "SDKMAN already exists"; return; fi
176 + log "Installing SDKMAN..."
177 + curl -s "[https://get.sdkman.io](https://get.sdkman.io)" | bash
178 + }
179 +
180 + install_dotnet() {
181 + log "Installing .NET from official script..."
182 + curl -fsSL [https://dot.net/v1/dotnet-install.sh](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 +
190 + install_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/$](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 + else
203 + curl -fsSL [https://get.docker.com](https://get.docker.com) | sudo sh
204 + sudo usermod -aG docker "$USER"
205 + log "Added $USER to docker group. You may need to logout/login."
206 + fi
207 + }
208 +
209 + install_aws() {
210 + if require_cmd aws; then warn "AWS CLI exists"; return; fi
211 + log "Installing AWS CLI directly from Amazon..."
212 +
213 + if [[ "$OS" == "macOS" ]]; then
214 + curl -fsSL -o /tmp/AWSCLIV2.pkg "[https://awscli.amazonaws.com/AWSCLIV2.pkg](https://awscli.amazonaws.com/AWSCLIV2.pkg)"
215 + sudo installer -pkg /tmp/AWSCLIV2.pkg -target /
216 + rm /tmp/AWSCLIV2.pkg
217 + else
218 + if ! require_cmd unzip; then
219 + err "unzip is required. Please install 'Build Tools' (Option 1) first."
220 + return 1
221 + fi
222 + curl -fsSL -o /tmp/awscliv2.zip "[https://awscli.amazonaws.com/awscli-exe-linux-$](https://awscli.amazonaws.com/awscli-exe-linux-$){AWS_ARCH}.zip"
223 + cd /tmp && unzip -q awscliv2.zip && sudo ./aws/install
224 + rm -rf /tmp/awscliv2.zip /tmp/aws
225 + fi
226 + }
227 +
228 + install_gcloud() {
229 + if require_cmd gcloud; then warn "Google Cloud CLI exists"; return; fi
230 + log "Installing Google Cloud CLI..."
231 + curl -fsSL [https://sdk.cloud.google.com](https://sdk.cloud.google.com) | bash -s -- --disable-prompts
232 + add_to_path_config "GCLOUD" 'source "$HOME/google-cloud-sdk/path.bash.inc"'
233 + }
234 +
235 + install_firebase() {
236 + if require_cmd firebase; then warn "Firebase CLI exists"; return; fi
237 + log "Installing Standalone Firebase CLI..."
238 + curl -sL [https://firebase.tools](https://firebase.tools) | bash
239 + }
240 +
241 + # =============================
242 + # DEV TOOLS & SECURITY
243 + # =============================
244 +
245 + install_gh() {
246 + if require_cmd gh; then warn "GitHub CLI exists"; return; fi
247 + log "Fetching latest GitHub CLI version..."
248 + LATEST_GH=$(curl -s [https://api.github.com/repos/cli/cli/releases/latest](https://api.github.com/repos/cli/cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
249 + TAR_NAME="gh_${LATEST_GH}_${OS_LOWER}_${SYS_ARCH}"
250 +
251 + curl -fsSL -o /tmp/gh.tar.gz "[https://github.com/cli/cli/releases/download/v$](https://github.com/cli/cli/releases/download/v$){LATEST_GH}/${TAR_NAME}.tar.gz"
252 + tar -xzf /tmp/gh.tar.gz -C /tmp
253 + sudo mv "/tmp/${TAR_NAME}/bin/gh" /usr/local/bin/
254 + sudo rm -rf "/tmp/${TAR_NAME}" /tmp/gh.tar.gz
255 + }
256 +
257 + install_infisical() {
258 + if require_cmd infisical; then warn "Infisical exists"; return; fi
259 + log "Fetching latest Infisical binary from GitHub Releases..."
260 + LATEST_INF=$(curl -s [https://api.github.com/repos/Infisical/infisical-cli/releases/latest](https://api.github.com/repos/Infisical/infisical-cli/releases/latest) | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
261 + TAR_FILE="infisical_${LATEST_INF}_${OS_LOWER}_${SYS_ARCH}.tar.gz"
262 +
263 + curl -fsSL -o /tmp/infisical.tar.gz "[https://github.com/Infisical/infisical-cli/releases/download/v$](https://github.com/Infisical/infisical-cli/releases/download/v$){LATEST_INF}/${TAR_FILE}"
264 + tar -xzf /tmp/infisical.tar.gz -C /tmp
265 + sudo mv /tmp/infisical /usr/local/bin/
266 + rm /tmp/infisical.tar.gz
267 + }
268 +
269 + # =============================
270 + # AI & AGENTIC TOOLS
271 + # =============================
272 +
273 + install_claude() { log "Installing Claude Code..."; curl -fsSL [https://claude.ai/install.sh](https://claude.ai/install.sh) | bash; }
274 + install_opencode() { log "Installing OpenCode..."; curl -fsSL [https://opencode.ai/install](https://opencode.ai/install) | bash; }
275 +
276 + install_codex() {
277 + log "Installing OpenAI Codex CLI..."
278 + if ! require_cmd npm; then err "Node.js/NPM is required. Install NVM (3) first."; return 1; fi
279 + npm install -g openai
280 + }
281 +
282 + # =============================
283 + # MENU LOGIC
284 + # =============================
285 + show_menu() {
286 + clear
287 + echo -e "${BLUE}==================================================${NC}"
288 + echo -e "${GREEN} DEVELOPER ENVIRONMENT INSTALLER (Strict) ${NC}"
289 + echo -e "${BLUE}==================================================${NC}"
290 + echo -e "${YELLOW}--- Core Runtimes & Managers ---${NC}"
291 + echo " 1) Build Tools (GCC/Make) 2) Homebrew (Optional)"
292 + echo " 3) NVM (Node.js) 4) Python 3 (Official API)"
293 + echo " 5) Go (Official -> /usr/local) 6) SDKMAN (Java/Kotlin)"
294 + echo " 7) .NET (Official Script)"
295 + echo -e "${YELLOW}--- Cloud & Infrastructure ---${NC}"
296 + echo " 8) Docker (Official DMG/sh) 9) AWS CLI (Official Bin)"
297 + echo " 10) Google Cloud CLI (gcloud) 11) Firebase CLI (Standalone)"
298 + echo -e "${YELLOW}--- Dev Tools & Security ---${NC}"
299 + echo " 12) GitHub CLI (Official Bin) 13) Infisical (Official Bin)"
300 + echo -e "${YELLOW}--- AI & Agentic Tools ---${NC}"
301 + echo " 14) Claude Code CLI 15) OpenCode (opencode.ai)"
302 + echo " 16) OpenAI Codex CLI"
303 + echo -e "${BLUE}==================================================${NC}"
304 + echo " 99) Quit"
305 + echo -e "${BLUE}==================================================${NC}"
306 + }
307 +
308 + while true; do
309 + show_menu
310 + read -p "Select options (space-separated): " input
311 + for choice in $input; do
312 + case "$choice" in
313 + 1) install_build_tools ;;
314 + 2) install_brew ;;
315 + 3) install_nvm ;;
316 + 4) install_python ;;
317 + 5) install_go ;;
318 + 6) install_sdkman ;;
319 + 7) install_dotnet ;;
320 + 8) install_docker ;;
321 + 9) install_aws ;;
322 + 10) install_gcloud ;;
323 + 11) install_firebase ;;
324 + 12) install_gh ;;
325 + 13) install_infisical ;;
326 + 14) install_claude ;;
327 + 15) install_opencode ;;
328 + 16) install_codex ;;
329 + 99) log "Exiting..."; exit 0 ;;
330 + *) warn "Option $choice not valid." ;;
331 + esac
332 + done
333 + read -p "Press Enter to continue..."
334 + done
Newer Older