This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
quickpkg is a macOS command-line tool that builds installer packages (.pkg files) from applications. It wraps Apple's pkgbuild and productbuild tools and automatically extracts app metadata (name, version, identifier, minimum OS version) to create properly named packages.
Two implementations exist:
- Swift (
Sources/quickpkg/) - Primary implementation (macOS 15+, Swift 6.0) using swift-argument-parser and swift-subprocess - Python (
quickpkg) - Original implementation using MacAdmins Managed Python
# Build and run (use Numbers.app for testing)
swift build
.build/debug/quickpkg /Applications/Numbers.app
# Release build
swift build -c release
# Test with verbosity (-v, -vv, or -vvv)
.build/debug/quickpkg -vvv /Applications/Numbers.app
# Test scripts option
.build/debug/quickpkg /Applications/Numbers.app --scripts testscripts/
# Build distribution package (default)
.build/debug/quickpkg /Applications/Numbers.app
# Build component package
.build/debug/quickpkg /Applications/Numbers.app --componentThe Swift implementation in Sources/quickpkg/ follows this flow:
QuickPkg.swift- Entry point usingAsyncParsableCommand, parses CLI argsInputType.swift- Detects input type from file extension (app, dmg, zip, xip); also definesOwnership,Compression, andPackageTypeenums- For archives:
DMGManager.swift- Actor for mounting/unmounting DMGs viahdiutilArchiveExtractor.swift- Handles zip/xip extraction (Sendable)
AppMetadata.swift- Extracts name/version/identifier/minimumSystemVersion using Bundle APIPackageBuilder.swift- Runspkgbuild --analyze, removes quarantine attributes, thenpkgbuild(andproductbuildfor distribution packages)PlistHandler.swift- Modifies component plist for non-relocatable packages (Sendable)
Supporting modules:
ShellExecutor.swift- Async subprocess execution wrapper using StringOutput (Sendable)TempDirectory.swift- Manages temp directories with cleanupLogger.swift- Verbosity-aware logging (levels 1-3)QuickPkgError.swift- Error types with LocalizedError conformanceURLExtension.swift- URL extension withfileExistsproperty
- Distribution packages by default - Uses
productbuildto wrap the component package (use--componentfor component-only) - Non-relocatable by default - Installer won't search for moved apps (use
--relocatableto change) - Automatic min-os-version - Extracts
LSMinimumSystemVersionfrom app bundle and passes to pkgbuild - Quarantine removal - Removes
com.apple.quarantinexattr from payload before packaging - Output naming:
{name}-{version}.pkgwith placeholders{name},{version},{identifier} - DMGManager is an actor to safely manage mount/unmount lifecycle
- All shell commands go through ShellExecutor which logs at verbosity level 3
- Types marked
Sendablefor Swift 6 concurrency safety:ShellExecutor,PackageBuilder,PlistHandler,ArchiveExtractor,Logger
Key options beyond the Python version:
--compression <latest|legacy>- Compression type for pkgbuild--component/--distribution- Package type (distribution is default)--min-os-versionis automatically extracted from the app's Info.plist
pkgAndNotarize.sh- Build, sign, package, notarize, and staple workflow for creating signed releases
- Use
URL(filePath:)not the deprecatedURL(fileURLWithPath:) - Use
url.fileExistsextension instead ofFileManager.default.fileExists(atPath:) - Use
BundleAPI for reading app metadata (seeAppMetadata.swift) - Use
ArgumentHelp(abstract:discussion:)for multi-line help text - Use
EnumerableFlagfor mutually exclusive flags like--component/--distribution