macOS Shortcuts Generator
Generate valid .shortcut files that can be signed and imported into Apple's Shortcuts app.
Quick Start
A shortcut is a binary plist with this structure:
<?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>WFWorkflowActions</key>
<array>
<!-- Actions go here -->
</array>
<key>WFWorkflowClientVersion</key>
<string>2700.0.4</string>
<key>WFWorkflowHasOutputFallback</key>
<false/>
<key>WFWorkflowIcon</key>
<dict>
<key>WFWorkflowIconGlyphNumber</key>
<integer>59511</integer>
<key>WFWorkflowIconStartColor</key>
<integer>4282601983</integer>
</dict>
<key>WFWorkflowImportQuestions</key>
<array/>
<key>WFWorkflowMinimumClientVersion</key>
<integer>900</integer>
<key>WFWorkflowMinimumClientVersionString</key>
<string>900</string>
<key>WFWorkflowName</key>
<string>My Shortcut</string>
<key>WFWorkflowOutputContentItemClasses</key>
<array/>
<key>WFWorkflowTypes</key>
<array/>
</dict>
</plist>
Minimal Hello World
<dict>
<key>WFWorkflowActionIdentifier</key>
<string>is.workflow.actions.gettext</string>
<key>WFWorkflowActionParameters</key>
<dict>
<key>UUID</key>
<string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
<key>WFTextActionText</key>
<string>Hello World!</string>
</dict>
</dict>
<dict>
<key>WFWorkflowActionIdentifier</key>
<string>is.workflow.actions.showresult</string>
<key>WFWorkflowActionParameters</key>
<dict>
<key>Text</key>
<dict>
<key>Value</key>
<dict>
<key>attachmentsByRange</key>
<dict>
<key>{0, 1}</key>
<dict>
<key>OutputName</key>
<string>Text</string>
<key>OutputUUID</key>
<string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
<key>Type</key>
<string>ActionOutput</string>
</dict>
</dict>
<key>string</key>
<string></string>
</dict>
<key>WFSerializationType</key>
<string>WFTextTokenString</string>
</dict>
</dict>
</dict>
Core Concepts
1. Actions
Every action has:
- Identifier:
is.workflow.actions.<name> (e.g., is.workflow.actions.showresult)
- Parameters: Action-specific configuration in
WFWorkflowActionParameters
- UUID: Unique identifier for referencing this action's output
2. Variable References
To use output from a previous action:
- The source action needs a
UUID parameter
- Reference it using
OutputUUID in an attachmentsByRange dictionary
- Use
 (U+FFFC) as placeholder in the string where the variable goes
