A blazingly fast, drop-in companion to SwiftPM
swx resolves, builds and runs Swift packages, and writes SwiftPM's own files byte for byte.
It is written in Swift, reads Package.swift as it is, and works alongside
swift and Xcode, so there is nothing to migrate.
curl -fsSL https://swx.quadratic.xyz/install.sh | sh
macOS 13+ (universal) and Linux (static, x86_64 and aarch64). Other ways to install.
Key features
- Fast: cold resolves 4–7× faster than SwiftPM, and a no-op in 20 ms.
- Drop-in: the same
Package.resolved,.build/checkoutsandworkspace-state.jsonas SwiftPM. - Familiar: SwiftPM's commands and flags; anything swx doesn't handle is forwarded to
swift package. - Xcode-aware: prepares
SourcePackagessoxcodebuildbuilds offline. - Apple platforms: build, run and test on iOS, watchOS, tvOS and visionOS simulators and devices.
- Toolchains: installs swift.org releases and snapshots, and honours
.swift-version. - Tools and scripts: runs package executables like
uvx, and single-file scripts with dependencies. - Registries: SE-0292 registries with authentication, SE-0391 signatures and SwiftPM's trust store.
Philosophy
The goal of swx is to make working with Swift packages fast, without ever being distinguishable from SwiftPM in the files it leaves behind. To that end, swx:
- Writes exactly what SwiftPM and Xcode would, and proves it with differential checks in CI.
- Does no work it can avoid: an unchanged lockfile is a no-op, and missing checkouts are restored without solving.
- Keeps the network and every core busy, pipelining tag listing, manifest fetches and checkouts with resolution.
- Never guesses: a manifest it can't prove harmless is evaluated by the compiler, as SwiftPM does.
- Leaves building to the build systems: SwiftPM for the host,
xcodebuildfor Apple platforms.
swx is written in Swift. It reads manifests with SwiftParser, adapts parts of SwiftPM itself, and keeps one global, content-addressed store whose checkouts are copy-on-write clones, so a dependency is fetched once per machine instead of once per project.
Example
swx package resolve # same Package.resolved as `swift package resolve` swx build -c release # resolves, then SwiftPM builds with resolution disabled swx test swift build # still works: everything is already resolved
swx devices # simulators and paired devices swx run --platform ios HelloApp # build, install, launch, stream console swx test --platform watchos # package tests on a watchOS simulator
swx xcode resolve --source-packages SourcePackages
xcodebuild -clonedSourcePackagesDirPath SourcePackages \
-disableAutomaticPackageResolution -onlyUsePackageVersionsFromResolvedFile …
#!/usr/bin/env -S swx run // swx-dependencies: // .package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.0") import ArgumentParser
The user guide covers every command.
Performance
Vapor + Fluent (32 packages), Apple Silicon, Swift 6.4. Both tools start from their own
empty caches, and every run produced byte-identical files. Scripts/benchmark.py
reproduces the runs.
Cold resolve, empty caches 7×
No lockfile, warm cache 8×
update, warm cache 5×
Fresh clone: lockfile, no .build 15×
No-op 13×
Contributing
A difference from SwiftPM is a bug: please report it. To work on swx, read the contributing guide.
License
swx is licensed under the Apache License v2.0 with Runtime Library Exception, like SwiftPM.