Notarising a Mac app: what we learned shipping Altillo, Pegote and Cajón

For four months we shipped our free Mac apps without notarisation, and every download ended in an Apple warning. In November 2026 we notarised all three. What it is, what it costs and the mistakes we made.

Notarising a Mac app means sending Apple the finished program, signed with a Developer ID certificate, so Apple can scan it for malware and hand back a ticket. With that ticket stapled to the app, macOS opens it with the usual question ("are you sure you want to open it?") instead of a warning that Apple couldn't check it for malicious software. It costs an Apple Developer account (99 US dollars a year, Apple's price), an afternoon the first time round and a few minutes per release after that. For four months we shipped Altillo and Pegote without it. On 3 November 2026 we notarised all three of our Studio apps, with Cajón just out. Here is what we learned, mistakes included.

First, why we put it off. In July 2026 we released Pegote (a clipboard history) and Altillo (the Mac notch turned into a shelf) for free, as tools to give away. We signed them "ad hoc", the signature any Mac can produce without a developer account, and decided not to pay the 99 dollars yet. A fair bet for two apps nobody might use. The cost fell on whoever downloaded them: on opening the zip, macOS warns it cannot check the app, and you have to go to System Settings, Privacy & Security, and click "Open Anyway". We documented it on every download page, screenshots and all, in a block called "Won't it open?". It worked. But every person who stalled in front of that warning was a lost download, and there is no way to count those.

What we hadn't reckoned with is what comes next. An ad hoc signature changes with every build: as far as macOS was concerned, each version of Altillo was a different app. And Altillo asks for sensitive permissions (Accessibility to arrange windows, Screen Recording for captures), so with every update macOS forgot what had been granted and asked again, even though Settings still showed it as on. We ended up writing a one-click permission repair into the app. Engineering to dodge a 99-dollar account. In October came the second warning sign: someone at the coworking space couldn't install Altillo 1.6. The zip was compiled for Apple silicon only and for macOS 26, and the signature didn't seal the whole bundle. None of that was notarisation's fault, but it forced us to rebuild the recipe (universal binary, macOS 13 or later, the full bundle signed, a zip with nothing but the app), and once the recipe was in order, notarising was one more step.

On 3 November, with Cajón ready to go, we stopped putting it off. You pay for the Apple Developer account on the web; Apple says activation can take up to 48 hours, and ours was live about ten minutes later. One detail that saves days: an individual account is approved the same day; a company account needs a D-U-N-S number and takes considerably longer. Then come the "Developer ID Application" certificate (requested from Keychain Access with a signing request), an app-specific password so the notarisation tool can sign in with your Apple ID, and a profile saved in the keychain with xcrun notarytool store-credentials. That same afternoon we published Altillo 1.8, Pegote 1.1.1 and Cajón 1.0, all notarised, and Cajón 1.1 the following day. The "Won't it open?" block vanished from all three pages.

  1. Sign the whole bundle, with hardened runtime and a timestamp Notarisation demands both: codesign --options runtime --timestamp, with the Developer ID identity and over the complete bundle, not just the binary. Anything that lives in Resources (for us, the permission prompts in Spanish and English) must be copied in before signing: the signature seals that folder, and a file added afterwards breaks it. The permissions the app needs under that runtime (camera, microphone, automation) go in an entitlements file.
  2. Build a zip that carries the app and nothing else No hidden macOS files, no extended attributes, nothing alongside it. Early on we shipped a README next to the app, which has an effect nobody expects: Safari unpacks the zip into a folder, and whoever drags that whole folder into Applications ends up with the app running "translocated" from a temporary location, which keeps neither permissions nor settings. We build the zip with ditto, stripped of resource forks and attributes, and it only takes its final name once every check has passed.
  3. Submit, and read the status, not just the exit code xcrun notarytool submit Cajon.zip --keychain-profile tresojotas --wait uploads the zip and waits for the verdict. Careful: the tool can finish without an error even when Apple rejects the submission. Our script reads the status in the response and aborts unless it says "Accepted"; on a rejection, notarytool log tells you what was missing. Timings vary: Altillo and Pegote came back that same afternoon; Cajón's first run took over an hour.
  4. Staple the ticket and rebuild the zip xcrun stapler staple attaches the ticket to the app, and stapler validate checks it. Without stapling the app still opens, but the first time macOS has to ask Apple over the internet. And the zip you submitted doesn't carry the ticket, so you have to build it again with the stapled app.
  5. Check it the way anyone else would Unpack the final zip into a clean folder and verify the signature there, not on the copy sitting in your repo. spctl --assess on a downloaded app should say "Notarized Developer ID". It is the only test that counts: the one that travels the same path as the person downloading it.

Our silliest mistake was with Cajón. While Apple was reviewing the zip, we opened the app to carry on testing, accepted its own "Move to Applications" prompt, and the original went to the Bin. When the ticket came back, there was nothing left to staple. Always notarise from a copy nobody is going to touch until the process is over. The second lesson is less visible but dearer: with the stable identity of a Developer ID, the permissions a person grants survive between versions, so the permission repair we had written was left as a fallback. Had we paid for the account in July, we would never have needed to write it.

What changes for the person downloading, according to Apple itself: with an app from an identified developer, macOS only asks whether you really want to open it; with an app Apple couldn't check, the main button is "Move to Bin" and there is no option to open. And according to Apple's notarisation guide for organisations, on a Mac managed by an organisation that override may be blocked outright: there, an un-notarised app simply doesn't get in. Worth knowing if what you ship is a tool for teams.

If you are going to release a Mac app outside the App Store, don't do what we did: pay for the account before the first version. What you save in 99 dollars you spend on "Open Anyway" screenshots, on permissions lost with every update and on downloads you will never know you lost. Notarisation is not an app review and not a quality mark: it is a malware scan and a stable identity. But for the person downloading, it is the difference between "I'll open it" and "better not". All three apps, now notarised, are in Studio.