- Set
WFSerializationType to WFTextTokenString
3. Control Flow
Control flow actions (repeat, conditional, menu) use:
GroupingIdentifier: UUID linking start/middle/end actions
WFControlFlowMode: 0=start, 1=middle (else/case), 2=end
Common Actions Quick Reference
| Action |
Identifier |
Key Parameters |
| Text |
is.workflow.actions.gettext |
WFTextActionText |
| Show Result |
is.workflow.actions.showresult |
Text |
| Ask for Input |
is.workflow.actions.ask |
WFAskActionPrompt, WFInputType |
| Use AI Model |
is.workflow.actions.askllm |
WFLLMPrompt, WFLLMModel, WFGenerativeResultType |
| Comment |
is.workflow.actions.comment |
WFCommentActionText |
| URL |
is.workflow.actions.url |
WFURLActionURL |
| Get Contents of URL |
is.workflow.actions.downloadurl |
WFURL, WFHTTPMethod |
| Get Weather |
is.workflow.actions.weather.currentconditions |
(none required) |
| Open App |
is.workflow.actions.openapp |
WFAppIdentifier |
| Open URL |
is.workflow.actions.openurl |
WFInput |
| Alert |
is.workflow.actions.alert |
WFAlertActionTitle, WFAlertActionMessage |
| Notification |
is.workflow.actions.notification |
WFNotificationActionTitle, WFNotificationActionBody |
| Set Variable |
is.workflow.actions.setvariable |
WFVariableName, WFInput |
| Get Variable |
is.workflow.actions.getvariable |
WFVariable |
| Number |
is.workflow.actions.number |
WFNumberActionNumber |
| List |
is.workflow.actions.list |
WFItems |
| Dictionary |
is.workflow.actions.dictionary |
WFItems |
| Repeat (count) |
is.workflow.actions.repeat.count |
WFRepeatCount, GroupingIdentifier, WFControlFlowMode |
| Repeat (each) |
is.workflow.actions.repeat.each |
WFInput, GroupingIdentifier, WFControlFlowMode |
| If/Otherwise |
is.workflow.actions.conditional |
WFInput, WFCondition, GroupingIdentifier, WFControlFlowMode |
| Choose from Menu |
is.workflow.actions.choosefrommenu |
WFMenuPrompt, WFMenuItems, GroupingIdentifier, WFControlFlowMode |
| Find Photos |
is.workflow.actions.filter.photos |
WFContentItemFilter (see FILTERS.md) |
| Delete Photos |
is.workflow.actions.deletephotos |
photos (NOT WFInput!) |
Detailed Reference Files
For complete documentation, see:
- PLIST_FORMAT.md - Complete plist structure
- ACTIONS.md - All 427 WF*Action identifiers and parameters
- APPINTENTS.md - All 728 AppIntent actions
- PARAMETER_TYPES.md - All parameter value types and serialization formats
- VARIABLES.md - Variable reference system
- CONTROL_FLOW.md - Repeat, Conditional, Menu patterns
- FILTERS.md - Content filters for Find/Filter actions (photos, files, etc.)
- EXAMPLES.md - Complete working examples
Signing Shortcuts
Shortcuts MUST be signed before they can be imported. Use the macOS shortcuts CLI:
# Sign for anyone to use
shortcuts sign --mode anyone --input MyShortcut.shortcut --output MyShortcut_signed.shortcut
# Sign for people who know you
shortcuts sign --mode people-who-know-me --input MyShortcut.shortcut --output MyShortcut_signed.shortcut
The signing process:
- Write your plist as XML to a
.shortcut file
- Run
shortcuts sign to add cryptographic signature (~19KB added)
- The signed file can be opened/imported into Shortcuts.app
Workflow for Creating Shortcuts
- Define actions - List what the shortcut should do
- Generate UUIDs - Each action that produces output needs a unique UUID
- Build action array - Create each action dictionary with identifier and parameters
- Wire variable references - Connect outputs to inputs using
OutputUUID
- Wrap in plist - Add the root structure with icon, name, version
- Write to file - Save as
.shortcut (XML plist format is fine)
- Sign - Run
shortcuts sign to make it importable
Key Rules
- UUIDs must be uppercase:
A1B2C3D4-E5F6-7890-ABCD-EF1234567890
- WFControlFlowMode is an integer: Use
<integer>0</integer> not <string>0</string>
- Range keys use format:
{position, length} - e.g., {0, 1} for first character
- The placeholder character:
 (U+FFFC) marks where variables are inserted
- Control flow needs matching ends: Every repeat/if/menu start needs an end action with same
GroupingIdentifier
1---2name: shortcuts-generator3description: Generate macOS/iOS Shortcuts by creating plist files. Use when asked to create shortcuts, automate workflows, build .shortcut files, or generate Shortcuts plists. Covers 1,155 actions (427 WF*Actions + 728 AppIntents), variable references, and control flow.4---5
6# macOS Shortcuts Generator
7
8Generate valid `.shortcut` files that can be signed and imported into Apple's Shortcuts app.
9
10## Quick Start
11
12A shortcut is a binary plist with this structure:
13
14```xml
15<?xml version="1.0" encoding="UTF-8"?>
16<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
17<plist version="1.0">
18<dict>
19 <key>WFWorkflowActions</key>
20 <array>
21 <!-- Actions go here -->
22 </array>
23 <key>WFWorkflowClientVersion</key>
24 <string>2700.0.4</string>
25 <key>WFWorkflowHasOutputFallback</key>
26 <false/>
27 <key>WFWorkflowIcon</key>
28 <dict>
29 <key>WFWorkflowIconGlyphNumber</key>
30 <integer>59511</integer>
31 <key>WFWorkflowIconStartColor</key>
32 <integer>4282601983</integer>
33 </dict>
34 <key>WFWorkflowImportQuestions</key>
35 <array/>
36 <key>WFWorkflowMinimumClientVersion</key>
37 <integer>900</integer>
38 <key>WFWorkflowMinimumClientVersionString</key>
39 <string>900</string>
40 <key>WFWorkflowName</key>
41 <string>My Shortcut</string>
42 <key>WFWorkflowOutputContentItemClasses</key>
43 <array/>
44 <key>WFWorkflowTypes</key>
45 <array/>
46</dict>
47</plist>
48```
49
50### Minimal Hello World
51
52```xml
53<dict>
54 <key>WFWorkflowActionIdentifier</key>
55 <string>is.workflow.actions.gettext</string>
56 <key>WFWorkflowActionParameters</key>
57 <dict>
58 <key>UUID</key>
59 <string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
60 <key>WFTextActionText</key>
61 <string>Hello World!</string>
62 </dict>
63</dict>
64<dict>
65 <key>WFWorkflowActionIdentifier</key>
66 <string>is.workflow.actions.showresult</string>
67 <key>WFWorkflowActionParameters</key>
68 <dict>
69 <key>Text</key>
70 <dict>
71 <key>Value</key>
72 <dict>
73 <key>attachmentsByRange</key>
74 <dict>
75 <key>{0, 1}</key>
76 <dict>
77 <key>OutputName</key>
78 <string>Text</string>
79 <key>OutputUUID</key>
80 <string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
81 <key>Type</key>
82 <string>ActionOutput</string>
83 </dict>
84 </dict>
85 <key>string</key>
86 <string></string>
87 </dict>
88 <key>WFSerializationType</key>
89 <string>WFTextTokenString</string>
90 </dict>
91 </dict>
92</dict>
93```
94
95## Core Concepts
96
97### 1. Actions
98Every action has:
99- **Identifier**: `is.workflow.actions.<name>` (e.g., `is.workflow.actions.showresult`)
100- **Parameters**: Action-specific configuration in `WFWorkflowActionParameters`
101- **UUID**: Unique identifier for referencing this action's output
102
103### 2. Variable References
104To use output from a previous action:
1051. The source action needs a `UUID` parameter
1062. Reference it using `OutputUUID` in an `attachmentsByRange` dictionary
1073. Use `` (U+FFFC) as placeholder in the string where the variable goes
1084. Set `WFSerializationType` to `WFTextTokenString`
109
110### 3. Control Flow
111Control flow actions (repeat, conditional, menu) use:
112- `GroupingIdentifier`: UUID linking start/middle/end actions
113- `WFControlFlowMode`: 0=start, 1=middle (else/case), 2=end
114
115## Common Actions Quick Reference
116
117| Action | Identifier | Key Parameters |
118|--------|------------|----------------|
119| Text | `is.workflow.actions.gettext` | `WFTextActionText` |
120| Show Result | `is.workflow.actions.showresult` | `Text` |
121| Ask for Input | `is.workflow.actions.ask` | `WFAskActionPrompt`, `WFInputType` |
122| Use AI Model | `is.workflow.actions.askllm` | `WFLLMPrompt`, `WFLLMModel`, `WFGenerativeResultType` |
123| Comment | `is.workflow.actions.comment` | `WFCommentActionText` |
124| URL | `is.workflow.actions.url` | `WFURLActionURL` |
125| Get Contents of URL | `is.workflow.actions.downloadurl` | `WFURL`, `WFHTTPMethod` |
126| Get Weather | `is.workflow.actions.weather.currentconditions` | (none required) |
127| Open App | `is.workflow.actions.openapp` | `WFAppIdentifier` |
128| Open URL | `is.workflow.actions.openurl` | `WFInput` |
129| Alert | `is.workflow.actions.alert` | `WFAlertActionTitle`, `WFAlertActionMessage` |
130| Notification | `is.workflow.actions.notification` | `WFNotificationActionTitle`, `WFNotificationActionBody` |
131| Set Variable | `is.workflow.actions.setvariable` | `WFVariableName`, `WFInput` |
132| Get Variable | `is.workflow.actions.getvariable` | `WFVariable` |
133| Number | `is.workflow.actions.number` | `WFNumberActionNumber` |
134| List | `is.workflow.actions.list` | `WFItems` |
135| Dictionary | `is.workflow.actions.dictionary` | `WFItems` |
136| Repeat (count) | `is.workflow.actions.repeat.count` | `WFRepeatCount`, `GroupingIdentifier`, `WFControlFlowMode` |
137| Repeat (each) | `is.workflow.actions.repeat.each` | `WFInput`, `GroupingIdentifier`, `WFControlFlowMode` |
138| If/Otherwise | `is.workflow.actions.conditional` | `WFInput`, `WFCondition`, `GroupingIdentifier`, `WFControlFlowMode` |
139| Choose from Menu | `is.workflow.actions.choosefrommenu` | `WFMenuPrompt`, `WFMenuItems`, `GroupingIdentifier`, `WFControlFlowMode` |
140| Find Photos | `is.workflow.actions.filter.photos` | `WFContentItemFilter` (see FILTERS.md) |
141| Delete Photos | `is.workflow.actions.deletephotos` | `photos` (**NOT** `WFInput`!) |
142
143## Detailed Reference Files
144
145For complete documentation, see:
146- [PLIST_FORMAT.md](PLIST_FORMAT.md) - Complete plist structure
147- [ACTIONS.md](ACTIONS.md) - All 427 WF*Action identifiers and parameters
148- [APPINTENTS.md](APPINTENTS.md) - All 728 AppIntent actions
149- [PARAMETER_TYPES.md](PARAMETER_TYPES.md) - All parameter value types and serialization formats
150- [VARIABLES.md](VARIABLES.md) - Variable reference system
151- [CONTROL_FLOW.md](CONTROL_FLOW.md) - Repeat, Conditional, Menu patterns
152- [FILTERS.md](FILTERS.md) - Content filters for Find/Filter actions (photos, files, etc.)
153- [EXAMPLES.md](EXAMPLES.md) - Complete working examples
154
155## Signing Shortcuts
156
157Shortcuts MUST be signed before they can be imported. Use the macOS `shortcuts` CLI:
158
159```bash
160# Sign for anyone to use
161shortcuts sign --mode anyone --input MyShortcut.shortcut --output MyShortcut_signed.shortcut
162
163# Sign for people who know you
164shortcuts sign --mode people-who-know-me --input MyShortcut.shortcut --output MyShortcut_signed.shortcut
165```
166
167The signing process:
1681. Write your plist as XML to a `.shortcut` file
1692. Run `shortcuts sign` to add cryptographic signature (~19KB added)
1703. The signed file can be opened/imported into Shortcuts.app
171
172## Workflow for Creating Shortcuts
173
1741. **Define actions** - List what the shortcut should do
1752. **Generate UUIDs** - Each action that produces output needs a unique UUID
1763. **Build action array** - Create each action dictionary with identifier and parameters
1774. **Wire variable references** - Connect outputs to inputs using `OutputUUID`
1785. **Wrap in plist** - Add the root structure with icon, name, version
1796. **Write to file** - Save as `.shortcut` (XML plist format is fine)
1807. **Sign** - Run `shortcuts sign` to make it importable
181
182## Key Rules
183
1841. **UUIDs must be uppercase**: `A1B2C3D4-E5F6-7890-ABCD-EF1234567890`
1852. **WFControlFlowMode is an integer**: Use `<integer>0</integer>` not `<string>0</string>`
1863. **Range keys use format**: `{position, length}` - e.g., `{0, 1}` for first character
1874. **The placeholder character**: `` (U+FFFC) marks where variables are inserted
1885. **Control flow needs matching ends**: Every repeat/if/menu start needs an end action with same `GroupingIdentifier`