setup.sh script automates the complete setup of a macOS development environment. It handles everything from cloning configuration files to installing software packages.
Overview
The setup script performs these tasks in order:- Ensures the config repository is cloned to
~/.config - Symlinks dotfiles from the config repo to your home directory
- Installs Xcode Command Line Tools if missing
- Enables Touch ID for sudo authentication
- Installs Homebrew if not present
- Runs
brew bundleto install all packages from the Brewfile
Script Configuration
The script uses these settings:CONFIG_REPO_URL:https://github.com/mac9sb/config.gitCONFIG_DIR:$HOME/.config
Utility Functions
log()
Logs informational messages with timestamps. Location: setup.sh:4-7 Signature:$1: Message to log$2: Log level (default: “INFO”)
2026-03-01T10:30:45-0800 [INFO] Starting macOS setup
die()
Logs an error message and exits the script with status code 1. Location: setup.sh:9-12 Signature:$*: Error message to log
warn()
Logs a warning message without stopping script execution. Location: setup.sh:14-16 Signature:$*: Warning message to log
Core Functions
ensure_config_repo()
Clones the config repository to~/.config if not already present.
Location: setup.sh:24-36
Behavior:
- If
~/.config/.gitexists, assumes repo is already present and returns - If
~/.configexists but is not a git repo, exits with error - Otherwise, clones the repository from GitHub
~/.config exists but is not a git repository.
symlink_home_dotfiles()
Creates symbolic links from dotfiles in~/.config to the home directory.
Location: setup.sh:39-49
Behavior:
- Iterates through all hidden files (
.prefix) in~/.config - Skips
.,.., and.git - Creates symlinks using
ln -sf(force overwrites existing files)
~/.config/.zshrc exists, creates ~/.zshrc pointing to it.
install_xcode_clt()
Installs Xcode Command Line Tools if not already present. Location: setup.sh:52-62 Behavior:- Checks if CLT is installed using
xcode-select -p - If missing, triggers the GUI installation prompt
- Exits with status 0 and asks user to re-run after installation completes
setup.sh after the GUI installation finishes.
enable_touchid_for_sudo()
Configures Touch ID authentication for sudo commands. Location: setup.sh:65-86 Behavior:- Checks for
/etc/pam.d/sudo_local.template - If target file already has Touch ID enabled, skips
- Copies template to
/etc/pam.d/sudo_local - Uncomments the
pam_tid.soline using sed
/etc/pam.d/sudo_local.
Error handling: If modification fails, logs a warning but continues execution.
install_brew_if_missing()
Installs Homebrew if not already present on the system. Location: setup.sh:89-97 Behavior:- Checks if
brewcommand is available - If missing, downloads and runs the official Homebrew installation script
https://brew.sh/install
brew_bundle()
Runsbrew bundle to install all packages defined in the Brewfile.
Location: setup.sh:100-111
Behavior:
- Changes to
$CONFIG_DIRdirectory - Verifies Brewfile exists
- Sources Homebrew shell environment
- Executes
brew bundleto install all packages
Execution Flow
The main execution block (setup.sh:114-121) runs these functions in order:Error Handling Strategy
The script uses several error handling approaches:- Fatal errors: Use
die()to log and exit (e.g., wrong OS, conflicting paths) - Non-fatal warnings: Use
warn()for issues that don’t prevent continuation - Early returns: Functions check if work is already done and return early
- Set flags:
set -euensures the script exits on any command failure or undefined variable