Terminal commands

Prefab runs in the macOS sandbox, which means it cannot run a shell command by itself. Commands go through a small script that lives outside the sandbox, in your own Application Scripts folder, and nothing runs until you have switched the feature on and installed that script.

Nothing runs until you have switched the feature on. There is no second step: Windows apps are not sandboxed, so Prefab starts a command itself rather than handing it to a helper the way it has to on macOS. The switch is in Settings ▸ Permissions and is off until you turn it on.

Switching it on

Terminal commands are off unless you turn them on in Settings ▸ Permissions ▸ Terminal Access. The switch is there for every kind of user. The experience you chose when you set Prefab up only decides whether it starts on or off.

The Terminal Access section of Prefab's Permissions settings, with a switch for terminal commands and the shell runner's status below it

Shown on macOS. This screen has no Windows equivalent.

Under the switch, the Shell runner row gives the status and the version installed.
Prefab's Permissions settings on Windows, with the switch for terminal commands
Prefab's Permissions settings on Windows, with the switch for terminal commands
The switch is the whole of it. There is no runner to install.

Installing the shell runner

Turning the switch on offers the install straight away. It happens once.

Turn on Terminal commands

Prefab checks whether the runner is already there and offers to install it if not. The button beside the status starts the same thing at any time.

Save the script where the panel suggests

A save panel appears, already pointed at your Application Scripts folder (~/Library/Application Scripts/) with the name prefab-runner.sh filled in. Saving it there is what gives Prefab permission to run it. A sandboxed app cannot put a file in that folder on its own, which is why you are asked rather than told.

Check the status

The Shell runner row reads Ready, with the version underneath. Test runs a command through the script and reports what came back below the buttons.

Nothing runs until the runner is installed

With the setting off, or the script not installed, a terminal action does not run and the deploy reports why. The folder and files are still created, but the command is not attempted. If a template you shared with someone relies on a command, they have to do this on their own Mac too.

What the command runs in

The runner is a zsh script. Before it runs anything it sources ~/.zprofile and ~/.zshrc, and loads nvm from ~/.nvm if it is there, so commands see the same environment you get in Terminal: Homebrew on the PATH, the Node version you actually use, your own aliases and functions.

The working directory is the folder the action is attached to, so a command can be written as though you had already cd-ed into it. Placeholders are replaced before the command runs, so git commit -m "Start of {{project_name}}" uses the value you gave for that deploy.

For a command attached to a watched folder rather than run at deploy, the file that arrived is available as {{file}} - quote it, as paths contain spaces - with {{file_name}} for the name on its own. That case is covered in the Rule reference.

When a command fails

The exit code comes back to Prefab, and a non-zero one is reported at the end of the deploy along with anything the command printed to standard error.

Continue on error decides what happens next. With it off, a failed command stops the actions after it on the same item. With it on, the rest run regardless - reasonable for something optional, less so for a command the next one depends on.

Timeouts

Each command carries a Timeout in seconds, 300 by default. The runner starts a watchdog alongside the command, and when the time is up it ends the command and everything the command started. Prefab reports it as having timed out rather than as a failure with an odd exit code, so one command that hangs cannot hold up the ones behind it.

Set the timeout to 0 to wait indefinitely. Do that only for something you are sure will finish, as nothing else on that item runs until it does.

Updating the runner

The installed script records which version of itself it is, and Settings reads that version back without running anything. The Shell runner row shows what you have against what this build of Prefab expects, and the button beside it is always offered: Install Shell Runner when there is none, Update Shell Runner when Prefab has moved on, and Reinstall Shell Runner otherwise, for a script that has been edited or removed by hand. Each of them walks through the same save panel.

An older script is worth replacing when the update is offered. It still runs commands, but it cannot tell Prefab whether one succeeded, so every command looks as though it worked, including the ones that did not. Timeouts are not enforced on an older script either - Prefab does not send one, because a script that predates them would treat the extra argument as part of the command.