Skip to content
Mobile
Skill

/expo-app-intents

Add or maintain Apple App Intents in existing Expo apps using expo-app-intents. Use for Siri and Shortcuts actions, Swift intent declarations, JavaScript invocation handling, dynamic entity catalogs, intent donations, Spotlight indexing, and on-screen entity associations.

BOOST
From plugin
expo
53k6 skills
Install
$ npx -y skills add expo/expo --skill expo-app-intents --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/expo-app-intents

Context preview

The summary Claude sees to decide when to auto-load this skill.

Add or maintain Apple App Intents in existing Expo apps using expo-app-intents. Use for Siri and Shortcuts actions, Swift intent declarations, JavaScript invocation handling, dynamic entity catalogs, intent donations, Spotlight indexing, and on-screen entity associations.

SKILL.md

expo-app-intents.SKILL.md
name: expo-app-intents
description: Add or maintain Apple App Intents in existing Expo apps using expo-app-intents. Use for Siri and Shortcuts actions, Swift intent declarations, JavaScript invocation handling, dynamic entity catalogs, intent donations, Spotlight indexing, and on-screen entity associations.
license: MIT

expo-app-intents

Expose actions from the app's existing features. Reuse its business logic, persistence, authentication, and navigation; do not replace them with the counter, restaurant, or mail demo state.

Inspect the app first

Check the installed `expo` and `expo-app-intents` versions, app config, native build workflow, existing intent Swift files, and where application state becomes ready. This package is alpha: verify that the installed version supports the APIs used below. All integration guidance is bundled in this skill folder; no Expo repository checkout is required.

The runtime supports iOS 16.4+, macOS 13.4+, and tvOS 16.4+. The initializer and examples focus on iOS. Individual Apple APIs need newer SDKs or OS versions. Expo Go cannot run this integration; use a native development build. Android and web have fallback behavior, not App Intents support.

Choose the smallest native surface needed:

  • A plain `AppIntent` for an action; add an `AppShortcutsProvider` when launch phrases are wanted.
  • An `AppEntity` plus query for parameters selected from existing app records. Read [entities.md](references/entities.md) when implementing record-valued parameters or catalog synchronization.
  • A schema intent when the feature matches a schema listed in Apple's [App schema domains](https://developer.apple.com/documentation/appintents/app-schema-domains). Consult the domain's action and entity pages for supported names, required properties, and availability before writing declarations. Follow [advanced-features.md](references/advanced-features.md) to integrate that contract with the app; do not infer schema names or rely on a fixed domain list in this skill.
  • Donations, Spotlight, and on-screen associations only when requested or needed for the feature. Read the relevant sections of [advanced-features.md](references/advanced-features.md) for these features or schema intents.

Understand the native/JavaScript boundary

Intent, entity, query, and shortcut declarations are app-owned Swift compiled into the **app target**. Apple's metadata extraction cannot discover these declarations inside the package's static pod. Expo inline modules connect the app-owned Swift to that target; the package supplies storage and the bridge.

`AppIntentDispatcher.shared.dispatch(name:params:)` records an invocation in native `UserDefaults` storage and emits a live event when JavaScript is observing. It returns the invocation ID without waiting for JavaScript. There is no JavaScript response channel to `perform()`.

Return system-facing values and dialogs from Swift. When an action must finish before Siri reports success, implement the required work natively or adjust the feature's contract. Do not return a success dialog merely because a JavaScript mutation was queued. For actions that need the app's JavaScript immediately, use `openAppWhenRun = true`; dispatch alone does not start a headless JavaScript task. Without opening the app, work can remain queued until a later launch.

Configure an existing app

Run commands from the application directory, not a monorepo root:

npx expo install expo-app-intents
npx expo-app-intents init --examples minimal

`minimal` creates the setup module without demo intents or a shortcut provider. When a template materially helps, choose `counter`, `restaurant`, or `mail` explicitly, then adapt it to the app. `--examples` avoids the interactive picker. Use `--dir existing-directory` when extending an existing setup.

Merge this configuration into the existing config, preserving its other plugins, experiments, and watched directories:

{
  "expo": {
    "plugins": ["expo-app-intents"],
    "experiments": {
      "inlineModules": {
        "watchedDirectories": ["app-intents"]
      }
    }
  }
}

For another directory, use `["expo-app-intents", { "directory": "siri" }]` and ensure the watched directories cover `siri`. Watching an ancestor works recursively. The plugin validates coverage; it does not create intent declarations or configure the watched list for you. If the initializer cannot edit dynamic config, apply its printed changes to the actual config source and verify the evaluated result.

Keep app-owned Swift outside Expo Router's `app/` and `src/app/`, and outside generated `ios/` or `android/` directories in prebuild-managed apps. Do not watch the entire project. Reuse the existing setup directory so autolinking does not compile duplicate setup modules or intent types.

The initializer **never overwrites existing Swift files**. After extending a setup, read its warnings and merge missing shortcut entries, refresh wiring, entity registrations, or donation registrations into the existing files. Preserve the `AppIntentsSetup` class and module name, and merge into its existing `OnCreate` block.

For apps using prebuild, apply the config and build a new binary:

npx expo prebuild -p ios
npx expo run:ios

For a manually maintained native project, follow its native integration workflow and verify inline-module app-target membership instead of regenerating it blindly. Avoid `prebuild --clean` as a default in an existing app. Native declarations, phrases, registrations, and config changes require rebuilding; an OTA JavaScript update cannot add Swift intent types or phrases.

Declare the action and optional phrases

Adapt this custom intent's dispatch name and parameters to an existing app action. The example demonstrates the bridge; it does not adopt an Apple domain schema.

import AppIntents
internal import ExpoAppIntents

struct SaveItemIntent: AppIntent {
  static let title: LocalizedStringReso
Read more
Ships withexpo

An open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.

Get the whole plugin
Stats
52,630
Stars
14,468
Forks
Active
Maintenance
TypeScript
Language
MIT
License
36m ago
Last commit
10y ago
Created
1mo ago
Added

Repo: expo/expo

Other skills on expo.