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 | |