macos-spm-app-packaging — Claude Code skill: build macOS apps without
A skill that scaffolds, builds and packages SwiftPM macOS apps without an Xcode project, from the starter layout to signing and notarization.
npx skills add Dimillian/Skills --skill macos-spm-app-packaging -a claude-codeWhat macos-spm-app-packaging does
The skill walks you through two steps. First you copy assets/templates/bootstrap/ into a new repo, rename MyApp in Package.swift, Sources/MyApp/ and version.env, then set APP_NAME, BUNDLE_ID and versions. Next you copy the scripts from assets/templates/ into Scripts/, build with swift build and swift test, package with Scripts/package_app.sh and run Scripts/compile_and_run.sh.
What you get is a set of templates: .app bundle assembly with resources and signing, a dev loop that kills the running app and relaunches it, .icns generation from an Icon Composer file, notarization with stapling and zip, Sparkle appcast entries, a stable dev signing identity and a plain launcher. For releases there are Scripts/sign-and-notarize.sh and Scripts/make_appcast.sh, followed by a git tag and a GitHub release.
A table of common notarization failures lists the symptom, the likely cause and the recovery: duplicate version submissions, mismatched entitlements, a missing --options runtime flag in codesign, a hung xcrun notarytool, a staple ticket that has not propagated. The scripts target macOS, and build_icon.sh needs Xcode installed. If you do not use Sparkle for updates, strip those steps from the templates — otherwise BUILD_NUMBER in version.env has to go up with every release.
What it helps with
- scaffold a SwiftPM macOS app from scratch
- assemble a .app bundle with a script instead of Xcode
- sign and notarize a release build
- generate Sparkle appcast entries for updates
- set up a stable dev code-signing identity
Example prompts for the agent
- Scaffold a SwiftPM macOS app and rename MyApp to HelloApp
- Package the app with Scripts/package_app.sh and launch it
- Sign and notarize the release build, then make the appcast
How to install macos-spm-app-packaging
1Skills CLI (Vercel)
npx skills add Dimillian/Skills --skill macos-spm-app-packaging -a claude-code2Manually: put the files in place
~/.claude/skills/macos-spm-app-packaging/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/macos-spm-app-packaging/
1Skills CLI (Vercel)
npx skills add Dimillian/Skills --skill macos-spm-app-packaging -a codex2Manually: put the files in place
.agents/skills/macos-spm-app-packaging/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add Dimillian/Skills --skill macos-spm-app-packaging -a cursor2Manually: put the files in place
.cursor/skills/macos-spm-app-packaging/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install Dimillian/Skills macos-spm-app-packaging2Manually: put the files in place
.github/skills/macos-spm-app-packaging/SKILL.md1Skills CLI (Vercel)
npx skills add Dimillian/Skills --skill macos-spm-app-packaging -a gemini-cli2Platform CLI
gemini skills install https://github.com/Dimillian/Skills --path macos-spm-app-packagingManually: put the files in place
.devin/skills/macos-spm-app-packaging/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add Dimillian/Skills --skill macos-spm-app-packaging -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about macos-spm-app-packaging
How do I install macos-spm-app-packaging in Claude?
Run npx skills add Dimillian/Skills --skill macos-spm-app-packaging -a claude-code. The skill lands in ~/.claude/skills/macos-spm-app-packaging/SKILL.md.
What does macos-spm-app-packaging do?
It takes a SwiftPM macOS app from an empty folder to a built, packaged .app, then handles signing, notarization and appcast generation, all without an Xcode project.
What do I need for it to work?
The scripts run on macOS, and Scripts/build_icon.sh requires Xcode installed. Notarization needs an App Store Connect API key.
Source text
SKILL.md · MIT
--- name: macos-spm-app-packaging description: Scaffold, build, and package SwiftPM-based macOS apps without an Xcode project. Use when you need a from-scratch macOS app layout, SwiftPM targets/resources, a custom .app bundle assembly script, or signing/notarization/appcast steps outside Xcode. --- # macOS SwiftPM App Packaging (No Xcode) ## Overview Bootstrap a complete SwiftPM macOS app folder, then build, package, and run it without Xcode. Use `assets/templates/bootstrap/` for the starter layout and `references/packaging.md` + `references/release.md` for packaging and release details. ## Two-Step Workflow 1) Bootstrap the project folder - Copy `assets/templates/bootstrap/` into a new repo. - Rename `MyApp` in `Package.swift`, `Sources/MyApp/`, and `version.env`. - Customize `APP_NAME`, `BUNDLE_ID`, and versions. 2) Build, package, and run the bootstrapped app - Copy scripts from `assets/templates/` into your repo (for example, `Scripts/`). - Build/tests: `swift build` and `swift test`. - Package: `Scripts/package_app.sh`. - Run: `Scripts/compile_and_run.sh` (preferred) or `Scripts/launch.sh`. - Release (optional): `Scripts/sign-and-notarize.sh` and `Scripts/make_appcast.sh`. - Tag + GitHub release (optional): create a git tag, upload the zip/appcast to the GitHub release, and publish. ## Minimum End-to-End Example Shortest path from bootstrap to a running app: ```bash # 1. Copy and rename the skeleton cp -R assets/templates/bootstrap/ ~/Projects/MyApp cd ~/Projects/MyApp sed -i '' 's/MyApp/HelloApp/g' Package.swift version.env # 2. Copy scripts cp assets/templates/package_app.sh Scripts/ cp assets/templates/compile_and_run.sh Scripts/ chmod +x Scripts/*.sh # 3. Build and launch swift build Scripts/compile_and_run.sh ``` ## Validation Checkpoints Run these after key steps to catch failures early before proceeding to the next stage. **After packaging (`Scripts/package_app.sh`):** ```bash # Confirm .app bundle structure is intact ls -R build/HelloApp.app/Contents # Check that the binary is present and executable file build/HelloApp.app/Contents/MacOS/HelloApp ``` **After signing (`Scripts/sign-and-notarize.sh` or ad-hoc dev signing):** ```bash # Inspect signature and entitlements codesign -dv --verbose=4 build/HelloApp.app # Verify the bundle passes Gatekeeper checks locally spctl --assess --type execute --verbose build/HelloApp.app ``` **After notarization and stapling:** ```bash # Confirm the staple ticket is attached stapler validate build/HelloApp.app # Re-run Gatekeeper to confirm notarization is recognised spctl --assess --type execute --verbose build/HelloApp.app ``` ## Common Notarization Failures | Symptom | Likely Cause | Recovery | |---|---|---| | `The software asset has already been uploaded` | Duplicate submission for same version | Bump `BUILD_NUMBER` in `version.env` and repackage. | | `Package Invalid: Invalid Code Signing Entitlements` | Entitlements in `.entitlements` file don't match provisioning | Audit entitlements against Apple's allowed set; remove unsupported keys. | | `The executable does not have the hardened runtime enabled` | Missing `--options runtime` flag in `codesign` invocation | Edit `sign-and-notarize.sh` to add `--options runtime` to all `codesign` calls. | | Notarization hangs / no status email | `xcrun notarytool` network or credential issue | Run `xcrun notarytool history` to check status; re-export App Store Connect API key if expired. | | `stapler validate` fails after successful notarization | Ticket not yet propagated | Wait ~60 s, then re-run `xcrun stapler staple`. | ## Templates - `assets/templates/package_app.sh`: Build binaries, create the .app bundle, copy resources, sign. - `assets/templates/compile_and_run.sh`: Dev loop to kill running app, package, launch. - `assets/templates/build_icon.sh`: Generate .icns from an Icon Composer file (requires Xcode install). - `assets/templates/sign-and-notarize.sh`: Notarize, staple, and zip a release build. - `assets/templates/make_appcast.sh`: Generate Sparkle appcast entries for updates. - `assets/templates/setup_dev_signing.sh`: Create a stable dev code-signing identity. - `assets/templates/launch.sh`: Simple launcher for a packaged .app. - `assets/templates/version.env`: Example version file consumed by packaging scripts. - `assets/templates/bootstrap/`: Minimal SwiftPM macOS app skeleton (Package.swift, Sources/, version.env). ## Notes - Keep entitlements and signing configuration explicit; edit the template scripts instead of reimplementing. - Remove Sparkle steps if you do not use Sparkle for updates. - Sparkle relies on the bundle build number (`CFBundleVersion`), so `BUILD_NUMBER` in `version.env` must increase for each update. - For menu bar apps, set `MENU_BAR_APP=1` when packaging to emit `LSUIElement` in Info.plist.
© Dimillian · MIT · Dimillian/Skills