Skip to content

Conditions and Skipping

Rod Christiansen edited this page Sep 3, 2026 · 1 revision

Conditions and Skipping

BootstrapMate has one conditional key, skipIf, and it gates on processor architecture and nothing else. This page covers what it accepts, how a skipped item is reported, and the defect you need to know about before you put it in a production manifest.

What can be conditional

skipIf is the only condition in the schema. There is no OS-version check, no model check, no hostname or site check, no dependency between items, and no required flag. Items in a stage always run in array order and each is attempted independently.

The other ways an item can be passed over are not conditions you author:

  • A package whose packageid and version show a new-enough receipt is skipped as already installed.
  • Any item whose payload already exists at file with a matching hash skips only the download, then still installs or runs.
  • A preflight script exiting 0 skips both remaining stages — see Stages.

How skipIf is evaluated

The value is lowercased and matched by substring against two groups:

Value contains Item is skipped on
arm or apple_silicon Apple silicon (arm64)
x86_64 or intel Intel (x86_64)

The key names the architecture to skip on, not the architecture to run on. So "skipIf": "arm64" means "not on Apple silicon", and expressing "only on Apple silicon" means excluding Intel:

{
  "file": "/Library/Application Support/BootstrapMate/rosetta-setup.sh",
  "hash": "0000000000000000000000000000000000000000000000000000000000000000",
  "url": "https://example.com/bootstrap/scripts/rosetta-setup.sh",
  "name": "Apple Silicon Only",
  "type": "rootscript",
  "skipIf": "x86_64"
}

Matching is by substring, so arm64, arm, apple_silicon are equivalent, as are x86_64 and intel. A value matching neither group — "universal", "none", an empty string, a typo — matches nothing and the item runs everywhere. There is no error for an unrecognised value.

The download side-effect

skipIf is evaluated in two separate places, and they disagree. The stage loop uses the table above to skip the item. The downloader uses the opposite sense, and returns early — reporting success without fetching anything — on the architecture where the item is meant to run.

The practical consequence: an item carrying skipIf never downloads its payload. On the named architecture it is skipped, correctly. On the other architecture it is not skipped, but its payload is never fetched, so the install or script step then acts on a file that is not there and the item fails. It only succeeds if the file already happens to exist at file with a matching hash from an earlier run.

Until that is resolved, express architecture differences another way: serve a different manifest URL per architecture, or make the item a rootscript that checks /usr/bin/uname -m itself and exits 0 when there is nothing to do. See Troubleshooting and Gotchas.

How a skip is reported

A skipped item is neither a success nor a failure. The stage loop moves to the next item, and the stage can still finish Completed.

In the log:

[SKIPPED] Munki Admin Tools (architecture: arm64)

In the SwiftDialog window the item's row shows "Not for this architecture". An already-installed package shows the already-installed status instead. Skipped items still count towards the dialog's total item count, so the progress bar reflects a total that includes work that was never attempted.

There is no line in the reported run summary identifying which items were skipped — the summary is per-stage, not per-item. The log is the only per-item record. See Logging and Reporting.

See also

Clone this wiki locally