Figment.so
Mac hostingWebsite hostingGuidesHow to usePricing

Run macOS Shortcuts Remotely from the Command Line

MacOS Shortcuts can reach work shell scripts cannot touch directly: PDF export, image processing through system frameworks, URL-scheme calls, and cross-app automation. Apple's shortcuts tool makes any of those shortcuts callable from a script, a CI step, or a launchd job. This page shows how to pick a hosted Mac plan for the job, pin an input/output contract per shortcut, and verify every run with an exit-status test before scheduling it.

Pick a hosted Mac plan for the job

Start on Figment's $29/month virtual Intel macOS environment (2 vCPU, 8 GiB RAM, 80 GiB disk) if your Shortcut only needs standard Intel-compatible actions: text handling, file transformation, PDF export, URL-scheme calls, and macOS framework actions all run there. Access is through the browser console; outbound network to your own services works, and you can drive shortcuts run from the desktop terminal.

Move to an M-series Mac (from $95/month, request-based) when the Shortcut:

  • Uses an action that explicitly requires Apple silicon or launches an ARM-only binary.
  • Depends on Xcode 27 or a toolchain that requires Apple silicon, per Apple's porting guidance.
  • Calls an app that itself ships only as Apple silicon.

The $29 VM is a real macOS environment, not a jump host — shortcuts run executes locally on it. It just will not execute ARM-only code. Confirm the exact chip, RAM, and disk for the M-series plan in the quote; stock on physical hardware is confirmed per order.

The shortcuts CLI, verified against Apple's reference

Apple documents the tool in Run shortcuts from the command line. The operations relevant to automation:

CommandPurpose
shortcuts run "Name"Execute a shortcut by name
shortcuts run "Name" -i /path/to/filePass one or more file paths as input
shortcuts run "Name" -o /path/to/outputWrite output to a file
shortcuts run "Name" --output-type public.pdfPin the output format with a UTI
shortcuts listList installed shortcuts
shortcuts list --foldersList shortcut folders
shortcuts list -f FolderNameList shortcuts in a folder
shortcuts view "Name"Open the shortcut in the editor
shortcuts sign --mode people-who-know-me --input in.shortcut --output out.shortcutSign a shortcut for sharing

Exit code 0 means success; 1 means an action in the shortcut failed. Piping data into shortcuts run treats it as text input; use -i when you need the shortcut to receive file references. Check shortcuts --help on your installed macOS version to confirm current flags.

Pin an input/output contract before you automate

The common failure mode for scripted Shortcuts is assuming the shortcut handles inputs and errors the way it does when a human taps Run. Fill this in once per shortcut you plan to schedule:

FieldYour shortcut's value
Shortcut nameExact name as shown in Shortcuts.app
Input typeFile path / text / none
Input formate.g. .jpg, .txt, no input
Output typeFile / stdout text / none
Output formate.g. public.pdf, public.plain-text
Minimum output sizeBytes or character count you consider valid
Side effectsFiles written, URLs opened, emails sent
Needs user sessionYes for UI-touching actions, otherwise no

The last row matters most on a hosted Mac. The browser console gives you a logged-in session, so UI-touching actions work interactively, but a launchd daemon at system level is headless. Schedule UI-touching shortcuts as LaunchAgents that run in the user session, not as LaunchDaemons.

An exit-status test for every shortcut

Run this once before wiring any shortcut into launchd or CI. It checks the exit code and the output size against the contract.

#!/usr/bin/env bash
# test-shortcut.sh — verify a shortcut's input/output contract
# Usage: ./test-shortcut.sh "My Shortcut" /path/to/input /tmp/out.pdf 1000
set -euo pipefail

SHORTCUT="${1:?name required}"
INPUT="${2:-}"
OUTPUT="${3:-}"
MIN_BYTES="${4:-1000}"
LOG=$(mktemp -t shortcut-test.XXXXXX)

