install.sh. Adding your own module follows the same pattern: create a directory, add an install.sh, and register it in provision.sh. The scaffold.sh script handles the directory and file creation for you.
How modules work
Each module is a subdirectory of the Orchard root. At minimum, every module contains aninstall.sh that performs its work. Modules can also include a test.bats file with Bats tests. The main provision.sh runs every registered module in order:
provision.sh
install_scripts array. The order matters — modules run top to bottom, so place your module after any dependencies it has.
Creating a module with scaffold.sh
Runscaffold.sh from the Orchard root, passing your module name as the argument:
my-module/install.sh— a minimal shell script with#!/bin/bash -euo pipefail, marked executablemy-module/test.bats— a Bats test file with a placeholder failing test to remind you to write real tests
my-module/install.sh
my-module/test.bats
scaffold.sh automatically runs chmod +x on the generated install.sh. If you create an install.sh manually without using scaffold.sh, you must make it executable yourself: chmod +x my-module/install.sh. Otherwise provision.sh will fail with a permission error when it tries to run it.Complete example: git global settings
Here is a walkthrough of creating a module that writes global Git configuration settings.Generate the module
Run This creates
scaffold.sh from the Orchard root:git-config/install.sh and git-config/test.bats.Write the install logic
Open Each line runs as a standard shell command. You can use any tool that is available on the system — including packages installed by earlier modules in
git-config/install.sh and add the commands you want to run. For example:git-config/install.sh
provision.sh.Register the module in provision.sh
Open
provision.sh and add git-config to the install_scripts array. Place it after brew-packages so that Git is already installed when the module runs:provision.sh
Run provision.sh
Execute the provisioner to run your new module along with everything else:To run only your new module during development, call its
install.sh directly:Replace the placeholder test
Open Orchard runs all
git-config/test.bats and replace the failing placeholder with a real assertion. For example:git-config/test.bats
test.bats files at the end of provision.sh via test.sh. A failing placeholder test will cause the overall run to report failure until you replace it.Adding packages
Add Homebrew, cask, or Mac App Store packages to an existing module.
System settings
Modify defaults write values to tune macOS behavior.