deep-code-review
In-depth design-focused code review - understands codebase context before evaluating PR…
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.
$ npx -y skills add expo/expo --skill expo-app-intents --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/expo-app-intentsContext 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.
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
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.
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:
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.
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.
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: LocalizedStringResoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.
Repo: expo/expo
In-depth design-focused code review - understands codebase context before evaluating PR…
Write TSDoc comments for Expo SDK APIs following official conventions. MUST USE when…
Run Expo's configured AI code reviewer on local changes or an expo/expo pull request,…
Test Expo Router features on Android emulators using ADB. Use after implementing native…
Persist and query local data with expo-sqlite in Expo or React Native apps. Use for SQLite…