Agent skill

cherri

Use when writing Apple Shortcuts as code using Cherri language. Covers syntax, actions, compilation, and common patterns.

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/cherri

SKILL.md

Cherri - Apple Shortcuts Programming Language

Cherri compiles to .shortcut files for iOS/macOS. Store .cherri files in dotfiles for version-controlled Shortcuts.

Installation

bash
brew tap electrikmilk/cherri
brew install electrikmilk/cherri/cherri

Compilation

bash
cherri file.cherri              # Compile + sign via macOS/AppleID
cherri file.cherri --hubsign    # Sign via RoutineHub (fallback)
cherri file.cherri --skip-sign  # Unsigned (won't import on macOS)
cherri file.cherri --debug      # Debug output

Output: Shortcut Name.shortcut (name from #define name or filename)

Note: macOS requires signed shortcuts. Use --skip-sign only for syntax checks.

Syntax Reference

Defines (Shortcut Metadata)

cherri
#define name My Shortcut
#define color red
#define glyph heart
#define version 18.4
#define inputs text, image
#define outputs file

Colors: red, darkorange, orange, yellow, green, teal, lightblue, blue, darkblue, violet, purple, pink, taupe, gray, darkgray

Glyphs: Use cherri --glyph=search to find icons.

Variables

cherri
@name = "World"                    // Variable assignment
const greeting = "Hello"           // Constant
@message = "{greeting}, {name}!"   // String interpolation

Global variables: Ask, Clipboard, CurrentDate, ShortcutInput, RepeatIndex, RepeatItem

Essential Actions

cherri
// Dialogs
alert("Message", "Title")          // Alert with title
alert("Message")                   // Alert without title
show("Text to display")            // Show output

// User input
@text = prompt("Enter text:")      // Text input
@num = askNumber("Enter number:")  // Number input

// Control
nothing()                          // Clear output
stop()                             // Stop shortcut
exit()                             // Same as stop
comment("Note")                    // Add comment

Control Flow

cherri
// If statement
if condition {
    // code
} else {
    // code
}

// Repeat n times
repeat 5 {
    alert("{RepeatIndex}")
}

// Repeat with named index
repeat i for 5 {
    alert("Index: {i}")
}

// For each in list
for item in list {
    alert(item)
}

Menus

IMPORTANT: Use colon : after item name, NOT curly braces!

cherri
menu "Choose an option:" {
    item "Option 1":
        alert("You chose 1")
    item "Option 2":
        alert("You chose 2")
        show("More actions here")
}

Lists

cherri
#include 'actions/scripting'

@items = list("apple", "banana", "cherry")
@chosen = chooseFromList(items, "Pick one")

repeatEach fruit in items {
    alert(fruit)
}

Custom Actions (Functions)

cherri
action greet(text name) {
    alert("Hello, {name}!")
}

greet("World")

Includes

cherri
#include "other_file.cherri"
#include 'actions/scripting'   // Built-in action libraries

Common Patterns

Hello World

cherri
#define name Hello World
#define color green
#define glyph star

alert("Hello World!", "Greeting")

User Input Flow

cherri
#define name Greeter

@name = prompt("What's your name?")
@age = askNumber("What's your age?")
alert("Hello {name}, you are {age} years old!", "Welcome")

Menu-Driven Shortcut

cherri
#define name Color Picker
#define color blue
#define glyph paintbrush

menu "Pick a color:" {
    item "Red":
        @color = "red"
    item "Green":
        @color = "green"
    item "Blue":
        @color = "blue"
}

alert("You picked: {color}", "Result")

Common Mistakes

Wrong Correct Why
alert(title, message) alert(message, title) Message first, title second
var = value @var = value Variables need @ prefix
askText("prompt") prompt("prompt") Action is prompt, not askText
menu { item "X" { ... } } menu { item "X": ... } Colon after item, not braces

CLI Reference

bash
cherri --help                     # All options
cherri --action=alert             # Search action definitions
cherri --glyph=star               # Search glyphs
cherri --docs=scripting           # Action documentation by category

Discovering Third-Party Actions

macOS stores all available Shortcuts actions in a ToolKit database. Use the dotfiles script to explore:

bash
# In dotfiles/shortcuts/
./analyze-shortcuts-actions.fish stats      # Show action counts
./analyze-shortcuts-actions.fish vendors    # List third-party app vendors
./analyze-shortcuts-actions.fish actions raycast  # Find actions for an app
./analyze-shortcuts-actions.fish search clipboard # Search by keyword
./analyze-shortcuts-actions.fish doc        # Generate SHORTCUTS_ACTIONS.md reference

The generated SHORTCUTS_ACTIONS.md lists all third-party action identifiers you can use in Cherri.

Workflow: Adding New Extension Apps

When you install a new Shortcuts extension (Toolbox Pro, Actions, etc.):

  1. Regenerate actions doc:

    bash
    ./analyze-shortcuts-actions.fish doc
    
  2. Find the app's actions:

    bash
    ./analyze-shortcuts-actions.fish actions toolbox
    
  3. Check if Cherri has built-in support:

    bash
    cherri --action=globalVariable
    
  4. If no built-in support, document the raw action pattern (see below)

  5. Update this skill if you discover useful patterns for the app

Using Third-Party Actions in Cherri

For actions not built into Cherri, use raw action syntax:

cherri
// Raw action with identifier from analyze-shortcuts-actions.fish
rawAction("com.alexhay.ToolboxProForShortcuts.IsDarkModeOnIntent", {
    "placeholder": "unused"  // rawAction requires at least one parameter
})

Important: Cherri's rawAction crashes with empty {}. Always include at least one placeholder parameter.

Discovering parameters: Use the analysis script to query the ToolKit database:

bash
# Show all parameters for an action
./analyze-shortcuts-actions.fish params GlobalVariablesIntent

# Find actions for an app
./analyze-shortcuts-actions.fish actions sindre

The ToolKit database at ~/Library/Shortcuts/ToolKit/ contains all parameter definitions.

Known Extension App Patterns

Toolbox Pro

Action prefix: com.alexhay.ToolboxProForShortcuts

Key actions:

  • GlobalVariablesIntent - Get/set/check global variables
  • CheckGVIntent - Check if global variable exists
  • IsDarkModeOnIntent - Check dark mode ✅ verified
  • DeviceDetailsIntent - Device info
  • GetTextFromImageIntent - OCR
  • CreateMenuIntent / SmartMenuIntent - Custom menus
cherri
// ✅ VERIFIED: Check if dark mode is on
rawAction("com.alexhay.ToolboxProForShortcuts.IsDarkModeOnIntent", {
    "ShowWhenRun": true
})

// ✅ VERIFIED: Global Variables (use `./analyze-shortcuts-actions.fish params GlobalVariablesIntent` for all params)
// Set a variable
rawAction("com.alexhay.ToolboxProForShortcuts.GlobalVariablesIntent", {
    "mode": "set",
    "setVariableKey": "myVariable",
    "setVariableValue": "myValue"
})

// Get a variable
rawAction("com.alexhay.ToolboxProForShortcuts.GlobalVariablesIntent", {
    "mode": "get",
    "getVariableKey": "myVariable"
})

// Delete a variable
rawAction("com.alexhay.ToolboxProForShortcuts.GlobalVariablesIntent", {
    "mode": "delete",
    "deleteVariableKey": "myVariable"
})

Persistent Config (JSON in iCloud) ✅ THE WAY

For persistent data across shortcuts, use a JSON file in iCloud Drive:

Location: ~/Library/Mobile Documents/com~apple~CloudDocs/dotfiles/shortcuts/config.json

CLI access (fish):

bash
shortcuts-config get                    # View all
shortcuts-config get currentProject     # Get key
shortcuts-config set currentProject foo # Set key
shortcuts-config del currentProject     # Delete key

Shortcuts access: Use "Get File" and "Save File" actions pointing to: /dotfiles/shortcuts/config.json in iCloud Drive

Why this (not Data Jar or other apps):

  • Direct CLI access with jq and shortcuts-config
  • Version controllable (can symlink to dotfiles repo)
  • No app dependency
  • Works on iOS via Files app + Shortcuts "Get File"/"Save File"
  • Claude Code can read/write directly

Menu Box ✅ installed

Action prefix: dev.alexhay.MenuBox

Beautiful custom menus with SF Symbols, colors, and hidden data fields. Fully CLI-driven - no GUI needed.

Quick Menu (inline, no pre-config):

cherri
// Create menu from marked-up text
// Format: "Title | symbol" per line
rawAction("dev.alexhay.MenuBox.QuickMenuIntent", {
    "text": "Settings | gear\nProfile | person.circle\nHelp | questionmark.circle"
})

Custom Menu Items (full control):

cherri
// Create styled menu item with SF Symbol
rawAction("dev.alexhay.MenuBox.CreateSymbolItemIntent", {
    "title": "Settings",
    "subtitle": "Configure options",
    "symbol": "gear",
    "symbolColourHex": "#FFFFFF",
    "bgColourHex": "#007AFF",
    "mask": "circle"
})

// Create menu item from emoji
rawAction("dev.alexhay.MenuBox.CreateEmojiItemIntent", {
    "title": "Coffee Break",
    "emoji": "☕️"
})

// Create menu item from image
rawAction("dev.alexhay.MenuBox.CreateImageItemIntent", {
    "title": "Photo",
    "image": imageVariable
})

Hidden Data Fields: Each menu item supports field1 through field4 for storing data that isn't visible but accessible when item is selected.

Menu Sets: Save menus to reuse across shortcuts:

cherri
rawAction("dev.alexhay.MenuBox.CreateMenuSetIntent", {
    "menuItems": menuItemsVariable,
    "setType": "new",
    "setName": "My Project Menu"
})

// Later, choose from saved set
rawAction("dev.alexhay.MenuBox.ChooseMenuSetIntent", {
    "menuSet": "My Project Menu"
})

Run ./analyze-shortcuts-actions.fish params CreateSymbolItemIntent for all styling options (weights, scales, masks).

FocusCuts ✅ installed (macOS only)

Action prefix: dev.snailedit.FocusCuts

FocusCuts provides Focus Mode awareness with 3 custom actions + a status bar menu.

Get current Focus Mode:

cherri
// Returns the currently active Focus Mode name (or empty if none)
rawAction("dev.snailedit.FocusCuts.GetCurrentFocusModeIntent", {
    "ShowWhenRun": false
})

Check if specific Focus is active:

cherri
rawAction("dev.snailedit.FocusCuts.IsFocusModeActiveIntent", {
    "focusMode": "Work"  // returns true/false
})

List all Focus Modes:

cherri
rawAction("dev.snailedit.FocusCuts.ListFocusModesIntent", {
    "ShowWhenRun": false
})

Focus-aware conditional logic pattern:

cherri
// Get current focus, then branch
rawAction("dev.snailedit.FocusCuts.GetCurrentFocusModeIntent", {
    "ShowWhenRun": false
})
@focusMode = ShortcutInput

if focusMode == "Work" {
    alert("Loading work projects...", "Work Mode")
} else if focusMode == "Personal" {
    alert("Loading personal projects...", "Personal Mode")
} else {
    alert("No Focus Mode active", "Default")
}

FocusCuts menu bar: Also provides a status bar menu showing shortcuts relevant to your current Focus Mode (configure in app).

Logger ✅ installed

Action prefix: com.alexhay.Console

Real-time debugging console with log levels, tags, and iCloud sync. Much better than alert() spam.

Basic logging:

cherri
// Log a message with category (info/success/warning/error)
rawAction("com.alexhay.Console.LogMessageIntent", {
    "title": "API Response",
    "messages": "Got 200 OK",
    "category": "success",
    "tag": "api"
})

// Log with error fallback if empty
rawAction("com.alexhay.Console.LogMessageIntent", {
    "title": "User Input",
    "messages": userInput,
    "errorIfEmpty": true,
    "errorMessage": "No input provided!"
})

Session control:

cherri
// Start a logging session
rawAction("com.alexhay.Console.StartLoggingIntent", {
    "mode": "start"
})

// ... your shortcut logic ...

// Stop logging
rawAction("com.alexhay.Console.StartLoggingIntent", {
    "mode": "stop"
})

Log files/items:

cherri
rawAction("com.alexhay.Console.LogItemsIntent", {
    "items": fileVariable,
    "title": "Downloaded File",
    "message": "Processing complete"
})

Conditional logging:

cherri
// Log different messages based on condition
rawAction("com.alexhay.Console.LogConditionalMessageIntent", {
    "condition": "equals",
    "sourceValue": statusCode,
    "query": "200",
    "trueTitle": "Success",
    "trueMessage": "Request completed",
    "trueCategory": "success",
    "falseTitle": "Failed",
    "falseMessage": "Request failed with status",
    "falseCategory": "error",
    "tag": "api"
})

Export logs:

cherri
// Output all logs as markdown
rawAction("com.alexhay.Console.OutputMessagesIntent", {
    "outputMode": "markdown"
})

// Clear console after export
rawAction("com.alexhay.Console.ClearMessagesIntent", {
    "ShowWhenRun": false
})

System diagnostics:

cherri
// Log device details (model, OS, battery, etc.)
rawAction("com.alexhay.Console.LogDeviceDetailsIntent", {
    "tag": "system"
})

// Log internet connection info
rawAction("com.alexhay.Console.LogInternetConnectionIntent", {
    "tag": "network"
})

Debugging workflow:

  1. Add StartLoggingIntent at shortcut start
  2. Sprinkle LogMessageIntent calls at key points
  3. Use tags to filter (e.g., "api", "ui", "data")
  4. Use categories for severity (info/success/warning/error)
  5. Export with OutputMessagesIntent when done
  6. Logs sync via iCloud - debug iOS shortcuts from Mac

Actions by Sindre Sorhus ✅ installed

Action prefix: com.sindresorhus.Actions

199 utility actions. Key ones:

cherri
// Generate UUID
rawAction("com.sindresorhus.Actions.GenerateUUIDIntent", {
    "placeholder": "unused"
})

// Format duration
rawAction("com.sindresorhus.Actions.FormatDurationIntent", {
    "placeholder": "unused"
})

// Debug (shows variables in console)
rawAction("com.sindresorhus.Actions.DebugIntent", {
    "placeholder": "unused"
})

Run ./analyze-shortcuts-actions.fish actions sindre for full list (199 actions).

Charty ✅ installed

Action prefix: com.brogrammers.charty

Generate charts and graphs from Shortcuts. 24 actions for 7 chart types: bar, line, pie, donut, scatter, area, rings.

Create a chart:

cherri
// Create new chart (returns chart ID)
rawAction("com.brogrammers.charty.NewChartIntent", {
    "title": "Monthly Stats",
    "automaticId": true
})
@chartId = ShortcutInput

Add data series:

cherri
// Add bar series
rawAction("com.brogrammers.charty.AddSeriesToChartIntent", {
    "chartId": "{chartId}",
    "label": "Revenue",
    "type": "bar",
    "barXValues": ["Jan", "Feb", "Mar"],
    "barYValues": [100, 150, 200]
})

// Add line series
rawAction("com.brogrammers.charty.AddSeriesToChartIntent", {
    "chartId": "{chartId}",
    "label": "Trend",
    "type": "line",
    "lineXValues": [1, 2, 3],
    "lineYValues": [100, 150, 200]
})

// Add pie/donut series
rawAction("com.brogrammers.charty.AddSeriesToChartIntent", {
    "chartId": "{chartId}",
    "label": "Distribution",
    "type": "pie",
    "pieLabels": ["A", "B", "C"],
    "pieValues": [30, 50, 20]
})

Export chart:

cherri
rawAction("com.brogrammers.charty.ExportChartAsImageIntent", {
    "chartId": "{chartId}"
})

Other actions: StyleChartIntent, StyleAxisIntent, AddAverageIntent, FilterDataIntent, GroupDataIntent, AddSeriesFromCSVIntent

Run ./analyze-shortcuts-actions.fish actions charty for full list (24 actions).


Update this skill with verified patterns when you discover them. Use ./analyze-shortcuts-actions.fish actions <name> to find action identifiers for installed apps.

Community Reference (Not Installed)

Other Shortcuts extensions worth exploring later:

App Purpose Link
Pushcut Webhook triggers, location/schedule automation, home server https://pushcut.io
a-Shell Run shell commands (Python, Unix tools) on iOS https://holzschu.github.io/a-Shell_iOS/
Jayson JSON viewer/editor with Shortcuts actions https://jayson.app
GizmoPack CSV parsing, Wallet pass generation App Store
Jellycuts Write Shortcuts in code (alternative to Cherri) App Store
Shortcutify Control Mac from iPhone, Google/Todoist integration App Store
Text Case Advanced text formatting App Store
AI Actions AI-powered Shortcuts actions (Sindre Sorhus) App Store

Development Workflow

Use the shortcuts-dev fish function for quick iteration:

bash
shortcuts-dev compile myshortcut.cherri  # Compile and sign
shortcuts-dev run myshortcut.cherri      # Compile, sign, and open
shortcuts-dev check myshortcut.cherri    # Syntax check only (fast)

shortcuts-dev params GlobalVariablesIntent  # Discover action params
shortcuts-dev actions toolbox               # List app's actions
shortcuts-dev vendors                       # List all apps

shortcuts-dev examples                      # List example templates

Example templates in shortcuts/examples/:

  • menu-driven.cherri - Menu Box with SF Symbols
  • focus-aware.cherri - FocusCuts conditional logic
  • with-logging.cherri - Logger debugging workflow

SF Symbols

Apple's icon library (5,000+ icons). Used by Menu Box symbol parameter.

Naming convention: base name + modifiers (dot-separated)

person                    # Outline
person.fill               # Solid fill
person.circle             # With circle background
person.circle.fill        # Solid with circle background
person.badge.plus         # With badge
person.2                  # Multiple (2 people)
person.2.fill             # Multiple, solid

Common modifiers:

  • .fill - Solid version
  • .circle / .square / .rectangle - Shape background
  • .badge.plus / .badge.minus - With badge
  • .slash - Crossed out / disabled
  • 2 / 3 - Multiple items

Common symbols:

Category Symbols
Actions plus, minus, xmark, checkmark, arrow.right, arrow.left
Objects gear, folder, doc, photo, video, music.note
People person, person.2, person.circle
Status bell, star, heart, flag, bookmark
System magnifyingglass, house, trash, pencil, link
Alerts exclamationmark.triangle, info.circle, questionmark.circle

Browse icons:

Resources

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results