Weeks ago, we introduced a new package resolution process for tuist install that:
Reduces the file-system footprint at .build by using a globally content-addressable store.
Does sub-second warm dependency resolutions.
This is extremely valuable if you are using generated projects with Git worktrees. Without it, every worktree will end up with a large .build directory, and additional tuist installs that are slow.
The feature is not enabled by default, and we need your input before we make it the default. All you need to do is to set the TUIST_USE_SWIFTERPM=1 env variable in your project, which you can easily do with Mise if that’s what you are using to install Tuist by doing:
[env]
TUIST_USE_SWIFTERPM=1
I’d hugely appreciate If you could report back if everything is working smoothly or if you are running into any issues with it.
I tested tuist install with two independent Git worktrees created from exactly the same commits.
Both worktrees used:
Tuist 4.201.0
OpenSwiftUI commit e2c69fa4
Byte-identical Package.swift and Package.resolved files
Clean project-local .build directories
The same populated global caches, modeling the creation of an additional worktree
Measurement
Standard resolver
swifterpm
Difference
Fresh worktree install
28.39s
0.45s
swifterpm was 63.1× faster
Immediate second install
3.19s
0.18s
swifterpm was 17.7× faster
Local Tuist/.build usage
151 MB
596 KB
About 260× smaller
swifterpm reused 11 packages through symlinks from the shared ~/.cache/swifterpm store, which occupied 56 MB.
I also observed a lockfile compatibility issue. The SwiftPM-generated Package.resolved naturally contains a mixture of repository URLs with and without .git, because the package manifests use both valid forms. For example, this dependency graph declares equatable, SymbolLocator, and swift-snapshot-testing with .git, while Compute, OpenCoreGraphics, and OpenObservation are declared without it. SwiftPM treats these forms as equivalent package identities and preserves a location derived from those declarations.
When swifterpm runs, it rewrites six GitHub locations by lowercasing their owner and repository paths and removing .git suffixes no matter how. For example:
Hey @pepicrft! I had a couple of things I wanted to flag for attention. As you may have seen on the GitHub issues, another user and I have both reported (1, 2) that SwifterPM can’t retrieve registry credentials from the keychain without manual approval of a GUI popup.
In the case of my issue, the Dosu bot suggested a reasonable sounding solution, which is to provide the credentials via SWIFTPM_REGISTRY_TOKEN instead of via the keychain.
However, I’ve determined that this only works on Xcode versions greater than 26.3. Because SwifterPM utilizes native SwiftPM when the cache is cold for any pinned dependency, and the SWIFTPM_REGISTRY_TOKEN variable (and others such as SWIFTPM_NETRC_DATA, etc.) are only supported on Swift 6.3 and up, this means that SwifterPM is nonfunctional for teams who are still on an older Xcode/Swift version and need to use a private Swift registry.