expo-migrate-module

Migrates Swift Expo native modules from the 1.0 definition DSL to the 2.0 macro API.

2.5k|140|Updated Nov 30, 2025
One-click install
npx skills add https://github.com/expo/skills --skill expo-migrate-module
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: expo-migrate-module
Source: https://github.com/expo/skills/tree/main/plugins/expo-experiments/skills/expo-migrate-module
Command: npx skills add https://github.com/expo/skills --skill expo-migrate-module

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve?

Migrating an existing Expo native module from the Expo Modules API 1.0 definition DSL to the 2.0 macro API (@ExpoModule, @JS, @Event, @SharedObject, @Record) is error-prone: macro support varies across expo-modules-core versions, wire names can silently change, and async queue semantics differ. This Skill guides an agent through a contract-preserving, incremental migration of the Swift side of a module without changing its JavaScript/TypeScript API.

Core Features & Use Cases

  • Contract-first migration: Inventories every exported member (functions, properties, constants, events, records, shared objects, lifecycle hooks) and preserves JS-visible names, arity, nullability, and sync/async behavior.
  • Compatibility verification: Checks the actually installed expo-modules-core and macro declarations before migrating each member, classifying items as Migrate, Keep in DSL (mixed mode), or Blocked.
  • Incremental mixed-mode support: Keeps unsupported members in the 1.0 definition() DSL alongside @ExpoModule, with a fallback flow that asks the user to co-exist or revert and files a tracking issue on expo/expo.
  • Use Case: You maintain an Expo module written against the 1.0 DSL and want to adopt the 2.0 macros after upgrading to expo 57.0.7+. The Skill migrates functions, properties, events, and records group by group, keeps a queue-pinned AsyncFunction in the DSL, and verifies the result with builds, native tests, and the example app.

Quick Start

Use the expo-migrate-module skill to migrate this module's Swift implementation from the 1.0 definition DSL to the 2.0 macro API without changing its JavaScript contract.

Frequently Asked Questions about expo-migrate-module

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I migrate an Expo module from the 1.0 DSL to the 2.0 macro API?▼

Inventory every exported member first, then migrate one semantic group at a time: module naming, functions, properties/constants, events, shared objects, then records. Verify macro and core runtime support in the checked-out expo-modules-core before migrating each item, and keep unsupported members in the 1.0 definition() DSL.

What Expo version is required for the Expo Modules API 2.0 macros?▼

The 2.0 macros require expo 57.0.7 or newer. Check the installed version in package.json or with npm ls expo before editing; if it is older, upgrade first because the migration cannot proceed against an unsupported version.

Does the 2.0 macro API support everything in the 1.0 definition DSL?▼

No. Views, @Union, synchronous events, shared-object static functions, and same-JS-name overloads may lack verified support depending on the checked-out core. Unsupported members stay in the 1.0 definition() DSL in mixed mode, which coexists safely with @ExpoModule.

Why does my event name change after migrating to @Event?▼

The default @Event wire name strips a leading 'on' and decapitalizes the remainder, so Swift onProgress emits 'progress' instead of 'onProgress'. Pass the original wire name explicitly, for example @Event("onProgress"), to preserve the existing JS listener contract.

Can I migrate Android/Kotlin modules or create new modules with this skill?▼

No. This skill covers only migrating existing Apple/Swift modules from the 1.0 DSL to the 2.0 macro API. It explicitly excludes creating new modules, general Expo SDK upgrades, and Android/Kotlin migrations, which remain on the 1.0 DSL.

What happens when a module member cannot be migrated to 2.0?▼

The migration stops on that group and asks whether to co-exist (keep it in the 1.0 DSL alongside @ExpoModule) or revert the group's edits. A tracking issue is opened on expo/expo documenting the missing macro or core hook, and other groups continue migrating.