Skip to content

Instantly share code, notes, and snippets.

@trinvh
Last active March 9, 2026 14:47
Show Gist options
  • Select an option

  • Save trinvh/aa39a600714660350d43672d237295f6 to your computer and use it in GitHub Desktop.

Select an option

Save trinvh/aa39a600714660350d43672d237295f6 to your computer and use it in GitHub Desktop.
macOS Dev Environment Setup Script — Tri's Mac mini (Apple Silicon) with M2-500 SSD integration

macOS Dev Environment Setup — Tri's Mac mini (Apple Silicon)

A single idempotent script that recreates my full development environment on a fresh macOS install, including M2-500 external SSD integration for offloading large data (Android SDK, Docker, VS Code, workspaces).

What's Inside

Homebrew Packages

Formula Purpose
cloudflared Cloudflare Tunnel client
gh GitHub CLI
fvm Flutter Version Management
mole SSH tunnel manager
nano Improved text editor
postgresql@17 PostgreSQL database
pyenv Python version manager
tmux Terminal multiplexer
zsh Latest Z shell

Homebrew Casks (GUI Apps)

Android Studio, Bruno (API client), Claude Code, Figma, IINA (media player), Rectangle (window manager), Stats (system monitor)

Shell Environment

  • Oh My Zsh with Powerlevel10k theme
  • Plugins: git, zsh-autosuggestions, zsh-syntax-highlighting, z, docker, node, npm, python
  • Version managers: nvm (Node.js 22), fvm (Flutter 3.32.8), pyenv (Python 3.10.4)
  • Custom aliases for git, docker, and project shortcuts

M2-500 SSD Symlinks

Large directories are symlinked to the external SSD to save internal storage:

~/.android          → /Volumes/M2-500/AndroidData/.android
~/.gradle           → /Volumes/M2-500/AndroidData/.gradle
~/Workspaces        → /Volumes/M2-500/Workspaces
~/.claude           → /Volumes/M2-500/ClaudeCode/claude
~/.claude.json      → /Volumes/M2-500/ClaudeCode/claude.json
~/.vscode           → /Volumes/M2-500/VSCode/vscode
~/Library/App.../Code → /Volumes/M2-500/VSCode/AppSupport
Docker.raw          → /Volumes/M2-500/DockerData/DockerDesktop/Docker.raw
postgresql@17       → /Volumes/M2-500/PostgresData/postgresql@17

VS Code Extensions (74)

Full stack coverage: Flutter/Dart, React/TypeScript, Python, Java/Spring, C#/.NET, Go, Swift, PHP, Terraform, Docker, Prisma, Jupyter, and productivity tools.

Configuration Files

  • ~/.zshrc — full shell config with aliases and PATH
  • ~/.zprofile — Homebrew env
  • ~/.gitconfig — user identity
  • ~/.ssh/config — 6 host entries (Bitbucket multi-account, Azure DevOps, EC2)

Usage

# 1. Mount M2-500 SSD
# 2. Download and run:
curl -fsSL <gist-raw-url>/setup-mac.sh -o setup-mac.sh
chmod +x setup-mac.sh
./setup-mac.sh

