Skip to content

/kotlin-tooling-cocoapods-spm-migration

Migrate KMP projects from CocoaPods (kotlin("native.cocoapods")) to Swift Package Manager (swiftPMDependencies DSL) — replaces pod() with swiftPackage(), transforms cocoapods.* imports to swiftPMImport.*, and reconfigures the Xcode project.

From plugin
kotlin-agent-skills
1k10 skills
Install
$ npx -y skills add kotlin/kotlin-agent-skills --skill kotlin-tooling-cocoapods-spm-migration --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/kotlin-tooling-cocoapods-spm-migration

Context preview

The summary Claude sees to decide when to auto-load this skill.

Migrate KMP projects from CocoaPods (kotlin("native.cocoapods")) to Swift Package Manager (swiftPMDependencies DSL) — replaces pod() with swiftPackage(), transforms cocoapods.* imports to swiftPMImport.*, and reconfigures the Xcode project.

SKILL.md

kotlin-tooling-cocoapods-spm-migration.SKILL.md
name: kotlin-tooling-cocoapods-spm-migration
description: Migrate KMP projects from CocoaPods (kotlin("native.cocoapods")) to Swift Package Manager (swiftPMDependencies DSL) — replaces pod() with swiftPackage(), transforms cocoapods.* imports to swiftPMImport.*, and reconfigures the Xcode project.
license: Apache-2.0
metadata:
  author: JetBrains
  version: "1.0.0"

CocoaPods to SwiftPM Migration for KMP

Migrate Kotlin Multiplatform projects from `kotlin("native.cocoapods")` to `swiftPMDependencies {}` DSL.

Requirements

  • **Kotlin**: 2.4.0-Beta2 or later (first public release with `swiftPMDependencies` support, available on Maven Central)
  • **Xcode**: 16.4 or 26.0+
  • **iOS Deployment Target**: 16.0+ recommended

Migration Overview

**IMPORTANT**: Keep the `cocoapods {}` block and plugin active until Phase 6. The migration adds `swiftPMDependencies {}` alongside the existing CocoaPods setup first, reconfigures Xcode, and only then removes CocoaPods.

| Phase | Action | |-------|--------| | 1 | Analyze existing CocoaPods configuration | | 2 | Update Gradle configuration (repos, Kotlin version) | | 3 | Add `swiftPMDependencies {}` alongside existing `cocoapods {}` | | 4 | Transform Kotlin imports | | 5 | Reconfigure iOS project and deintegrate CocoaPods | | 6 | Remove CocoaPods plugin from Gradle | | 7 | Verify Gradle build and Xcode project build | | 8 | Write MIGRATION_REPORT.md |

---

Phase 1: Pre-Migration Analysis

1.0 Verify the project builds

Before starting migration, identify the module to migrate and confirm it compiles successfully.

1. **Find the module that uses CocoaPods** — look for `build.gradle.kts` files containing `cocoapods`:

   grep -rl "cocoapods" --include="build.gradle.kts" .

Extract the module name from the path (e.g., `./shared/build.gradle.kts` → module name is `shared`). Note: multiple modules may use CocoaPods — record all of them. Typically only the module that produces the framework linked into the iOS app needs `swiftPMDependencies`; the others only need CocoaPods removed (Phase 6).

2. **Compile Kotlin code** — run the Kotlin compilation task for that module to verify the Kotlin source compiles:

   ./gradlew :moduleName:compileKotlinIosSimulatorArm64

Replace `moduleName` with the directory name of the module (e.g., `:shared:compileKotlinIosSimulatorArm64`). This is faster than a full `build` (which also runs release linkage) and sufficient to verify Kotlin code correctness.

3. **Build the iOS app (optional)** — try to locate the Xcode project and build it to confirm the full app compiles:

   # Find the Xcode project
   find . -name "*.xcworkspace" -not -path "*/Pods/*" -maxdepth 2
   # Build (replace scheme name with the actual app scheme)
   cd /path/to/iosApp
   xcodebuild -workspace *.xcworkspace -scheme "<AppScheme>" -destination 'generic/platform=iOS Simulator' ARCHS=arm64

If the user wants to skip the Xcode build or no Xcode project is found, proceed without it — the Kotlin compilation from step 2 is sufficient to continue.

4. **If the Kotlin compilation fails**, ask the user to either:

  • Provide the correct Gradle command to verify the module builds, or
  • Confirm the module is in a working state and it's safe to proceed

If the user confirms without providing a build command, **record that the pre-migration build could not be verified** and warn about this at the end of migration (Phase 7).

1.0a Confirm Kotlin version with Swift Import support

Read the current Kotlin version from `gradle/libs.versions.toml` (or `build.gradle.kts`).

**If the project already uses Kotlin 2.4.0-Beta2 or later** → record the version and skip Phase 2.1 (no version change needed).

**If the project uses an older Kotlin version** → Phase 2.1 will upgrade it to `2.4.0-Beta2` (the first public release with `swiftPMDependencies` support, available on Maven Central — no custom repository needed). Warn the user: "⚠️ Kotlin version jump — upgrading across minor versions can introduce breaking changes unrelated to this migration. Recommended: update first, verify it builds, then re-run this migration." If the user confirms, proceed.

1.1 Check for deprecated CocoaPods workaround property

Search `gradle.properties` for the deprecated property:

kotlin.apple.deprecated.allowUsingEmbedAndSignWithCocoaPodsDependencies=true

This property was a workaround (see [KT-64096](https://youtrack.jetbrains.com/issue/KT-64096)) for projects using `embedAndSign` alongside CocoaPods dependencies. It suppresses an error about unsupported configurations that can cause runtime crashes or symbol duplication. After migrating to SwiftPM import, this property is no longer needed and **must be removed** in Phase 6. Record its presence if found.

1.2 Check for EmbedAndSign disablers

Search all `build.gradle.kts` files for code that disables `EmbedAndSign` tasks (e.g., `TaskGraph.whenReady` filters, `tasks.matching` blocks). This is a CocoaPods-era workaround that **breaks the migration** because `integrateEmbedAndSign` (needed in Phase 5) gets disabled too. Record any such code — it **must be removed** in Phase 6, and may need to be removed earlier. See [troubleshooting.md](references/troubleshooting.md) § "`integrateEmbedAndSign` Skipped" for patterns.

1.3 Check for third-party KMP libraries with bundled cinterop klibs

Some KMP libraries ship pre-built cinterop klibs with `cocoapods.*` package namespaces. After migration, the swiftPMDependencies cinterop generator detects these existing bindings and **skips generating new bindings** for those Clang modules to avoid duplicates. This means `cocoapods.*` imports for those modules must be **kept as-is** — they resolve to the third-party library's bundled klib, not to actual CocoaPods.

**Known libraries with bundled `cocoapods.*` klibs:**

| Library | Maven artifact | Bundled klib namespace | Classes provided | |--------

Read more
Ships withkotlin-agent-skills

A collection of AI agent skills useful for projects using the Kotlin language. Skills are following the Agent Skills standard, see agentskills.io for more information.

Get the whole plugin, auto-invoked

Other skills on kotlin-agent-skills.