Skip to content

Feature: Bootstrap Orchestration

1. Overview

  • Goal: Bring a macOS machine to its declared target state with a single, safe-to-repeat command.
  • Target audience: The Operator (interactive) and the Automation (unattended).
  • Entry point: ./sync_mac.sh (aliased to sync_mac).

sync_mac.sh is the orchestrator. It runs a fixed sequence of steps, each idempotent and each logging what it did in colour. A failure in package installation is tolerated; the rest of the configuration still runs.

2. Access & Trust Boundary

Runs entirely as the invoking macOS user. The only privilege escalation that can occur is a sudo prompt raised by Homebrew when a cask installs into /Applications. See Actors & Trust Boundary.

3. Orchestration sequence

The main function runs these steps in order:

#StepWhat it does
0macOS guardExit immediately if the OS is not Darwin.
1ensure_homebrewUse an existing brew, or install Homebrew, then load its shell environment.
2load / prompt / save choicesLoad persisted choices, ask (or skip) the container-runtime and browser questions, persist the answers.
3build_effective_brewfile + brew bundleCompose the base Brewfile with the interactive selections and install everything.
4apply_dotfiles_if_availableRun chezmoi apply if chezmoi and a source directory are present.
5setup_shellSymlink zsh/starship/ssh config; install zsh-autosuggestions and zsh-syntax-highlighting.
6setup_pythonInstall the latest stable Python via pyenv and set it global.
7setup_nodeInstall Node LTS via nvm and set it default.
8setup_javaInstall SDKMAN and the pinned Java LTS.
9setup_fontsInstall the Hack Nerd Font cask.
10setup_gitRewrite the global Git config, aliases, and template directory.
11setup_vimSymlink the vimrc and install the Dracula theme.
12setup_vscodeSymlink settings/keybindings and install the curated extensions.
13setup_opencodeSymlink the Opencode config and TUI files.
14restart_affected_appskillall Finder, Dock and SystemUIServer so changes take effect.

4. Business rules

  • Idempotent by construction. Each step checks the current state and does nothing when there is nothing to change.
  • Fail-soft packages. If brew bundle returns an error, the run records a warning, continues all remaining steps, and reports "synchronized with package install warnings" at the end.
  • macOS only. Any non-Darwin OS causes an immediate non-zero exit before anything is touched.
  • Missing sources are surfaced. If a source file for a symlink is absent, the step logs an error and returns rather than creating a broken link.

5. Behavioural scenarios (BDD)

gherkin
Scenario: First run on a fresh Mac
  Given a machine running macOS with no Homebrew installed
  When I run ./sync_mac.sh interactively
  Then Homebrew is installed
  And I am asked for a container runtime and a browser
  And all Brewfile packages plus my selections are installed
  And dotfiles, toolchains, Git and editors are configured
  And Finder, Dock and SystemUIServer are restarted

Scenario: Re-running on an already configured machine
  Given a machine that was previously synchronized
  When I run sync_mac again
  Then already-present symlinks and plugins are detected and skipped
  And only changed or missing items are applied
  And no existing configuration is destroyed

Scenario: A single package fails to install
  Given one cask in the Brewfile cannot be installed
  When brew bundle runs
  Then the failure is logged as a warning
  And the remaining configuration steps still run
  And the final message notes package install warnings

Scenario: Running on a non-macOS system
  Given the script is executed on Linux
  When it starts
  Then it prints an error and exits with a non-zero status
  And nothing on the machine is modified