Automate macOS workstation setup with Ansible. The playbook installs Homebrew packages, copies shell and editor configuration, configures global Git identity, writes Worktrunk shell integration, and installs Pi agent settings.
Install and sign in to the 1Password CLI before running the playbook. ansible.cfg uses ./vault-password.sh, which reads the Ansible vault password from 1Password:
op signin
op read "op://Private/dotfiles Ansible vault/password"Install Ansible before the first run if the machine does not have it yet:
brew install ansibleBoth inventory entries target localhost:
homeconfigures the home laptop.workconfigures the work laptop.
Always pass --limit so Ansible loads one host's variables and does not run against both entries.
ansible-playbook site.yml --limit home
ansible-playbook site.yml --limit worksite.ymlinstalls packages and runs configuration roles.inventory.ymldefines thehomeandworklocalhost targets.ansible.cfgsetsinventory,roles_path, andvault_password_file.group_vars/all.ymldefines shared Homebrew packages, casks, config file mappings, Git variables, and Pi agent packages.host_vars/<host>/vars.ymldefines host-specific non-secret values such asansible_user,ansible_group, Python interpreter, andconfig_files_hostfor config files rendered only on that host.host_vars/<host>/vault.ymlstores vaulted host secrets such as Git name and email.roles/config_files/templates files fromtemplates/into the home directory.roles/git/configures global Git identity and excludes.roles/osx_settings/sets macOS system preferences viacommunity.general.osx_defaults, withoutbecome.roles/pi_agent/merges Pisettings.jsonandmcp.jsonwithout replacing unrelated existing keys.templates/contains managed dotfiles, editor settings, agent skills, and Codex rules.
The main playbook performs these steps:
- Install Homebrew taps from
homebrew_taps. - Update Homebrew (refresh tap/formula metadata only — no machine-wide upgrade).
- Install and keep current the formulae in
homebrew_packages(only those, not anything else installed on the machine). - Install and keep current the casks in
homebrew_casks(only those; self-updating casks are left to their own updater, per Homebrew's own outdated-check logic). On first install, if a cask's target app path is already occupied (e.g. a manually installed app), the task fails loudly instead of silently adopting or overwriting it. - Copy templated config files listed in
config_files. - Configure global Git user name, email, and excludes file.
- Configure macOS defaults, restarting affected apps only when a preference changes.
- Create
~/.config/mise/conf.d. - Generate Worktrunk shell integration at
~/.zshrc.worktrunk. - Configure Pi agent settings and MCP servers.
- Run
mise upgradeandpi update --extensionsafter the main tasks.
Host-specific variables are split so Ansible can auto-load plain values and encrypted secrets for the selected host:
host_vars/
home/
vars.yml
vault.yml
work/
vars.yml
vault.yml
Edit vaulted files with Ansible Vault so vault-password.sh can fetch the password from 1Password:
ansible-vault edit host_vars/home/vault.yml
ansible-vault edit host_vars/work/vault.ymlEncrypt a new or decrypted vault file with:
ansible-vault encrypt host_vars/home/vault.yml
ansible-vault encrypt host_vars/work/vault.ymlCheck syntax before applying changes:
ansible-playbook site.yml --limit home --syntax-check
ansible-playbook site.yml --limit work --syntax-checkPreview the task list for one host:
ansible-playbook site.yml --limit home --list-tasksRun check mode when you need a dry run:
ansible-playbook site.yml --limit home --check --diff
ansible-playbook site.yml --limit work --check --diff