For Mac developers selling outside the App Store
Licence keys that survive a flight and a refund. Signed, notarised, auto-updating DMGs from one command. And 35 checks that stop the release which would have failed silently on a Mac you don't own.
One-time purchase · Unlimited apps · Kept current as Apple moves
A working menu bar app, built and shipped by this kit — signed, notarised and stapled by ship.sh. No signup, no email. Verify it yourself:
spctl -a -vv -t install /Volumes/FocusTimer/FocusTimer.app
The full run from certificate to notarised DMG, in order.
The log is the tool's own output, word for word.
Sell from your own site and you keep 100% minus payment fees, own your customers, and escape the sandbox. In exchange, Apple hands you this list and no tooling.
| The job | Handled alone | With the kit |
|---|---|---|
| Menu bar app shell | No Xcode template exists; tutorials are outdated, LLMs suggest deprecated APIs | Working skeleton, macOS 13+ |
| Notarization | Xcode notarises the app. The DMG you actually ship is a separate submission, and every release repeats the GUI by hand | One script, both submissions, signature flags checked before the round-trip |
| DMG packaging | hdiutil incantations; the DMG itself must be notarized too, which most guides skip | Signed, notarized, stapled |
| Auto-updates | Sparkle setup, EdDSA keys, appcast hosting, three silent failure modes | Wired, with delta updates |
| License keys | Verification API, offline handling, refund handling, keychain storage | Gumroad flow, 14-day grace |
Config.xcconfigThe one file you edit. Name, bundle id, team, versions, update feed, product id. Everything follows it.ship.shBuild → sign → notarize → staple → DMG. Verifies its own signature flags before wasting a round-trip to Apple, and refuses to ship what would silently fail.appcast.shGenerates your signed update feed. Rejects an unsigned one, a failure Sparkle's own tooling lets through without a word.# you edit one file: Config.xcconfig ShipKit.xcodeproj Sources/ ExampleFeatureView ← your app goes here SettingsView launch-at-login, tabs UpdaterView Sparkle wired License* Gumroad + grace period scripts/ ship.sh one command → DMG appcast.sh signed update feed docs/ 01-quickstart … 05-troubleshooting
Nothing here is proprietary. Every command is public, and the ten worst ones are written up on this site for free. What you'd be buying is knowing which ones matter before one of them costs you a release.
Measured July 2026 on a real machine and a real Developer account. Not projected, not "up to". The long version is the ten traps, free and complete.
Three of the ten. Any one of these costs a lost afternoon, or worse, ships broken silently.
Apple's certificate page pre-selects "Previous Sub-CA". Accept it and your Developer ID dies in February 2027 no matter what the expiry says. The guide walks you past it; ship.sh's error text warns about it too.
Add Sparkle after your first release and its own tool generates an unsigned feed with no warning. Updates then fail silently on every user's machine. appcast.sh verifies the signature and refuses to let it through.
errSecInternalComponent is codesign's way of saying "keychain permissions". It just never mentions keychains, or permissions. You get the one-line fix in the error message itself, when it happens, not after two hours of searching.
Apple has changed the rules of this pipeline before, and macOS 27 is in beta right now. Every change arrives the same way: a release that worked last month stops working, and nothing tells you why.
Our scripts stay current because we ship our own apps through them. When Apple moves, it breaks our releases first. We find it, fix it, and you get the fix.
A pipeline you assembled yourself gets updated when a customer emails you to say your app won't open.
Fixes and improvements to v1 are free, delivered through your original download link.
One file to configure. One command to ship. Every trap already documented.
$99 one-time
Requires Apple's own Developer Program membership ($99/year, paid to Apple). Everyone shipping Mac apps pays that, kit or not.
ship.sh and appcast.sh, and five guides. Then it walks you through the certificate and notary setup. Full readable source, no obfuscation. The key is checked once, when you unlock; your copy is stamped with your name and the app never phones home again.ship.sh runs on your machine, not in GitHub Actions. Swift and SwiftUI only, macOS 13+, no Objective-C skeleton and no iOS. And the licence check runs on the client, so it makes casual copying inconvenient rather than impossible. We say the same thing in the write-up.