Agent skill
cocoapods-to-spm
Guide to migrating iOS Capacitor plugins and dependencies from CocoaPods to Swift Package Manager (SPM). Use this skill when users want to modernize their iOS project, remove CocoaPods, or add SPM-based dependencies.
Install this agent skill to your Project
npx add-skill https://github.com/Cap-go/capgo-skills/tree/main/skills/cocoapods-to-spm
SKILL.md
CocoaPods to Swift Package Manager Migration
Step-by-step guide for migrating Capacitor iOS projects from CocoaPods to Swift Package Manager.
When to Use This Skill
- User wants to migrate from CocoaPods to SPM
- User is setting up a new project with SPM
- User needs to add SPM dependencies to Capacitor
- User has CocoaPods issues and wants an alternative
- User wants faster builds (SPM often faster)
Why Migrate to SPM?
| Aspect | CocoaPods | SPM |
|---|---|---|
| Build Speed | Slower | Faster |
| Apple Integration | Third-party | Native Xcode |
| Ruby Dependency | Required | None |
| Version Management | Podfile.lock | Package.resolved |
| Xcodeproj Changes | Modifies project | Uses workspace |
| Binary Caching | Limited | Built-in |
Migration Process
Step 1: Analyze Current Dependencies
First, identify what you're currently using:
cd ios/App
cat Podfile
pod outdated
Common Capacitor pods to migrate:
# Podfile (before)
target 'App' do
capacitor_pods
pod 'Firebase/Analytics'
pod 'Firebase/Messaging'
pod 'Alamofire'
pod 'KeychainAccess'
end
Step 2: Find SPM Equivalents
Most popular libraries support SPM. Use these URLs:
| Library | SPM URL |
|---|---|
| Firebase | https://github.com/firebase/firebase-ios-sdk |
| Alamofire | https://github.com/Alamofire/Alamofire |
| KeychainAccess | https://github.com/kishikawakatsumi/KeychainAccess |
| SDWebImage | https://github.com/SDWebImage/SDWebImage |
| SnapKit | https://github.com/SnapKit/SnapKit |
| Realm | https://github.com/realm/realm-swift |
| Lottie | https://github.com/airbnb/lottie-spm |
Step 3: Clean CocoaPods
cd ios/App
# Remove CocoaPods integration
pod deintegrate
# Remove Podfile.lock and Pods directory
rm -rf Podfile.lock Pods
# Remove workspace (we'll use project directly or create new workspace)
rm -rf App.xcworkspace
Step 4: Add SPM Dependencies in Xcode
- Open
ios/App/App.xcodeprojin Xcode - Select the project in navigator
- Go to Package Dependencies tab
- Click + to add package
- Enter the package URL
- Choose version rules
- Select target
App
Step 5: Update Podfile for Capacitor Core
Capacitor still needs CocoaPods for its core. Create minimal Podfile:
# ios/App/Podfile
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
platform :ios, '14.0'
use_frameworks!
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
end
target 'App' do
capacitor_pods
# Other plugin pods that don't support SPM yet
end
post_install do |installer|
assertDeploymentTarget(installer)
end
Then run:
cd ios/App && pod install
Step 6: Configure Plugin for SPM Support
If you're creating a Capacitor plugin with SPM support:
Package.swift:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "CapacitorNativeBiometric",
platforms: [.iOS(.v14)],
products: [
.library(
name: "CapacitorNativeBiometric",
targets: ["NativeBiometricPlugin"]
),
],
dependencies: [
.package(url: "https://github.com/nicholasalx/capacitor-swift-pm", from: "6.0.0"),
],
targets: [
.target(
name: "NativeBiometricPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
],
path: "ios/Sources/NativeBiometricPlugin",
publicHeadersPath: "include"
),
]
)
Step 7: Xcode Project Structure for SPM
ios/
├── App/
│ ├── App/
│ │ ├── AppDelegate.swift
│ │ ├── Info.plist
│ │ └── ...
│ ├── App.xcodeproj/
│ │ └── project.xcworkspace/
│ │ └── xcshareddata/
│ │ └── swiftpm/
│ │ └── Package.resolved # SPM lock file
│ ├── Podfile
│ └── Podfile.lock
└── ...
Hybrid Approach (Recommended)
Most Capacitor projects work best with a hybrid approach:
Keep in CocoaPods:
@capacitor/ioscore- Capacitor plugins without SPM support
Move to SPM:
- Firebase
- Third-party libraries
- Your own Swift packages
Example Hybrid Setup
Podfile:
require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers'
platform :ios, '14.0'
use_frameworks!
install! 'cocoapods', :disable_input_output_paths => true
def capacitor_pods
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
# Plugins without SPM support
pod 'CapacitorCamera', :path => '../../node_modules/@capacitor/camera'
end
target 'App' do
capacitor_pods
# NO Firebase here - use SPM instead
end
Xcode Package Dependencies:
- Firebase iOS SDK
- Any other SPM-compatible libraries
Common Issues and Solutions
Issue: Duplicate Symbols
Cause: Same library in both CocoaPods and SPM
Solution: Remove from Podfile if using SPM
# Podfile - WRONG
pod 'Firebase/Analytics' # Remove this
# Use SPM instead in Xcode
Issue: Module Not Found
Cause: SPM package not linked to target
Solution:
- Xcode > Project > Targets > App
- General > Frameworks, Libraries, and Embedded Content
- Add the SPM package product
Issue: Build Errors After Migration
Cause: Missing frameworks or wrong imports
Solution: Clean and rebuild
# Clean derived data
rm -rf ~/Library/Developer/Xcode/DerivedData
# Clean build folder in Xcode
# Cmd + Shift + K
# Rebuild
npx cap sync ios
cd ios/App && pod install
Issue: Capacitor Plugin Not Found
Cause: Plugin needs registration
Solution: Ensure plugin is registered in AppDelegate.swift:
import Capacitor
import YourPlugin
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Capacitor handles plugin registration automatically
return true
}
}
Creating SPM-Compatible Capacitor Plugin
Directory Structure
my-capacitor-plugin/
├── Package.swift
├── ios/
│ └── Sources/
│ └── MyPlugin/
│ ├── MyPlugin.swift
│ ├── MyPlugin.m # Objc bridge if needed
│ └── include/
│ └── MyPlugin.h # Public headers
├── src/
│ ├── index.ts
│ ├── definitions.ts
│ └── web.ts
└── package.json
Package.swift Template
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "CapacitorMyPlugin",
platforms: [.iOS(.v14)],
products: [
.library(
name: "CapacitorMyPlugin",
targets: ["MyPluginPlugin"]
),
],
dependencies: [
.package(url: "https://github.com/nicholasalx/capacitor-swift-pm", from: "6.0.0"),
],
targets: [
.target(
name: "MyPluginPlugin",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm"),
],
path: "ios/Sources/MyPlugin"
),
]
)
Plugin Swift Code
import Foundation
import Capacitor
@objc(MyPlugin)
public class MyPlugin: CAPPlugin, CAPBridgedPlugin {
public let identifier = "MyPlugin"
public let jsName = "MyPlugin"
public let pluginMethods: [CAPPluginMethod] = [
CAPPluginMethod(name: "echo", returnType: CAPPluginReturnPromise),
]
@objc func echo(_ call: CAPPluginCall) {
let value = call.getString("value") ?? ""
call.resolve(["value": value])
}
}
Migration Checklist
- List all current CocoaPods dependencies
- Identify SPM equivalents for each
- Run
pod deintegrate - Add SPM packages in Xcode
- Create minimal Podfile for Capacitor core
- Run
pod install - Clean derived data
- Build and test
- Commit
Package.resolvedto git - Update CI/CD scripts if needed
Resources
- Swift Package Manager Documentation: https://swift.org/package-manager
- Capacitor iOS Documentation: https://capacitorjs.com/docs/ios
- CocoaPods to SPM Migration: https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
konsta-ui
Guide to using Konsta UI for pixel-perfect iOS and Material Design components in Capacitor apps. Works with React, Vue, and Svelte. Use this skill when users want native-looking UI without Ionic, or prefer a lighter framework.
capacitor-plugin-upgrades
Guides the agent through upgrading a Capacitor plugin to a newer major version. Covers dependency alignment, native platform changes, example app verification, and multi-version jumps. Do not use for app project upgrades or non-Capacitor plugin frameworks.
capacitor-testing
Complete testing guide for Capacitor apps covering unit tests, integration tests, E2E tests, and native testing. Includes Jest, Vitest, Playwright, Appium, and native testing frameworks. Use this skill when users need to test their mobile apps.
capacitor-plugins
Official Capacitor package guide plus Capgo ecosystem plugin recommendations. Use this skill when users need native functionality, want the right official Capacitor package, or need a stronger Capgo/community plugin when the official package is missing or too limited.
capgo-release-management
Guides the agent through Capgo OTA release workflows including bundle uploads, compatibility checks, channels, cleanup, and encryption key setup. Use when managing Capgo bundle and channel operations. Do not use for native build requests or organization administration.
ionic-enterprise-sdk-migration
Guides the agent through migrating Capacitor apps from Ionic Enterprise SDK plugins to Capgo and Capacitor alternatives. Covers dependency detection, API replacement, local storage changes, and platform cleanup. Do not use for generic Capacitor version upgrades or Capgo live updates.
Didn't find tool you were looking for?