Manual Steps After Running

  1. Install these apps manually (not available via Homebrew):

    • Amphetamine (App Store), Claude.app, Docker Desktop, Google Chrome, Microsoft Edge, Microsoft Teams, Postman, Raycast, RustDesk, Slack, Surfshark VPN, Tailscale, VS Code, Xcode/Xcodes, Zalo, Zoom, GoNhanh
  2. Restore SSH keys from secure backup to ~/.ssh/

  3. Authenticate GitHub CLI: gh auth login

  4. Configure Powerlevel10k: p10k configure

  5. Docker Desktop — install it, then re-run the script to create the Docker.raw symlink

  6. Android Studio — open to complete SDK/emulator setup

  7. PostgreSQL — restore databases from old machine:

    # On old Mac: pg_dumpall > postgres_backup.sql
    # Transfer the file, then on new Mac:
    psql -f postgres_backup.sql postgres
  8. Cloudflare Tunnel — authenticate and configure:

    # Login to Cloudflare (opens browser)
    cloudflared tunnel login
    
    # Create a tunnel (or recreate an existing one)
    cloudflared tunnel create <tunnel-name>
    
    # Configure the tunnel — create/edit ~/.cloudflared/config.yml:
    # tunnel: <TUNNEL-UUID>
    # credentials-file: /Users/trinvh/.cloudflared/<TUNNEL-UUID>.json
    # ingress:
    #   - hostname: app.example.com
    #     service: http://localhost:3000
    #   - service: http_status:404
    
    # Route DNS to the tunnel
    cloudflared tunnel route dns <tunnel-name> app.example.com
    
    # Install as a macOS service (starts on boot)
    sudo cloudflared service install
    
    # Or run manually
    cloudflared tunnel run <tunnel-name>

    If migrating from old Mac, copy ~/.cloudflared/ (contains credentials and config).

  9. DataGrip — migrate data sources from old machine:

    • Open DataGrip on the old Mac, select all data sources in the Database panel
    • Press Cmd+C to copy, then open DataGrip on the new Mac and press Cmd+V to paste
    • Re-enter passwords when prompted (passwords are stored in macOS Keychain, not in config files)

Migration Checklist (Old Mac → New Mac)

Copy these from the old machine before wiping it:

Shell & Terminal

  • ~/.zsh_history — command history
  • ~/.p10k.zsh — Powerlevel10k theme config (avoids re-running p10k configure)
  • ~/.tmux.conf — tmux config (if customized)
  • ~/.npmrc — npm registry config and tokens

Fonts

  • ~/Library/Fonts/ — custom fonts (e.g. MesloLGS NF for Powerlevel10k)

App Settings

  • Raycast — export via Raycast > Settings > Advanced > Export
  • Rectangle — export via Rectangle > Settings (gear icon) > Export
  • Postman — collections sync via Postman account, or File > Export
  • Bruno — collections stored as files; already covered if in ~/Workspaces

Browser

  • Chrome — bookmarks/extensions sync via Google account
  • Edge — bookmarks/extensions sync via Microsoft account

Docker

  • Save important custom images: docker save myimage:tag > myimage.tar
  • On new Mac restore with: docker load < myimage.tar

Cloudflare Tunnel

  • ~/.cloudflared/ — tunnel credentials (<UUID>.json) and config.yml

System

  • crontab -l > ~/crontab_backup.txt — scheduled jobs (if any)
  • macOS settings — Dock size, key repeat rate, trackpad, keyboard shortcuts (consider scripting with defaults write)

Notes

  • The script is idempotent — running it again skips already-installed components
  • SSH keys are not included for security; restore from backup
  • The .zshrc will be overwritten on each run; back up customizations first
  • Tested on macOS Sequoia (Apple Silicon)
