SnippetIntent PRO

Requires Scripting PRO

SnippetIntent is a special kind of AppIntent whose purpose is to render interactive Snippet UI cards inside the Shortcuts app (iOS 26+).

Key characteristics:

  1. Must be registered in app_intents.tsx
  2. Must specify protocol: AppIntentProtocol.SnippetIntent
  3. perform() must return a VirtualNode (TSX UI)
  4. Must be returned via Intent.snippetIntent()
  5. Must be invoked from the Shortcuts action “Show Snippet Intent”
  6. SnippetIntent is ideal for building interactive, step-based UI inside a Shortcut

It is not a data-returning Intent; it is exclusively for UI rendering in Shortcuts.


2. System Requirements

SnippetIntent requires iOS 26 or later.

On iOS versions earlier than 26:

  • Intent.snippetIntent() is not available
  • Intent.requestConfirmation() cannot be used
  • The Shortcuts action “Show Snippet Intent” does not exist
  • SnippetIntent-type AppIntents cannot be invoked by Shortcuts

3. Registering a SnippetIntent (app_intents.tsx)

Example:

1export const PickColorIntent = AppIntentManager.register<void>({
2  name: "PickColorIntent",
3  protocol: AppIntentProtocol.SnippetIntent,
4  perform: async () => {
5    return <PickColorView />
6  }
7})

Another SnippetIntent:

1export const ShowResultIntent = AppIntentManager.register({
2  name: "ShowResultIntent",
3  protocol: AppIntentProtocol.SnippetIntent,
4  perform: async ({ content }: { content: string }) => {
5    return <ResultView content={content} />
6  }
7})

Requirements:

  • protocol must be AppIntentProtocol.SnippetIntent
  • perform() must return a TSX UI (VirtualNode)
  • SnippetIntent cannot return non-UI types such as text, numbers, JSON, or file paths

4. Wrapping SnippetIntent Return Values — Intent.snippetIntent

A SnippetIntent cannot be passed directly to Script.exit(). It must be wrapped in a IntentSnippetIntentValue.

1const snippetValue = Intent.snippetIntent(
2  ShowResultIntent({ content: "Example Text" })
3)
4
5Script.exit(snippetValue)

Type Definition

1type SnippetIntentValue = {
2  value?: IntentAttributedTextValue | IntentFileURLValue | IntentJsonValue | IntentTextValue | IntentURLValue | IntentFileValue | null
3  snippetIntent: AppIntent<any, VirtualNode, AppIntentProtocol.SnippetIntent>
4}
5
6declare class IntentSnippetIntentValue extends IntentValue<
7  'SnippetIntent',
8  SnippetIntentValue
9> {
10  value: SnippetIntentValue
11  type: 'SnippetIntent'
12}

This wrapper makes the return value compatible with the Shortcuts “Show Snippet Intent” action.


5. Snippet Confirmation UI — Intent.requestConfirmation

iOS 26 Snippet Framework provides built-in confirmation UI driven by SnippetIntent.

API

1Intent.requestConfirmation(
2  actionName: ConfirmationActionName,
3  intent: AppIntent<any, VirtualNode, AppIntentProtocol.SnippetIntent>,
4  options?: {
5    dialog?: Dialog;
6    showDialogAsPrompt?: boolean;
7  }
8): Promise<void>

ConfirmationActionName

A predefined list of semantic action names used by system UI:

"add" | "addData" | "book" | "buy" | "call" | "checkIn" | "continue" | "create" | "do" | "download" | "filter" | "find" | "get" | "go" | "log" | "open" | "order" | "pay" | "play" | "playSound" | "post" | "request" | "run" | "search" | "send" | "set" | "share" | "start" | "startNavigation" | "toggle" | "turnOff" | "turnOn" | "view"

Example

1await Intent.requestConfirmation(
2  "set",
3  PickColorIntent()
4)

Execution behavior:

  • Displays a Snippet UI for confirmation
  • If the user confirms → Promise resolves and script continues
  • If the user cancels → execution stops (system-driven behavior)

6. The “Show Snippet Intent” Action in Shortcuts (iOS 26+)

iOS 26 adds a new Shortcuts action:

Show Snippet Intent

This action is the only correct way to display SnippetIntent UI.

Comparison with Other Scripting Actions

