Skip to content
Skill Authoring
Skill

/releasing-macos-apps

Create notarized macOS app releases with Sparkle auto-updates, DMG installers, and GitHub releases. Use when releasing macOS apps, creating DMG files, notarizing apps, or setting up Sparkle updates. Handles version updates, code signing, notarization, and distribution.

From plugin
jamesrochabrun-skills
19424 skills
Install
$ npx -y skills add jamesrochabrun/skills --skill releasing-macos-apps --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/releasing-macos-apps

Context preview

The summary Claude sees to decide when to auto-load this skill.

Create notarized macOS app releases with Sparkle auto-updates, DMG installers, and GitHub releases. Use when releasing macOS apps, creating DMG files, notarizing apps, or setting up Sparkle updates. Handles version updates, code signing, notarization, and distribution.

SKILL.md

releasing-macos-apps.SKILL.md
name: releasing-macos-apps
description: Create notarized macOS app releases with Sparkle auto-updates, DMG installers, and GitHub releases. Use when releasing macOS apps, creating DMG files, notarizing apps, or setting up Sparkle updates. Handles version updates, code signing, notarization, and distribution.

Releasing macOS Apps

Complete workflow for creating notarized macOS app releases with Sparkle auto-updates, DMG installers, and GitHub releases.

Release Checklist

Copy this checklist and track progress:

Release Progress:
- [ ] Step 1: Check prerequisites (certificates, credentials)
- [ ] Step 2: Update version in .xcconfig file
- [ ] Step 3: Build and archive the app
- [ ] Step 4: Export with proper code signing
- [ ] Step 5: Create zip and generate Sparkle signature
- [ ] Step 6: Create DMG with Applications folder
- [ ] Step 7: Submit for notarization
- [ ] Step 8: Staple notarization ticket to DMG
- [ ] Step 9: Update appcast.xml with new signature
- [ ] Step 10: Commit and push changes
- [ ] Step 11: Update GitHub release assets
- [ ] Step 12: Verify DMG and version number

Prerequisites

Before starting a release, verify:

1. **Apple Developer ID Application certificate** installed and valid 2. **Apple ID credentials** for notarization:

  • Apple ID email
  • App-specific password (generate at appleid.apple.com)
  • Team ID

3. **Sparkle private key** for signing updates 4. **GitHub CLI** (`gh`) installed and authenticated 5. **Version configuration location** identified (usually `.xcconfig` file)

Check certificate:

security find-identity -v -p codesigning | grep "Developer ID Application"

Step 1: Update Version

Locate your version configuration file (commonly `ProjectName.xcconfig` or `project.pbxproj`).

**For .xcconfig files:**

# Edit the APP_VERSION line
# Example: APP_VERSION = 1.0.9

**Verify the update:**

xcodebuild -project PROJECT.xcodeproj -showBuildSettings | grep MARKETING_VERSION

Step 2: Build and Archive

Archive the app with the new version:

xcodebuild -project PROJECT.xcodeproj \
  -scheme SCHEME_NAME \
  -configuration Release \
  -archivePath ~/Desktop/APP-VERSION.xcarchive \
  archive

**Verify archive was created:**

ls -la ~/Desktop/APP-VERSION.xcarchive

Step 3: Export with Code Signing

Create export options file:

cat > /tmp/ExportOptions.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>destination</key>
	<string>export</string>
	<key>method</key>
	<string>developer-id</string>
	<key>signingStyle</key>
	<string>automatic</string>
	<key>teamID</key>
	<string>YOUR_TEAM_ID</string>
	<key>signingCertificate</key>
	<string>Developer ID Application</string>
</dict>
</plist>
EOF

Replace `YOUR_TEAM_ID` with your actual team ID.

Export the archive:

xcodebuild -exportArchive \
  -archivePath ~/Desktop/APP-VERSION.xcarchive \
  -exportPath ~/Desktop/APP-VERSION-Export \
  -exportOptionsPlist /tmp/ExportOptions.plist

**Verify the exported app version:**

defaults read ~/Desktop/APP-VERSION-Export/APP.app/Contents/Info.plist CFBundleShortVersionString

This should show the new version number.

**Verify code signing:**

codesign -dvvv ~/Desktop/APP-VERSION-Export/APP.app

Look for "Developer ID Application" in the Authority lines.

Step 4: Create Zip and Generate Sparkle Signature

Create zip file for Sparkle auto-updates:

cd ~/Desktop/APP-VERSION-Export
ditto -c -k --keepParent APP.app APP.app.zip

Generate Sparkle EdDSA signature (you'll be prompted for the private key):

echo "YOUR_SPARKLE_PRIVATE_KEY" | \
  ~/Library/Developer/Xcode/DerivedData/PROJECT-HASH/SourcePackages/artifacts/sparkle/Sparkle/bin/sign_update \
  APP.app.zip --ed-key-file -

**Output format:**

sparkle:edSignature="BASE64_SIGNATURE" length="FILE_SIZE"

Save both the signature and length for updating appcast.xml.

For more details, see [SPARKLE.md](SPARKLE.md).

Step 5: Create DMG with Applications Folder

Create DMG installer with Applications folder symlink for drag-and-drop installation:

TEMP_DMG_DIR="/tmp/APP_dmg" && \
rm -rf "${TEMP_DMG_DIR}" && \
mkdir -p "${TEMP_DMG_DIR}" && \
cp -R ~/Desktop/APP-VERSION-Export/APP.app "${TEMP_DMG_DIR}/" && \
ln -s /Applications "${TEMP_DMG_DIR}/Applications" && \
hdiutil create -volname "APP VERSION" \
  -srcfolder "${TEMP_DMG_DIR}" \
  -ov -format UDZO ~/Desktop/APP-VERSION.dmg && \
rm -rf "${TEMP_DMG_DIR}"

**Verify DMG contents:**

hdiutil attach ~/Desktop/APP-VERSION.dmg -readonly -nobrowse -mountpoint /tmp/verify_dmg && \
ls -la /tmp/verify_dmg && \
hdiutil detach /tmp/verify_dmg

You should see both `APP.app` and `Applications` (symlink).

Step 6: Submit for Notarization

Submit the DMG to Apple for notarization (you'll be prompted for credentials):

xcrun notarytool submit ~/Desktop/APP-VERSION.dmg \
  --apple-id YOUR_APPLE_ID@gmail.com \
  --team-id YOUR_TEAM_ID \
  --password YOUR_APP_SPECIFIC_PASSWORD \
  --wait

The `--wait` flag makes the command wait for processing to complete (typically 1-2 minutes).

**Expected output:**

Processing complete
  id: [submission-id]
  status: Accepted

If status is "Invalid", get detailed logs:

xcrun notarytool log SUBMISSION_ID \
  --apple-id YOUR_APPLE_ID@gmail.com \
  --team-id YOUR_TEAM_ID \
  --password YOUR_APP_SPECIFIC_PASSWORD

For notarization troubleshooting, see [NOTARIZATION.md](NOTARIZATION.md).

Step 7: Staple Notarization Ticket

Staple the notarization ticket to the DMG:

xcrun stapler staple ~/Desktop/APP-VERSION.dmg

**Expected output:**

The staple and validate action worked!

**Verify notarization:**

spctl -a -vvv ~/Desktop/APP-VERSION-Export/APP.app

Should show:

ac
Read more
Ships withjamesrochabrun-skills

A comprehensive plugin and marketplace for Claude Code containing 24 custom skills across engineering, Apple development, product management, design, content, trading, database, QA, educational, and AI architecture domains.

Get the whole plugin