echo "Testing: $SHORTCUT" | tee "$LOG"
CMD=(shortcuts run "$SHORTCUT")
[[ -n "$INPUT"  ]] && CMD+=(-i "$INPUT")
[[ -n "$OUTPUT" ]] && CMD+=(-o "$OUTPUT")

if ! "${CMD[@]}" >>"$LOG" 2>&1; then
  echo "FAIL: shortcuts run exited non-zero. See $LOG and Console.app." >&2
  exit 1
fi

if [[ -n "$OUTPUT" ]]; then
  [[ -f "$OUTPUT" ]] || { echo "FAIL: expected $OUTPUT not created" >&2; exit 1; }
  BYTES=$(wc -c < "$OUTPUT" | tr -d ' ')
  if (( BYTES < MIN_BYTES )); then
    echo "FAIL: output $BYTES bytes, expected >= $MIN_BYTES" >&2
    exit 1
  fi
  echo "PASS: $OUTPUT ($BYTES bytes)"
else
  echo "PASS: no output file expected"
fi

This is an example, not a benchmark. Run it on your own input and tune MIN_BYTES to whatever "clearly not empty" means for the shortcut.

Schedule with launchd

Once the contract test passes, put the plist at ~/Library/LaunchAgents/com.example.my-shortcut.plist so it runs in your user session:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>com.example.my-shortcut</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/shortcuts</string>
    <string>run</string>
    <string>My Shortcut Name</string>
    <string>-i</string><string>/Users/agent/inputs/source.jpg</string>
    <string>-o</string><string>/Users/agent/outputs/result.pdf</string>
  </array>
  <key>StartCalendarInterval</key>
  <dict>
    <key>Hour</key><integer>6</integer>
    <key>Minute</key><integer>30</integer>
  </dict>
  <key>StandardOutPath</key><string>/Users/agent/Library/Logs/my-shortcut.log</string>
  <key>StandardErrorPath</key><string>/Users/agent/Library/Logs/my-shortcut-err.log</string>
</dict>
</plist>

Load it with launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.example.my-shortcut.plist. Each <string> in ProgramArguments is one argv entry, so a shortcut name with spaces needs no shell escaping — see Apple's Creating Launch Daemons and Agents. Confirm the binary path on your Mac with which shortcuts before pinning /usr/bin/shortcuts.

Failure and recovery checks

SymptomLikely causeFix
Exit 1, no outputA shortcut action erroredOpen Console.app, filter shortcuts, find the action error
Exit 1, "not found"Name mismatch or shortcut removedRun shortcuts list and match the exact name
Exit 0, no output fileShortcut has no save-file actionAdd "Save File", or drop -o from the contract
Output exists but emptyAction produced no dataRe-run with the real input; check the shortcut's expected input UTI
Works interactively, fails under launchdAction needs the user sessionUse a LaunchAgent, not a LaunchDaemon

For a specific action failure, drive the shortcut once from the browser-console terminal with Console.app open. The system log shows action-level detail the CLI exit code does not.

Operating limits on a hosted Mac

The $29 VM runs on shared Linux/KVM infrastructure, with no GPU acceleration and no audio pipeline, so image-processing shortcuts that rely on GPU encoders will be CPU-bound. If a scheduled shortcut uses several seconds of CPU and you plan to run it often, watch top from the terminal before adding more concurrent jobs. For GPU work, ARM-only code, or heavier parallelism, move the workload to an M-series plan and confirm the exact hardware in the quote.

Start or migrate

New setup: open Mac hosting, pick the plan that matches your shortcut's requirements, connect through the browser console, build and import the shortcut in Shortcuts.app, run the contract test, write the plist, and bootstrap it.

Migration: export each shortcut from Shortcuts.app (File → Export, or shortcuts sign for a distributable file), import on the new Mac, re-run the contract test with the same inputs, and load the plist.

Start your Mac →

Related guides


Subscribe for Figma design and website publishing guides.


Figment.so

Contact

Twitter

Website pricing

Compute index

About

Privacy

Terms