swifterpm is a faster Swift package restoration tool built for workflows where dependency resolution happens often, across many clean worktrees, and under heavy concurrency.
Concurrent package installation is becoming the default in a world of coding agents. A single developer may now have several agents resolving dependencies in parallel, often across different worktrees of the same project. In that world, slow resolution and duplicated package checkouts become very expensive.
Other package managers have already iterated on this problem. Tools like pnpm and aube show that a global cache plus cheap project-local links can make installs both faster and much more disk efficient. Tuist users reported SwiftPM resolution and checkout restoration as a bottleneck, so we felt compelled to solve it for them.
Tuist generated projects gave us a clean contract to replace: package resolution is decoupled from project integration, so tuist install can use a faster resolver/restorer before Tuist generates or updates the Xcode project.
Important
swifterpm cannot transparently speed up standard Xcode projects. Xcode integrates SwiftPM internally, and that integration does not expose a supported hook where we can replace the resolver or checkout restorer. For now, this improvement is aimed at Tuist workflows and other flows that can call swifterpm before project integration.
- Lockfile fast path: When
Package.resolvedis available,swifterpmcan use--force-resolved-versionsto skip dependency solving and restore exactly the pinned revisions. - GitHub archives first: For GitHub dependencies, it downloads source tarballs for pinned revisions instead of cloning full repositories. A shallow Git fetch is kept as a fallback.
- Swift registry archives: Registry packages declared with
.package(id:)are resolved through SwiftPM-compatible registry configuration, downloaded as checksum-verified ZIP archives, and restored under.build/registry/downloads. - XDG global source cache: Archives and extracted source trees are stored once under
$XDG_CACHE_HOME/swifterpm, or~/.cache/swifterpmwhenXDG_CACHE_HOMEis unset, keyed by package identity, version, and revision. - Project-local checkout shells:
.build/checkoutsentries stay as real directories whose contents link back to the global cache, so Xcode and Tuist-relative paths keep resolving inside the worktree. - Concurrent-safe writes: Package restoration runs in parallel, while cache writes use file locks, temporary files, and atomic moves so multiple installs can share the same cache safely.
- Tuist package-info cache:
swifterpmcan also persist SwiftPM manifest JSON under.build/swifterpm/package-info, allowing Tuist to avoid re-running parts of manifest loading later.
Install the latest release with mise:
mise use -g github:tuist/swifterpm@latestResolve and restore a package:
swifterpm --package-path . resolveUse the fastest path when Package.resolved already exists:
swifterpm --package-path . --force-resolved-versions resolveOr run without changing your mise config:
mise x github:tuist/swifterpm@latest -- swifterpm --package-path . --force-resolved-versions resolveUseful SwiftPM-shaped flags are supported, including --package-path, --cache-path, --scratch-path, --build-path, --config-path, --default-registry-url, --skip-update, --force-resolved-versions, --disable-automatic-resolution, and --only-use-versions-from-resolved-file.
The benchmark script is mise/tasks/benchmark/resolution.sh. It clones each repository into a temporary directory, deletes it on completion, and compares SwiftPM against swifterpm for cold resolution and worktree-warm resolution.
Run it with:
mise run benchmark:resolution -- --runs 3Latest single-run sample, generated on macOS 26.4.1 with Apple Swift 6.3.2:
| Codebase | Scenario | SwiftPM | swifterpm | Time reduction | Speedup |
|---|---|---|---|---|---|
Pocket Casts iOS Modules/Package.swift |
Cold | 225.498 s | 9.392 s | 95.83% | 24.01x |
Pocket Casts iOS Modules/Package.swift |
Worktree-warm | 54.705 s | 0.014 s | 99.97% | 3989.37x |
Firefox iOS root Package.swift |
Cold | 37.414 s | 1.203 s | 96.78% | 31.10x |
Firefox iOS root Package.swift |
Worktree-warm | 4.439 s | 0.008 s | 99.82% | 522.78x |
Cold resolution removes package-local scratch directories and swifterpm's cache before each run. Worktree-warm resolution removes package-local scratch directories before each run while keeping already-primed global caches, which models switching to another clean worktree.