Modernize Apple dependencies safely.
PkgLift analyzes native Xcode projects, builds a dependency migration plan, and safely moves the supported subset of CocoaPods dependencies to Swift Package Manager.
No blind conversions. No guesswork.
Analyze → Plan → Migrate → Verify
Project website · Installation · Quick Start · Compatibility · Safety Philosophy · Pilot Evidence · Diagnostics · Support · Report a Migration · Propose a Registry Mapping
Condensed from PkgLift v0.4.0 output against the repository-owned mixed-language fixture. This demo stops at dry run; the separate end-to-end workflow is the apply-and-build proof. See the full pilot boundary.
If PkgLift helps with a migration, star the repository or share a redacted migration report. Both make the next unsupported project shape easier to prioritize.
What PkgLift Does
PkgLift automates the evidence-backed parts of moving a native iOS or macOS Xcode project from CocoaPods to Swift Package Manager (SwiftPM), while preserving uncertain dependencies under CocoaPods for human review.
pkglift analyze pkglift plan pkglift migrate # dry run; no project mutation pkglift migrate --apply # reviewed AUTO entries only pkglift verify --build --scheme MyApp
A Reviewed Migration, Not a Conversion Guess
A project might begin with direct CocoaPods declarations such as:
target 'MyApp' do pod 'Alamofire', '5.9.1' pod 'InternalAnalytics' end
PkgLift can produce a plan where the exact, version-supported Alamofire mapping is executable while the unknown internal dependency is preserved:
Alamofire 5.9.1 AUTO exact verified mapping
InternalAnalytics UNKNOWN no registry evidence
After review, only the AUTO entry may be added as a Swift package. The unknown pod and the remaining CocoaPods integration stay in place. PkgLift does not invent a package URL, product name, target, or compatible version.
Why PkgLift Exists
CocoaPods has announced a plan for trunk to stop accepting new Podspecs on December 2, 2026. The plan explicitly keeps existing trunk and CDN builds available, and does not mean CocoaPods itself or private spec repositories stop working. PkgLift provides a reviewable path for native Xcode projects that want to move supported dependencies to SwiftPM without pretending every pod or project shape can be converted automatically.
What Is New in v0.4.0
- Analysis dependencies and migration-plan entries can carry additive typed
sourceProvenanceevidence for a bounded literal external Git declaration. - Supported HTTPS, SSH, and SCP-style repository identities are canonicalized deterministically without guessing transport equivalence.
- Podfile declarations are reconciled with CocoaPods
EXTERNAL SOURCESandCHECKOUT OPTIONSevidence without executing Ruby or contacting the repository. - Credentials, URL user information, queries, and fragments are removed at the parser trust boundary and raw source URLs are not retained in standard or portable JSON.
- Saved and current external provenance is compared during migration preflight; missing, changed, conflicting, credential-bearing, or lossy evidence refuses mutation.
- XcodeBenchmark and Hammerspoon provide independent pinned, read-only real-project evidence for deliberate external Git refusal paths.
- External sources remain analysis-only: every result is
REVIEW,BLOCKED, orUNKNOWN, neverAUTO.
See the v0.4.0 release notes, changelog, JSON contract, migration-safety guide, and real-project pilot documentation for the complete evidence and refusal boundaries.
Safety Philosophy
PkgLift operates on a strict safety model. Every dependency is classified before migration:
| Classification | Meaning | Executed automatically |
|---|---|---|
| AUTO | Exact pod or subspec mapping, supported locked version, verified package product, exact destination target, and complete supported consumer-language evidence | Yes, after plan review and --apply |
| REVIEW | A plausible migration exists, but human judgment or unsupported project context is involved | No |
| BLOCKED | A known incompatibility or unsafe project construct prevents automatic migration | No |
| UNKNOWN | PkgLift lacks exact registry evidence | No |
REVIEW, BLOCKED, and UNKNOWN are not failed conversions. They are safe outcomes that prevent PkgLift from changing a project without sufficient evidence.
We never guess. We never blindly edit project files without a reviewed plan.
Compatibility
PkgLift targets partial CocoaPods-to-SwiftPM migration in native Xcode projects. A language or ecosystem listed as detected is not necessarily eligible for automatic migration.
| Project or integration | Current behavior |
|---|---|
| Swift-only target | AUTO-eligible when the complete target profile and exact registry mapping both support Swift |
| Objective-C-only target | AUTO-eligible only when the exact mapping explicitly supports Objective-C |
| Mixed Swift/Objective-C target | AUTO-eligible only when the same mapping explicitly supports both languages |
| Objective-C++, C, or C++ target | Detected from PBX metadata; currently REVIEW unless a mapping explicitly supports every detected language |
| Carthage | Root metadata and confirmed Xcode integration are detected; Carthage dependencies are not parsed, migrated, or modified, and confirmed presence prevents AUTO |
| React Native | use_react_native! is detected as an unsupported project integration and prevents AUTO |
| Flutter | flutter_install_all_ios_pods is detected as an unsupported project integration and prevents AUTO |
| Capacitor | capacitor_pods is detected as an unsupported project integration and prevents AUTO |
| Kotlin Multiplatform (KMP) | No heuristic detection is claimed; local pods and dynamic generation remain non-automatic under existing safety rules |
| External Git pod | PkgLift v0.4.0 can analyze bounded literal repository/ref provenance, but the dependency remains REVIEW, BLOCKED, or UNKNOWN and is never migrated automatically |
Local :path pod |
Detected as an external source; typed local provenance and automatic migration are not implemented |
Host support remains macOS 14 or later on Apple Silicon (arm64). Distribution is through a Developer ID-signed and Apple-notarized binary, Homebrew, or a source build. See Limitations for the intentionally conservative boundaries.
Installation
PkgLift v0.4.0 is distributed as a Developer ID-signed and Apple-notarized Apple Silicon binary for macOS 14 or later.
Install with Homebrew:
brew install Alexsvensson99/tap/pkglift
Release archives are also available from GitHub Releases. Maintainer signing, notarization, and release instructions are documented in Distribution.
Verify and extract a downloaded archive before installing it:
shasum -a 256 -c pkglift-macos-arm64.tar.gz.sha256 tar -xzf pkglift-macos-arm64.tar.gz sudo mkdir -p /usr/local/libexec/pkglift /usr/local/bin sudo cp pkglift /usr/local/libexec/pkglift/ sudo cp -R PkgLift_PkgLiftRegistry.bundle /usr/local/libexec/pkglift/ sudo ln -sf /usr/local/libexec/pkglift/pkglift /usr/local/bin/pkglift
From a source checkout:
swift build -c release sudo mkdir -p /usr/local/libexec/pkglift /usr/local/bin sudo cp .build/release/pkglift /usr/local/libexec/pkglift/ sudo cp -R .build/release/PkgLift_PkgLiftRegistry.bundle /usr/local/libexec/pkglift/ sudo ln -sf /usr/local/libexec/pkglift/pkglift /usr/local/bin/pkglift
Quick Start
- Navigate to the repository root containing the
Podfile; Xcode projects and workspaces may be nested beneath it. - Run
pkglift analyzeto see what PkgLift can classify. - Run
pkglift planto generate.pkglift/plan.json. - Review every entry in the plan.
- Run
pkglift migratefor a validated dry run. - Keep the generated
.pkglift/plan.jsonfrom appearing as an untracked change. For a one-off test, add only that file to the repository-local Git exclude; for a shared policy, add it to.gitignoreand commit the policy change. See Testing PkgLift on a Real Project for the safe commands and review flow. - Confirm that
git status --shortis empty, then runpkglift migrate --apply. - Run
pod installso CocoaPods updates the dependencies that remain. - Run
pkglift verify; add--build --scheme <scheme>for a full build.
PkgLift deliberately refuses --apply when Git reports a dirty worktree. Do not bypass that safeguard to work around the generated plan file.
PkgLift discovers projects and workspaces recursively while excluding generated dependency and build trees. If a workspace references multiple projects, select both the workspace and project explicitly:
pkglift analyze --path . \
--workspace Workspaces/Products.xcworkspace \
--project Projects/App.xcodeprojSelection paths are standardized and resolved through symlinks beneath --path. Workspace references that escape that root or use unsupported location schemes are refused rather than guessed.
For a reproducible full build, pass the same explicit settings used by the project or CI:
pkglift verify \ --path . \ --workspace MyApp.xcworkspace \ --project MyApp.xcodeproj \ --build \ --scheme MyApp \ --configuration Debug \ --destination 'generic/platform=iOS Simulator' \ --derived-data-path .pkglift/DerivedData
Commands
analyze: Scans the project and dependencies.plan: Generates a migration plan.migrate: Validates the saved plan and previews it;--applyperforms only typedAUTOactions.verify: Verifies the project after migration and can optionally resolve packages and run a build.diagnostics: Writes a local, privacy-preserving JSON report without uploading it.registry validate: Validates local and bundled registry mappings.version: Prints the current version.
analyze and plan accept --portable-json as an alternative to --json. Portable output removes local paths and URL credentials and adds portableOutput.version = 1, but still contains dependency and target names. External Git literals are already canonicalized and stripped of credentials, queries, and fragments before either standard or portable JSON is constructed. plan --portable-json prints the portable representation while keeping the standard executable plan in .pkglift/plan.json.
analyze also accepts a CI policy without changing its normal behavior:
pkglift analyze --json --fail-on unresolved > pkglift-analysis.jsonPkgLift writes the complete result before exiting with status 1. Only direct dependencies affect the policy: blocked matches BLOCKED; unresolved matches BLOCKED or UNKNOWN; and non-auto matches every direct dependency that is not AUTO. Analysis never creates or changes a migration plan.
Share a Real-World Result
Testing on varied public and private project layouts helps PkgLift improve without weakening its safety model.
Generate a minimized report when it helps reproduce the result:
pkglift diagnostics \
--path . \
--output pkglift-diagnostics.jsonReview the JSON before sharing it. The report contains counts, flags, tool versions, Git state, and typed failure stages; it excludes source code, complete Podfiles, dependency and target names, repository URLs, changed filenames, arbitrary error messages, and absolute user paths. See Privacy-Preserving Diagnostics.
- Use the real-world migration report for successful, partial, and intentionally refused migrations.
- Use the registry mapping proposal when an exact CocoaPods-to-SwiftPM mapping can be supported by official upstream evidence.
- Read Testing PkgLift on a Real Project before applying changes, and remove private or proprietary information before publishing a report.
Registry
The PkgLift Registry is an open-source database mapping exact CocoaPods identifiers to verified SwiftPM repositories and products. It handles module naming, version requirements, and compatibility evidence.
See Registry and Contributing Registry Mappings to learn how mappings are verified.
Configuration
Customize PkgLift using a .pkglift.yml file in the project root:
schemaVersion: 1 migration: allow: - Alamofire deny: - SomeInternalPod
An invalid configuration is an error; PkgLift does not silently ignore it.
Limitations
PkgLift v0.4.0 retains these safety boundaries:
- Only CocoaPods-to-SwiftPM migration is supported.
- Migration is partial: non-automatic pods and their CocoaPods integration are preserved.
- A stable
major.minor.patchlockfile version at or above the exact mapping's verified SwiftPM minimum, exactly one matching Xcode target, a complete non-empty target language profile, and mapping support for every detected language are required forAUTO. - Dynamic Ruby, install hooks,
script_phase,use_frameworks!,inherit! :search_paths,abstract_target, external pod sources, and ambiguous target mappings are non-automatic. PkgLift analyzes only bounded literal:gitprovenance; every external dependency still resolves toREVIEW,BLOCKED, orUNKNOWN, neverAUTO. - Local
:pathprovenance, repository network resolution, Podspec generation, and automatic external-source migration are not implemented. - Confirmed Carthage integration and React Native, Flutter, or Capacitor Podfile markers prevent
AUTO; PkgLift does not migrate or remove those integrations. - KMP is not detected through speculative file or name heuristics.
- Base pod mappings never apply automatically to undeclared subspecs.
- Parenthesized target and pod calls are accepted only for bounded literal forms in balanced static Ruby scopes. Interpolation, variables, raw control characters, non-ASCII whitespace, excessive scope nesting, multiline literals or continuations, unrecognized executable statements, CocoaPods DSL method shadowing, unsupported enclosing blocks or heredocs, external or extra options and expression tails, postfix conditions, semicolons, and unbalanced syntax remain non-automatic. Ruby block comments and
__END__data are ignored only at valid column-zero markers and cannot create dependencies. - Project and workspace selection never follows a reference outside
--path; widen--pathexplicitly if a legitimate workspace spans a broader repository root. - PkgLift removes only exact migrated pod declarations. It deliberately preserves target blocks, unrelated Ruby, and CocoaPods integration for pods that remain.
- PkgLift does not run
pod installautomatically. - Objective-C and mixed targets are automatic only for mappings with explicit matching consumer-language evidence. Current bundled C-family coverage is intentionally limited.
Roadmap
See ROADMAP.md, the analysis-only Podspec semantic model, the v0.5.0 tracker, the v0.4.0 release tracker, and the v0.3.0 release tracker for planned scope and release evidence.
Contributing
Contributions are welcome. See CONTRIBUTING.md to get started and SUPPORT.md to choose the correct support or reporting path.
License
PkgLift is licensed under the MIT License. See LICENSE.
Note: PkgLift is an independent open-source project and is not affiliated with Apple Inc. or the CocoaPods organization.
