Open source
Patch edits your Xcode project and injects code into your @main App struct. You
shouldn’t have to take that on trust, so the engine that does it and the runtime
that ships inside your binary are both public.
One repository, two packages
Section titled “One repository, two packages”Both live in patch-release/patch-swift.
The SDK is the SwiftPM package at the repository root — which is why the package
URL you add in Xcode is just the repository URL — and the engine is a second,
independent SwiftPM package nested at cli/.
Directorypatch-swift/
- Package.swift the SDK — MIT, the package SwiftPM resolves
DirectorySources/ the SDK’s targets
- …
Directorycli/ the engine — Apache-2.0, its own SwiftPM package
- Package.swift
DirectorySources/ the engine’s targets
- …
Why two licences
Section titled “Why two licences”The SDK executes a WebAssembly interpreter inside your users’ app, so it has to be maximally auditable and maximally permissive — MIT, no conditions worth arguing about.
The engine is Apache-2.0 rather than MIT for one reason: Apache-2.0 carries an express patent grant. Patch’s partitioning and lowering approach is novel enough that a licence which says nothing about patents is a worse answer for you, not just for us.
What’s in the engine
Section titled “What’s in the engine”Directorycli/
DirectorySources/
DirectoryPartitioningEngine/ decides, per function, what can ship OTA
- …
DirectoryCodeGenerator/ SwiftUI + UIKit lowering to the view IR
- …
DirectoryCompiler/ Swift→WebAssembly pipeline, fingerprinting, upload
- …
DirectoryViewNodeIR/ the wire format the SDK renders
- …
DirectoryPatchCLI/ the
patchclicommand surface- …
DirectoryTests/ ~1,700 tests
- …
The interesting part is PartitioningEngine + CodeGenerator. Everything else
is plumbing. If you want to understand how a SwiftUI view body becomes
WebAssembly, start at CodeGenerator/SwiftUIClassifier.swift and follow it into
SwiftUIEmitter.swift.
What’s in the SDK
Section titled “What’s in the SDK”Directory(repository root)
DirectorySources/
DirectoryPatchSDK/ runtime, loader, fallback chain, update checker, host bridges
- …
DirectoryPatchSwiftUI/ the thunk entry point every generated view calls
- …
DirectoryPatchRender/ reconstitutes the view IR into real SwiftUI
- …
DirectoryPatchViewIR/ the SDK’s copy of the wire format
- …
DirectoryPatchUIKit/ the UIKit equivalent
- …
DirectoryTests/ ~1,000 tests
- …
Building from source
Section titled “Building from source”-
Clone the repository and build the SDK. One clone gets you both packages. Nothing exotic — the SDK is a normal SwiftPM package at the root.
Terminal window git clone https://github.com/patch-release/patch-swiftcd patch-swiftswift build && swift test -
Build the engine, the separate package in
cli/.Terminal window cd cliswift build -c release.build/release/patchcli --help -
Add the WebAssembly toolchain — only needed to actually compile patches.
Terminal window patchcli setupThis installs the pinned swift.org toolchain and the WebAssembly SDK. The Apple/Xcode toolchain cannot target WebAssembly, which is why a second toolchain is required at all.
-
Check the setup.
Terminal window patchcli doctor
Reproducing our coverage numbers
Section titled “Reproducing our coverage numbers”Every coverage figure on this site is generated from a committed measurement, not written by hand. You can re-run that measurement:
./corpus/fetch.sh # the corpus apps, at pinned commits./tools/swiftui-corpus-coverage/run.sh # the censuscorpus/fetch.sh clones each app at the exact commit recorded in
corpus/manifest.yml, so the corpus is reproducible rather than a snapshot we
happen to have on a laptop. See what Patch can and can’t update for
the current results.
Contributing
Section titled “Contributing”Issues and pull requests for both packages go to the same repository,
patch-release/patch-swift. Two
things that make a bug report actionable immediately:
patchcli doctor --jsonThat prints your setup as JSON — versions, toolchain, and whether the app’s fingerprint is registered. Attach it.
If you’re reporting that a view didn’t patch when you expected it to, the build output already names the blocking reads per view; paste that too.