### Install Cherri via Homebrew Source: https://github.com/electrikmilk/cherri/blob/main/ReadMe.md Installs the Cherri command-line tool using Homebrew. Ensure you have run 'brew tap electrikmilk/cherri' first. ```bash brew install electrikmilk/cherri/cherri ``` -------------------------------- ### Install Cherri Package Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Fetches a Git repository and adds it to the .cherri-package.json file. ```bash cherri --install=electrikmilk/cherri-packages/common ``` -------------------------------- ### Cherri Action Syntax Example Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md A basic example of a Cherri alert action. ```cherri alert("Hello World") ``` -------------------------------- ### Usage of getDictionary action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Examples of retrieving a dictionary and accessing its keys. ```cherri const dict = getDictionary(@someVar) const value = dict.get("key") ``` -------------------------------- ### Example output for attachmentValues Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-plist-generation.md Shows the structure of a WFTextTokenString with attachments. ```text Input: "Hello {@name}, you are {@age} years old" Output: WFTextTokenString{ String: "Hello , you are  years old", AttachmentsByRange: { "{3}": , "{20}": , }, } ``` -------------------------------- ### Complete variable flow example Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-variables-functions.md Demonstrates variable assignment, constant declaration, and string interpolation with variable attachments. ```cherri @name = "Alice" const greeting = text("Hello {@name}") @count = 0 @count += 1 ``` -------------------------------- ### For-In Loop Example Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Iterating through an array of strings and displaying each element. ```cherri @colors = ["red", "green", "blue"] for color in @colors { alert("{color}") } ``` -------------------------------- ### Install Cherri via Nix Source: https://github.com/electrikmilk/cherri/blob/main/ReadMe.md Installs Cherri using the Nix package manager. This command adds Cherri to your user profile. ```bash nix profile install github:electrikmilk/cherri ``` -------------------------------- ### If Statement Example Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Demonstrates conditional logic with if, else if, and else branches. ```cherri @x = 5 if @x > 0 { alert("Positive") } else if @x < 0 { alert("Negative") } else { alert("Zero") } ``` -------------------------------- ### Usage of getValue action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Example of retrieving a value from a dictionary variable. ```cherri const name = getValue(@person, "name") ``` -------------------------------- ### Usage of ask action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Examples of invoking the ask action with and without specific input types. ```cherri const name = ask("What is your name?") const number = ask("Enter a number", "Number") ``` -------------------------------- ### Shortcuts Action Plist Structure Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md Example of a raw Shortcuts action definition in XML plist format. ```xml WFWorkflowActionIdentifier is.workflow.actions.gettext WFWorkflowActionParameters WFTextActionText hello ``` -------------------------------- ### Repeat Loop Example Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Iterating using a loop variable that starts at 1 and is immutable within the block. ```cherri repeat i for 10 { alert("Iteration {@i}") } ``` -------------------------------- ### Nix Flake Configuration for Cherri Source: https://github.com/electrikmilk/cherri/blob/main/ReadMe.md Example Nix flake.nix configuration to include Cherri in a development environment. This allows Cherri to be available when using tools like nix-direnv. ```nix { inputs.cherri.url = "github:electrikmilk/cherri"; { # outputs.packages.${system}.default = pkgs.mkShell etc - omitted for brevity buildInputs = [ inputs.cherri.packages.${system}.cherri ] } } ``` -------------------------------- ### Plist Input for Decompilation Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/types-and-decompilation.md Example of a workflow action definition in Plist format used as input for the decompilation process. ```xml WFWorkflowActionIdentifier is.workflow.actions.ask WFWorkflowActionParameters WFQuestion What is your name? ``` -------------------------------- ### Usage of alert action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Examples of invoking the alert action in Cherri code. ```cherri alert("Hello World") const dismissed = alert("Show this") ``` -------------------------------- ### Add Homebrew Tap for Cherri Source: https://github.com/electrikmilk/cherri/blob/main/ReadMe.md Adds the official Cherri repository to your Homebrew sources. This is a prerequisite for installing Cherri via Homebrew. ```bash brew tap electrikmilk/cherri ``` -------------------------------- ### Plist representation of variable assignment Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-variables-functions.md Example of the generated Plist structure for a Set Variable action. ```xml WFWorkflowActionIdentifier is.workflow.actions.setvariable WFWorkflowActionParameters WFInput Alice WFVariableName name ``` -------------------------------- ### Load Standard Actions Entry Point Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Main function to initialize all standard actions, called once at startup. ```go func loadStandardActions() ``` -------------------------------- ### Initialize Cherri Project Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Creates a .cherri-package.json file in the current directory. ```bash cherri --init ``` -------------------------------- ### Define Shortcut Metadata and Includes Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/OVERVIEW.md Configure shortcut properties and include external files or libraries. ```cherri #define name My Shortcut #define color blue #define glyph apple #define inputs image, text #define outputs file #define noinput stopwith "No input provided" #define from menubar, sharesheet #define mac true #define version 18.4 ``` ```cherri #include 'actions/device' // standard library category #include 'path/to/file.cherri' // arbitrary file ``` -------------------------------- ### Initialize Parse Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Sets up the global parsing state, including maps for variables and UUIDs, and initializes the line/character cursor. ```go func initParse() ``` -------------------------------- ### Create shortcut file Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-plist-generation.md Serializes the shortcut struct to an XML plist file, including signing steps. ```go func createShortcut() ``` -------------------------------- ### Import from iCloud Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Fetches a shortcut from an iCloud URL, decompiles it, and prints the source to stdout. ```bash cherri --import="https://www.icloud.com/shortcuts/abcd1234" ``` -------------------------------- ### Collect Metadata Definitions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Parses #define metadata statements to populate shortcut configuration. ```go func collectDefine() ``` ```cherri #define name My Shortcut #define color blue #define version 18.4 #define inputs image, text #define from menubar, sharesheet ``` -------------------------------- ### Enum Declaration in Parameters Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/types-and-decompilation.md Example of defining a parameter that requires a literal enum value. ```go parameterDefinition{ name: "order", validType: String, key: "WFSortOrder", enum: "sortOrder", literal: true, // must be a literal enum value } ``` -------------------------------- ### Action Registration and Enumeration Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md Functions and structures for loading standard actions and retrieving parameter enumerations. ```go func loadStandardActions() ``` ```go var enumerations = map[string][]string{ "sortOrder": {"asc", "desc"}, "focusModes": {"Do Not Disturb", "Personal", "Work", "Sleep", "Driving"}, // ... many more } ``` ```go func getEnum(identifier string) []string ``` -------------------------------- ### Conditional Variable Coercion Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Examples of valid and invalid conditional checks based on type inference. ```cherri @x = 5 if @x > 0 { } // OK: @x is known to be number const result = someAction() if result > 0 { } // ERROR: result type may be unknown if result.number > 0 { } // OK: .number coerces to number ``` -------------------------------- ### Create a shell wrapper for compiler configuration Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Use a shell script to persist common CLI flags and arguments as a workaround for the lack of a native configuration file. ```bash #!/bin/bash cherri "$@" --output=/my/output/dir --debug ``` -------------------------------- ### Build ShortcutAction with makeAction Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md Constructs a ShortcutAction from arguments and adds it to the workflow. ```go var params = getActionParameters(arguments) makeAction(arguments, &WFActionReference{UUID: "action-uuid", CustomOutputName: "result"}) ``` -------------------------------- ### Main Entry Point Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md The primary entry point for the application, routing flags to compilation, decompilation, or utility functions. ```go func main() ``` -------------------------------- ### Generate Shortcut Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Walks the emitted tokens to generate the shortcut structure after pre-processing and parsing are complete. ```go func generateShortcut() { preParse() // pre-processing passes parse() // main parse, emits tokens[] // tokens[] now contains all parsed constructs // Walk tokens and build shortcut.WFWorkflowActions } ``` -------------------------------- ### Collect Identifier Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Reads an identifier starting from the current position. Valid characters include letters, digits, and underscores, with the first character restricted to letters or underscores. ```go func collectIdentifier() string ``` -------------------------------- ### Compile a Cherri file Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Compiles a .cherri source file into a .shortcut file in the current directory. ```bash cherri file.cherri ``` -------------------------------- ### Generate Shortcut Output Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Compiles a .cherri file into a signed binary plist shortcut. ```bash cherri myapp.cherri ``` -------------------------------- ### Handle File Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Splits the input file path and reads the file contents into global variables. ```go func handleFile() ``` -------------------------------- ### Define Actions using Cherri DSL Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md Use the Cherri DSL syntax in .cherri files to define simple actions, static parameters, and platform-specific modifiers. ```cherri // Simple value pass-through action 'getText' getText(text text: 'WFTextActionText'): text // With static parameters action 'output' outputOrClipboard(text output: 'WFOutput') { "WFNoOutputSurfaceBehavior": "Copy to Clipboard" } // With modifiers !mac action 'macSpecific' someMacAction(number value: 'WFValue'): number ``` -------------------------------- ### Parse Action Definitions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Main entry point for parsing DSL action definitions. ```go func parseActionDefinitions() ``` ```cherri [!mac] action ['shortIdentifier'] name(params): type { staticBody } action 'toggle-set' toggleSetAction(params) { ... } ``` -------------------------------- ### Parse Single File with Includes Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/README.md Test specific modules by adding include statements to a file and running it via the Go compiler. ```cherri #include 'actions/basic' #include 'actions/network' // ... rest of file ``` -------------------------------- ### Configure External Signing Server Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Set the CHERRI_SIGNING_SERVER environment variable to point to a compatible signing server. ```bash export CHERRI_SIGNING_SERVER="https://my-signing-server.example.com" cherri file.cherri ``` -------------------------------- ### Compile and Run Cherri File Source: https://github.com/electrikmilk/cherri/blob/main/ReadMe.md Compiles and runs a Cherri source file. This is the basic command to process a .cherri file. ```bash cherri file.cherri ``` -------------------------------- ### Define Shortcut Metadata Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md Use #define directives to set Shortcut properties, inputs, and environment requirements. ```ruby #define name My Shortcut #define color blue #define glyph apple #define inputs image, text #define outputs file #define noinput stopwith "No input provided" #define from menubar, sharesheet #define mac true #define version 18.4 ``` -------------------------------- ### Execute Actions Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md Basic actions can be called directly, while others may require specific library includes. ```ruby alert("Hello!") // no include needed for basic actions #include 'actions/network' @data = getContentsOfURL("https://example.com") ``` -------------------------------- ### Collect Control Flow Constructs Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Parses conditional and loop constructs to generate Shortcuts control flow actions. ```go func collectIf() func collectRepeat() func collectFor() ``` -------------------------------- ### Cherri Compiler CLI Commands Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md Standard commands for building, running, testing, and searching actions within the Cherri project. ```bash # Build go build ./... # Run compiler on a file — filename MUST be the first argument go run . file.cherri go run . file.cherri --debug # also writes .plist and preprocessed file # Tests go test -run TestCherriNoSign # compile all tests/*.cherri files, skip signing (use on non-macOS) go test -run TestCherri # same but with signing (macOS only) go test -run TestDecomp # decompile tests/decomp-me.plist, compare to tests/decomp-expected.cherri go test -run TestActionIdentifiers # verify specific action identifier output # Search actions and glyphs (requires build) cherri --action=actionName cherri --glyph=glyphName ``` -------------------------------- ### Define Shortcut Outputs Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Declares the content types produced by the Shortcut. ```cherri #define outputs file, url ``` -------------------------------- ### Static Parameters Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Explains how to include static plist parameters in an action invocation using an inline dictionary. ```APIDOC ## Static Parameters ### Description Use an inline dictionary to add static plist parameters to every invocation of the action. ``` -------------------------------- ### Decompile Entry Point Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/types-and-decompilation.md The main function for initiating the decompilation process from binary plist contents. ```go func decompile(b []byte) ``` -------------------------------- ### Action Compilation Logic Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md Demonstrates the internal Go representation and function calls generated when compiling a Cherri action. ```go currentAction.identifier = "alert" currentAction.definition = actions["alert"] currentAction.arguments = []actionArgument{{valueType: String, value: "Hello World"}} checkAction() makeAction(currentAction.arguments, reference) ``` -------------------------------- ### Specify output path Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Defines a custom output path for the compiled shortcut file. ```bash cherri file.cherri --output=/tmp/output.shortcut ``` -------------------------------- ### Shortcuts Management (shortcuts.cherri) Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Methods for managing and executing shortcuts. ```APIDOC ## shortcuts.cherri - `runShortcut()`: Executes another shortcut. - `openShortcutsApp()`: Launches the Shortcuts app. - `getShortcut()`: Accesses a shortcut from the library. ``` -------------------------------- ### Collect If Block Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Parses if-else blocks and generates the corresponding shortcut actions. ```go func collectIf() ``` -------------------------------- ### Request runtime user input Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-variables-functions.md Use the Ask variable to pause execution and prompt the user for input, optionally providing a custom prompt string. ```cherri wait(Ask) wait(Ask: 'What is your name?') ``` -------------------------------- ### Embed Standard Library Files Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Uses Go's embed package to include library files in the binary at compile time. ```go //go:embed actions var stdActions embed.FS //go:embed stdfunc.cherri var stdFuncs embed.FS ``` -------------------------------- ### Define Content Item Mappings Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/types-and-decompilation.md Maps short names to their corresponding Shortcuts plist content classes for input/output declarations. ```go var contentItems = map[string]string{ "installedapp": "WFAppContentItem", "app": "WFAppStoreAppContentItem", "article": "WFArticleContentItem", "contact": "WFContactContentItem", "date": "WFDateContentItem", "email": "WFEmailAddressContentItem", "folder": "WFFolderContentItem", "file": "WFGenericFileContentItem", "image": "WFImageContentItem", "itunes": "WFiTunesProductContentItem", "location": "WFLocationContentItem", "maplink": "WFDCMapsLinkContentItem", "media": "WFAVAssetContentItem", "pdf": "WFPDFContentItem", "phonenumber": "WFPhoneNumberContentItem", "richtext": "WFRichTextContentItem", "webpage": "WFSafariWebPageContentItem", "text": "WFStringContentItem", "dictionary": "WFDictionaryContentItem", "number": "WFNumberContentItem", "url": "WFURLContentItem", } ``` -------------------------------- ### Main Compilation Pipeline Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Integration of the parser within the main loop and test environment. ```go func main() { filePath = fileArg() filename = checkFile(filePath) handleFile() // read file, split parts initParse() // init global state generateShortcut() // preParse + parse + emit tokens createShortcut() // plist gen + sign } ``` ```go func compile() { resetParser() // reset ALL global state main() // invokes full pipeline } ``` -------------------------------- ### Handle Includes Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Resolves and inlines #include statements, modifying the contents and updating the cursor state. ```go func handleIncludes() ``` -------------------------------- ### Define a version-constrained action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Specify minimum and maximum Shortcuts versions to control action availability. Violating these constraints results in a compile error. ```json "newFeatureAction": { identifier: "newFeature", minVersion: 18.4, // requires Shortcuts 18.4+ maxVersion: 26.4, // not available after 26.4 parameters: [...], outputType: String, } ``` -------------------------------- ### Inspect Action Signature Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/README.md Retrieve metadata for a specific action, including parameters and constraints. ```bash cherri --action=actionName ``` -------------------------------- ### Simple Action Definition with DSL Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md Basic DSL syntax for mapping a direct value pass-through action. ```cherri // [Doc]: Get Text: Returns `text`. action 'gettext' getText(text text: 'WFTextActionText'): text ``` -------------------------------- ### Define Shortcut Version Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Specifies the minimum required Shortcuts version for the workflow. ```cherri #define version 18.4 ``` ```go var versions = map[string]string{ "26.4": "4528.0.4.2", "26": "4033.0.4.3", "18.4": "3218.0.4.100", "18": "3036.0.4.2", // ... } ``` -------------------------------- ### Embed Compiler Resources Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/EXPORTED-API-INDEX.md Compile-time embedding of standard actions and library functions using embed.FS. ```go //go:embed actions var stdActions embed.FS ``` ```go //go:embed stdfunc.cherri var stdFuncs embed.FS ``` -------------------------------- ### Handle Action Definitions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Parses DSL action definitions and removes the DSL lines from the contents. ```go func handleActionDefinitions() ``` -------------------------------- ### Define Shortcut Inputs Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Declares the expected content types for the Shortcut input. ```cherri #define inputs image, text, number ``` ```go var contentItems = map[string]string{ "text": "WFStringContentItem", "number": "WFNumberContentItem", "image": "WFImageContentItem", // ... 20+ types } ``` -------------------------------- ### Restrict actions by platform Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Use the mac or !mac prefix to limit action availability to specific operating systems. ```cherri mac action 'macOnly' macSpecific(number value): number !mac action 'nonMac' iosSpecific(text input: 'WFInput'): text ``` -------------------------------- ### Define Custom Actions in Go Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md Implement complex parameter handling and dynamic plist generation by defining custom action structures in actions_std.go. ```go "someComplexAction": { parameters: []parameterDefinition{ {name: "input", validType: String, key: "WFInput"}, {name: "mode", validType: String, key: "WFMode", literal: true, enum: "sortOrder"}, }, makeParams: func(args []actionArgument) map[string]any { // Custom logic to build parameters params := make(map[string]any) if len(args) > 0 { params["WFInput"] = paramValue(args[0], String) } if len(args) > 1 { params["WFMode"] = args[1].value.(string) } return params }, appendParamsFunc: func(args []actionArgument) map[string]any { // Add dynamic parameters without overriding automatic handling return map[string]any{ "WFDynamicFlag": len(args) > 2, } }, outputType: String, }, ``` -------------------------------- ### Fetch and Convert Shortcuts iCloud Plist Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md Commands to retrieve a shortcut's metadata, download the binary plist, and convert it to XML format for comparison. ```bash # Given a share URL like https://www.icloud.com/shortcuts/{identifier} # Replace /shortcuts/ with /shortcuts/api/records/ to get the metadata JSON curl "https://www.icloud.com/shortcuts/api/records/{identifier}" | jq '.fields.shortcut.value.downloadURL' # Download the binary plist from the returned URL curl -L "{downloadURL}" -o reference.shortcut # Convert binary plist to readable XML (macOS) plutil -convert xml1 reference.shortcut -o reference.plist ``` -------------------------------- ### Define static parameters with inline dictionaries Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Include static plist parameters by appending an inline dictionary block to the action definition. ```cherri action 'output' outputOrClipboard(text output: 'WFOutput') { "WFNoOutputSurfaceBehavior": "Copy to Clipboard" } ``` -------------------------------- ### Extract references Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Fetches a shortcut from an iCloud URL and prints a map of variable references and cross-links. ```bash cherri --refs="https://www.icloud.com/shortcuts/abcd1234" ``` -------------------------------- ### Compiler Package Imports Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/EXPORTED-API-INDEX.md Standard library and third-party dependencies required by the Cherri compiler. ```go import ( "bufio" "crypto/sha1" "crypto/x509" "embed" "encoding/json" "fmt" "maps" "math" "os" "os/exec" "path/filepath" "reflect" "regexp" "runtime" "slices" "strings" "sync" "unicode" "github.com/electrikmilk/args-parser" "howett.net/plist" ) ``` -------------------------------- ### Collect Include Statements Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Parses #include statements to identify files for the pre-parse phase. ```go func collectInclude() ``` -------------------------------- ### Implement paramValue logic Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-plist-generation.md Simplified switch logic for handling different Cherri argument types. ```go switch arg.valueType { case String: return attachmentValues(arg.value.(string)) // handle interpolation case Integer, Float: return arg.value // numeric literal case Variable: return variableValue(arg.value.(varValue)) // variable reference case Dict: return makeDictValue(arg.value.(map[string]any)) case Arr: return makeArrayValue(arg.value.([]any)) // ... more cases } ``` -------------------------------- ### Define Shortcut Name Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Sets the display name for the generated Shortcut. ```cherri #define name Weather App ``` -------------------------------- ### Search for Available Glyphs Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Use this command to list available icons for use in #define glyph directives. ```bash cherri --glyph=glyphName ``` -------------------------------- ### Define Shortcut Trigger Locations Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Configures where the Shortcut appears and how it is triggered. ```cherri #define from menubar, sharesheet ``` ```go var workflowTypes = map[string]string{ "menubar": "MenuBar", "quickactions": "QuickActions", "sharesheet": "ActionExtension", // ... } ``` -------------------------------- ### Collect Parameter Definitions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Parses comma-separated parameter definitions with support for optionality, literal requirements, and default values. ```go func collectParameterDefinitions() []parameterDefinition ``` ```text type? name: 'plistKey' = defaultValue ``` -------------------------------- ### Convert Binary Plist to XML Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/README.md Use the macOS plutil tool to convert binary shortcut files into readable XML format. ```bash plutil -convert xml1 file.shortcut -o file.plist ``` -------------------------------- ### Define and Call Functions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/OVERVIEW.md Functions run in an isolated scope and return values via the output function. ```cherri function add(number op1, number op2): number { const s = @op1 + @op2 output("{s}") } const sum = add(2, 3) ``` -------------------------------- ### Manage Variables and Constants Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md Mutable variables use the @ prefix, while constants reference action outputs. Globals provide access to built-in Shortcut variables. ```ruby // Mutable variable — compiles to a "Set Variable" action @name = "value" @count = 0 @count += 1 // also -=, *=, /= // Constant (magic variable) — references the action output directly, smaller Shortcut const result = someAction() // Type declaration with no initial value @builder: text @items: array // Globals (case-sensitive) @input = ShortcutInput @now = CurrentDate @clip = Clipboard @dev = Device // Ask the user at runtime wait(Ask) wait(Ask: 'How many seconds?') ``` -------------------------------- ### Make Function Call Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-variables-functions.md Generates an action struct representing a function call, including metadata and the runSelf action. ```go func makeFunctionCall(identifier string, args []actionArgument) action ``` -------------------------------- ### Generate parameters with getActionParameters Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md Builds the plist parameter dictionary for the current action based on collected arguments. ```go var params = getActionParameters([]actionArgument{ {valueType: String, value: "Hello"}, }) // Result: map[string]any{"WFTextActionText": "Hello", ...} ``` -------------------------------- ### ask(text? prompt, string type) Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Prompts the user for input with an optional prompt and input type. ```APIDOC ## ask(text? prompt, string type) ### Description Requests input from the user. Supported input types include Text, Number, URL, Date, Time, and Date and Time. ### Signature `ask(text? prompt): string` or `ask(text? prompt, string type): string` ### Parameters - **prompt** (String) - Optional - The question or prompt shown to the user. - **type** (String) - Optional - The expected input type (e.g., "Number"). ### Usage ```cherri const name = ask("What is your name?") const number = ask("Enter a number", "Number") ``` ``` -------------------------------- ### Define ask action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Internal definition for the ask action, supporting optional prompts and input types. ```go "ask": { parameters: []parameterDefinition{ {name: "text", validType: String, key: "WFQuestion", optional: true}, {name: "type", validType: String, key: "WFAskActionType", literal: true, enum: "inputType"}, }, outputType: String, } ``` -------------------------------- ### Load Embedded DSL Actions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Parses and registers action definitions from embedded .cherri files. ```go func includeStandardActions() ``` -------------------------------- ### Pre-Parse Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Executes sequential pre-processing passes, including resolving includes and collecting function definitions. ```go func preParse() ``` -------------------------------- ### Define Shortcut Root Structure Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-plist-generation.md The primary struct representing the entire Shortcut, containing metadata, actions, and configuration fields. ```go type Shortcut struct { WFWorkflowIcon ShortcutIcon WFWorkflowActions []ShortcutAction WFQuickActionSurfaces []string WFWorkflowInputContentItemClasses []string WFWorkflowClientVersion string WFWorkflowMinimumClientVersion int WFWorkflowMinimumClientVersionString string WFWorkflowImportQuestions []WFQuestion WFWorkflowTypes []string WFWorkflowOutputContentItemClasses []string WFWorkflowHasShortcutInputVariables bool WFWorkflowHasOutputFallback bool WFWorkflowNoInputBehavior map[string]any } var shortcut Shortcut ``` -------------------------------- ### Marshal shortcut to Plist Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-plist-generation.md Uses the howett.net/plist library to convert the shortcut struct into XML bytes. ```go var plistBytes, marshalErr = plist.Marshal(shortcut, plist.XMLFormat) ``` -------------------------------- ### Search for an action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Queries the compiler for information regarding a specific action name. ```bash cherri --action=getText ``` -------------------------------- ### Define Version Constraints for Actions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/types-and-decompilation.md Sets minimum and maximum version requirements for an action, checked against the defined version setting. ```go actionDefinition{ identifier: "newFeature", minVersion: 18.4, // requires Shortcuts 18.4+ maxVersion: 26.0, // deprecated in 26.0+ } ``` -------------------------------- ### Define an action structure Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-action-system.md The actionDefinition struct defines the metadata, parameters, and behavior for a single Shortcuts action. ```go type actionDefinition struct { doc selfDoc identifier string appIdentifier string overrideIdentifier string parameters []parameterDefinition check checkFunc makeParams paramsFunc appendParams map[string]any appendParamsFunc paramsFunc decomp func(action *ShortcutAction) (arguments []string) appIntent appIntent outputType tokenType defaultAction bool macOnly bool nonMacOnly bool minVersion float64 maxVersion float64 builtin bool } ``` -------------------------------- ### UI Actions (ui.cherri) Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Methods for interacting with the user interface. ```APIDOC ## ui.cherri - `chooseFromList()`: Displays a selection dialog. - `showResult()`: Displays a result to the user. - `playAlert()`: Plays a notification sound. - `vibrate()`: Triggers device vibration. ``` -------------------------------- ### Enable Debug Mode Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/README.md Run the compiler with the --debug flag to generate intermediate files and view parser state. ```bash cherri file.cherri --debug ``` -------------------------------- ### Version-Specific Actions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Configuration for actions constrained by specific Shortcuts version requirements. ```APIDOC ## Version-Specific Action Definition ```json "newFeatureAction": { "identifier": "newFeature", "minVersion": 18.4, "maxVersion": 26.4, "parameters": [...], "outputType": "String" } ``` ``` -------------------------------- ### Define getDictionary action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Internal definition for the getDictionary action, which converts input into a dictionary object. ```go "getDictionary": { parameters: []parameterDefinition{ {name: "text", validType: Variable, key: "WFInput"}, }, outputType: Dict, } ``` -------------------------------- ### Data Flow Architecture Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/README.md The transformation path of data from raw parser tokens to the final signed shortcut file. ```text Parser → Tokens → Action Definitions → Plist Structs → XML Serialization → Signed .shortcut ``` -------------------------------- ### Dictionary Iteration Workaround Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Iterating over dictionary keys using a helper action to retrieve values. ```cherri @dict = {"name": "Alice", "age": "30"} const keys = getDictionary(@dict).keys() // custom action for key in keys { const value = getValue(@dict, key) alert("{key}: {value}") } ``` -------------------------------- ### Register Go-Defined Actions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Registers actions defined in Go source files. ```go func loadBasicStandardActions() ``` -------------------------------- ### Define No-Input Behavior Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Configures how the Shortcut behaves when executed without input. ```cherri #define noinput stopwith "This Shortcut requires input" ``` -------------------------------- ### Define Global Condition Mappings Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Maps token types to integer identifiers for conditions and logical filter prefixes as defined in shortcut.go. ```go var conditions = map[tokenType]int{ Is: 4, Not: 5, Any: 100, Empty: 101, Contains: 99, DoesNotContain: 999, BeginsWith: 8, EndsWith: 9, GreaterThan: 2, GreaterOrEqual: 3, LessThan: 0, LessOrEqual: 1, Between: 1003, IsToday: 1002, } var conditionFilterPrefixes = map[tokenType]int{ Or: 0, And: 1, } ``` -------------------------------- ### Define and Modify Variables Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/OVERVIEW.md Use the @ prefix for mutable variables and standard assignment operators. ```cherri @name = "Alice" @count = 0 @count += 1 ``` -------------------------------- ### Device Actions (device.cherri) Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Methods for querying device-specific information and attributes. ```APIDOC ## device.cherri - `getDeviceAttribute()`: Retrieves device model, OS version, etc. - `getDeviceModel()`: Returns the device model (e.g., iPhone, iPad, Mac). - `getSystemVersion()`: Returns the current iOS/macOS version. - `isFamilyHub()`: Returns a boolean indicating if the device is a Family Hub. ``` -------------------------------- ### Define For-Each Action in Plist Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Configures a for-each loop to iterate over an array input. ```go ShortcutAction{ WFWorkflowActionIdentifier: "is.workflow.actions.foreach", WFWorkflowActionParameters: map[string]any{ "WFInput": /* array value */, "WFVariable": map[string]any{ "Type": "Variable", "VariableName": /* loop var name */, }, }, } ``` -------------------------------- ### Web Actions (web.cherri) Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Methods for web-related operations and URL handling. ```APIDOC ## web.cherri - `openURL()`: Opens a link. - `getWebPageAttribute()`: Extracts metadata from a webpage. - `encodeURL()`: URL encodes text. ``` -------------------------------- ### Cherri Compilation Pipeline Stages Source: https://github.com/electrikmilk/cherri/blob/main/AGENTS.md The sequential flow of the Cherri compiler from source file reading to final shortcut generation. ```text .cherri source ↓ handleFile() — read file, split into lines/chars ↓ initParse() — initialize global state ↓ preParse() — sequential pre-processing passes: handleIncludes() — inline #include files, resetParse() handleFunctions() — collect function defs, inject header, resetParse() handleActionDefinitions() — collect user-defined action blocks ↓ parse() — main pass: walk chars, emit tokens[] ↓ generateShortcut() — walk tokens[], build shortcut.WFWorkflowActions[] ↓ createShortcut() — serialize to plist, sign, write .shortcut ``` -------------------------------- ### Initialize Variable Storage Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-variables-functions.md The variables map acts as the central registry for all user-defined variables and constants during compilation. ```go var variables map[string]varValue ``` -------------------------------- ### Parse Functions Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-variables-functions.md Walks the source code to collect all function definitions into the functions map. ```go func parseFunctions() ``` -------------------------------- ### Report Line Debug Info Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Prints character and line context for debugging purposes. ```go func lineReport(label string) ``` -------------------------------- ### Collect Action Arguments Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/api-parser.md Reads comma-separated arguments between parentheses, supporting literals, variable references, nested action calls, and nil values. ```go func collectActionArguments() []actionArgument ``` -------------------------------- ### Repeat Loop Workaround Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/control-flow-reference.md Simulating a while loop using a repeat block with a conditional check. ```cherri // Workaround: repeat with conditional break repeat i for 1000 { if some_condition { // break not available; use nested if to skip remaining } } ``` -------------------------------- ### Define macOS-only Action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/compiler-configuration.md Use the macOnly flag in an action definition to restrict usage to macOS platforms. ```go actionDefinition{ macOnly: true, // only available on macOS } ``` -------------------------------- ### Define Shortcut Structure Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/EXPORTED-API-INDEX.md Represents the root plist container for a Shortcuts workflow, used during compilation and XML serialization. ```go type Shortcut struct { WFWorkflowIcon ShortcutIcon WFWorkflowActions []ShortcutAction WFQuickActionSurfaces []string WFWorkflowInputContentItemClasses []string WFWorkflowClientVersion string WFWorkflowMinimumClientVersion int WFWorkflowMinimumClientVersionString string WFWorkflowImportQuestions []WFQuestion WFWorkflowTypes []string WFWorkflowOutputContentItemClasses []string WFWorkflowHasShortcutInputVariables bool WFWorkflowHasOutputFallback bool WFWorkflowNoInputBehavior map[string]any } ``` -------------------------------- ### Cherri Project Directory Structure Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/README.md Visual representation of the project file hierarchy. ```text cherri/ ├── main.go — CLI entry point, file handling, main loop ├── parser.go — Character parser, tokenization, pre-processing ├── action.go — Action definition system, validation, parameter handling ├── actions_std.go — Go-defined standard actions (~100 actions) ├── shortcutgen.go — Plist value generation and serialization ├── shortcut.go — Plist struct definitions and constants ├── variables.go — Variable storage, lookup, UUID management ├── functions.go — Function parsing, header generation, calls ├── decompile.go — Reverse .shortcut → .cherri ├── token.go — Token type constants ├── includes.go — #include directive handling ├── packages.go — Package manager ├── glyphs.go — Glyph name → ID database ├── actions/ — Embedded DSL action definitions (by category) │ ├── basic.cherri │ ├── device.cherri │ ├── network.cherri │ └── ... (20+ category files) ├── stdfunc.cherri — Standard library Cherri functions ├── tests/ — Test .cherri files ├── assets/ — Icons and resources └── README.md, go.mod, etc. ``` -------------------------------- ### Define an App Intent action Source: https://github.com/electrikmilk/cherri/blob/main/_autodocs/standard-library.md Use this structure to define an action that calls functionality from another application. ```go actionDefinition{ identifier: "someAppAction", appIntent: appIntent{ name: "Action Name", bundleIdentifier: "com.example.app", appIntentIdentifier: "com.example.app.actionIdentifier", }, } ```