Last active
May 12, 2026 06:37
-
-
Save martynhaigh/4441a32fdf9b46d7d4cb911a6323d95d to your computer and use it in GitHub Desktop.
Mac bootstrap for marty's dotfiles
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 | |
| # | |
| # Public Mac bootstrap. Live at: | |
| # https://gist.githubusercontent.com/martynhaigh/<GIST_ID>/raw/install.sh | |
| # | |
| # Run on a fresh Mac: | |
| # bash <(curl -fsSL https://gist.githubusercontent.com/.../install.sh) | |
| # | |
| # What it does: | |
| # 1. Installs Xcode Command Line Tools (sudo prompt). | |
| # 2. Installs Homebrew. | |
| # 3. Installs gh, chezmoi, age, and pipx (just enough to bootstrap). | |
| # 4. Logs you into GitHub via browser OAuth (Keeper autofills). | |
| # 5. Generates an SSH key (or reuses existing) and registers it with GitHub. | |
| # 6. Runs `chezmoi init --apply` against the private dotfiles repo. | |
| # 7. chezmoi prompts for machine context (work/personal) and user details. | |
| # 8. chezmoi takes over — installs Brewfiles, applies configs, runs macOS defaults. | |
| # | |
| # Idempotent: re-run any time. Skips steps that already succeeded. | |
| # --------------------------------------------------------------------------- | |
| set -Eeuo pipefail | |
| DOTFILES_REPO="[email protected]:martynhaigh/dotfiles.git" | |
| DOTFILES_REPO_HTTPS="https://github.com/martynhaigh/dotfiles.git" | |
| # Colours | |
| RED=$'\033[0;31m'; GRN=$'\033[0;32m'; YEL=$'\033[0;33m'; BLU=$'\033[0;34m'; RST=$'\033[0m' | |
| info() { printf "%s[INFO]%s %s\n" "$BLU" "$RST" "$*"; } | |
| ok() { printf "%s[ OK ]%s %s\n" "$GRN" "$RST" "$*"; } | |
| warn() { printf "%s[WARN]%s %s\n" "$YEL" "$RST" "$*"; } | |
| err() { printf "%s[ERR ]%s %s\n" "$RED" "$RST" "$*"; } | |
| prompt(){ printf "%s[ ?? ]%s %s " "$YEL" "$RST" "$*"; } | |
| trap 'err "Bootstrap failed at line $LINENO. Re-run when ready."' ERR | |
| # 1. Xcode CLI Tools --------------------------------------------------------- | |
| if xcode-select -p >/dev/null 2>&1; then | |
| ok "Xcode Command Line Tools already installed" | |
| else | |
| info "Installing Xcode Command Line Tools (a GUI prompt will appear)" | |
| xcode-select --install | |
| until xcode-select -p >/dev/null 2>&1; do sleep 5; done | |
| ok "Xcode Command Line Tools installed" | |
| fi | |
| # 2. Homebrew ---------------------------------------------------------------- | |
| if command -v brew >/dev/null 2>&1; then | |
| ok "Homebrew already installed" | |
| else | |
| info "Installing Homebrew" | |
| NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
| fi | |
| # Ensure brew is on PATH for this script | |
| if [[ -x /opt/homebrew/bin/brew ]]; then | |
| eval "$(/opt/homebrew/bin/brew shellenv)" | |
| elif [[ -x /usr/local/bin/brew ]]; then | |
| eval "$(/usr/local/bin/brew shellenv)" | |
| fi | |
| # 3. Bootstrap tools --------------------------------------------------------- | |
| info "Installing bootstrap tools: gh, chezmoi, age, git-delta, jq, neovim, pipx" | |
| brew install gh chezmoi age git-delta jq neovim pipx | |
| pipx ensurepath >/dev/null 2>&1 || true | |
| export PATH="$HOME/.local/bin:$PATH" | |
| # 4. GitHub OAuth ------------------------------------------------------------ | |
| if gh auth status >/dev/null 2>&1; then | |
| ok "Already logged into GitHub" | |
| else | |
| info "Logging into GitHub via browser (Keeper will autofill)" | |
| gh auth login --web --git-protocol ssh --scopes "repo,read:org,admin:public_key" | |
| fi | |
| gh auth setup-git | |
| # 5. SSH key ----------------------------------------------------------------- | |
| SSH_KEY="$HOME/.ssh/id_ed25519" | |
| if [[ -f "$SSH_KEY" ]]; then | |
| ok "SSH key already present at $SSH_KEY (preserving)" | |
| else | |
| info "Generating SSH key" | |
| EMAIL_GUESS="$(git config --global user.email 2>/dev/null || echo "")" | |
| if [[ -z "$EMAIL_GUESS" ]]; then | |
| prompt "Email for SSH key:" | |
| read -r EMAIL_GUESS | |
| fi | |
| ssh-keygen -t ed25519 -C "$EMAIL_GUESS" -f "$SSH_KEY" -N "" | |
| fi | |
| # Add to ssh-agent + macOS Keychain | |
| mkdir -p ~/.ssh && chmod 700 ~/.ssh | |
| if ! grep -q "UseKeychain yes" ~/.ssh/config 2>/dev/null; then | |
| cat >> ~/.ssh/config <<'EOF' | |
| Host github.com | |
| HostName github.com | |
| User git | |
| AddKeysToAgent yes | |
| UseKeychain yes | |
| IdentityFile ~/.ssh/id_ed25519 | |
| EOF | |
| fi | |
| ssh-add --apple-use-keychain "$SSH_KEY" 2>/dev/null || ssh-add -K "$SSH_KEY" 2>/dev/null || true | |
| # Register the public key with GitHub if not already there | |
| PUBKEY="$(cat "${SSH_KEY}.pub")" | |
| HOSTNAME_LABEL="$(scutil --get ComputerName 2>/dev/null || hostname)-$(date +%Y%m%d)" | |
| if gh ssh-key list 2>/dev/null | grep -qF "$(awk '{print $2}' <<<"$PUBKEY")"; then | |
| ok "SSH key already registered with GitHub" | |
| else | |
| info "Uploading SSH key to GitHub as '$HOSTNAME_LABEL'" | |
| gh ssh-key add "${SSH_KEY}.pub" --title "$HOSTNAME_LABEL" --type authentication | |
| fi | |
| # Verify SSH works | |
| if ssh -T -o StrictHostKeyChecking=accept-new [email protected] 2>&1 | grep -q "successfully authenticated"; then | |
| ok "GitHub SSH auth working" | |
| else | |
| warn "Initial SSH probe ambiguous; chezmoi clone below will surface any real problem" | |
| fi | |
| # 6. chezmoi init ------------------------------------------------------------ | |
| if [[ -d "$HOME/.local/share/chezmoi/.git" ]]; then | |
| info "chezmoi already initialized — running update" | |
| chezmoi update --force | |
| else | |
| info "Cloning dotfiles repo via chezmoi (you'll be asked a few setup questions)" | |
| chezmoi init --apply --ssh "$DOTFILES_REPO" || { | |
| warn "SSH clone failed, falling back to HTTPS" | |
| chezmoi init --apply "$DOTFILES_REPO_HTTPS" | |
| } | |
| fi | |
| ok "Bootstrap complete." | |
| cat <<EOF | |
| Next steps: | |
| • Open a new terminal so PATH + shell config is fresh. | |
| • Read ~/Code/dotfiles/README.md (or wherever chezmoi cloned). | |
| • To make changes: | |
| chezmoi edit ~/.zshrc # opens the source file | |
| chezmoi apply # renders to ~ | |
| chezmoi cd # cd into the source repo | |
| • To sync from another machine: | |
| chezmoi update | |
| EOF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment