How to Migrate a Capacitor Plugin to Swift Package Manager¶
Capacitor 8 made Swift Package Manager (SPM) the default dependency manager for iOS. If you maintain a Capacitor plugin that still relies on CocoaPods and Objective-C bridge files, your plugin won't work out of the box in SPM-based projects. This post walks you through what needs to change and three ways to get it done.
What Changes Are Needed¶
The migration from CocoaPods to SPM touches a handful of files. Here's what's involved at a high level:
Add a Package.swift Manifest¶
SPM needs a Package.swift at the root of your plugin repository. This file defines the package name, supported platforms, dependencies, and targets. A typical setup points the main target at ios/Plugin and the test target at ios/PluginTests:
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyCapacitorPlugin",
platforms: [.iOS(.v15)],
products: [
.library(
name: "MyCapacitorPlugin",
targets: ["MyCapacitorPluginTarget"])
],
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", branch: "8.0.0")
],
targets: [
.target(
name: "MyCapacitorPluginTarget",
dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
.product(name: "Cordova", package: "capacitor-swift-pm")
],
path: "ios/Plugin"),
.testTarget(
name: "MyCapacitorPluginTests",
dependencies: ["MyCapacitorPluginTarget"],
path: "ios/PluginTests")
]
)
If your plugin depends on third-party libraries (like a database driver or a networking library), add them to the dependencies array and reference them in your target's dependencies.
Replace Objective-C Bridge Files with CAPBridgedPlugin¶
Older Capacitor plugins use Objective-C files (typically Plugin.h and Plugin.m) containing the CAP_PLUGIN macro to register plugin methods. SPM doesn't support mixing Objective-C and Swift in the same target, so these files need to go.
Instead, your plugin's main Swift class should conform to the CAPBridgedPlugin protocol. This means adding three properties: identifier, jsName, and pluginMethods:
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),
CAPPluginMethod(name: "getData", returnType: CAPPluginReturnPromise)
]
// ... plugin implementation
}
The pluginMethods array replaces the CAP_PLUGIN_METHOD entries from the old .m file. Make sure every method your plugin exposes to JavaScript is listed here — any omission means that method won't be callable at runtime.
After updating the Swift file, delete the .h and .m bridge files.
Update .gitignore¶
Add SPM-related entries to your .gitignore to keep build artifacts out of version control:
Package.resolved
/.build
/Packages
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
Clean Up the Xcode Project File¶
The ios/Plugin.xcodeproj/project.pbxproj file still references the deleted Objective-C files. Remove any lines that reference your old .h and .m files from the PBXBuildFile, PBXFileReference, PBXGroup, PBXHeadersBuildPhase, and PBXSourcesBuildPhase sections. This step is tedious to do by hand, which is one reason the automated tools described below are helpful.
Update package.json¶
Add Package.swift to the files array in your package.json so it gets included when you publish to npm:
You can also add a convenience script for resolving SPM dependencies locally:
Migration Options¶
You don't have to do all of this manually. Here are three approaches, depending on your situation.
Option 1: Capacitor Plugin Converter¶
The Ionic team maintains capacitor-plugin-converter, a CLI tool called cap2spm that automates the conversion. It reads your Plugin.m and Plugin.h files, modifies your Plugin.swift to add CAPBridgedPlugin conformance, and generates a Package.swift.
Install it via curl:
curl -OL https://github.com/ionic-team/capacitor-plugin-converter/releases/latest/download/cap2spm.zip
Then run it against your plugin directory:
A few things to keep in mind:
- The tool is still under heavy development. It works for most cases, but make sure you have a clean commit before running it.
-
The binary is currently unsigned. If you download it from a browser on macOS, you'll need to remove the quarantine attribute first:
Option 2: Capawesome Skills¶
Capawesome Skills is a collection of AI-powered agent skills for Claude Code and other AI coding agents. It includes a dedicated capacitor-plugin-spm-support skill that guides the agent through the full migration: creating Package.swift, replacing Objective-C bridge files, updating .gitignore, cleaning up the Xcode project file, and updating package.json.
Install the skills:
Then prompt your AI agent:
The agent will walk through each step, adapting to your plugin's specific setup and dependencies.
Option 3: Create a New Plugin from Scratch¶
If your plugin is relatively simple or you're planning a rewrite anyway, you can scaffold a fresh plugin using create-capacitor-plugin:
New plugins created with this tool already include full SPM support out of the box. Once the scaffold is ready, migrate your existing implementation code into the new project structure. This approach works best for smaller plugins where copying the implementation is less effort than modifying the existing project files.
Try Capawesome Cloud¶
If you're building Capacitor apps or plugins, Capawesome Cloud can help you ship faster with cloud-based native builds, over-the-air updates, and automated app store publishing.
Conclusion¶
Adding SPM support to your Capacitor plugin is becoming essential as the iOS ecosystem moves away from CocoaPods. The changes are well-defined — a Package.swift manifest, CAPBridgedPlugin conformance, and some cleanup — and you have several tools to help automate the process. Whether you prefer a CLI tool, an AI agent, or a fresh scaffold, you can get your plugin ready for SPM-based projects without too much effort.
If you still need CocoaPods for your app project, check out How to Use CocoaPods Instead of SPM with Capacitor for guidance on when and how to use it as a fallback.
If you have questions, feel free to join the Capawesome Discord server. To stay up to date with the latest news, subscribe to the Capawesome newsletter.