介绍
# macOS Shortcuts Generator
生成有效的 `.shortcut` 文件,该文件可被签名并导入到 Apple 的“快捷指令” App 中。
## 快速开始
快捷指令是具有以下结构的二进制 plist:
```xml <?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> ```
### 最小的 Hello World 示例
```xml <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> ```
## 核心概念
### 1. 操作 (Actions) 每个操作包含: - **标识符**:`is.workflow.actions.<name>` (例如 `is.workflow.actions.showresult`) - **参数**:`WFWorkflowActionParameters` 中特定于操作的配置 - **UUID**:用于引用此操作输出的唯一标识符
### 2. 变量引用 要使用先前操作的输出: 1. 源操作需要一个 `UUID` 参数 2. 在 `attachmentsByRange` 字典中使用 `OutputUUID` 引用它 3. 在变量插入位置的字符串中使用 `` (U+FFFC) 作为占位符 4. 将 `WFSerializationType` 设置为 `WFTextTokenString`
### 3. 控制流 控制流操作(循环、条件、菜单)使用: - `GroupingIdentifier`:链接开始/中间/结束操作的 UUID - `WFControlFlowMode`:0=开始,1=中间(else/case),2=结束
## 常用操作快速参考
| 操作 | 标识符 | 关键参数 | |--------|------------|----------------| | 文本 | `is.workflow.actions.gettext` | `WFTextActionText` | | 显示结果 | `is.workflow.actions.showresult` | `Text` | | 请求输入 | `is.workflow.actions.ask` | `WFAskActionPrompt`, `WFInputType` | | 使用 AI 模型 | `is.workflow.actions.askllm` | `WFLLMPrompt`, `WFLLMModel`, `WFGenerativeResultType` | | 注释 | `is.workflow.actions.comment` | `WFCommentActionText` | | URL | `is.workflow.actions.url` | `WFURLActionURL` | | 获取 URL 的内容 | `is.workflow.actions.downloadurl` | `WFURL`, `WFHTTPMethod` | | 获取天气 | `is.workflow.actions.weather.currentconditions` | (无需参数) | | 打开 App | `is.workflow.actions.openapp` | `WFAppIdentifier` | | 打开 URL | `is.workflow.actions.openurl` | `WFInput` | | 提示 | `is.workflow.actions.alert` | `WFAlertActionTitle`, `WFAlertActionMessage` | | 通知 | `is.workflow.actions.notification` | `WFNotificationActionTitle`, `WFNotificationActionBody` | | 设定变量 | `is.workflow.actions.setvariable` | `WFVariableName`, `WFInput` | | 获取变量 | `is.workflow.actions.getvariable` | `WFVariable` | | 数字 | `is.workflow.actions.number` | `WFNumberActionNumber` | | 列表 | `is.workflow.actions.list` | `WFItems` | | 字典 | `is.workflow.actions.dictionary` | `WFItems` | | 重复 (次数) | `is.workflow.actions.repeat.count` | `WFRepeatCount`, `GroupingIdentifier`, `WFControlFlowMode` | | 重复 (每个) | `is.workflow.actions.repeat.each` | `WFInput`, `GroupingIdentifier`, `WFControlFlowMode` | | 如果/否则 | `is.workflow.actions.conditional` | `WFInput`, `WFCondition`, `GroupingIdentifier`, `WFControlFlowMode` | | 从菜单选取 | `is.workflow.actions.choosefrommenu` | `WFMenuPrompt`, `WFMenuItems`, `GroupingIdentifier`, `WFControlFlowMode` | | 查找照片 | `is.workflow.actions.filter.photos` | `WFContentItemFilter` (参见 FILTERS.md) | | 删除照片 | `is.workflow.actions.deletephotos` | `photos` (**注意不是** `WFInput`!) |
## 详细参考文件
完整文档请参阅: - [PLIST_FORMAT.md](PLIST_FORMAT.md) - 完整的 plist 结构 - [ACTIONS.md](ACTIONS.md) - 所有 427 个 WF*Action 标识符和参数 - [APPINTENTS.md](APPINTENTS.md) - 所有 728 个 AppIntent 操作 - [PARAMETER_TYPES.md](PARAMETER_TYPES.md) - 所有参数值类型和序列化格式 - [VARIABLES.md](VARIABLES.md) - 变量引用系统 - [CONTROL_FLOW.md](CONTROL_FLOW.md) - 重复、条件、菜单模式 - [FILTERS.md](FILTERS.md) - 用于查找/筛选操作的内容过滤器(照片、文件等) - [EXAMPLES.md](EXAMPLES.md) - 完整的可用示例
## 签名快捷指令
快捷指令必须先签名才能导入。使用 macOS 的 `shortcuts` 命令行工具:
```bash # 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 ```
签名过程: 1. 将 plist 以 XML 格式写入 `.shortcut` 文件 2. 运行 `shortcuts sign` 以添加加密签名(增加约 19KB) 3. 签名后的文件可以在 Shortcuts.app 中打开/导入
## 创建快捷指令的工作流程
1. **定义操作** - 列出快捷指令应该执行的操作 2. **生成 UUID** - 每个产生输出的操作都需要一个唯一的 UUID 3. **构建操作数组** - 使用标识符和参数创建每个操作字典 4. **连接变量引用** - 使用 `OutputUUID` 将输出连接到输入 5. **封装到 plist** - 添加包含图标、名称、版本的根结构 6. **写入文件** - 保存为 `.shortcut`(XML plist 格式即可) 7. **签名** - 运行 `shortcuts sign` 使其可导入
## 关键规则
1. **UUID 必须大写**:`A1B2C3D4-E5F6-7890-ABCD-EF1234567890` 2. **WFControlFlowMode 是整数**:使用 `<integer>0</integer>` 而非 `<string>0</string>` 3. **范围键使用格式**:`{位置, 长度}` - 例如 `{0, 1}` 表示第一个字符 4. **占位符字符**:`` (U+FFFC) 标记变量插入的位置 5. **控制流需要匹配的结束**:每个重复/如果/菜单开始操作都需要一个具有相同 `GroupingIdentifier` 的结束操作