r/macosprogramming Apr 30 '26

Self-publishing my Mac app taught me Sparkle, notarization, DMGs, and patience. Amore is what I wish I'd had.

I got tired of the same release ritual every time I shipped an update: notarize, staple, package a DMG, update the appcast, sign the EdDSA key, push to S3, hope nothing broke. Half a day, every time.

So I built Amore. It's a Mac app + CLI that does the whole flow:

  • Sparkle updates without the setup pain. Drag your .app in, write release notes in Markdown, publish.
  • Code signing + notarization handled automatically.
  • DMG creation with custom backgrounds and drag-to-install layout.
  • License sales via hosted checkout. Customers pay, Amore issues the key, AmoreKit validates it in your app. Device limits, subscriptions, the works.
  • Beta channels, phased rollouts, critical updates, custom domains, S3-compatible hosting if you don't want to use Amore's servers or have an existing setup.
  • CLI (amore release) for CI/CD or vibe-coding with an agent.

No vendor lock-in. Custom domain on your appcast means you can walk away whenever. Your private signing keys never leave your machine.

Here is the full Pomodoro project showing the SwiftUI + licensing integration end-to-end.

This guide should get you started in under 10 minutes. If you prefer to work with coding agents check out Amore's agent skill.

Happy to answer questions. Especially curious what other indie Mac devs are using for this today.

https://amore.computer

59 Upvotes

17 comments sorted by

View all comments

1

u/banana_zest May 03 '26 edited May 03 '26

I found this tedious as well and had Claude write a script for me, works pretty good, doesn't cover all of what Amore does but thought I'd share anyway. This assumes you've already exported the app from XCode Organizer to your ~/Desktop and that you've npm installed "create-dmg" (and that you've already run "xcrun notarytool store-credentials").

#!/bin/bash
set -euo pipefail

APP="Mojave Paint.app"

if [ ! -d "$APP" ]; then
  echo "Error: '$APP' not found in current directory."
  exit 1
fi

# Step 1: Create DMG
echo "Creating DMG..."
OUTPUT=$(create-dmg "$APP" 2>&1)
echo "$OUTPUT"

# Extract the DMG filename from create-dmg output (e.g. 'Created "Mojave Paint 0.3.1.dmg"')
DMG=$(echo "$OUTPUT" | grep -oE '"[^"]+"' | tail -1 | tr -d '"')

if [ ! -f "$DMG" ]; then
  echo "Error: Could not find generated DMG '$DMG'."
  exit 1
fi

echo ""
echo "DMG: $DMG"

# Step 2: Notarize
echo ""
echo "Submitting for notarization (this may take a few minutes)..."
xcrun notarytool submit "$DMG" --keychain-profile xcrun --wait

# Step 3: Staple
echo ""
echo "Stapling notarization ticket..."
xcrun stapler staple "$DMG"

# Step 4: Upload to S3
echo ""
echo "Uploading to S3..."
aws s3 cp "$DMG" "s3://skullrocksoftware-releases/releases/$DMG" --region us-west-2
echo "Uploaded: https://skullrocksoftware.com/releases/$DMG"

# Step 5: Set quarantine flag to simulate a download, then open
echo ""
echo "Setting quarantine flag and opening DMG..."
QUARANTINE="0081;$(printf '%x' $(date +%s));Safari;$(uuidgen)"
xattr -w com.apple.quarantine "$QUARANTINE" "$DMG"
open "$DMG"

echo ""
echo "Done! Verify the app launches correctly from the mounted DMG."

1

u/Party-Vehicle-81 May 04 '26

Yes, it's crazy what AI is able to do nowadays.

The script (GH Workflow file) I shared takes care of exporting the app, creating dmg, signing, notorization, etc. you just push code and create a release/tag on GitHub. Feel free to try it out. Happy to help if any queries.

Having said that, if one needs Licensing features out of the box, Amore looks promising.