Shortcuts Action UI Shown Supports SnippetIntent Usage
Run Script None No Background logic
Run Script in App Fullscreen UI inside Scripting No Rich app-level UI
Show Snippet Intent (iOS 26+) Snippet card UI Yes SnippetIntent flows

Usage

  1. Add “Show Snippet Intent” in Shortcuts
  2. Select a Scripting script project
  3. The script must return Intent.snippetIntent(...)
  4. Shortcuts renders the UI in a Snippet card

7. IntentMemoryStorage — Cross-Intent State Store

Why It Exists

Every AppIntent execution runs in an isolated environment:

  • After an AppIntent perform() completes → its execution context is destroyed
  • After a script calls Script.exit() → the JS context is destroyed

This means local variables cannot persist between AppIntent calls.

Snippet flows commonly involve: PickColor → SetColor → ShowResult

Therefore a cross-Intent state mechanism is required.


IntentMemoryStorage API

1namespace IntentMemoryStorage {
2  function get<T>(key: string): T | null
3  function set(key: string, value: any): void
4  function remove(key: string): void
5  function contains(key: string): boolean
6  function clear(): void
7  function keys(): string[]
8}

Purpose

  • Store small pieces of shared data across multiple AppIntents
  • Works during the entire Shortcut flow
  • Ideal for selections, temporary configuration, or intent-to-intent handoff

Example

1IntentMemoryStorage.set("color", "systemBlue")
2
3const color = IntentMemoryStorage.get<Color>("color")

Guidelines

Not recommended for large data. For large data:

  • Use Storage (persistent key-value store)
  • Or save files via FileManager in appGroupDocumentsDirectory

IntentMemoryStorage should be treated as temporary, lightweight state.


8. Full Example Combining All Features (iOS 26+)

app_intents.tsx

1export const SetColorIntent = AppIntentManager.register({
2  name: "SetColorIntent",
3  protocol: AppIntentProtocol.AppIntent,
4  perform: async (color: Color) => {
5    IntentMemoryStorage.set("color", color)
6  }
7})
8
9export const PickColorIntent = AppIntentManager.register<void>({
10  name: "PickColorIntent",
11  protocol: AppIntentProtocol.SnippetIntent,
12  perform: async () => {
13    return <PickColorView />
14  }
15})
16
17export const ShowResultIntent = AppIntentManager.register({
18  name: "ShowResultIntent",
19  protocol: AppIntentProtocol.SnippetIntent,
20  perform: async ({ content }: { content: string }) => {
21    const color = IntentMemoryStorage.get<Color>("color") ?? "systemBlue"
22    return <ResultView content={content} color={color} />
23  }
24})

intent.tsx

1async function runIntent() {
2
3  // 1. Ask the user to confirm setting the color via Snippet
4  await Intent.requestConfirmation(
5    "set",
6    PickColorIntent()
7  )
8
9  // 2. Read Shortcuts input
10  const textContent =
11    Intent.shortcutParameter?.type === "text"
12      ? Intent.shortcutParameter.value
13      : "No text parameter from Shortcuts"
14
15  // 3. Create final SnippetIntent UI
16  const snippetIntentValue = Intent.snippetIntent({
17    snippetIntent: ShowResultIntent({ content: textContent })
18  })
19
20  Script.exit(snippetIntentValue)
21}
22
23runIntent()

Shortcuts Flow

  1. User provides text
  2. “Show Snippet Intent” runs the script
  3. Script displays PickColorIntent confirmation UI via requestConfirmation
  4. After confirmation, displays ShowResultIntent Snippet UI
  5. Uses IntentMemoryStorage to persist the selected color

9. Summary

This document introduces all new Scripting features added for iOS 26+:

  1. SnippetIntent

    • Registered using AppIntentManager
    • Returns TSX UI
    • Requires iOS 26+
  2. Intent.snippetIntent

    • Wraps a SnippetIntent for Script.exit
  3. Intent.requestConfirmation

    • Presents a confirmation Snippet UI
    • Requires SnippetIntent
  4. “Show Snippet Intent” action in Shortcuts

    • Required to display SnippetIntent UI
  5. IntentMemoryStorage

    • Lightweight cross-AppIntent storage
    • Not suitable for large binary/content data
    • Complements multi-step Snippet flows