swift-package-manifest/SKILL.md
Clean, maintainable Package.swift creation and editing using the static property pattern from Facebook iOS SDK. Use when creating new Package.swift files, refactoring existing ones, adding modules/targets to Swift packages, or organizing Swift Package Manager manifests for better maintainability.
npx skillsauth add igor1309/skills swift-package-manifestInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create and edit Package.swift files using the clean static property pattern that eliminates magic strings and improves maintainability.
Announce: "I'm using the Swift Package Manifest skill to apply the static property pattern."
Transform verbose, string-heavy Package.swift files into clean, type-safe manifests using extensions with static properties.
Place the main Package declaration at the top, using static properties:
// swift-tools-version: 6.1
@preconcurrency import PackageDescription
let package = Package(
name: "package-name",
platforms: [.iOS(.v15)],
products: [.core],
dependencies: [.externalDep],
targets: [.core, .tests]
)
Follow this extension order (use // MARK: - comments):
To add a new module like ThisFeature:
// Add to Products
private extension Product {
static let thisFeature = library(name: .thisFeature, targets: [.thisFeature])
}
// Add to Targets
private extension Target {
static let thisFeature = target(name: .thisFeature, dependencies: [.core])
}
// Add to Target.Dependency (if needed by other targets)
private extension Target.Dependency {
static let thisFeature = byName(name: .thisFeature)
}
// Add to String Constants
private extension String {
static let thisFeature = "ThisFeature"
}
// Update main declaration
products: [.core, .thisFeature]
targets: [.core, .thisFeature, .tests]
privatedependencies: [] if empty@preconcurrency import PackageDescriptionbyName() for internal targetsproduct() for external packagesPackage.Dependency circular referenceInside private extension Package.Dependency, calling package(url:from:) causes a circular reference compiler error because Swift resolves package as the global let package = Package(...) variable rather than the static factory method.
Fix: use fully-qualified Package.Dependency.package(url:from:):
// ❌ Circular reference — `package` resolves to the global `let package`
private extension Package.Dependency {
static let alamofire = package(url: "https://...", from: "5.8.0")
}
// ✅ Correct — explicit type qualification forces static method resolution
private extension Package.Dependency {
static let alamofire = Package.Dependency.package(url: "https://...", from: "5.8.0")
}
This applies to all Package.Dependency factory variants: package(url:from:), package(url:exact:), package(path:), etc.
See assets/single-product-template.swift for a complete example.
See assets/multi-module-template.swift for organizing multiple targets.
For 10+ targets, use array grouping:
let package = Package(
name: "my-app",
products: .core + .features,
targets: .core + .features + .tests
)
private extension Array where Element == Product {
static let core: Self = [.domain, .shared]
static let features: Self = [.auth, .payments]
}
// In Package dependencies
dependencies: [.alamofire, .swiftLint]
// In Target dependencies
dependencies: [.alamofire]
// Define in extensions
private extension Target.Dependency {
static let alamofire = product(name: "Alamofire", package: "Alamofire")
}
private extension Package.Dependency {
static let alamofire = package(
url: "https://github.com/Alamofire/Alamofire.git",
from: "5.8.0"
)
}
Group test targets under a nested enum:
private extension Target {
enum Tests {
static let core = testTarget(name: .Tests.core, dependencies: [.core])
static let feature = testTarget(name: .Tests.feature, dependencies: [.thisFeature])
}
}
private extension String {
enum Tests {
static let core = "CoreTests"
static let feature = "ThisFeatureTests"
}
}
For complete pattern documentation and advanced techniques, see references/pattern-details.md.
testing
Evaluates test name scaffolds for TDD readiness by determining if each test name provides enough specification clarity to write a failing test. Use when reviewing test scaffolds, evaluating executable specifications, or assessing whether test names clearly define testable behavior without implementation ambiguity.
development
Interactive Test-Driven Development workflow with reviewer-in-the-loop. Implements the RED-GREEN-REFACTOR cycle with two mandatory verification gates where a reviewer (human or AI) approves work before progression. Applies to any code development that follows test-first methodology: features, bug fixes, refactoring, or enhancements. Invoked when TDD discipline with step-by-step verification is required.
development
Use when the user needs a concise description of a component, module, product, or entire codebase for someone with zero project context. Triggers on "synopsis", "describe this for outsiders", "write a description", "explain what this does", "elevator pitch", or when producing text for READMEs, marketplace listings, or onboarding docs.
development
Review and improve existing Claude Code skills. Use when evaluating skill quality, auditing skill collections, asking "review my skill", "is this skill effective", "improve skill description", or maintaining a skill library.