Migrates Capacitor iOS apps from CocoaPods to Swift Package Manager (SPM), using spm-migration-assistant, generating CapApp-SPM/Package.swift, adding debug.xcconfig, verifying plugin SPM support, and removing Podfile/Pods.
npx claudepluginhub cap-go/capgo-skills --plugin capacitor-app-migrationsThis skill uses the workspace's default tool permissions.
Migrate a Capacitor iOS app from CocoaPods to Swift Package Manager without losing native project customizations.
Adds Swift Package Manager support to existing Capacitor iOS plugins by creating Package.swift, converting to CAPBridgedPlugin, removing Objective-C bridges, and updating manifests. For Xcode SPM integration without CocoaPods.
Upgrades Capacitor app projects to newer major versions via step-by-step process handling multi-jumps, dependency updates, native iOS/Android checks, syncs, and builds.
Guides migration from Apache Cordova/PhoneGap to Capacitor including plugin equivalents, config updates, platform addition for iOS/Android, and key differences.
Share bugs, ideas, or general feedback.
Migrate a Capacitor iOS app from CocoaPods to Swift Package Manager without losing native project customizations.
npx cap spm-migration-assistantCapApp-SPM, generated Package.swift, or debug.xcconfigios/App/Podfile, Pods, Podfile.lock, or App.xcworkspaceDo not use this for adding SPM support to a plugin package. Use capacitor-plugin-spm-support for plugin repositories.
ios/App/CapApp-SPM.CapApp-SPM by hand. The Capacitor CLI rewrites it during npx cap sync.package.json need SPM support before the app can fully move.npx cap ... so the project-local Capacitor CLI is used.npx cap ....Detected Capacitor, iOS, Cordova, and plugin dependencies:
!node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.startsWith('@capacitor/')||name.startsWith('@capgo/')||name.startsWith('@capacitor-community/')||name.startsWith('@awesome-cordova-plugins/')||name.startsWith('cordova-')||name.includes('capacitor'))out.push(section+'.'+name+'='+version)}}console.log(out.sort().join('\n'))"
Relevant iOS dependency files:
!find ios -maxdepth 5 \( -name 'Podfile' -o -name 'Podfile.lock' -o -name 'Pods' -o -name 'App.xcworkspace' -o -name 'Package.swift' -o -name 'Package.resolved' -o -name 'CapApp-SPM' -o -name 'debug.xcconfig' -o -name 'project.pbxproj' -o -name 'Info.plist' -o -name '*.entitlements' -o -name 'GoogleService-Info.plist' \) 2>/dev/null
Inspect:
package.json for Capacitor major version and installed pluginsios/App/Podfile and ios/App/Podfile.lock for current CocoaPods dependenciesios/App/App.xcodeproj/project.pbxproj for custom build settings, package references, entitlements, signing, and native source filesios/App/App/ for app customizationsBefore changing files, verify:
If the migration is part of a Capacitor 8 upgrade, combine this skill with capacitor-app-upgrade-v7-to-v8.
Record and preserve anything under ios/ that a fresh template would overwrite:
ios/App/App/Info.plistios/App/App/AppDelegate.swiftios/App/App/SceneDelegate.swift, if presentios/App/App/Assets.xcassets/ios/App/App/Base.lproj/ios/App/App/*.entitlementsios/App/App/GoogleService-Info.plist, if Firebase is used.xcconfig filesPrefer preserving through git and explicit diffs. Do not rely on memory.
Use the safest path for the project:
| Path | Use When | Tradeoff |
|---|---|---|
| CLI assistant | The iOS project has moderate customization and plugins mostly support SPM | Automates CocoaPods removal but still needs Xcode steps |
| Fresh SPM re-scaffold | The iOS project is close to the Capacitor template | Cleanest result, but native customizations must be restored carefully |
| Manual repair | The assistant already ran or the project is heavily customized | More control, more Xcode project editing |
If unsure, start with plugin compatibility and backup work. Do not delete ios/ until the preservation list is complete.
Preferred first attempt for many existing apps:
npx cap spm-migration-assistant
Expect it to:
Podfile, Podfile.lock, Pods, and App.xcworkspaceios/App/CapApp-SPMPackage.swift from installed pluginsdebug.xcconfigThen open the iOS project:
npx cap open ios
In Xcode:
CapApp-SPM package.debug.xcconfig to the project configuration as directed by the assistant output.After Xcode changes, run:
npx cap sync ios
Use this when the iOS project has little or no custom native configuration, or the assistant path is messier than regenerating.
Before deleting anything, preserve the native files listed in Step 2.
Then re-create iOS with SPM:
rm -rf ios
npx cap add ios --packagemanager SPM
npx cap sync ios
For Capacitor 8+, npx cap add ios uses SPM by default, but keep --packagemanager SPM when documenting the migration so the intent is explicit.
Restore custom files and settings deliberately:
Info.plist keys without overwriting new template changes blindlyIf npx cap sync or the assistant warns about unsupported plugins:
capacitor-plugin-spm-support if it is owned by the projectDo not keep a plugin in CocoaPods while the app is otherwise migrated to SPM.
Run the repo's normal web build first, then sync and build iOS:
npx cap sync ios
npx cap open ios
In Xcode, verify:
CapApp-SPM is present as a local package dependencydebug.xcconfig is attached to the debug configurationPodfile, Pods, Podfile.lock, and App.xcworkspace are gone for the migrated appPackage.resolved is generated and committed if presentIf using command-line verification, use the workspace/project and scheme that actually exist after migration.
Cause: a Capacitor or Cordova plugin does not ship SPM metadata.
Fix: upgrade, replace, or migrate the plugin. If the plugin is project-owned, use capacitor-plugin-spm-support.
CapApp-SPMCause: the assistant did not finish, files were deleted, or npx cap sync has not regenerated the package.
Fix:
npx cap sync ios
Then add the local package in Xcode if it is not already linked.
debug.xcconfigCause: generated config was not added to the Xcode project.
Fix: add ios/App/debug.xcconfig to the project configuration in Xcode, following the migration assistant output.
Cause: the same dependency is still referenced by leftover CocoaPods artifacts and SPM.
Fix: remove CocoaPods artifacts from the app, clean derived data, reset package caches in Xcode, and rebuild.
Cause: a fresh iOS scaffold overwrote customized files.
Fix: recover from git or the preserved backup list, then reapply changes selectively against the new SPM template.
For planning tasks, return:
## SPM Migration Plan
### Current State
- Capacitor version:
- CocoaPods files:
- Plugins needing SPM check:
- Native customizations to preserve:
### Recommended Path
- CLI assistant / fresh re-scaffold / manual repair:
- Reason:
### Steps
1. Preserve native files
2. Verify plugin SPM support
3. Run migration
4. Complete Xcode package/config setup
5. Sync and build
### Risks
- Unsupported plugins:
- Native customizations:
- Manual Xcode steps:
For implementation tasks, make the migration changes, run the relevant build or verification command available in the repo, and report any remaining Xcode-only or device-only checks.