Choose the automation

Design input and output

Give an automation explicit data types, paths, exit behavior, and output so it can run from more than one trigger.

10 minute lesson

~~~

An automation that silently reads the current Finder selection is hard to test. You cannot run it from a script, you cannot write a fixture for it, and it behaves differently depending on which window happens to be frontmost. Prefer explicit input such as file paths, text, or a project directory.

The same goes for output. An automation that “just does things” leaves the next step nothing to work with. Print the paths you created on stdout, keep messages on stderr, and exit non-zero on failure. That is the whole interface.

For a shell command, write the contract before the implementation:

input: one existing image path
output: new JPG path on stdout
failure: non-zero exit with message on stderr
side effect: original remains unchanged

Then implement exactly that, and nothing more:

#!/bin/zsh
if [[ ! -f "$1" ]]; then
  echo "input file not found: $1" >&2
  exit 1
fi
output="${1%.*}.jpg"
sips -s format jpeg "$1" --out "$output" >/dev/null
echo "$output"

sips is the built-in macOS image tool, so this runs on any Mac. Verify the contract from both directions:

./to-jpg.sh ~/Desktop/sample.png
# /Users/flavio/Desktop/sample.jpg
echo $?
# 0

./to-jpg.sh missing.png
# input file not found: missing.png
echo $?
# 1

Because data goes to stdout and complaints go to stderr, another program can capture the result with output=$(./to-jpg.sh "$file") without accidentally parsing error text as a path. That is what makes the automation trigger-independent: a Shortcut, a scheduled job, and your own terminal all call the same contract and read the same answer.

Shortcuts can follow the same contract with accepted input types and Stop and Output. Declare which types the shortcut receives, decide what happens when no input arrives, and end with an explicit output instead of relying on whatever the last action happened to return.

The common failure here is mixing the streams. If your script echoes progress messages to stdout, the caller receives “processing sample.png” glued to the real path, and the next step fails on a file that does not exist. Everything that is not the answer belongs on stderr.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →