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.