Guide · Swift packages
Best Swift packages every indie Mac app needs
A shipping Mac app needs updates, licensing, secure storage, and preferences long before it needs anything clever. These are the packages that cover that ground.
Start FreeUpdated July 2026
Before an indie Mac app has anything clever, it needs four unglamorous things working: a way to ship updates without going through the App Store, a way to know who paid, somewhere safe to keep that answer, and somewhere sane to keep the user’s preferences. None of the four are hard problems exactly, but each one has a wrong-by-default answer that looks fine until a customer hits it — an update mechanism that silently stops working, a license check with no offline story, a Keychain integration that loses data on a device swap, a preferences file that races itself on write.
The honest move is to stop treating these as things you’ll get to. They’re infrastructure, not features, and the Swift package ecosystem has settled on strong, boring answers for most of them. This list covers the ones worth adding, what each one actually buys you, and — just as important — the handful of things indies reach for a package to solve that are genuinely faster to write yourself.
One disclosure up front, since it matters for how much to trust the rest of this list: we make one of the eight packages below. It gets one entry, ranked on the same terms as everything else here, because a list that quietly inflates its own product isn’t worth reading — and it’s ranked as one option among several credible ones, not the reason this page exists.
The best Swift packages for indie Mac apps
1. Sparkle — best for shipping your own updates
Sparkle is the software-update framework almost every Mac app distributed outside the App Store is built on — 9,400+ GitHub stars, actively maintained, currently at 2.9.4 (released July 2026) under a permissive MIT-style license. It handles the appcast feed, background download, delta updates, and EdDSA-signed update verification so a compromised CDN can’t push a malicious build to your users. If you’re not distributing through the App Store, this is close to a required dependency rather than an optional one.
2. Keylight — best for licensing and device activations
Keylight is our own Swift SDK, currently at 0.8.4, for adding license keys, device-activation limits, trials, offline verification, and usage analytics (active devices, activations, country/platform breakdowns) to a Mac or iOS app sold outside the App Store. A Stripe payment mints a signed Ed25519 lease server-side; the SDK verifies it locally with no network call at launch. Worth being precise about storage, since a lot of Mac licensing writing assumes the Keychain: as of SDK 0.6.0 the default backend is a device-bound encrypted file under Application Support, sealed with AES-256-GCM under a key derived from the machine’s hardware identifier. The Keychain is not touched unless you opt in with .keychain or keychainMirror: true, which is what keeps a permission prompt off first launch. It’s the one package on this list that’s a commercial dependency rather than a free one; see how it compares to the rest of the licensing field if licensing is the piece you’re missing.
3. Valet — best for secure storage
The Keychain API is notoriously fiddly to get right by hand, and the package most people reach for to smooth it over — KeychainAccess — hasn’t shipped a release since 2021 or taken a commit since November 2023. It isn’t broken, but it’s not a dependency you want to bet a new app on going into 2027. Valet, Square’s Keychain wrapper, is the better default today: actively maintained (commits as recent as July 2026), v5.1.0, Apache-2.0 licensed, 4,100+ stars. It gives you a small, accessibility-aware API over Keychain storage without making you learn the underlying SecItem calls, and it’s the one to reach for anywhere you’re storing something sensitive that you manage yourself, outside what a licensing SDK already persists for you.
4. Defaults — best for type-safe preferences
UserDefaults works, but it’s stringly-typed and easy to typo a key on. Defaults, from Sindre Sorhus, wraps it in a strongly-typed, Codable-aware facade with a SwiftUI property wrapper that updates a view automatically when a value changes, plus optional iCloud key-value sync. It’s MIT-licensed, actively maintained, currently v9.0.9, with 2,400+ stars, and it’s used in production across Sindre’s own apps. For anything beyond a handful of @AppStorage flags, it’s a meaningfully nicer API for the same underlying store.
5. swift-log — best for structured logging
swift-log is Apple’s own logging API for Swift — Apache-2.0, actively maintained, currently v1.14.0. It’s deliberately just an API: a Logger you instantiate with a label and call .info(), .error(), and so on against, backed by whichever logging implementation you (or a library you depend on) plug in. The value isn’t the API surface, which is small — it’s that adopting the same logging front-end as the rest of the Swift server and package ecosystem means any library you pull in later that also uses swift-log slots into the same log stream instead of writing to its own place.
6. Swift Collections — best for the data structures the standard library doesn’t have
Swift Collections is Apple’s own package of data structures the standard library leaves out: OrderedSet, OrderedDictionary, Deque, a heap, and a persistent hash-tree collection, among others. Apache-2.0, actively maintained, currently v1.6.0. Reach for it the moment you need insertion-order-preserving uniqueness or an efficient double-ended queue — writing a correct, performant ordered set by hand is a worse use of an afternoon than adding an official Apple package for it.
7. Factory — best for dependency injection
Factory is a small, container-based dependency-injection library built with SwiftUI in mind — MIT-licensed, actively maintained (releases and commits as recent as July 2026), v3.3.2, under 1,000 lines of executable code, with 2,800+ stars. You declare a factory for a type once, inject it with a property wrapper, and swap in a fake for tests or SwiftUI previews without hand-writing a protocol and a mock for every service. It’s compile-time safe — miss a registration and the code doesn’t build, rather than crashing at runtime. Worth adding once your app has more than two or three services that need swapping out for tests; not worth it for a single-screen utility.
8. ViewInspector — best for testing SwiftUI views
SwiftUI’s view hierarchy is opaque by design, which makes asserting “this view shows the trial banner when state is .trial” surprisingly hard without help. ViewInspector traverses a SwiftUI view tree at runtime and gives your tests direct access to the underlying view structs — find a button by label, read a Text view’s string, pull out a custom view’s actual state. MIT-licensed, 2,600+ stars, actively maintained (commits into 2026). It’s a unit-testing tool for view structure and state, not a replacement for snapshot testing or full UI tests — pair it with those rather than instead of them.
What is not worth a dependency
Not everything that feels tedious needs a package. A few things indies commonly reach for a dependency to solve that are genuinely faster and safer to write with plain Foundation:
- A networking library for straightforward REST calls.
URLSessionplusasync/awaitplusCodablecovers a GET-and-decode-JSON call in well under twenty lines. Reach for something heavier only once you need request interceptors, multipart uploads, or shared retry policy you don’t want to maintain yourself. - Debouncing a search field or a save action. A
TaskwithTask.sleepand a cancellation check is shorter than the API surface of most debounce packages, and it doesn’t tie your code to someone else’s Combine version. - Reading the app’s version string.
Bundle.main.infoDictionary?["CFBundleShortVersionString"]is one line. No package needed. - Copying text to the pasteboard.
NSPasteboard.general.setString(_:forType:)on macOS is a one-liner; so isUIPasteboard.general.stringon iOS. - Comparing two version strings for an update banner. Splitting on
.and comparing components is a dozen lines. A dedicated SemVer package for this one check is more dependency than the problem deserves. - Detecting dark mode.
NSApp.effectiveAppearanceon AppKit, or thecolorSchemeenvironment value in SwiftUI, is already there — no package adds anything to it.
The pattern across all of these: they’re one API call or a screenful of code, and the “convenience” a package adds is mostly a name for something you’d have written correctly anyway. Save the dependency budget for the things above that actually replace real complexity — cryptographic verification, Keychain access, an appcast protocol — not the ones-liners.
How to choose
- Distributing outside the App Store and need auto-updates → Sparkle.
- Selling the app and need license keys, device limits, or trials → Keylight.
- Storing a token or credential you manage yourself → Valet.
- Type-safe preferences with a SwiftUI binding → Defaults.
- Structured logging that plays well with other Swift packages → swift-log.
- An ordered set, ordered dictionary, or a deque → Swift Collections.
- Swapping dependencies for tests or SwiftUI previews without hand-rolled protocols → Factory.
- Asserting on SwiftUI view state and structure in unit tests → ViewInspector.
Where Keylight fits
Licensing is one line item on this list, not the whole page — but it’s the one we build. If you’re shipping a paid Mac or Swift app and want license keys, device limits, and offline verification wired to your own Stripe account instead of assembled from scratch, plans start at $19/month with a free tier.
Start licensing your app today
Drop in the Swift SDK, point it at your dashboard, and sell paid apps in under a minute. Free forever tier included.
Start Free