Install
$ agentstack add skill-patrickserrano-lacquer-release-macos-spm-packaging ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
macOS SwiftPM App Packaging
Overview
Bootstrap a complete SwiftPM macOS app, then build, package, and run it without Xcode. This skill covers the full workflow from project scaffolding to release distribution.
Project Scaffolding
Basic Structure
MyApp/
├── Package.swift
├── Sources/
│ └── MyApp/
│ ├── MyApp.swift # @main App entry
│ └── ContentView.swift
├── Resources/
│ ├── Assets.xcassets/
│ └── Info.plist
├── Scripts/
│ ├── package_app.sh
│ ├── compile_and_run.sh
│ └── sign-and-notarize.sh
└── version.env
Package.swift
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyApp",
platforms: [.macOS(.v14)],
products: [
.executable(name: "MyApp", targets: ["MyApp"])
],
targets: [
.executableTarget(
name: "MyApp",
resources: [
.process("Resources")
]
)
]
)
version.env
APP_NAME="MyApp"
BUNDLE_ID="com.example.myapp"
VERSION="1.0.0"
BUILD_NUMBER="1"
MIN_MACOS="14.0"
# Set to 1 for menu bar apps
MENU_BAR_APP=0
Build and Run
Build with SwiftPM
# Debug build
swift build
# Release build
swift build -c release
# Run tests
swift test
Package as .app Bundle
Create Scripts/package_app.sh:
#!/bin/bash
set -e
source version.env
BUILD_DIR=".build/release"
APP_BUNDLE="$BUILD_DIR/$APP_NAME.app"
CONTENTS="$APP_BUNDLE/Contents"
MACOS="$CONTENTS/MacOS"
RESOURCES="$CONTENTS/Resources"
# Build release
swift build -c release
# Create bundle structure
rm -rf "$APP_BUNDLE"
mkdir -p "$MACOS" "$RESOURCES"
# Copy binary
cp "$BUILD_DIR/$APP_NAME" "$MACOS/"
# Copy resources
cp -r Resources/* "$RESOURCES/" 2>/dev/null || true
# Generate Info.plist
cat > "$CONTENTS/Info.plist"
CFBundleExecutable
$APP_NAME
CFBundleIdentifier
$BUNDLE_ID
CFBundleName
$APP_NAME
CFBundleVersion
$BUILD_NUMBER
CFBundleShortVersionString
$VERSION
LSMinimumSystemVersion
$MIN_MACOS
CFBundlePackageType
APPL
$([ "$MENU_BAR_APP" = "1" ] && echo " LSUIElement
")
EOF
echo "Created $APP_BUNDLE"
Development Run Script
Create Scripts/compile_and_run.sh:
#!/bin/bash
set -e
source version.env
# Kill existing instance
pkill -x "$APP_NAME" 2>/dev/null || true
# Package
./Scripts/package_app.sh
# Launch
open ".build/release/$APP_NAME.app"
Code Signing
Development Signing
# Sign for local development
codesign --force --sign - ".build/release/MyApp.app"
# Or with a specific identity
codesign --force --sign "Developer ID Application: Your Name" ".build/release/MyApp.app"
Create Stable Dev Identity
# Generate self-signed certificate for consistent dev signing
security create-keychain -p "" dev-signing.keychain
security default-keychain -s dev-signing.keychain
# Follow prompts in Keychain Access to create certificate
Notarization and Release
One-time setup. Notarization needs the full Xcode.app, not the lightweight Command Line Tools package — CLT omits notarytool/stapler. Store credentials once so scripts never carry a plaintext password:
xcrun notarytool store-credentials "AC_PASSWORD" \
--apple-id "your@email.com" \
--team-id "TEAM_ID"
# Prompts interactively for an app-specific password (appleid.apple.com,
# Sign-In and Security -> App-Specific Passwords). Stored in the login
# keychain under the given profile name; `--keychain-profile "AC_PASSWORD"`
# below reads it back. Regenerate if the Apple ID password ever changes --
# app-specific passwords go stale silently, with no warning at submit time.
Create Scripts/sign-and-notarize.sh:
#!/bin/bash
set -e
source version.env
APP_PATH=".build/release/$APP_NAME.app"
ZIP_PATH=".build/release/$APP_NAME-$VERSION.zip"
# Sign with Developer ID
codesign --force --options runtime --sign "Developer ID Application: Your Name" "$APP_PATH"
# Create zip for notarization
ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"
# Submit for notarization (--keychain-profile reads the credentials stored
# above by `store-credentials` -- notarytool does not take a literal
# --password value or the altool-style "@keychain:" reference syntax)
xcrun notarytool submit "$ZIP_PATH" \
--keychain-profile "AC_PASSWORD" \
--wait
# Staple the ticket
xcrun stapler staple "$APP_PATH"
# Re-zip with stapled ticket
rm "$ZIP_PATH"
ditto -c -k --keepParent "$APP_PATH" "$ZIP_PATH"
echo "Release ready: $ZIP_PATH"
Verify the release
Run all three before shipping — each catches a different failure mode (wrong signing identity, Gatekeeper rejection, missing/unstapled ticket):
codesign -dv --verbose=4 "$APP_PATH" # confirms who signed it and with what identity
spctl -a -vvv -t exec "$APP_PATH" # confirms Gatekeeper will actually accept it
xcrun stapler validate "$APP_PATH" # confirms the notarization ticket is attached
Sparkle Updates (Optional)
Generate Appcast Entry
#!/bin/bash
source version.env
ZIP_PATH=".build/release/$APP_NAME-$VERSION.zip"
SIZE=$(stat -f%z "$ZIP_PATH")
SIGNATURE=$(./bin/sign_update "$ZIP_PATH")
DATE=$(date -R)
cat
Version $VERSION
$DATE
$BUILD_NUMBER
$VERSION
EOF
GitHub Release
# Create tag
git tag -a "v$VERSION" -m "Release $VERSION"
git push origin "v$VERSION"
# Create GitHub release
gh release create "v$VERSION" \
".build/release/$APP_NAME-$VERSION.zip" \
--title "v$VERSION" \
--notes "Release notes here"
Checklist
Scaffolding
- [ ] Package.swift with correct targets and resources
- [ ] version.env with app metadata
- [ ] Info.plist template or generation script
- [ ] Basic app entry point (@main App)
Build
- [ ]
swift buildsucceeds - [ ]
swift testpasses - [ ] Resources copied correctly
Packaging
- [ ] .app bundle structure correct
- [ ] Info.plist generated with correct values
- [ ] App launches from Finder
Release
- [ ] Code signed with Developer ID
- [ ] Notarized and stapled
- [ ] Verified with
codesign -dv,spctl -a -vvv -t exec, andstapler validate - [ ] Zip created for distribution
- [ ] (Optional) Sparkle appcast updated
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: patrickserrano
- Source: patrickserrano/lacquer
- License: MIT
- Homepage: https://patrickserrano.github.io/lacquer/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.