{"id":"7f6aefed-7207-4f51-8f64-0494f8d9e72d","shortId":"Tn69gP","kind":"skill","title":"appmigrationkit","tagline":"Transfer app data between platforms using AppMigrationKit. Use when implementing one-time data migration from Android or other platforms to iOS, managing cross-platform transfer sessions with AppMigrationExtension, packaging and archiving user data for export, importing resources","description":"# AppMigrationKit\n\nOne-time cross-platform data transfer for app resources. Enables apps to\nexport data from one platform (e.g., Android) and import it on iOS during\ndevice setup or onboarding. iOS 26+ / iPadOS 26+ / Swift 6.3.\n\n> **Beta-sensitive.** AppMigrationKit is new in iOS 26 and may change before GM.\n> Re-check current Apple documentation before relying on specific API details.\n\nAppMigrationKit uses an app extension model. The system orchestrates the\ntransfer between devices. The app provides an extension conforming to export\nand import protocols, and the system calls that extension at the appropriate\ntime. The app itself never manages the network connection between devices.\n\n## Contents\n\n- [Architecture Overview](#architecture-overview)\n- [Setup and Entitlements](#setup-and-entitlements)\n- [App Migration Extension](#app-migration-extension)\n- [Exporting Resources](#exporting-resources)\n- [Importing Resources](#importing-resources)\n- [Migration Status](#migration-status)\n- [Progress Tracking](#progress-tracking)\n- [Testing](#testing)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Architecture Overview\n\nAppMigrationKit operates through three layers:\n\n1. **App extension** -- An `AppMigrationExtension` conforming type that the\n   system invokes during migration. It handles data export and import.\n2. **System orchestration** -- The OS manages the device-to-device session,\n   transport, and scheduling. The extension does not control when it runs.\n3. **Containing app** -- After migration completes, the app checks\n   `MigrationStatus.importStatus` on first launch to determine whether\n   migration occurred and whether it succeeded.\n\nKey types:\n\n| Type | Role |\n|---|---|\n| `AppMigrationExtension` | Protocol for the app extension entry point |\n| `ResourcesExportingWithOptions` | Protocol for exporting files via archiver |\n| `ResourcesExporting` | Simplified export protocol (no custom options) |\n| `ResourcesImporting` | Protocol for importing files on the destination |\n| `ResourcesArchiver` | Streams files into the export archive |\n| `MigrationDataContainer` | Access to the containing app's data directories |\n| `MigrationStatus` | Check import result from the containing app |\n| `MigrationPlatform` | Identifies the other device's platform (e.g., `.android`) |\n| `MigrationAppIdentifier` | Identifies the source app by store and bundle ID |\n| `AppMigrationTester` | Test-only actor for validating export/import logic |\n\n## Setup and Entitlements\n\n### Entitlement\n\nThe app extension requires the `com.apple.developer.app-migration.data-container-access`\nentitlement. Its value is a single-element string array containing the bundle\nidentifier of the containing app:\n\n```xml\n<key>com.apple.developer.app-migration.data-container-access</key>\n<array>\n    <string>com.example.myapp</string>\n</array>\n```\n\nNo other values are valid. This entitlement grants the extension read access\nto the containing app's data container during export and write access during\nimport.\n\n### Extension Target\n\nAdd a new App Extension target to the Xcode project. The extension conforms\nto one or more of the migration protocols (`ResourcesExportingWithOptions`,\n`ResourcesExporting`, `ResourcesImporting`).\n\n## App Migration Extension\n\nThe extension entry point conforms to `AppMigrationExtension`. During\nmigration, the system prevents launching the containing app and its other\nextensions to ensure exclusive data access.\n\n### Accessing the Data Container\n\nThe extension accesses the containing app's files through `appContainer`:\n\n```swift\nimport AppMigrationKit\n\nstruct MyMigrationExtension: ResourcesExportingWithOptions, ResourcesImporting {\n    // Access the containing app's directories\n    let container = appContainer\n\n    // container.bundleIdentifier     -- app's bundle ID\n    // container.containerRootDirectory -- root of the app container\n    // container.documentsDirectory    -- Documents/\n    // container.applicationSupportDirectory -- Application Support/\n}\n```\n\n`MigrationDataContainer` provides `containerRootDirectory`, `documentsDirectory`,\nand `applicationSupportDirectory` as `URL` values pointing into the containing\napp's sandbox.\n\n## Exporting Resources\n\nConform to `ResourcesExportingWithOptions` (or `ResourcesExporting` for no\ncustom options) to package files for transfer. The system calls\n`exportResources(to:request:)` with a `ResourcesArchiver` and a\n`MigrationRequestWithOptions`.\n\n### Declaring Export Properties\n\n```swift\nstruct MyMigrationExtension: ResourcesExportingWithOptions {\n    typealias OptionsType = MigrationDefaultSupportedOptions\n\n    var resourcesSizeEstimate: Int {\n        // Return estimated total bytes of exported data\n        calculateExportSize()\n    }\n\n    var resourcesVersion: String {\n        \"1.0\"\n    }\n\n    var resourcesCompressible: Bool {\n        true  // Let the system compress during transport\n    }\n}\n```\n\n- `resourcesSizeEstimate` -- Estimated total bytes. The system uses this for\n  progress UI and free-space checks.\n- `resourcesVersion` -- Format version string. The import side receives this\n  to handle versioned data formats.\n- `resourcesCompressible` -- When `true`, the archiver may compress files\n  during transport.\n\n### Implementing Export\n\n```swift\nfunc exportResources(\n    to archiver: sending ResourcesArchiver,\n    request: MigrationRequestWithOptions<MigrationDefaultSupportedOptions>\n) async throws {\n    let docsDir = appContainer.documentsDirectory\n\n    // Check destination platform if needed\n    if request.destinationPlatform == .android {\n        // Platform-specific export logic\n    }\n\n    // Append files one at a time -- make continuous progress\n    let userDataURL = docsDir.appending(path: \"user_data.json\")\n    try await archiver.appendItem(at: userDataURL)\n\n    // Append with a custom archive path\n    let settingsURL = docsDir.appending(path: \"settings.plist\")\n    try await archiver.appendItem(at: settingsURL, pathInArchive: \"preferences/settings.plist\")\n\n    // Append a directory\n    let photosDir = docsDir.appending(path: \"photos\")\n    try await archiver.appendItem(at: photosDir, pathInArchive: \"media/photos\")\n}\n```\n\nThe archiver streams files incrementally. Call `appendItem(at:pathInArchive:)`\nrepeatedly as each resource is ready. The system may terminate the extension\nif it appears hung, so avoid long gaps between append calls.\n\n### Cancellation\n\n`ResourcesArchiver` handles task cancellation automatically by throwing\ncancellation errors. Do not catch these errors -- doing so causes the system\nto kill the extension.\n\n### Migration Platform\n\n`MigrationRequestWithOptions` exposes `destinationPlatform` as a\n`MigrationPlatform` value. Use this to tailor exported data:\n\n```swift\nif request.destinationPlatform == .android {\n    // Export in a format the Android app expects\n}\n```\n\n`MigrationPlatform` provides `.android` as a static constant. Custom\nplatforms can be created with `MigrationPlatform(\"customPlatform\")`.\n\n## Importing Resources\n\nConform to `ResourcesImporting` to receive transferred files on the\ndestination device. The system calls `importResources(at:request:)` after\napp installation but before the app is launchable.\n\n```swift\nstruct MyMigrationExtension: ResourcesImporting {\n    func importResources(\n        at importedDataURL: URL,\n        request: ResourcesImportRequest\n    ) async throws {\n        let sourceVersion = request.sourceVersion\n        let sourceApp = request.sourceAppIdentifier\n\n        // sourceApp.platform        -- e.g., .android\n        // sourceApp.bundleIdentifier -- source app's bundle ID\n        // sourceApp.storeIdentifier  -- e.g., .googlePlay\n\n        // Copy imported files into the app container\n        let docsDir = appContainer.documentsDirectory\n\n        let userData = importedDataURL.appending(path: \"user_data.json\")\n        if FileManager.default.fileExists(atPath: userData.path()) {\n            try FileManager.default.copyItem(\n                at: userData,\n                to: docsDir.appending(path: \"user_data.json\")\n            )\n        }\n    }\n}\n```\n\n### Error Handling During Import\n\nOn import error, the system clears the containing app's data container to\nprevent partial state. However, app group containers are not cleared. The\nimport implementation should clear any app group containers before writing\nimported content:\n\n```swift\nfunc importResources(\n    at importedDataURL: URL,\n    request: ResourcesImportRequest\n) async throws {\n    // Clear shared app group data first\n    let groupURL = FileManager.default.containerURL(\n        forSecurityApplicationGroupIdentifier: \"group.com.example.myapp\"\n    )\n    if let groupURL {\n        try? FileManager.default.removeItem(at: groupURL.appending(path: \"shared_data\"))\n    }\n\n    // Then import\n    try await performImport(from: importedDataURL)\n}\n```\n\n### Source App Identifier\n\n`ResourcesImportRequest` provides `sourceAppIdentifier` as a\n`MigrationAppIdentifier` with three properties:\n\n- `platform` -- The source device's platform (e.g., `.android`)\n- `bundleIdentifier` -- The source app's bundle identifier\n- `storeIdentifier` -- The app store (e.g., `.googlePlay`)\n\n## Migration Status\n\nAfter migration completes, the containing app checks the result on first\nlaunch:\n\n```swift\nimport AppMigrationKit\n\nfunc application(\n    _ application: UIApplication,\n    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?\n) -> Bool {\n    if let status = MigrationStatus.importStatus {\n        switch status {\n        case .success:\n            showMigrationSuccessUI()\n            MigrationStatus.clearImportStatus()\n        case .failure(let error):\n            showMigrationFailureUI(error: error)\n            MigrationStatus.clearImportStatus()\n        }\n    }\n    return true\n}\n```\n\n- `MigrationStatus.importStatus` is `nil` if no migration occurred.\n- Call `clearImportStatus()` after handling the result to prevent showing\n  the notification on subsequent launches.\n- The enum has two cases: `.success` and `.failure(any Error)`.\n\n## Progress Tracking\n\nThe import side exposes a `Progress` object via `resourcesImportProgress`.\nThe system uses this to display transfer progress to the user. Update\n`completedUnitCount` incrementally during import:\n\n```swift\nvar resourcesImportProgress: Progress {\n    Progress(totalUnitCount: 100)\n}\n\nfunc importResources(\n    at importedDataURL: URL,\n    request: ResourcesImportRequest\n) async throws {\n    let progress = resourcesImportProgress\n    let files = try FileManager.default.contentsOfDirectory(\n        at: importedDataURL, includingPropertiesForKeys: nil\n    )\n    let increment = Int64(100 / max(files.count, 1))\n    for file in files {\n        try processFile(file)\n        progress.completedUnitCount += increment\n    }\n    progress.completedUnitCount = 100\n}\n```\n\n## Testing\n\n`AppMigrationTester` is a test-only actor for validating migration logic\nin unit tests hosted by the containing app. Do not use it in production.\n\n```swift\nimport Testing\nimport AppMigrationKit\n\n@Test func testExportImportRoundTrip() async throws {\n    let tester = try await AppMigrationTester(platform: .android)\n\n    // Export\n    let result = try await tester.exportController.exportResources(\n        request: nil, progress: nil\n    )\n    #expect(result.exportProperties.uncompressedBytes > 0)\n\n    // Import the exported data\n    try await tester.importController.importResources(\n        from: result.extractedResourcesURL,\n        importRequest: nil, progress: nil\n    )\n    try await tester.importController.registerImportCompletion(with: .success)\n}\n```\n\n`DeviceToDeviceExportProperties` on the result exposes `uncompressedBytes`,\n`compressedBytes` (nil if not compressible), `sizeEstimate`, and `version`.\n\nSee [references/appmigrationkit-patterns.md](references/appmigrationkit-patterns.md) for additional test patterns.\n\n## Common Mistakes\n\n### DON'T: Catch cancellation errors from ResourcesArchiver\n\n```swift\n// WRONG -- system kills the extension if cancellation is swallowed\nfunc exportResources(to archiver: sending ResourcesArchiver, request: ...) async throws {\n    do {\n        try await archiver.appendItem(at: fileURL)\n    } catch is CancellationError {\n        // Swallowing this causes termination\n    }\n}\n\n// CORRECT -- let cancellation propagate\nfunc exportResources(to archiver: sending ResourcesArchiver, request: ...) async throws {\n    try await archiver.appendItem(at: fileURL)\n}\n```\n\n### DON'T: Leave long gaps between archiver append calls\n\n```swift\n// WRONG -- system may assume the extension is hung and terminate it\nfunc exportResources(to archiver: sending ResourcesArchiver, request: ...) async throws {\n    let allFiles = gatherAllFiles()  // Takes 30 seconds\n    for file in allFiles {\n        try await archiver.appendItem(at: file)\n    }\n}\n\n// CORRECT -- interleave file preparation with archiving\nfunc exportResources(to archiver: sending ResourcesArchiver, request: ...) async throws {\n    for file in knownFilePaths() {\n        try await archiver.appendItem(at: file)\n    }\n}\n```\n\n### DON'T: Convert files to intermediate format during export\n\n```swift\n// WRONG -- may exhaust disk space creating temporary copies\nfunc exportResources(to archiver: sending ResourcesArchiver, request: ...) async throws {\n    let converted = try convertToJSON(originalDatabase)  // Doubles disk usage\n    try await archiver.appendItem(at: converted)\n}\n\n// CORRECT -- export files as-is, convert on import side if needed\nfunc exportResources(to archiver: sending ResourcesArchiver, request: ...) async throws {\n    try await archiver.appendItem(at: originalDatabase)\n}\n```\n\n### DON'T: Ignore app group containers during import error recovery\n\n```swift\n// WRONG -- system clears app container but not app groups on error\nfunc importResources(at url: URL, request: ResourcesImportRequest) async throws {\n    try writeToAppGroup(data)\n    try writeToAppContainer(data)  // If this throws, app group has stale data\n}\n\n// CORRECT -- clear app group data before importing\nfunc importResources(at url: URL, request: ResourcesImportRequest) async throws {\n    try clearAppGroupData()\n    try writeToAppGroup(data)\n    try writeToAppContainer(data)\n}\n```\n\n### DON'T: Forget to clear import status after handling it\n\n```swift\n// WRONG -- migration UI shows every launch\nif let status = MigrationStatus.importStatus {\n    showMigrationResult(status)\n    // Missing clearImportStatus()\n}\n\n// CORRECT\nif let status = MigrationStatus.importStatus {\n    showMigrationResult(status)\n    MigrationStatus.clearImportStatus()\n}\n```\n\n## Review Checklist\n\n- [ ] Extension target added with `com.apple.developer.app-migration.data-container-access` entitlement\n- [ ] Entitlement array contains exactly one string: the containing app's bundle identifier\n- [ ] Extension conforms to `ResourcesExportingWithOptions` or `ResourcesExporting` for export\n- [ ] Extension conforms to `ResourcesImporting` for import\n- [ ] `resourcesSizeEstimate` returns a reasonable byte estimate\n- [ ] `resourcesVersion` is set and will be checked on import for format compatibility\n- [ ] Export calls `appendItem` incrementally without long pauses\n- [ ] Cancellation errors from `ResourcesArchiver` are not caught\n- [ ] Import clears app group containers before writing new data\n- [ ] Containing app checks `MigrationStatus.importStatus` on first launch\n- [ ] `clearImportStatus()` called after handling the migration result\n- [ ] `AppMigrationTester` used in unit tests to validate export and import\n- [ ] Files are exported as-is without intermediate format conversion on the export side\n- [ ] `sourceVersion` from import request used to handle versioned data formats\n\n## References\n\n- Extended patterns (combined extension, versioned migration, file enumeration, error recovery): [references/appmigrationkit-patterns.md](references/appmigrationkit-patterns.md)\n- [AppMigrationKit framework](https://sosumi.ai/documentation/appmigrationkit)\n- [AppMigrationExtension](https://sosumi.ai/documentation/appmigrationkit/appmigrationextension)\n- [ResourcesExportingWithOptions](https://sosumi.ai/documentation/appmigrationkit/resourcesexportingwithoptions)\n- [ResourcesImporting](https://sosumi.ai/documentation/appmigrationkit/resourcesimporting)\n- [ResourcesArchiver](https://sosumi.ai/documentation/appmigrationkit/resourcesarchiver)\n- [MigrationStatus](https://sosumi.ai/documentation/appmigrationkit/migrationstatus)\n- [MigrationDataContainer](https://sosumi.ai/documentation/appmigrationkit/migrationdatacontainer)\n- [AppMigrationTester](https://sosumi.ai/documentation/appmigrationkit/appmigrationtester)\n- [Data container entitlement](https://sosumi.ai/documentation/bundleresources/entitlements/com.apple.developer.app-migration.data-container-access)","tags":["appmigrationkit","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills"],"capabilities":["skill","source-dpearson2699","skill-appmigrationkit","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/appmigrationkit","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.684","qualityRationale":"deterministic score 0.68 from registry signals: · indexed on github topic:agent-skills · 468 github stars · SKILL.md body (16,829 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:53:41.494Z","embedding":null,"createdAt":"2026-04-18T22:00:44.179Z","updatedAt":"2026-04-22T00:53:41.494Z","lastSeenAt":"2026-04-22T00:53:41.494Z","tsv":"'/documentation/appmigrationkit)':1701 '/documentation/appmigrationkit/appmigrationextension)':1705 '/documentation/appmigrationkit/appmigrationtester)':1729 '/documentation/appmigrationkit/migrationdatacontainer)':1725 '/documentation/appmigrationkit/migrationstatus)':1721 '/documentation/appmigrationkit/resourcesarchiver)':1717 '/documentation/appmigrationkit/resourcesexportingwithoptions)':1709 '/documentation/appmigrationkit/resourcesimporting)':1713 '/documentation/bundleresources/entitlements/com.apple.developer.app-migration.data-container-access)':1735 '0':1222 '1':210,1155 '1.0':591 '100':1128,1152,1166 '2':229 '26':74,76,87 '3':252 '30':1355 '6.3':78 'access':316,372,395,408,420,476,477,483,498,1567 'actor':355,1174 'ad':1562 'add':425 'addit':1259 'allfil':1352,1360 'android':18,62,340,665,797,803,808,870,1004,1209 'api':103 'app':3,51,54,108,119,140,162,166,211,254,259,282,320,331,345,365,390,412,428,449,467,486,501,508,516,536,804,841,846,873,885,919,928,940,959,986,1008,1014,1025,1186,1459,1470,1474,1496,1503,1577,1629,1637 'app-migration-extens':165 'appcontain':490,506 'appcontainer.documentsdirectory':657,889 'appear':746 'append':671,690,708,753,1328 'appenditem':729,1615 'appl':97 'applic':521,1036,1037 'applicationsupportdirectori':528 'appmigrationextens':31,214,278,458,1702 'appmigrationkit':1,8,41,82,105,205,493,1034,1197,1697 'appmigrationtest':351,1168,1207,1650,1726 'appropri':137 'architectur':150,153,203 'architecture-overview':152 'archiv':34,292,314,636,648,694,724,1284,1310,1327,1345,1371,1375,1411,1445 'archiver.appenditem':687,703,718,1293,1318,1363,1387,1427,1453 'array':382,1570 'as-i':1433,1663 'assum':1334 'async':653,860,955,1136,1201,1288,1314,1349,1379,1415,1449,1485,1515 'atpath':897 'automat':760 'avoid':749 'await':686,702,717,981,1206,1214,1228,1237,1292,1317,1362,1386,1426,1452 'beta':80 'beta-sensit':79 'bool':594,1043 'bundl':349,385,510,875,1010,1579 'bundleidentifi':1005 'byte':583,605,1599 'calculateexports':587 'call':132,557,728,754,836,1071,1329,1614,1644 'cancel':755,759,763,1267,1278,1305,1620 'cancellationerror':1298 'case':1050,1054,1089 'catch':767,1266,1296 'caught':1626 'caus':772,1301 'chang':90 'check':95,260,325,617,658,1026,1607,1638 'checklist':197,200,1559 'clear':916,933,938,957,1469,1502,1529,1628 'clearappgroupdata':1518 'clearimportstatus':1072,1549,1643 'com.apple.developer.app-migration.data':369,392,1564 'com.example.myapp':396 'combin':1687 'common':191,194,1262 'common-mistak':193 'compat':1612 'complet':257,1022 'completedunitcount':1118 'compress':599,638,1251 'compressedbyt':1247 'conform':123,215,437,456,541,823,1582,1590 'connect':146 'constant':812 'contain':253,319,330,371,383,389,394,411,415,466,480,485,500,505,517,535,886,918,922,930,942,1024,1185,1461,1471,1566,1571,1576,1631,1636,1731 'container-access':370,393,1565 'container.applicationsupportdirectory':520 'container.bundleidentifier':507 'container.containerrootdirectory':512 'container.documentsdirectory':518 'containerrootdirectori':525 'content':149,946 'continu':678 'control':248 'convers':1669 'convert':1392,1418,1429,1436 'converttojson':1420 'copi':880,1407 'correct':1303,1366,1430,1501,1550 'creat':817,1405 'cross':26,46 'cross-platform':25,45 'current':96 'custom':298,548,693,813 'customplatform':820 'data':4,15,36,48,57,225,322,414,475,479,586,630,793,921,961,977,1226,1489,1492,1500,1505,1521,1524,1635,1682,1730 'declar':567 'destin':307,659,832 'destinationplatform':783 'detail':104 'determin':266 'devic':69,117,148,237,239,336,833,1000 'device-to-devic':236 'devicetodeviceexportproperti':1241 'didfinishlaunchingwithopt':1039 'directori':323,503,710 'disk':1403,1423 'display':1111 'docsdir':656,888 'docsdir.appending':682,698,713,904 'document':98,519 'documentsdirectori':526 'doubl':1422 'e.g':61,339,869,878,1003,1016 'element':380 'enabl':53 'ensur':473 'entitl':157,161,362,363,373,403,1568,1569,1732 'entri':284,454 'enum':1086 'enumer':1692 'error':764,769,907,913,1057,1059,1060,1094,1268,1464,1477,1621,1693 'estim':581,603,1600 'everi':1540 'exact':1572 'exclus':474 'exhaust':1402 'expect':805,1220 'export':38,56,125,169,172,226,289,295,313,417,539,568,585,643,669,792,798,1210,1225,1398,1431,1588,1613,1657,1662,1672 'export/import':358 'exporting-resourc':171 'exportresourc':558,646,1282,1308,1343,1373,1409,1443 'expos':782,1100,1245 'extend':1685 'extens':109,122,134,164,168,212,245,283,366,406,423,429,436,451,453,471,482,743,778,1276,1336,1560,1581,1589,1688 'failur':1055,1092 'file':290,304,310,488,552,639,672,726,829,882,1142,1157,1159,1162,1358,1365,1368,1382,1389,1393,1432,1660,1691 'filemanager.default.containerurl':965 'filemanager.default.contentsofdirectory':1144 'filemanager.default.copyitem':900 'filemanager.default.fileexists':896 'filemanager.default.removeitem':972 'files.count':1154 'fileurl':1295,1320 'first':263,962,1030,1641 'forget':1527 'format':619,631,801,1396,1611,1668,1683 'forsecurityapplicationgroupidentifi':966 'framework':1698 'free':615 'free-spac':614 'func':645,853,948,1035,1129,1199,1281,1307,1342,1372,1408,1442,1478,1508 'gap':751,1325 'gatherallfil':1353 'gm':92 'googleplay':879,1017 'grant':404 'group':929,941,960,1460,1475,1497,1504,1630 'group.com.example.myapp':967 'groupurl':964,970 'groupurl.appending':974 'handl':224,628,757,908,1074,1533,1646,1680 'host':1182 'howev':927 'hung':747,1338 'id':350,511,876 'identifi':333,342,386,987,1011,1580 'ignor':1458 'implement':11,642,936 'import':39,64,127,174,177,228,303,326,422,492,623,821,881,910,912,935,945,979,1033,1098,1121,1194,1196,1223,1438,1463,1507,1530,1594,1609,1627,1659,1676 'importeddataurl':856,951,984,1132,1146 'importeddataurl.appending':892 'importing-resourc':176 'importrequest':1232 'importresourc':837,854,949,1130,1479,1509 'includingpropertiesforkey':1147 'increment':727,1119,1150,1164,1616 'instal':842 'int':579 'int64':1151 'interleav':1367 'intermedi':1395,1667 'invok':220 'io':23,67,73,86 'ipado':75 'key':274 'kill':776,1274 'knownfilepath':1384 'launch':264,464,1031,1084,1541,1642 'launchabl':848 'launchopt':1040 'layer':209 'leav':1323 'let':504,596,655,680,696,711,862,865,887,890,963,969,1045,1056,1138,1141,1149,1203,1211,1304,1351,1417,1543,1552 'logic':359,670,1178 'long':750,1324,1618 'make':677 'manag':24,143,234 'max':1153 'may':89,637,740,1333,1401 'media/photos':722 'migrat':16,163,167,179,182,222,256,268,444,450,460,779,1018,1021,1069,1177,1537,1648,1690 'migration-status':181 'migrationappidentifi':341,993 'migrationdatacontain':315,523,1722 'migrationdefaultsupportedopt':576 'migrationplatform':332,786,806,819 'migrationrequestwithopt':566,652,781 'migrationstatus':324,1718 'migrationstatus.clearimportstatus':1053,1061,1557 'migrationstatus.importstatus':261,1047,1064,1545,1554,1639 'miss':1548 'mistak':192,195,1263 'model':110 'mymigrationextens':495,572,851 'need':662,1441 'network':145 'never':142 'new':84,427,1634 'nil':1066,1148,1217,1219,1233,1235,1248 'notif':1081 'object':1103 'occur':269,1070 'onboard':72 'one':13,43,59,439,673,1573 'one-tim':12,42 'oper':206 'option':299,549 'optionstyp':575 'orchestr':113,231 'originaldatabas':1421,1455 'os':233 'overview':151,154,204 'packag':32,551 'partial':925 'path':683,695,699,714,893,905,975 'pathinarch':706,721,731 'pattern':1261,1686 'paus':1619 'performimport':982 'photo':715 'photosdir':712,720 'platform':6,21,27,47,60,338,660,667,780,814,997,1002,1208 'platform-specif':666 'point':285,455,532 'preferences/settings.plist':707 'prepar':1369 'prevent':463,924,1078 'processfil':1161 'product':1192 'progress':184,187,611,679,1095,1102,1113,1125,1126,1139,1218,1234 'progress-track':186 'progress.completedunitcount':1163,1165 'project':434 'propag':1306 'properti':569,996 'protocol':128,279,287,296,301,445 'provid':120,524,807,989 're':94 're-check':93 'read':407 'readi':737 'reason':1598 'receiv':625,827 'recoveri':1465,1694 'refer':201,202,1684 'references/appmigrationkit-patterns.md':1256,1257,1695,1696 'reli':100 'repeat':732 'request':560,651,839,858,953,1134,1216,1287,1313,1348,1378,1414,1448,1483,1513,1677 'request.destinationplatform':664,796 'request.sourceappidentifier':867 'request.sourceversion':864 'requir':367 'resourc':40,52,170,173,175,178,540,735,822 'resourcesarchiv':308,563,650,756,1270,1286,1312,1347,1377,1413,1447,1623,1714 'resourcescompress':593,632 'resourcesexport':293,447,545,1586 'resourcesexportingwithopt':286,446,496,543,573,1584,1706 'resourcesimport':300,448,497,825,852,1592,1710 'resourcesimportprogress':1105,1124,1140 'resourcesimportrequest':859,954,988,1135,1484,1514 'resourcessizeestim':578,602,1595 'resourcesvers':589,618,1601 'result':327,1028,1076,1212,1244,1649 'result.exportproperties.uncompressedbytes':1221 'result.extractedresourcesurl':1231 'return':580,1062,1596 'review':196,199,1558 'review-checklist':198 'role':277 'root':513 'run':251 'sandbox':538 'schedul':243 'second':1356 'see':1255 'send':649,1285,1311,1346,1376,1412,1446 'sensit':81 'session':29,240 'set':1603 'settings.plist':700 'settingsurl':697,705 'setup':70,155,159,360 'setup-and-entitl':158 'share':958,976 'show':1079,1539 'showmigrationfailureui':1058 'showmigrationresult':1546,1555 'showmigrationsuccessui':1052 'side':624,1099,1439,1673 'simplifi':294 'singl':379 'single-el':378 'sizeestim':1252 'skill' 'skill-appmigrationkit' 'sosumi.ai':1700,1704,1708,1712,1716,1720,1724,1728,1734 'sosumi.ai/documentation/appmigrationkit)':1699 'sosumi.ai/documentation/appmigrationkit/appmigrationextension)':1703 'sosumi.ai/documentation/appmigrationkit/appmigrationtester)':1727 'sosumi.ai/documentation/appmigrationkit/migrationdatacontainer)':1723 'sosumi.ai/documentation/appmigrationkit/migrationstatus)':1719 'sosumi.ai/documentation/appmigrationkit/resourcesarchiver)':1715 'sosumi.ai/documentation/appmigrationkit/resourcesexportingwithoptions)':1707 'sosumi.ai/documentation/appmigrationkit/resourcesimporting)':1711 'sosumi.ai/documentation/bundleresources/entitlements/com.apple.developer.app-migration.data-container-access)':1733 'sourc':344,872,985,999,1007 'source-dpearson2699' 'sourceapp':866 'sourceapp.bundleidentifier':871 'sourceapp.platform':868 'sourceapp.storeidentifier':877 'sourceappidentifi':990 'sourcevers':863,1674 'space':616,1404 'specif':102,668 'stale':1499 'state':926 'static':811 'status':180,183,1019,1046,1049,1531,1544,1547,1553,1556 'store':347,1015 'storeidentifi':1012 'stream':309,725 'string':381,590,621,1574 'struct':494,571,850 'subsequ':1083 'succeed':273 'success':1051,1090,1240 'support':522 'swallow':1280,1299 'swift':77,491,570,644,794,849,947,1032,1122,1193,1271,1330,1399,1466,1535 'switch':1048 'system':112,131,219,230,462,556,598,607,739,774,835,915,1107,1273,1332,1468 'tailor':791 'take':1354 'target':424,430,1561 'task':758 'temporari':1406 'termin':741,1302,1340 'test':189,190,353,1167,1172,1181,1195,1198,1260,1654 'test-on':352,1171 'tester':1204 'tester.exportcontroller.exportresources':1215 'tester.importcontroller.importresources':1229 'tester.importcontroller.registerimportcompletion':1238 'testexportimportroundtrip':1200 'three':208,995 'throw':654,762,861,956,1137,1202,1289,1315,1350,1380,1416,1450,1486,1495,1516 'time':14,44,138,676 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'total':582,604 'totalunitcount':1127 'track':185,188,1096 'transfer':2,28,49,115,554,828,1112 'transport':241,601,641 'tri':685,701,716,899,971,980,1143,1160,1205,1213,1227,1236,1291,1316,1361,1385,1419,1425,1451,1487,1490,1517,1519,1522 'true':595,634,1063 'two':1088 'type':216,275,276 'typealia':574 'ui':612,1538 'uiapplic':1038 'uiapplication.launchoptionskey':1041 'uncompressedbyt':1246 'unit':1180,1653 'updat':1117 'url':530,857,952,1133,1481,1482,1511,1512 'usag':1424 'use':7,9,106,608,788,1108,1189,1651,1678 'user':35,1116 'user_data.json':684,894,906 'userdata':891,902 'userdata.path':898 'userdataurl':681,689 'valid':357,401,1176,1656 'valu':375,399,531,787 'var':577,588,592,1123 'version':620,629,1254,1681,1689 'via':291,1104 'whether':267,271 'without':1617,1666 'write':419,944,1633 'writetoappcontain':1491,1523 'writetoappgroup':1488,1520 'wrong':1272,1331,1400,1467,1536 'xcode':433 'xml':391","prices":[{"id":"9b2d10e6-f400-4d78-b341-05e389026761","listingId":"7f6aefed-7207-4f51-8f64-0494f8d9e72d","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:00:44.179Z"}],"sources":[{"listingId":"7f6aefed-7207-4f51-8f64-0494f8d9e72d","source":"github","sourceId":"dpearson2699/swift-ios-skills/appmigrationkit","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/appmigrationkit","isPrimary":false,"firstSeenAt":"2026-04-18T22:00:44.179Z","lastSeenAt":"2026-04-22T00:53:41.494Z"}],"details":{"listingId":"7f6aefed-7207-4f51-8f64-0494f8d9e72d","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"appmigrationkit","github":{"repo":"dpearson2699/swift-ios-skills","stars":468,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-21T19:26:16Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"c0d5a5c53cac43d76e3156fbc1060fc8e6cc2762","skill_md_path":"skills/appmigrationkit/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/appmigrationkit"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"appmigrationkit","description":"Transfer app data between platforms using AppMigrationKit. Use when implementing one-time data migration from Android or other platforms to iOS, managing cross-platform transfer sessions with AppMigrationExtension, packaging and archiving user data for export, importing resources on the destination device, tracking transfer progress, handling migration errors, or building onboarding flows that import existing user data."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/appmigrationkit"},"updatedAt":"2026-04-22T00:53:41.494Z"}}