Created
August 11, 2025 14:35
-
-
Save jaycdave88/d46328d1dc78749d111c80e4fbdeaf30 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # SA Mac bootstrap — idempotent, with logging | |
| set -u # don't exit on errors; we want to log them and continue | |
| LOG_FILE="$HOME/Desktop/Setup MacBook for SA.txt" | |
| mkdir -p "$HOME/Desktop" 2>/dev/null || true | |
| log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG_FILE"; } | |
| section() { echo | tee -a "$LOG_FILE"; log "==== $* ===="; } | |
| section "Starting SA Mac bootstrap" | |
| log "Logging to: $LOG_FILE" | |
| # --- Homebrew --- | |
| section "Homebrew" | |
| if ! command -v brew >/dev/null 2>&1; then | |
| log "Homebrew not found — installing" | |
| /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" >>"$LOG_FILE" 2>&1 || log "ERROR: Homebrew install failed" | |
| else | |
| log "Homebrew already installed" | |
| fi | |
| BREW_PREFIX="$(/usr/bin/arch | grep -qi arm && echo /opt/homebrew || echo /usr/local)" | |
| if [ -x "$BREW_PREFIX/bin/brew" ]; then | |
| eval "$("$BREW_PREFIX/bin/brew" shellenv)" | |
| else | |
| eval "$(brew shellenv)" | |
| fi | |
| brew update >>"$LOG_FILE" 2>&1 || log "WARN: brew update failed" | |
| install_formula() { | |
| local pkg="$1" | |
| if brew list --formula "$pkg" >/dev/null 2>&1; then | |
| log "SKIP: brew formula $pkg already installed" | |
| else | |
| if brew install "$pkg" >>"$LOG_FILE" 2>&1; then | |
| log "OK: installed brew formula $pkg" | |
| else | |
| log "ERROR: installing brew formula $pkg" | |
| fi | |
| fi | |
| } | |
| install_cask() { | |
| local cask="$1" | |
| if brew list --cask "$cask" >/dev/null 2>&1; then | |
| log "SKIP: brew cask $cask already installed" | |
| else | |
| if brew install --cask "$cask" >>"$LOG_FILE" 2>&1; then | |
| log "OK: installed brew cask $cask" | |
| else | |
| log "ERROR: installing brew cask $cask" | |
| fi | |
| fi | |
| } | |
| # --- Core installs --- | |
| for f in git gh jq wget curl zsh-completions fzf zoxide direnv; do install_formula "$f"; done | |
| install_formula pyenv | |
| install_formula fnm | |
| for c in iterm2 visual-studio-code sublime-text docker jetbrains-toolbox google-chrome slack zoom notion; do | |
| install_cask "$c" | |
| done | |
| # --- Shell bootstrap --- | |
| section "Shell bootstrap (.zshrc)" | |
| ZSHRC="$HOME/.zshrc" | |
| if ! grep -q "# augment-bootstrap" "$ZSHRC" 2>/dev/null; then | |
| cat >> "$ZSHRC" <<'EOF' | |
| # augment-bootstrap | |
| export PATH="$HOME/.local/bin:$PATH" | |
| if [ -d /opt/homebrew ]; then eval "$(/opt/homebrew/bin/brew shellenv)"; fi | |
| if command -v pyenv >/dev/null 2>&1; then export PYENV_ROOT="$HOME/.pyenv"; eval "$(pyenv init -)"; fi | |
| if command -v fnm >/dev/null 2>&1; then eval "$(fnm env --use-on-cd)"; fi | |
| if command -v direnv >/dev/null 2>&1; then eval "$(direnv hook zsh)"; fi | |
| if command -v zoxide >/dev/null 2>&1; then eval "$(zoxide init zsh)"; fi | |
| if [ -f "$(brew --prefix 2>/dev/null)/opt/fzf/shell/key-bindings.zsh" ]; then | |
| source "$(brew --prefix)/opt/fzf/shell/key-bindings.zsh" | |
| fi | |
| # end augment-bootstrap | |
| EOF | |
| log "OK: appended augment bootstrap to $ZSHRC" | |
| else | |
| log "SKIP: augment bootstrap already present in $ZSHRC" | |
| fi | |
| if [ -d /opt/homebrew ]; then eval "$(/opt/homebrew/bin/brew shellenv)"; fi | |
| # --- Python latest stable --- | |
| section "Python via pyenv" | |
| if command -v pyenv >/dev/null 2>&1; then | |
| PY_LATEST=$(pyenv install -l | grep -E '^\s*3\.[0-9]+\.[0-9]+$' | tr -d ' ' | tail -1) | |
| [ -z "$PY_LATEST" ] && PY_LATEST="3.12.5" | |
| log "Target Python: $PY_LATEST" | |
| if pyenv versions --bare | grep -qx "$PY_LATEST"; then | |
| log "SKIP: Python $PY_LATEST already installed" | |
| else | |
| pyenv install "$PY_LATEST" >>"$LOG_FILE" 2>&1 && log "OK: installed Python $PY_LATEST" || log "ERROR: Python install failed" | |
| fi | |
| pyenv global "$PY_LATEST" | |
| python3 -m ensurepip --upgrade >>"$LOG_FILE" 2>&1 || true | |
| python3 -m pip install --upgrade pip pipx >>"$LOG_FILE" 2>&1 || log "WARN: pip/pipx upgrade issue" | |
| else | |
| log "ERROR: pyenv not available" | |
| fi | |
| # --- Node latest LTS --- | |
| section "Node via fnm" | |
| if command -v fnm >/dev/null 2>&1; then | |
| fnm install --lts >>"$LOG_FILE" 2>&1 || log "ERROR: Node LTS install failed" | |
| CURRENT_LTS=$(fnm ls | awk '/LTS/ {print $1}' | tail -1) | |
| if [ -n "$CURRENT_LTS" ]; then | |
| fnm default "$CURRENT_LTS" && log "OK: set Node default to $CURRENT_LTS" | |
| else | |
| log "WARN: could not detect LTS label" | |
| fi | |
| else | |
| log "ERROR: fnm not available" | |
| fi | |
| # --- Editor commands --- | |
| section "Editor CLI commands" | |
| if ! command -v code >/dev/null 2>&1 && [ -x "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" ]; then | |
| sudo ln -sf "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" /usr/local/bin/code && log "OK: linked 'code'" | |
| else | |
| log "SKIP: 'code' already in PATH" | |
| fi | |
| if ! command -v subl >/dev/null 2>&1 && [ -x "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" ]; then | |
| sudo ln -sf "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" /usr/local/bin/subl && log "OK: linked 'subl'" | |
| else | |
| log "SKIP: 'subl' already in PATH" | |
| fi | |
| # --- Docker first run --- | |
| section "Docker first run" | |
| if command -v docker >/dev/null 2>&1; then | |
| open -ga Docker >>"$LOG_FILE" 2>&1 || true | |
| log "INFO: Accept Docker prompts if shown." | |
| else | |
| log "WARN: docker CLI not available" | |
| fi | |
| # --- Sanity checks --- | |
| section "Sanity checks" | |
| { | |
| which brew && brew --version | |
| which git && git --version | |
| which gh && gh --version | |
| which python3 && python3 --version | |
| which pyenv && pyenv versions | |
| which node && node -v | |
| which fnm && fnm ls | |
| which code && code --version | |
| which subl || true | |
| docker --version || true | |
| } >>"$LOG_FILE" 2>&1 | |
| section "Complete" | |
| log "Close/reopen iTerm to load changes." | |
| log "Review $LOG_FILE for errors or warnings." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment