shortcuts-playground 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/agents/shortcut-builder.md +172 -0
- package/agents/shortcut-remixer.md +239 -0
- package/commands/build-shortcut.md +32 -0
- package/commands/remix-shortcut.md +34 -0
- package/opencode.json +30 -0
- package/package.json +47 -0
- package/plugin/validator.ts +179 -0
- package/skills/shortcuts-playground/ACTIONS.md +713 -0
- package/skills/shortcuts-playground/APPINTENTS.md +2760 -0
- package/skills/shortcuts-playground/AUTOMATION_TRIGGERS.md +133 -0
- package/skills/shortcuts-playground/BEST_PRACTICES.md +357 -0
- package/skills/shortcuts-playground/CHANGELOG.md +585 -0
- package/skills/shortcuts-playground/CONTROL_FLOW.md +777 -0
- package/skills/shortcuts-playground/DATE_TIME.md +75 -0
- package/skills/shortcuts-playground/EXAMPLES.md +738 -0
- package/skills/shortcuts-playground/FILTERS.md +697 -0
- package/skills/shortcuts-playground/HEALTHKIT.md +317 -0
- package/skills/shortcuts-playground/ICONS_AND_COLORS.md +89 -0
- package/skills/shortcuts-playground/JAVASCRIPT_WEBPAGE.md +51 -0
- package/skills/shortcuts-playground/PARAMETER_TYPES.md +1117 -0
- package/skills/shortcuts-playground/PLIST_FORMAT.md +296 -0
- package/skills/shortcuts-playground/README.md +77 -0
- package/skills/shortcuts-playground/SKILL.md +459 -0
- package/skills/shortcuts-playground/THIRD_PARTY_ACTIONS.md +77 -0
- package/skills/shortcuts-playground/TOOLKIT_SNAPSHOT.md +62 -0
- package/skills/shortcuts-playground/URL_SCHEMES.md +59 -0
- package/skills/shortcuts-playground/VARIABLES.md +569 -0
- package/skills/shortcuts-playground/assets/shortcuts-small.svg +14 -0
- package/skills/shortcuts-playground/assets/shortcuts.png +0 -0
- package/skills/shortcuts-playground/data/healthkit-ios26.2-reference.json +2603 -0
- package/skills/shortcuts-playground/data/macos27-shortpy-grounding.json +4085 -0
- package/skills/shortcuts-playground/data/macos27-workflow-trigger-samples.json +1 -0
- package/skills/shortcuts-playground/data/shortcuts-glyph-synonyms.json +5102 -0
- package/skills/shortcuts-playground/data/shortcuts-icon-colors.json +107 -0
- package/skills/shortcuts-playground/data/shortcuts-official-glyph-mapping.json +509 -0
- package/skills/shortcuts-playground/data/toolkit-v63-tool-ids.json +1806 -0
- package/skills/shortcuts-playground/data/toolkit-v78-first-party-enum-cases.json +1 -0
- package/skills/shortcuts-playground/data/toolkit-v78-first-party-parameter-keys.json +1 -0
- package/skills/shortcuts-playground/data/toolkit-v78-ios27-tool-ids.json +1222 -0
- package/skills/shortcuts-playground/data/toolkit-v78-tool-ids.json +2745 -0
- package/skills/shortcuts-playground/data/toolkit-v78-trigger-parameter-keys.json +1051 -0
- package/skills/shortcuts-playground/golden-shortcuts/index.jsonl +19 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/1be4dde95b794253bf82438e201b33e7.xml +174 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/2e0fb675e45948aaacee7e534f910492.xml +1016 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/332c12a0060043b388b22b806be7ab58.xml +1924 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/3dd4ee24e43f464f92adaa70a0311eaa.xml +1177 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/4d102301c6e646faa7a8a221f4f4ec98.xml +321 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/51cc4e26d1044893a0c3f2f3630cf2d2.xml +1933 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/623e7f1ca5f948e2bd53811fec63e544.xml +136 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/6a18b76843ac45c384ac3400f3740997.xml +1791 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/71f0cacb0f604b399b76c5dcb7286e7c.xml +2228 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/807525ed9f974829bc8494defac923a8.xml +259 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/8ab0d39826ab4249be58672763caa3ba.xml +420 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/91c45fd3fd3b427897d9ba485efb1227.xml +800 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/97be626bb25c41709d175646a7f6d8f2.xml +424 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/ae59e10d409348f9bd33894f03f9beb4.xml +568 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/afa83b6be811483b9c32189c41eb9312.xml +391 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/cfdb083b857e4ac189629fa386d27cdc.xml +193 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/e01cebe192d64b2fbca80204d03d92ab.xml +111 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/ef669bcf8bad489d9ef4b88bfaf5772f.xml +780 -0
- package/skills/shortcuts-playground/golden-shortcuts/xml/f44f5caf5e3e48d4817e73af450c4404.xml +570 -0
- package/skills/shortcuts-playground/scripts/generate_healthkit_reference.py +394 -0
- package/skills/shortcuts-playground/scripts/lookup_action_grounding.py +1164 -0
- package/skills/shortcuts-playground/scripts/select_shortcut_icon_color.py +597 -0
- package/skills/shortcuts-playground/scripts/test_random_mixed_shortcuts.py +1067 -0
- package/skills/shortcuts-playground/scripts/test_wiring_regressions.py +2247 -0
- package/skills/shortcuts-playground/scripts/validate_shortcut.py +4526 -0
|
@@ -0,0 +1,697 @@
|
|
|
1
|
+
# Content Item Filters Reference
|
|
2
|
+
|
|
3
|
+
Documentation for `WFContentItemFilter` used in Find/Filter actions like FindPhotos, FindFiles, FindReminders, etc.
|
|
4
|
+
|
|
5
|
+
## Filter Structure
|
|
6
|
+
|
|
7
|
+
Filters are used in actions like `is.workflow.actions.filter.photos` to specify criteria for finding content.
|
|
8
|
+
|
|
9
|
+
### Basic Filter Template
|
|
10
|
+
|
|
11
|
+
```xml
|
|
12
|
+
<key>WFContentItemFilter</key>
|
|
13
|
+
<dict>
|
|
14
|
+
<key>Value</key>
|
|
15
|
+
<dict>
|
|
16
|
+
<key>WFActionParameterFilterPrefix</key>
|
|
17
|
+
<integer>1</integer>
|
|
18
|
+
<key>WFContentPredicateBoundedDate</key>
|
|
19
|
+
<false/>
|
|
20
|
+
<key>WFActionParameterFilterTemplates</key>
|
|
21
|
+
<array>
|
|
22
|
+
<!-- Filter conditions go here -->
|
|
23
|
+
</array>
|
|
24
|
+
</dict>
|
|
25
|
+
<key>WFSerializationType</key>
|
|
26
|
+
<string>WFContentPredicateTableTemplate</string>
|
|
27
|
+
</dict>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Operator Reference
|
|
33
|
+
|
|
34
|
+
Operators define the comparison type. These were discovered from Shortcuts internal JavaScript:
|
|
35
|
+
|
|
36
|
+
| Operator | Meaning | Use Case |
|
|
37
|
+
|----------|---------|----------|
|
|
38
|
+
| 2 | `is after` | Date is after a date/token |
|
|
39
|
+
| 3 | `>=` | Greater than or equal |
|
|
40
|
+
| 4 | `is` | Exact match |
|
|
41
|
+
| 5 | `is not` | Not equal |
|
|
42
|
+
| 8 | `begins with` | String prefix |
|
|
43
|
+
| 9 | `ends with` | String suffix |
|
|
44
|
+
| 99 | `contains` | String contains |
|
|
45
|
+
| 100 | `has any value` | Not empty |
|
|
46
|
+
| 101 | `does not have any value` | Is empty |
|
|
47
|
+
| 999 | `does not contain` | String not contains |
|
|
48
|
+
| 1000 | `is in the next` | Future date range |
|
|
49
|
+
| 1001 | `is in the last` | Past date range |
|
|
50
|
+
| 1002 | `is today` | Date is today |
|
|
51
|
+
| 1003 | `is between` | Date range |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Unit Reference
|
|
56
|
+
|
|
57
|
+
Units are used with date/time and enumeration filters:
|
|
58
|
+
|
|
59
|
+
### Date Units (for operators 1000, 1001)
|
|
60
|
+
|
|
61
|
+
| Unit | Meaning |
|
|
62
|
+
|------|---------|
|
|
63
|
+
| 4 | years |
|
|
64
|
+
| 8 | months |
|
|
65
|
+
| 8192 | weeks |
|
|
66
|
+
| 16384 | days |
|
|
67
|
+
|
|
68
|
+
### Boolean/Enum Unit
|
|
69
|
+
|
|
70
|
+
| Unit | Context |
|
|
71
|
+
|------|---------|
|
|
72
|
+
| 4 | Standard unit for boolean and enumeration values |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Filter Templates by Type
|
|
77
|
+
|
|
78
|
+
### Boolean Filter (e.g., Is a Screenshot)
|
|
79
|
+
|
|
80
|
+
```xml
|
|
81
|
+
<dict>
|
|
82
|
+
<key>Operator</key>
|
|
83
|
+
<integer>4</integer>
|
|
84
|
+
<key>Property</key>
|
|
85
|
+
<string>Is a Screenshot</string>
|
|
86
|
+
<key>Removable</key>
|
|
87
|
+
<true/>
|
|
88
|
+
<key>Values</key>
|
|
89
|
+
<dict>
|
|
90
|
+
<key>Bool</key>
|
|
91
|
+
<true/>
|
|
92
|
+
<key>Unit</key>
|
|
93
|
+
<integer>4</integer>
|
|
94
|
+
</dict>
|
|
95
|
+
</dict>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### "Is Today" Date Filter
|
|
99
|
+
|
|
100
|
+
The `is today` operator (1002) does NOT require Values:
|
|
101
|
+
|
|
102
|
+
```xml
|
|
103
|
+
<dict>
|
|
104
|
+
<key>Operator</key>
|
|
105
|
+
<integer>1002</integer>
|
|
106
|
+
<key>Property</key>
|
|
107
|
+
<string>Date Taken</string>
|
|
108
|
+
<key>Removable</key>
|
|
109
|
+
<true/>
|
|
110
|
+
</dict>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Find Calendar Events: Next Event After Now
|
|
114
|
+
|
|
115
|
+
For **Find Calendar Events** date predicates, use the date-specific operator codes. Do not use numeric comparison codes such as `3` (`>=`) for `Start Date` or `End Date`; Shortcuts can import that as a red invalid condition. The common "next event after now" pattern is:
|
|
116
|
+
|
|
117
|
+
- `Start Date is today`: `Operator = 1002`, `Values = {}`.
|
|
118
|
+
- `Start Date is after Current Date`: `Operator = 2`, `Values.Date = CurrentDate` token.
|
|
119
|
+
- Sort by `Start Date`, `Oldest First`, limit to `1`.
|
|
120
|
+
|
|
121
|
+
```xml
|
|
122
|
+
<dict>
|
|
123
|
+
<key>Operator</key>
|
|
124
|
+
<integer>1002</integer>
|
|
125
|
+
<key>Property</key>
|
|
126
|
+
<string>Start Date</string>
|
|
127
|
+
<key>Removable</key>
|
|
128
|
+
<true/>
|
|
129
|
+
<key>Values</key>
|
|
130
|
+
<dict/>
|
|
131
|
+
</dict>
|
|
132
|
+
<dict>
|
|
133
|
+
<key>Operator</key>
|
|
134
|
+
<integer>2</integer>
|
|
135
|
+
<key>Property</key>
|
|
136
|
+
<string>Start Date</string>
|
|
137
|
+
<key>Removable</key>
|
|
138
|
+
<true/>
|
|
139
|
+
<key>Values</key>
|
|
140
|
+
<dict>
|
|
141
|
+
<key>Date</key>
|
|
142
|
+
<dict>
|
|
143
|
+
<key>Value</key>
|
|
144
|
+
<dict>
|
|
145
|
+
<key>Type</key>
|
|
146
|
+
<string>CurrentDate</string>
|
|
147
|
+
</dict>
|
|
148
|
+
<key>WFSerializationType</key>
|
|
149
|
+
<string>WFTextTokenAttachment</string>
|
|
150
|
+
</dict>
|
|
151
|
+
</dict>
|
|
152
|
+
</dict>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Find Health Samples "Start Date Is Today" Filter
|
|
156
|
+
|
|
157
|
+
Verified from a manually created iOS Shortcuts XML example and generated shortcut failures. **Find Health Samples** uses the same `WFContentPredicateTableTemplate` wrapper, but the Health sample kind is a locked `Type` predicate row backed by an enumeration state. Do not use top-level `WFHealthQuantityType`, and do not use a `Value` predicate row with `Values.String`; current iOS Shortcuts renders that as an editable text filter instead of the Health type picker.
|
|
158
|
+
|
|
159
|
+
Use observed Find Health Samples picker labels. Examples: `Steps`, `Sleep`, `Walking + Running Distance`, `Active Calories`, and `Exercise Minutes`. Do not use SDK-derived labels such as `Sleep Analysis`, `Active Energy`, `Active Energy Burned`, or `Apple Exercise Time`.
|
|
160
|
+
|
|
161
|
+
```xml
|
|
162
|
+
<key>WFContentItemFilter</key>
|
|
163
|
+
<dict>
|
|
164
|
+
<key>Value</key>
|
|
165
|
+
<dict>
|
|
166
|
+
<key>WFActionParameterFilterPrefix</key>
|
|
167
|
+
<integer>1</integer>
|
|
168
|
+
<key>WFContentPredicateBoundedDate</key>
|
|
169
|
+
<false/>
|
|
170
|
+
<key>WFActionParameterFilterTemplates</key>
|
|
171
|
+
<array>
|
|
172
|
+
<dict>
|
|
173
|
+
<key>Bounded</key>
|
|
174
|
+
<true/>
|
|
175
|
+
<key>Operator</key>
|
|
176
|
+
<integer>4</integer>
|
|
177
|
+
<key>Property</key>
|
|
178
|
+
<string>Type</string>
|
|
179
|
+
<key>Removable</key>
|
|
180
|
+
<false/>
|
|
181
|
+
<key>Values</key>
|
|
182
|
+
<dict>
|
|
183
|
+
<key>Enumeration</key>
|
|
184
|
+
<dict>
|
|
185
|
+
<key>Value</key>
|
|
186
|
+
<string>Steps</string>
|
|
187
|
+
<key>WFSerializationType</key>
|
|
188
|
+
<string>WFStringSubstitutableState</string>
|
|
189
|
+
</dict>
|
|
190
|
+
</dict>
|
|
191
|
+
</dict>
|
|
192
|
+
<dict>
|
|
193
|
+
<key>Bounded</key>
|
|
194
|
+
<true/>
|
|
195
|
+
<key>Operator</key>
|
|
196
|
+
<integer>1002</integer>
|
|
197
|
+
<key>Property</key>
|
|
198
|
+
<string>Start Date</string>
|
|
199
|
+
<key>Removable</key>
|
|
200
|
+
<false/>
|
|
201
|
+
<key>Values</key>
|
|
202
|
+
<dict>
|
|
203
|
+
<key>Number</key>
|
|
204
|
+
<string>7</string>
|
|
205
|
+
<key>Unit</key>
|
|
206
|
+
<integer>16</integer>
|
|
207
|
+
</dict>
|
|
208
|
+
</dict>
|
|
209
|
+
</array>
|
|
210
|
+
</dict>
|
|
211
|
+
<key>WFSerializationType</key>
|
|
212
|
+
<string>WFContentPredicateTableTemplate</string>
|
|
213
|
+
</dict>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### "Is in the Last X" Date Filter
|
|
217
|
+
|
|
218
|
+
The `is in the last` operator (1001) requires Number and Unit:
|
|
219
|
+
|
|
220
|
+
```xml
|
|
221
|
+
<dict>
|
|
222
|
+
<key>Operator</key>
|
|
223
|
+
<integer>1001</integer>
|
|
224
|
+
<key>Property</key>
|
|
225
|
+
<string>Date Taken</string>
|
|
226
|
+
<key>Removable</key>
|
|
227
|
+
<true/>
|
|
228
|
+
<key>Values</key>
|
|
229
|
+
<dict>
|
|
230
|
+
<key>Number</key>
|
|
231
|
+
<integer>1</integer>
|
|
232
|
+
<key>Unit</key>
|
|
233
|
+
<integer>8192</integer> <!-- weeks -->
|
|
234
|
+
</dict>
|
|
235
|
+
</dict>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### "Is Between" Date Filter (verified against an Apple-built sample)
|
|
239
|
+
|
|
240
|
+
The `is between` operator (1003), **for date properties**, uses two value keys: `Date` for the lower bound (literal ISO date) and `AnotherDate` for the upper bound (token attachment, commonly `{Type: "CurrentDate"}` or another date variable):
|
|
241
|
+
|
|
242
|
+
```xml
|
|
243
|
+
<dict>
|
|
244
|
+
<key>Operator</key>
|
|
245
|
+
<integer>1003</integer>
|
|
246
|
+
<key>Property</key>
|
|
247
|
+
<string>Due Date</string>
|
|
248
|
+
<key>Removable</key>
|
|
249
|
+
<true/>
|
|
250
|
+
<key>Values</key>
|
|
251
|
+
<dict>
|
|
252
|
+
<key>Date</key>
|
|
253
|
+
<date>2026-04-13T09:54:12Z</date>
|
|
254
|
+
<key>AnotherDate</key>
|
|
255
|
+
<dict>
|
|
256
|
+
<key>Value</key>
|
|
257
|
+
<dict>
|
|
258
|
+
<key>Type</key>
|
|
259
|
+
<string>CurrentDate</string>
|
|
260
|
+
</dict>
|
|
261
|
+
<key>WFSerializationType</key>
|
|
262
|
+
<string>WFTextTokenAttachment</string>
|
|
263
|
+
</dict>
|
|
264
|
+
</dict>
|
|
265
|
+
</dict>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
⚠️ **Date filter `1003` ≠ numeric If conditional `1003`.** The If conditional version uses `WFNumberValue` + `WFAnotherNumber`. Filter-table version uses `Values.Date` + `Values.AnotherDate`. Do NOT copy one structure into the other.
|
|
269
|
+
|
|
270
|
+
### Enumeration Filter (e.g., Media Type)
|
|
271
|
+
|
|
272
|
+
**IMPORTANT**: Media Type only accepts: `Image`, `Video`, `Live Photo`
|
|
273
|
+
Do NOT use `Screenshot` - use the `Is a Screenshot` boolean filter instead.
|
|
274
|
+
|
|
275
|
+
```xml
|
|
276
|
+
<dict>
|
|
277
|
+
<key>Operator</key>
|
|
278
|
+
<integer>4</integer>
|
|
279
|
+
<key>Property</key>
|
|
280
|
+
<string>Media Type</string>
|
|
281
|
+
<key>Removable</key>
|
|
282
|
+
<true/>
|
|
283
|
+
<key>Values</key>
|
|
284
|
+
<dict>
|
|
285
|
+
<key>Unit</key>
|
|
286
|
+
<integer>4</integer>
|
|
287
|
+
<key>Enumeration</key>
|
|
288
|
+
<dict>
|
|
289
|
+
<key>Value</key>
|
|
290
|
+
<string>Image</string>
|
|
291
|
+
<key>WFSerializationType</key>
|
|
292
|
+
<string>WFStringSubstitutableState</string>
|
|
293
|
+
</dict>
|
|
294
|
+
</dict>
|
|
295
|
+
</dict>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### String Filter (e.g., Album name)
|
|
299
|
+
|
|
300
|
+
```xml
|
|
301
|
+
<dict>
|
|
302
|
+
<key>Operator</key>
|
|
303
|
+
<integer>4</integer>
|
|
304
|
+
<key>Property</key>
|
|
305
|
+
<string>Album</string>
|
|
306
|
+
<key>Removable</key>
|
|
307
|
+
<true/>
|
|
308
|
+
<key>Values</key>
|
|
309
|
+
<dict>
|
|
310
|
+
<key>String</key>
|
|
311
|
+
<string>Favorites</string>
|
|
312
|
+
<key>Unit</key>
|
|
313
|
+
<integer>4</integer>
|
|
314
|
+
</dict>
|
|
315
|
+
</dict>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## FindPhotos Complete Example
|
|
321
|
+
|
|
322
|
+
Find screenshots taken today:
|
|
323
|
+
|
|
324
|
+
```xml
|
|
325
|
+
<dict>
|
|
326
|
+
<key>WFWorkflowActionIdentifier</key>
|
|
327
|
+
<string>is.workflow.actions.filter.photos</string>
|
|
328
|
+
<key>WFWorkflowActionParameters</key>
|
|
329
|
+
<dict>
|
|
330
|
+
<key>UUID</key>
|
|
331
|
+
<string>FIND-PHOTOS-UUID</string>
|
|
332
|
+
<key>WFContentItemFilter</key>
|
|
333
|
+
<dict>
|
|
334
|
+
<key>Value</key>
|
|
335
|
+
<dict>
|
|
336
|
+
<key>WFActionParameterFilterPrefix</key>
|
|
337
|
+
<integer>1</integer>
|
|
338
|
+
<key>WFContentPredicateBoundedDate</key>
|
|
339
|
+
<false/>
|
|
340
|
+
<key>WFActionParameterFilterTemplates</key>
|
|
341
|
+
<array>
|
|
342
|
+
<!-- Is a Screenshot = true -->
|
|
343
|
+
<dict>
|
|
344
|
+
<key>Operator</key>
|
|
345
|
+
<integer>4</integer>
|
|
346
|
+
<key>Property</key>
|
|
347
|
+
<string>Is a Screenshot</string>
|
|
348
|
+
<key>Removable</key>
|
|
349
|
+
<true/>
|
|
350
|
+
<key>Values</key>
|
|
351
|
+
<dict>
|
|
352
|
+
<key>Bool</key>
|
|
353
|
+
<true/>
|
|
354
|
+
<key>Unit</key>
|
|
355
|
+
<integer>4</integer>
|
|
356
|
+
</dict>
|
|
357
|
+
</dict>
|
|
358
|
+
<!-- Date Taken is today -->
|
|
359
|
+
<dict>
|
|
360
|
+
<key>Operator</key>
|
|
361
|
+
<integer>1002</integer>
|
|
362
|
+
<key>Property</key>
|
|
363
|
+
<string>Date Taken</string>
|
|
364
|
+
<key>Removable</key>
|
|
365
|
+
<true/>
|
|
366
|
+
</dict>
|
|
367
|
+
</array>
|
|
368
|
+
</dict>
|
|
369
|
+
<key>WFSerializationType</key>
|
|
370
|
+
<string>WFContentPredicateTableTemplate</string>
|
|
371
|
+
</dict>
|
|
372
|
+
<key>WFContentItemSortProperty</key>
|
|
373
|
+
<string>Date Taken</string>
|
|
374
|
+
<key>WFContentItemSortOrder</key>
|
|
375
|
+
<string>Latest First</string>
|
|
376
|
+
</dict>
|
|
377
|
+
</dict>
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## DeletePhotos Action
|
|
383
|
+
|
|
384
|
+
**CRITICAL**: DeletePhotos uses `photos` as the parameter key, NOT `WFInput`:
|
|
385
|
+
|
|
386
|
+
```xml
|
|
387
|
+
<dict>
|
|
388
|
+
<key>WFWorkflowActionIdentifier</key>
|
|
389
|
+
<string>is.workflow.actions.deletephotos</string>
|
|
390
|
+
<key>WFWorkflowActionParameters</key>
|
|
391
|
+
<dict>
|
|
392
|
+
<key>UUID</key>
|
|
393
|
+
<string>DELETE-UUID</string>
|
|
394
|
+
<key>photos</key>
|
|
395
|
+
<dict>
|
|
396
|
+
<key>Value</key>
|
|
397
|
+
<dict>
|
|
398
|
+
<key>OutputName</key>
|
|
399
|
+
<string>Photos</string>
|
|
400
|
+
<key>OutputUUID</key>
|
|
401
|
+
<string>FIND-PHOTOS-UUID</string>
|
|
402
|
+
<key>Type</key>
|
|
403
|
+
<string>ActionOutput</string>
|
|
404
|
+
</dict>
|
|
405
|
+
<key>WFSerializationType</key>
|
|
406
|
+
<string>WFTextTokenAttachment</string>
|
|
407
|
+
</dict>
|
|
408
|
+
</dict>
|
|
409
|
+
</dict>
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Available Filter Properties by Content Type
|
|
415
|
+
|
|
416
|
+
### Photos (WFPhotoMediaContentItem)
|
|
417
|
+
|
|
418
|
+
| Property | Type | Values |
|
|
419
|
+
|----------|------|--------|
|
|
420
|
+
| `Album` | Enumeration | Album names |
|
|
421
|
+
| `Media Type` | Enumeration | `Image`, `Video`, `Live Photo` |
|
|
422
|
+
| `Is a Screenshot` | Boolean | true/false |
|
|
423
|
+
| `Is Hidden` | Boolean | true/false |
|
|
424
|
+
| `Is Favorite` | Boolean | true/false |
|
|
425
|
+
| `Date Taken` | Date | Use date operators |
|
|
426
|
+
| `Creation Date` | Date | Use date operators |
|
|
427
|
+
| `Width` | Number | Pixels |
|
|
428
|
+
| `Height` | Number | Pixels |
|
|
429
|
+
| `Orientation` | Enumeration | `Up`, `Down`, `Left`, `Right` |
|
|
430
|
+
| `Photo Type` | Enumeration | `HDR`, `Panorama`, etc. |
|
|
431
|
+
| `Frame Rate` | Number | FPS (for videos) |
|
|
432
|
+
| `Duration` | Number | Seconds (for videos) |
|
|
433
|
+
| `Camera Make` | String | Camera manufacturer |
|
|
434
|
+
| `Camera Model` | String | Camera model |
|
|
435
|
+
| `File Extension` | String | e.g., `png`, `jpg` |
|
|
436
|
+
|
|
437
|
+
### Files (WFGenericFileContentItem)
|
|
438
|
+
|
|
439
|
+
| Property | Type | Values |
|
|
440
|
+
|----------|------|--------|
|
|
441
|
+
| `Name` | String | Filename |
|
|
442
|
+
| `File Extension` | String | Extension without dot |
|
|
443
|
+
| `Creation Date` | Date | Use date operators |
|
|
444
|
+
| `File Size` | Number | Bytes |
|
|
445
|
+
| `Last Modified Date` | Date | Use date operators |
|
|
446
|
+
|
|
447
|
+
### Notes (WFNoteContentItem)
|
|
448
|
+
|
|
449
|
+
| Property | Type | Supported Operators |
|
|
450
|
+
|----------|------|---------------------|
|
|
451
|
+
| `Name` | String | **Contains (99) only** — see critical note below |
|
|
452
|
+
| `Body` | String | Contains (99), Does Not Contain (999) |
|
|
453
|
+
| `Creation Date` | Date | Use date operators |
|
|
454
|
+
| `Last Modified Date` | Date | Use date operators |
|
|
455
|
+
| `Folder` | Enumeration | Folder names |
|
|
456
|
+
|
|
457
|
+
> **CRITICAL — Name filter operator:**
|
|
458
|
+
> Find Notes actions only support operator `99` (contains) for `Name` matching.
|
|
459
|
+
> Using operator `4` (is/exact match) produces an **empty result set at runtime** — the filter silently fails.
|
|
460
|
+
> Always use operator `99` when searching notes by name, even when you want an exact title match.
|
|
461
|
+
|
|
462
|
+
```xml
|
|
463
|
+
<!-- CORRECT: Name contains -->
|
|
464
|
+
<key>WFFilterOperator</key>
|
|
465
|
+
<integer>99</integer>
|
|
466
|
+
|
|
467
|
+
<!-- WRONG: Name is — fails silently, returns nothing -->
|
|
468
|
+
<key>WFFilterOperator</key>
|
|
469
|
+
<integer>4</integer>
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Reminders (WFReminderContentItem)
|
|
473
|
+
|
|
474
|
+
| Property | Type | Values |
|
|
475
|
+
|----------|------|--------|
|
|
476
|
+
| `Title` | String | Reminder title |
|
|
477
|
+
| `Is Completed` | Boolean | `{ Bool: <true/false> }` — no `Unit` key (Reminders Boolean filters don't use it) |
|
|
478
|
+
| `Is Flagged` | Boolean | Same shape as Is Completed |
|
|
479
|
+
| `Priority` | Enumeration | `None`, `Low`, `Medium`, `High` |
|
|
480
|
+
| `Due Date` | Date | Use date operators (1000–1003) |
|
|
481
|
+
| `Creation Date` | Date | Use date operators |
|
|
482
|
+
| `List` | Enumeration | List names — match via operator `4` with `Values.Enumeration` |
|
|
483
|
+
|
|
484
|
+
⚠️ **Reminders Boolean filters skip `Unit: 4`.** Photos Boolean filters (e.g. `Is a Screenshot`) do require `Values = { Bool: <true/false>, Unit: 4 }`. Reminders Boolean filters use `Values = { Bool: <true/false> }` only — no `Unit` field. Verified against an Apple-built sample.
|
|
485
|
+
|
|
486
|
+
**"Is Completed = Yes" (find completed reminders):**
|
|
487
|
+
|
|
488
|
+
```xml
|
|
489
|
+
<dict>
|
|
490
|
+
<key>WFWorkflowActionIdentifier</key>
|
|
491
|
+
<string>is.workflow.actions.filter.reminders</string>
|
|
492
|
+
<key>WFWorkflowActionParameters</key>
|
|
493
|
+
<dict>
|
|
494
|
+
<key>UUID</key>
|
|
495
|
+
<string>FIND-COMPLETED-UUID</string>
|
|
496
|
+
<key>WFContentItemFilter</key>
|
|
497
|
+
<dict>
|
|
498
|
+
<key>Value</key>
|
|
499
|
+
<dict>
|
|
500
|
+
<key>WFActionParameterFilterPrefix</key>
|
|
501
|
+
<integer>1</integer>
|
|
502
|
+
<key>WFActionParameterFilterTemplates</key>
|
|
503
|
+
<array>
|
|
504
|
+
<dict>
|
|
505
|
+
<key>Operator</key>
|
|
506
|
+
<integer>4</integer>
|
|
507
|
+
<key>Property</key>
|
|
508
|
+
<string>Is Completed</string>
|
|
509
|
+
<key>Removable</key>
|
|
510
|
+
<true/>
|
|
511
|
+
<key>Values</key>
|
|
512
|
+
<dict>
|
|
513
|
+
<key>Bool</key>
|
|
514
|
+
<true/>
|
|
515
|
+
</dict>
|
|
516
|
+
</dict>
|
|
517
|
+
</array>
|
|
518
|
+
<key>WFContentPredicateBoundedDate</key>
|
|
519
|
+
<false/>
|
|
520
|
+
</dict>
|
|
521
|
+
<key>WFSerializationType</key>
|
|
522
|
+
<string>WFContentPredicateTableTemplate</string>
|
|
523
|
+
</dict>
|
|
524
|
+
</dict>
|
|
525
|
+
</dict>
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
**"Is Completed = No" (find incomplete reminders):** same action, same structure, only `Values.Bool` flips to `<false/>`.
|
|
529
|
+
|
|
530
|
+
### Find vs Filter: `WFContentItemInputParameter`
|
|
531
|
+
|
|
532
|
+
Shortcuts.app shows two variants in the UI:
|
|
533
|
+
- **"Find X where"** — queries the system's content database for the type (e.g., all reminders, all photos) matching the filter.
|
|
534
|
+
- **"Filter X where"** — applies the filter to the output of a preceding action, trimming down an already-collected list.
|
|
535
|
+
|
|
536
|
+
Both variants use the **same action identifier** (`is.workflow.actions.filter.<type>`). The difference is the presence of `WFContentItemInputParameter`:
|
|
537
|
+
|
|
538
|
+
- **Find** = no `WFContentItemInputParameter`. The filter operates on the system database.
|
|
539
|
+
- **Filter** = `WFContentItemInputParameter` set to a token attachment wrapping the previous action's `ActionOutput` (typically with `OutputName` matching the type — e.g., `"Reminders"`, `"Photos"`, `"Files"`).
|
|
540
|
+
|
|
541
|
+
**Chained "Filter Reminders where Is Completed = No" on the output of a preceding "Find Reminders where Is Completed = Yes":**
|
|
542
|
+
|
|
543
|
+
```xml
|
|
544
|
+
<dict>
|
|
545
|
+
<key>WFWorkflowActionIdentifier</key>
|
|
546
|
+
<string>is.workflow.actions.filter.reminders</string>
|
|
547
|
+
<key>WFWorkflowActionParameters</key>
|
|
548
|
+
<dict>
|
|
549
|
+
<key>UUID</key>
|
|
550
|
+
<string>FILTER-INCOMPLETE-UUID</string>
|
|
551
|
+
<key>WFContentItemFilter</key>
|
|
552
|
+
<dict>
|
|
553
|
+
<key>Value</key>
|
|
554
|
+
<dict>
|
|
555
|
+
<key>WFActionParameterFilterPrefix</key>
|
|
556
|
+
<integer>1</integer>
|
|
557
|
+
<key>WFActionParameterFilterTemplates</key>
|
|
558
|
+
<array>
|
|
559
|
+
<dict>
|
|
560
|
+
<key>Operator</key>
|
|
561
|
+
<integer>4</integer>
|
|
562
|
+
<key>Property</key>
|
|
563
|
+
<string>Is Completed</string>
|
|
564
|
+
<key>Removable</key>
|
|
565
|
+
<true/>
|
|
566
|
+
<key>Values</key>
|
|
567
|
+
<dict>
|
|
568
|
+
<key>Bool</key>
|
|
569
|
+
<false/>
|
|
570
|
+
</dict>
|
|
571
|
+
</dict>
|
|
572
|
+
</array>
|
|
573
|
+
<key>WFContentPredicateBoundedDate</key>
|
|
574
|
+
<false/>
|
|
575
|
+
</dict>
|
|
576
|
+
<key>WFSerializationType</key>
|
|
577
|
+
<string>WFContentPredicateTableTemplate</string>
|
|
578
|
+
</dict>
|
|
579
|
+
<key>WFContentItemInputParameter</key>
|
|
580
|
+
<dict>
|
|
581
|
+
<key>Value</key>
|
|
582
|
+
<dict>
|
|
583
|
+
<key>OutputName</key>
|
|
584
|
+
<string>Reminders</string>
|
|
585
|
+
<key>OutputUUID</key>
|
|
586
|
+
<string>PREVIOUS-FILTER-REMINDERS-UUID</string>
|
|
587
|
+
<key>Type</key>
|
|
588
|
+
<string>ActionOutput</string>
|
|
589
|
+
</dict>
|
|
590
|
+
<key>WFSerializationType</key>
|
|
591
|
+
<string>WFTextTokenAttachment</string>
|
|
592
|
+
</dict>
|
|
593
|
+
</dict>
|
|
594
|
+
</dict>
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
The same `WFContentItemInputParameter` chaining pattern applies to `filter.photos`, `filter.files`, `filter.notes`, `filter.calendarevents`, and every other `filter.*` action — wire it to a previous action's output via `Type=ActionOutput` and the filter becomes a "Filter X" instead of a "Find X".
|
|
598
|
+
|
|
599
|
+
**Reminders-specific filter example (verified from an Apple-built sample). Any-are-true OR of: List is "Reminders" OR Due Date is today OR Due Date is between a literal date and Current Date:**
|
|
600
|
+
|
|
601
|
+
**Reminders-specific filter example (verified from an Apple-built sample). Any-are-true OR of: List is "Reminders" OR Due Date is today OR Due Date is between a literal date and Current Date:**
|
|
602
|
+
|
|
603
|
+
```xml
|
|
604
|
+
<dict>
|
|
605
|
+
<key>WFWorkflowActionIdentifier</key>
|
|
606
|
+
<string>is.workflow.actions.filter.reminders</string>
|
|
607
|
+
<key>WFWorkflowActionParameters</key>
|
|
608
|
+
<dict>
|
|
609
|
+
<key>UUID</key>
|
|
610
|
+
<string>FIND-REMINDERS-UUID</string>
|
|
611
|
+
<key>WFContentItemFilter</key>
|
|
612
|
+
<dict>
|
|
613
|
+
<key>Value</key>
|
|
614
|
+
<dict>
|
|
615
|
+
<key>WFActionParameterFilterPrefix</key>
|
|
616
|
+
<integer>0</integer>
|
|
617
|
+
<key>WFActionParameterFilterTemplates</key>
|
|
618
|
+
<array>
|
|
619
|
+
<dict>
|
|
620
|
+
<key>Operator</key>
|
|
621
|
+
<integer>4</integer>
|
|
622
|
+
<key>Property</key>
|
|
623
|
+
<string>List</string>
|
|
624
|
+
<key>Removable</key>
|
|
625
|
+
<true/>
|
|
626
|
+
<key>Values</key>
|
|
627
|
+
<dict>
|
|
628
|
+
<key>Enumeration</key>
|
|
629
|
+
<dict>
|
|
630
|
+
<key>Value</key>
|
|
631
|
+
<string>Reminders</string>
|
|
632
|
+
<key>WFSerializationType</key>
|
|
633
|
+
<string>WFStringSubstitutableState</string>
|
|
634
|
+
</dict>
|
|
635
|
+
</dict>
|
|
636
|
+
</dict>
|
|
637
|
+
<dict>
|
|
638
|
+
<key>Operator</key>
|
|
639
|
+
<integer>1002</integer>
|
|
640
|
+
<key>Property</key>
|
|
641
|
+
<string>Due Date</string>
|
|
642
|
+
<key>Removable</key>
|
|
643
|
+
<true/>
|
|
644
|
+
<key>Values</key>
|
|
645
|
+
<dict/>
|
|
646
|
+
</dict>
|
|
647
|
+
<dict>
|
|
648
|
+
<key>Operator</key>
|
|
649
|
+
<integer>1003</integer>
|
|
650
|
+
<key>Property</key>
|
|
651
|
+
<string>Due Date</string>
|
|
652
|
+
<key>Removable</key>
|
|
653
|
+
<true/>
|
|
654
|
+
<key>Values</key>
|
|
655
|
+
<dict>
|
|
656
|
+
<key>Date</key>
|
|
657
|
+
<date>2026-04-13T09:54:12Z</date>
|
|
658
|
+
<key>AnotherDate</key>
|
|
659
|
+
<dict>
|
|
660
|
+
<key>Value</key>
|
|
661
|
+
<dict>
|
|
662
|
+
<key>Type</key>
|
|
663
|
+
<string>CurrentDate</string>
|
|
664
|
+
</dict>
|
|
665
|
+
<key>WFSerializationType</key>
|
|
666
|
+
<string>WFTextTokenAttachment</string>
|
|
667
|
+
</dict>
|
|
668
|
+
</dict>
|
|
669
|
+
</dict>
|
|
670
|
+
</array>
|
|
671
|
+
<key>WFContentPredicateBoundedDate</key>
|
|
672
|
+
<false/>
|
|
673
|
+
</dict>
|
|
674
|
+
<key>WFSerializationType</key>
|
|
675
|
+
<string>WFContentPredicateTableTemplate</string>
|
|
676
|
+
</dict>
|
|
677
|
+
</dict>
|
|
678
|
+
</dict>
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
For the editing side (`is.workflow.actions.setters.reminders`), see [PARAMETER_TYPES.md → Reminders — Filter & Setter Schemas](PARAMETER_TYPES.md#reminders--filter--setter-schemas-definitive) for the complete list of property names and their value keys.
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## Common Mistakes to Avoid
|
|
686
|
+
|
|
687
|
+
1. **Using `media_type="Screenshot"`** - This is WRONG. Use `Is a Screenshot` boolean filter instead.
|
|
688
|
+
|
|
689
|
+
2. **Using Operator 4 for "is today"** - WRONG. Use Operator 1002.
|
|
690
|
+
|
|
691
|
+
3. **Using `WFInput` for DeletePhotos** - WRONG. Use `photos` (lowercase).
|
|
692
|
+
|
|
693
|
+
4. **Adding Values to "is today" filter** - WRONG. Operator 1002 doesn't need Values.
|
|
694
|
+
|
|
695
|
+
5. **Forgetting OutputUUID reference** - When passing results between actions, you must reference the source action's UUID.
|
|
696
|
+
|
|
697
|
+
6. **Using Operator 4 (is) for Find Notes Name filter** - WRONG. Operator 4 produces empty results at runtime. Always use Operator 99 (contains) for Note name matching.
|