macos-auto-update
Skill90 starsChanged 5 months agoMITView on GitHub
Add Sparkle auto-update support to a native macOS app. Use this skill whenever the user wants to add auto-updates, implement Sparkle, set up an appcast feed, add "Check for Updates" to their app, or integrate automatic update checking. Also trigger when the user mentions Sparkle, appcast, SUFeedURL, EdDSA signing, or update notifications. This covers the full setup: adding the Sparkle SPM dependency, creating the UpdaterManager singleton, wiring it into the app delegate and UI, configuring Info.plist, and generating the initial appcast.xml.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- lingyired/status-trioword for word, first seen Nov 8, 2026
- fayazara/macos-app-skillsword for word, first seen May 27, 2026
Other versions2 projects use a version of this.
Word for word · 2
- lingyired/status-trio★ 1.8k100% same
- fayazara/macos-app-skills★ 660100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
- macos-buildSkill
- macos-notch-uiSkill
- macos-patternsSkill
- macos-releaseSkill
- macos-settings-uiSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 33
Use the "Up to Next Major Version" rule with 2.0.0.
- Very specific: line 59
Add these keys to your app's Info.plist:
- Very specific: line 146
Create an appcast.xml at the root of your repo.
- Very specific: line 163
If your app runs as .accessory (no Dock icon), Sparkle's update window won't appear unless you temporarily switch to .regular.
- Distinctive: line 177
If your app uses Hardened Runtime (required for notarization), no special Sparkle entitlements are needed.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Sparkle Auto-Update for macOS Apps
This skill adds Sparkle auto-update support to a native macOS app. Sparkle is the standard open-source framework for macOS app updates outside the Mac App Store.
Overview
The implementation has 4 parts:
- SPM dependency -- add the Sparkle package to the Xcode project
- UpdaterManager.swift -- a singleton that wraps
SPUStandardUpdaterController - Info.plist keys --
SUFeedURLandSUPublicEDKey - UI integration -- "Check for Updates" button in settings/menu bar
Step 1: Add Sparkle via SPM
In Xcode: File > Add Package Dependencies > enter:
https://github.com/sparkle-project/SparkleUse the "Up to Next Major Version" rule with 2.0.0. Add the Sparkle framework to your app target.
Or add it to Package.swift if your project uses one:
.package(url: "https://github.com/sparkle-project/Sparkle", from: "2.0.0")Step 2: Create UpdaterManager.swift
Copy references/UpdaterManager.swift into your project. This is a singleton that:
- Creates
SPUStandardUpdaterControllerearly (beforeapplicationDidFinishLaunchingreturns) - Publishes
canCheckForUpdatesfor UI binding - Exposes
automaticallyChecksForUpdatestoggle - Skips all update logic in DEBUG builds (so you don't get update prompts during development)
- For menu-bar-only apps: temporarily switches to
.regularactivation policy before showing the update window
The key design decisions in this file:
startingUpdater: falsein the initializer, then callingstart()explicitly inapplicationDidFinishLaunching. This gives you control over timing.- DEBUG guards on
start()andcheckForUpdates(). Sparkle should never run in debug builds -- it would try to update your debug app with a release build. ObservableObjectwith@Published(not@Observable) because we need the Combinepublisher(for:)bridge from Sparkle's KVO.
Step 3: Configure Info.plist
Add these keys to your app's Info.plist:
<key>SUFeedURL</key>
<string>https://raw.githubusercontent.com/OWNER/REPO/main/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>YOUR_PUBLIC_EDDSA_KEY_HERE</string>
<key>SUEnableInstallerLauncherService</key>
<true/>Generating EdDSA Keys
Sparkle uses EdDSA (Ed25519) signing. Generate a keypair:
# Find generate_keys in your DerivedData after building the project with Sparkle
find ~/Library/Developer/Xcode/DerivedData -name "generate_keys" -type f 2>/dev/null | head -1Run it:
/path/to/generate_keysThis prints the public key and stores the private key in your Keychain. Put the public key in SUPublicEDKey in Info.plist. The private key stays in Keychain and is used by sign_update during release.
Step 4: Wire Into App
App Delegate
final class AppDelegate: NSObject, NSApplicationDelegate {
private let updaterManager = UpdaterManager.shared
func applicationDidFinishLaunching(_ notification: Notification) {
updaterManager.start()
}
}The UpdaterManager.shared property must be accessed early so the SPUStandardUpdaterController is created before the app finishes launching. Referencing it in the AppDelegate property ensures this.
Settings UI (About Pane)
struct AboutSettingsPane: View {
@ObservedObject private var updaterManager = UpdaterManager.shared
var body: some View {
Form {
Section("Updates") {
Toggle(isOn: Binding(
get: { updaterManager.automaticallyChecksForUpdates },
set: { updaterManager.automaticallyChecksForUpdates = $0 }
)) {
Text("Automatically check for updates")
}
Button("Check for Updates...") {
updaterManager.checkForUpdates()
}
.disabled(!updaterManager.canCheckForUpdates)
}
}
.formStyle(.grouped)
.scrollContentBackground(.hidden)
}
}Menu Bar (optional)
Button {
updaterManager.checkForUpdates()
} label: {
Label("Check for Updates...", systemImage: "arrow.down.circle")
}
.disabled(!updaterManager.canCheckForUpdates)Step 5: Create Initial Appcast
Create an appcast.xml at the root of your repo. It starts empty and gets populated by your release process:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>YourApp</title>
<description>Most recent changes for YourApp.</description>
<language>en</language>
</channel>
</rss>Host this file on GitHub (raw URL) or any static file host. The URL must match SUFeedURL in Info.plist.
Menu-Bar-Only Apps
If your app runs as .accessory (no Dock icon), Sparkle's update window won't appear unless you temporarily switch to .regular. The reference UpdaterManager handles this in checkForUpdates():
func checkForUpdates() {
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
controller.checkForUpdates(nil)
}The app reverts to .accessory when the update window closes (handled by your existing activation policy manager).
Hardened Runtime Entitlements
If your app uses Hardened Runtime (required for notarization), no special Sparkle entitlements are needed. Sparkle 2.x works with the standard hardened runtime configuration.
Appcast Item Format
Each release in the appcast looks like this (for reference when building release tooling):
<item>
<title>Version 1.2 (Build 5)</title>
<pubDate>Mon, 26 May 2026 12:00:00 +0000</pubDate>
<sparkle:version>5</sparkle:version>
<sparkle:shortVersionString>1.2</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>14.0</sparkle:minimumSystemVersion>
<description><![CDATA[<ul><li>New feature</li><li>Bug fix</li></ul>]]></description>
<enclosure url="https://github.com/OWNER/REPO/releases/download/v1.2/YourApp.dmg"
type="application/octet-stream"
sparkle:edSignature="BASE64_EDDSA_SIGNATURE"
length="FILE_SIZE_BYTES" />
</item>sparkle:version=CFBundleVersion(build number)sparkle:shortVersionString=CFBundleShortVersionString(marketing version)sparkle:edSignature= output ofsign_update YourApp.dmglength= file size in bytes
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

