#!/usr/bin/env bash set -euo pipefail # Bootstrap a fresh macOS machine. # This script handles only the essentials that must exist BEFORE chezmoi can # run. Everything else (packages, shell config, defaults, etc.) is managed by # chezmoi run_once_ and run_onchange_ scripts triggered by `chezmoi apply`. # When run via curl-pipe-to-bash, stdin is the script stream, not the terminal. # Reconnect stdin to the terminal so interactive prompts work. if [ ! -t 0 ]; then exec < /dev/tty fi echo "==> Bootstrapping macOS machine..." # 1. Keep sudo alive for the duration of the script sudo -v while true; do sudo -n true; sleep 55; kill -0 "$$" || exit; done 2>/dev/null & SUDO_PID=$! cleanup() { kill "$SUDO_PID" 2>/dev/null; } trap cleanup EXIT INT TERM # 2. Install Homebrew if not present (casks, fonts + a few formulae only) if ! command -v brew &>/dev/null && [ ! -x /opt/homebrew/bin/brew ]; then echo "==> Installing Homebrew..." NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi if [ -x /opt/homebrew/bin/brew ]; then eval "$(/opt/homebrew/bin/brew shellenv)" fi # 3. Install mise (standalone, self-updating). CLI tools come from mise, not brew. # gh + chezmoi run via `mise exec` until chezmoi applies the real mise config # (`mise use -g` here would write config.toml and conflict with chezmoi apply). if [ ! -x "$HOME/.local/bin/mise" ]; then echo "==> Installing mise..." curl -fsSL https://mise.run | sh fi gh() { "$HOME/.local/bin/mise" exec gh@latest -- gh "$@"; } chezmoi() { "$HOME/.local/bin/mise" exec chezmoi@latest -- chezmoi "$@"; } # 4. Ensure GitHub auth (needed for private repo clone) if ! gh auth status &>/dev/null; then echo "==> GitHub authentication required to clone dotfiles..." gh auth login fi gh auth setup-git # Authenticated GitHub API calls during apply (mise github:/aqua: backends # hit anonymous rate limits on a fresh machine). MISE_ prefix so only mise # treats it as a credential; never echoed. MISE_GITHUB_TOKEN="$(gh auth token)" export MISE_GITHUB_TOKEN # Symlink to ~/Developer/dotfiles for convenience. Done before apply because # 99-macos-defaults restarts apps and the rest of this script may not run. DOTFILES_DIR="$(chezmoi source-path)" if [ ! -e "$HOME/Developer/dotfiles" ]; then mkdir -p "$HOME/Developer" ln -sf "$DOTFILES_DIR" "$HOME/Developer/dotfiles" fi # 5. Apply dotfiles # chezmoi init will prompt for name, email, and machine_type via .chezmoi.yaml.tmpl # chezmoi apply triggers all run_once_ and run_onchange_ scripts automatically echo "==> Initializing chezmoi (you'll be prompted for identity info)..." chezmoi init --apply dalberto echo "" echo "==> Bootstrap complete!" echo "" echo " Remaining manual steps:" STEPS_FILE="$DOTFILES_DIR/MANUAL_STEPS.md" if [ -f "$STEPS_FILE" ]; then sed -n '/^## After bootstrap/,$ { /^## /d; /^$/d; s/^/ /; p; }' "$STEPS_FILE" else echo " See MANUAL_STEPS.md in the dotfiles repo." fi