macOS
Base system setup for macOS, using Homebrew as the package manager. It is the macOS counterpart to the ubuntu role and imports the same unix base role for the ~/.profile.d/ shell framework — so a single personal repo covers Ubuntu, macOS, and WSL.
On a Mac, list macos instead of ubuntu in your playbook.yaml.
What it does
- Installs Homebrew if it is missing and puts it on
PATHin~/.zprofile/~/.zshrc - Updates Homebrew (and optionally upgrades everything)
- Installs the baseline formulae (
jq,yq,ripgrep,fd,tree,shellcheck), the counterpart ofubuntu_system_packages(theagentsrole adds the agent-motivated packages on top) - Installs Homebrew taps, formulae, and casks, plus opt-in Mac App Store apps (
mas) - Applies the macOS system preferences you declare in
macos_defaults(defaults write) - Shapes the Dock with
dockutilfrommacos_dock_persist/macos_dock_remove - Imports the
unixbase role, sourcing the framework from both zsh login files (the locale also comes fromunix, viaunix_locale)
Variables
| Variable | Default | Description |
|---|---|---|
macos_update_homebrew | dotpro_upgrade (or false) | Run brew update during an apply (on under dotpro apply --upgrade) |
macos_upgrade_all | dotpro_upgrade (or false) | Run brew upgrade (off on a normal apply; it is slow) |
macos_system_packages | jq yq ripgrep fd tree shellcheck | Baseline formulae every machine gets, the counterpart of ubuntu_system_packages |
macos_homebrew_taps | [] | Extra taps |
macos_packages | [] | Extra formulae (tool roles install their own CLIs) |
macos_casks | [] | GUI apps / fonts to install as casks |
macos_mas_apps | [] | Mac App Store app ids (pulls in mas when non-empty) |
macos_dock_persist | [] | .app paths to keep in the Dock (label derived from the filename; pulls in dockutil when non-empty) |
macos_dock_remove | [] | Dock item labels to remove (e.g. default apps you don't use) |
macos_defaults | small conservative set | osx_defaults entries — {domain, key, type, value} |
macos_brew_profile_files | ['~/.zprofile', '~/.zshrc'] | Login files brew shellenv is written to (the framework's own sourcing is handled by the unix role) |
Homebrew, root, and zsh
Homebrew refuses to run as root, so every Homebrew task runs unprivileged (no become). The installer needs sudo for the one-time directory setup, which the install.sh bootstrap handles; the role only installs Homebrew as a fallback.
macOS defaults to zsh, which never reads ~/.profile. The unix role sources ~/.profile.d/init.sh from both ~/.zprofile (login) and ~/.zshrc (interactive) — it derives those files from unix_shell, which is zsh on macOS — and a load-once guard in init.sh keeps the second source a no-op. The zsh role (which unix selects here) then brings up zsh's completion system. This role only adds Homebrew's own env to those same login files (macos_brew_profile_files).
Config (defaults)
These are the default macOS preferences the role ships, applied with defaults write through community.general.osx_defaults. macos_defaults is a list of {domain, key, type, value} entries rather than a deep-merged dict, so the role writes exactly the keys you declare and leaves every other preference untouched ("settings, not files"). Redeclare a key in your own macos_defaults to change its value, or trim and extend the list. Apple doesn't publish a central catalogue of these keys; the community macos-defaults.com documents the commonly tweaked ones:
| Key | Value | Effect |
|---|---|---|
AppleShowAllExtensions | true | Always show file extensions in Finder, so you see each file's real type and a .pdf.app can't pose as a document |
KeyRepeat | 2 | Faster key-repeat once a key is held (lower is faster), so holding a key flies through text and lists |
InitialKeyRepeat | 15 | Shorter delay before a held key starts repeating (lower is shorter), so the keyboard feels responsive |
AppleShowScrollBars | Always | Keep scroll bars visible instead of only while scrolling, so you always see your position and can grab the bar |
All four ship in the NSGlobalDomain domain. Applied, the list runs the equivalent of:
defaults write NSGlobalDomain AppleShowAllExtensions -bool true
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15
defaults write NSGlobalDomain AppleShowScrollBars -string AlwaysSome keys take effect only after a logout or a killall Finder / killall Dock.
Dock
Set macos_dock_persist and macos_dock_remove to shape the Dock with dockutil, which the role installs through Homebrew only when either list is non-empty. Like macos_defaults, the role touches only the items you name and leaves the rest of the Dock in place ("settings, not files"):
macos_dock_persist: # default: []
- /Applications/Visual Studio Code.app
- /System/Applications/Utilities/Terminal.app
macos_dock_remove: # default: []
- Maps
- NewsEach apply lists the current Dock, removes the labels in macos_dock_remove that are present, and adds the apps in macos_dock_persist that are missing, matching by the label dockutil derives from the .app filename. New apps are appended to the end of the Dock, and the Dock restarts once, only when an item actually changed, so re-running is a no-op. Emptying the lists later leaves the current Dock as it is rather than clearing it; run --tags dock to manage just the Dock.
Aliases
| Alias | Command | Description |
|---|---|---|
version | sw_vers | Show the macOS version |
The shared aliases and functions (system, home, header, kv, list, …) come from the unix role.
Container runtime
The docker role installs colima plus the docker CLI and docker compose on macOS (docker_macos_runtime: colima). Start it once with colima start; the docker aliases then work as on Linux.