#!/bin/bash
#
# macOS Setup Script for Tri Nguyen's Mac mini (Apple Silicon)
# Recreates the full development environment with M2-500 SSD integration.
#
# Prerequisites:
# - macOS on Apple Silicon (arm64)
# - External SSD mounted at /Volumes/M2-500
# - Internet connection
#
# Usage:
# chmod +x setup-mac.sh
# ./setup-mac.sh
#
# The script is idempotent — safe to re-run.
set -euo pipefail
SSD="/Volumes/M2-500"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
err() { echo -e "${RED}[✗]${NC} $1"; }
# -------------------------------------------------------------------
# 0. Pre-flight checks
# -------------------------------------------------------------------
echo ""
echo "=========================================="
echo " macOS Dev Environment Setup"
echo " Machine: Tris-Mac-mini (Apple Silicon)"
echo "=========================================="
echo ""
if [[ $(uname -m) != "arm64" ]]; then
err "This script is designed for Apple Silicon Macs."
exit 1
fi
if [[ ! -d "$SSD" ]]; then
err "M2-500 SSD not mounted at $SSD. Please connect it first."
exit 1
fi
# -------------------------------------------------------------------
# 1. Install Rosetta 2 (for x86 compatibility)
# -------------------------------------------------------------------
if ! /usr/bin/pgrep -q oahd 2>/dev/null; then
log "Installing Rosetta 2..."
softwareupdate --install-rosetta --agree-to-license
else
log "Rosetta 2 already installed."
fi
# -------------------------------------------------------------------
# 2. Install Homebrew
# -------------------------------------------------------------------
if ! command -v brew &>/dev/null; then
log "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
eval "$(/opt/homebrew/bin/brew shellenv zsh)"
else
log "Homebrew already installed."
fi
# -------------------------------------------------------------------
# 3. Homebrew formulae
# -------------------------------------------------------------------
FORMULAE=(
cloudflared # Cloudflare Tunnel client
gh # GitHub CLI
mole # SSH tunnel manager
nano # Better nano
postgresql@17 # PostgreSQL database
pyenv # Python version manager
tmux # Terminal multiplexer
zsh # Latest zsh
)
log "Installing Homebrew formulae..."
for pkg in "${FORMULAE[@]}"; do
pkg_name="${pkg%%#*}" # strip inline comment
pkg_name="${pkg_name// /}" # strip spaces
if brew list --formula "$pkg_name" &>/dev/null; then
log " $pkg_name already installed."
else
brew install "$pkg_name"
fi
done
# fvm (Flutter Version Management) — needs a tap
if ! brew list --formula fvm &>/dev/null; then
log "Installing fvm..."
brew tap leoafarias/fvm
brew install fvm
else
log " fvm already installed."
fi
# -------------------------------------------------------------------
# 4. Homebrew casks (GUI applications)
# -------------------------------------------------------------------
CASKS=(
android-studio
bruno
claude-code
figma
iina
rectangle
stats
)
log "Installing Homebrew casks..."
for cask in "${CASKS[@]}"; do
if brew list --cask "$cask" &>/dev/null; then
log " $cask already installed."
else
brew install --cask "$cask"
fi
done
# -------------------------------------------------------------------
# 5. Additional apps (manual / App Store / direct download)
# -------------------------------------------------------------------
echo ""
warn "The following apps must be installed manually:"
echo " - Amphetamine → Mac App Store"
echo " - Claude.app → https://claude.ai/download"
echo " - Docker Desktop → https://www.docker.com/products/docker-desktop/"
echo " - GoNhanh → Manual install"
echo " - Google Chrome → https://www.google.com/chrome/"
echo " - Microsoft Edge → https://www.microsoft.com/edge"
echo " - Microsoft Teams → https://www.microsoft.com/microsoft-teams"
echo " - Postman → https://www.postman.com/downloads/"
echo " - Raycast → https://www.raycast.com/"
echo " - RustDesk → https://rustdesk.com/"
echo " - Slack → Mac App Store or https://slack.com/downloads/mac"
echo " - Surfshark VPN → https://surfshark.com/download"
echo " - Tailscale → Mac App Store or https://tailscale.com/download"
echo " - Visual Studio Code → https://code.visualstudio.com/"
echo " - Xcode → Mac App Store (or Xcodes.app)"
echo " - Xcodes.app → https://github.com/XcodesOrg/XcodesApp"
echo " - Zalo → https://zalo.me/pc"
echo " - Zoom → https://zoom.us/download"
echo ""
# -------------------------------------------------------------------
# 6. Oh My Zsh + plugins + theme
# -------------------------------------------------------------------
if [[ ! -d "$HOME/.oh-my-zsh" ]]; then
log "Installing Oh My Zsh..."
RUNZSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
else
log "Oh My Zsh already installed."
fi
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
# Powerlevel10k theme
if [[ ! -d "$ZSH_CUSTOM/themes/powerlevel10k" ]]; then
log "Installing Powerlevel10k..."
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
"$ZSH_CUSTOM/themes/powerlevel10k"
else
log "Powerlevel10k already installed."
fi
# zsh-autosuggestions
if [[ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ]]; then
log "Installing zsh-autosuggestions..."
git clone https://github.com/zsh-users/zsh-autosuggestions \
"$ZSH_CUSTOM/plugins/zsh-autosuggestions"
else
log "zsh-autosuggestions already installed."
fi
# zsh-syntax-highlighting
if [[ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ]]; then
log "Installing zsh-syntax-highlighting..."
git clone https://github.com/zsh-users/zsh-syntax-highlighting \
"$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
else
log "zsh-syntax-highlighting already installed."
fi
# -------------------------------------------------------------------
# 7. nvm (Node Version Manager) + Node.js
# -------------------------------------------------------------------
export NVM_DIR="$HOME/.nvm"
if [[ ! -d "$NVM_DIR" ]]; then
log "Installing nvm..."
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
# shellcheck source=/dev/null
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
else
log "nvm already installed."
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
fi
if ! nvm ls 22 &>/dev/null; then
log "Installing Node.js 22 via nvm..."
nvm install 22
nvm use 22
nvm alias default 22
else
log "Node.js 22 already installed."
fi
# -------------------------------------------------------------------
# 8. pyenv + Python
# -------------------------------------------------------------------
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
if command -v pyenv &>/dev/null; then
eval "$(pyenv init -)"
if ! pyenv versions --bare | grep -q "^3\.10\.4$"; then
log "Installing Python 3.10.4 via pyenv..."
pyenv install 3.10.4
else
log "Python 3.10.4 already installed via pyenv."
fi
else
warn "pyenv not found. It should have been installed via Homebrew above."
fi
# -------------------------------------------------------------------
# 9. Flutter via fvm
# -------------------------------------------------------------------
if ! fvm list | grep -q "3.32.8"; then
log "Installing Flutter 3.32.8 via fvm..."
fvm install 3.32.8
fvm global 3.32.8
else
log "Flutter 3.32.8 already installed."
fi
# -------------------------------------------------------------------
# 10. CocoaPods (for iOS development)
# -------------------------------------------------------------------
if ! command -v pod &>/dev/null; then
log "Installing CocoaPods..."
sudo gem install cocoapods
else
log "CocoaPods already installed."
fi
# -------------------------------------------------------------------
# 11. Git configuration
# -------------------------------------------------------------------
log "Configuring Git..."
git config --global user.name "Tri Nguyen"
git config --global user.email "trinvhco@gmail.com"
# -------------------------------------------------------------------
# 12. M2-500 SSD directory structure
# -------------------------------------------------------------------
log "Ensuring M2-500 SSD directory structure..."
DIRS=(
"$SSD/AndroidData/.android"
"$SSD/AndroidData/.gradle"
"$SSD/ClaudeCode"
"$SSD/DockerData/DockerDesktop"
"$SSD/PostgresData"
"$SSD/VSCode/vscode"
"$SSD/VSCode/AppSupport"
"$SSD/Workspaces"
)
for dir in "${DIRS[@]}"; do
mkdir -p "$dir"
done
# -------------------------------------------------------------------
# 13. Symlinks to M2-500 SSD
# -------------------------------------------------------------------
log "Creating symlinks to M2-500 SSD..."
create_symlink() {
local target="$1"
local link="$2"
if [[ -L "$link" ]]; then
log " Symlink already exists: $link"
elif [[ -e "$link" ]]; then
warn " $link exists and is NOT a symlink. Back it up and re-run, or remove it manually."
else
# Ensure parent directory exists
mkdir -p "$(dirname "$link")"
ln -s "$target" "$link"
log " Created: $link → $target"
fi
}
# Android SDK data
create_symlink "$SSD/AndroidData/.android" "$HOME/.android"
create_symlink "$SSD/AndroidData/.gradle" "$HOME/.gradle"
# Workspaces
create_symlink "$SSD/Workspaces" "$HOME/Workspaces"
# Claude Code
create_symlink "$SSD/ClaudeCode/claude" "$HOME/.claude"
create_symlink "$SSD/ClaudeCode/claude.json" "$HOME/.claude.json"
# VS Code
create_symlink "$SSD/VSCode/vscode" "$HOME/.vscode"
create_symlink "$SSD/VSCode/AppSupport" "$HOME/Library/Application Support/Code"
# Docker data disk (only if Docker.raw exists on SSD)
if [[ -f "$SSD/DockerData/DockerDesktop/Docker.raw" ]]; then
DOCKER_RAW_DIR="$HOME/Library/Containers/com.docker.docker/Data/vms/0/data"
if [[ -d "$DOCKER_RAW_DIR" ]]; then
create_symlink "$SSD/DockerData/DockerDesktop/Docker.raw" "$DOCKER_RAW_DIR/Docker.raw"
else
warn " Docker raw directory not found. Install Docker Desktop first, then re-run."
fi
fi
# PostgreSQL data directory → SSD
PG_DATA_DEFAULT="/opt/homebrew/var/postgresql@17"
PG_DATA_SSD="$SSD/PostgresData/postgresql@17"
if [[ -d "$PG_DATA_DEFAULT" && ! -L "$PG_DATA_DEFAULT" ]]; then
log " Moving PostgreSQL data to M2-500 SSD..."
brew services stop postgresql@17 2>/dev/null || true
mv "$PG_DATA_DEFAULT" "$PG_DATA_SSD"
ln -s "$PG_DATA_SSD" "$PG_DATA_DEFAULT"
log " Created: $PG_DATA_DEFAULT → $PG_DATA_SSD"
brew services start postgresql@17
elif [[ -L "$PG_DATA_DEFAULT" ]]; then
log " PostgreSQL data symlink already exists: $PG_DATA_DEFAULT"
elif [[ -d "$PG_DATA_SSD" ]]; then
# SSD data exists but no default dir yet (fresh install after brew)
create_symlink "$PG_DATA_SSD" "$PG_DATA_DEFAULT"
brew services start postgresql@17 2>/dev/null || true
else
# Neither exists yet — PostgreSQL not initialized; let brew handle it on first start
warn " PostgreSQL data dir not found. Run 'brew services start postgresql@17' to initialize, then re-run to move data to SSD."
fi
# -------------------------------------------------------------------
# 14. .zshrc
# -------------------------------------------------------------------
log "Writing ~/.zshrc..."
cat > "$HOME/.zshrc" << 'ZSHRC'
# Powerlevel10k instant prompt (keep at top)
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# Oh My Zsh
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="powerlevel10k/powerlevel10k"
plugins=(git zsh-autosuggestions zsh-syntax-highlighting z docker node npm python)
source $ZSH/oh-my-zsh.sh
# Editor
export EDITOR='code'
# History
HISTSIZE=10000
SAVEHIST=10000
HISTFILE=~/.zsh_history
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_SPACE
setopt SHARE_HISTORY
# PATH
export PATH="/opt/homebrew/bin:$PATH"
export PATH="$HOME/fvm/bin:$PATH"
export PATH="$HOME/.pub-cache/bin:$PATH"
# Java (Android Studio JBR)
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
export PATH="$JAVA_HOME/bin:$PATH"
# Android SDK
export ANDROID_HOME="$HOME/Library/Android/sdk"
export PATH="$ANDROID_HOME/emulator:$PATH"
export PATH="$ANDROID_HOME/platform-tools:$PATH"
export PATH="$ANDROID_HOME/tools:$PATH"
export PATH="$ANDROID_HOME/tools/bin:$PATH"
# nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
# pyenv
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
command -v pyenv &>/dev/null && eval "$(pyenv init -)"
# fvm (Flutter)
export PATH="$HOME/fvm/bin:$PATH"
# Docker CLI completions
if [ -d "$HOME/.docker/completions" ]; then
fpath=("$HOME/.docker/completions" $fpath)
autoload -Uz compinit && compinit
fi
# --- Aliases ---
# Navigation
alias ll='ls -la'
alias ..='cd ..'
alias ...='cd ../..'
# Projects
alias walkin='cd ~/Workspaces/Projects/walkin-3.0 && tmux new-session -A -s walkin -d && claude --dangerously-skip-permissions'
alias pfweb='cd ~/Workspaces/PayEngine/pf-v2-web && tmux new-session -A -s pfweb -d && claude'
alias pfsystem='cd ~/Workspaces/PayEngine/pf-v2-system && make dev-system-up-local'
# Git
alias gs='git status'
alias gc='git commit'
alias gca='git commit --amend'
alias gp='git push'
alias gl='git log --oneline'
alias gco='git checkout'
alias gb='git branch'
# Docker
alias dps='docker ps'
alias dcu='docker compose up -d'
alias dcd='docker compose down'
# Powerlevel10k config
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
ZSHRC
# -------------------------------------------------------------------
# 15. .zprofile
# -------------------------------------------------------------------
log "Writing ~/.zprofile..."
cat > "$HOME/.zprofile" << 'ZPROFILE'
eval "$(/opt/homebrew/bin/brew shellenv zsh)"
ZPROFILE
# -------------------------------------------------------------------
# 16. VS Code extensions
# -------------------------------------------------------------------
if command -v code &>/dev/null; then
log "Installing VS Code extensions..."
EXTENSIONS=(
# Flutter / Dart
dart-code.dart-code
dart-code.flutter
alexisvt.flutter-snippets
aksharpatel47.vscode-flutter-helper
felixangelov.bloc
# JavaScript / TypeScript / React
dsznajder.es7-react-js-snippets
loiane.ts-extension-pack
ms-vscode.vscode-typescript-next
pmneo.tsimporter
jundat95.react-native-snippet
jasonnutter.search-node-modules
# Python
ms-python.python
ms-python.debugpy
ms-python.vscode-pylance
ms-python.vscode-python-envs
# Java / Spring
redhat.java
vscjava.vscode-java-pack
vscjava.vscode-java-debug
vscjava.vscode-java-dependency
vscjava.vscode-java-test
vscjava.vscode-maven
vscjava.vscode-gradle
vmware.vscode-boot-dev-pack
vmware.vscode-spring-boot
vscjava.vscode-spring-boot-dashboard
vscjava.vscode-spring-initializr
# C# / .NET
ms-dotnettools.csdevkit
ms-dotnettools.csharp
ms-dotnettools.vscode-dotnet-runtime
rahulsahay.csharp-aspnetcore
temilaj.asp-net-core-vs-code-extension-pack
# Go
golang.go
# Swift
swiftlang.swift-vscode
# PHP
bmewburn.vscode-intelephense-client
mehedidracula.php-namespace-resolver
# Infrastructure / Docker / Terraform
4ops.terraform
ms-azuretools.vscode-azureterraform
ms-azuretools.vscode-docker
coolbear.systemd-unit-file
# Prisma
prisma.prisma
# Git
eamodio.gitlens
github.vscode-pull-request-github
# Jupyter
ms-toolsai.jupyter
ms-toolsai.jupyter-keymap
ms-toolsai.jupyter-renderers
# Productivity / Utilities
formulahendry.auto-close-tag
formulahendry.code-runner
foxundermoon.shell-format
christian-kohler.path-intellisense
alefragnani.project-manager
alexdima.copy-relative-path
anjali.clipboard-history
naumovs.color-highlight
ritwickdey.liveserver
rvest.vs-code-prettier-eslint
schroeter.prettier-vscode-space-parenthesis
shd101wyy.markdown-preview-enhanced
bierner.markdown-mermaid
fcrespo82.markdown-table-formatter
simonsiefke.svg-preview
streetsidesoftware.code-spell-checker
qwtel.sqlite-viewer
treetrum.statusbar-format-on-save
ms-vscode.powershell
ms-vsliveshare.vsliveshare
redhat.vscode-yaml
redhat.vscode-commons
robertoachar.vscode-essentials-snippets
crazywolf.smali
llvm-vs-code-extensions.lldb-dap
anthropic.claude-code
firsttris.vscode-jest-runner
circlecodesolution.ccs-flutter-color
mrmlnc.vscode-jade-snippets
)
for ext in "${EXTENSIONS[@]}"; do
code --install-extension "$ext" --force 2>/dev/null || true
done
else
warn "VS Code CLI ('code') not found. Install VS Code and add to PATH, then re-run."
fi
# -------------------------------------------------------------------
# 17. GitHub CLI authentication reminder
# -------------------------------------------------------------------
echo ""
warn "Don't forget to authenticate GitHub CLI:"
echo " gh auth login"
echo ""
# -------------------------------------------------------------------
# 18. SSH keys reminder
# -------------------------------------------------------------------
warn "Restore your SSH keys to ~/.ssh/ (not automated for security):"
echo " - id_ed25519 / id_ed25519.pub"
echo " - id_rsa / id_rsa.pub"
echo " - id_rsa_handprint"
echo " - id_rsa_inapps / id_rsa_inapps.pub"
echo " - id_rsa_spoto / id_rsa_spoto.pub"
echo " - id_rsa_walkin / id_rsa_walkin.pub"
echo ""
# -------------------------------------------------------------------
# 19. SSH config
# -------------------------------------------------------------------
log "Writing ~/.ssh/config..."
mkdir -p "$HOME/.ssh"
chmod 700 "$HOME/.ssh"
cat > "$HOME/.ssh/config" << 'SSHCONFIG'
Host 3.142.201.135
HostName 3.142.201.135
User ec2-user
Host bitbucket.org
HostName bitbucket.org
User git
IdentityFile ~/.ssh/id_rsa
Host bitbucket.org-itrinvh
HostName bitbucket.org
User git
IdentityFile ~/.ssh/id_rsa_inapps
Host bitbucket.org-trinvhse
HostName bitbucket.org
User git
IdentityFile ~/.ssh/id_rsa_spoto
Host bitbucket.org-trinvhwalkin
HostName bitbucket.org
User git
IdentityFile ~/.ssh/id_rsa_walkin
Host ssh.dev.azure.com
HostName ssh.dev.azure.com
User git
IdentityFile ~/.ssh/id_rsa_handprint
SSHCONFIG
chmod 600 "$HOME/.ssh/config"
# -------------------------------------------------------------------
# Done!
# -------------------------------------------------------------------
echo ""
echo "=========================================="
echo " Setup complete!"
echo "=========================================="
echo ""
log "Installed: Homebrew, formulae, casks, Oh My Zsh, Powerlevel10k,"
log " zsh plugins, nvm, Node.js 22, pyenv, Python 3.10.4, Flutter 3.32.8,"
log " PostgreSQL 17, CocoaPods"
log "Configured: .zshrc, .zprofile, .gitconfig, .ssh/config"
log "Symlinked: M2-500 SSD directories"
log "VS Code: 74 extensions installed"
echo ""
warn "Manual steps remaining:"
echo " 1. Install manually-downloaded apps (see list above)"
echo " 2. Restore SSH keys from backup"
echo " 3. Run: gh auth login"
echo " 4. Restore Powerlevel10k config: p10k configure"
echo " 5. Install Docker Desktop and re-run to create Docker.raw symlink"
echo " 6. Open Android Studio to complete SDK setup"
echo " 7. Restore PostgreSQL databases: psql -f postgres_backup.sql postgres"
echo " 8. Cloudflare Tunnel: restore ~/.cloudflared/ from old Mac or run 'cloudflared tunnel login'"
echo ""
log "Restart your terminal or run: source ~/.zshrc"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment