registry/skills/swift-development/SKILL.md
This skill should be used when the user asks to "write Swift code", "create a Swift type", "set up a Swift package", "review Swift code", "refactor Swift", "use async/await in Swift", "fix Swift style", or when generating any Swift source code regardless of target platform. Provides modern Swift 6+ best practices covering type system, optionals, concurrency, error handling, protocols, generics, and idiomatic patterns. Does not cover any specific platform or framework.
npx skillsauth add provectus/awos-recruitment swift-developmentInstall 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.
Modern Swift best practices for writing safe, expressive, and idiomatic code. Targets Swift 6+ — language and standard library only, no platform frameworks.
Applicable to all Swift targets: Apple platforms, server-side (Vapor, Hummingbird), CLI tools, cross-platform (Linux, Windows).
references/type-system.md — Generics, protocols with associated types, opaque types (some), existentials (any), metatypes, @dynamicMemberLookup, @dynamicCallablereferences/concurrency.md — Actors, task groups, async sequences, Sendable, isolation, GCD migration, Combine interopreferences/patterns.md — Property wrappers, result builders, key paths, Codable, extensions, copy-on-write, DSL designreferences/project-structure.md — Swift Package Manager setup, multi-target packages, build configurations, plugins, testing setup@_exported unless building a module facade.private or internal. Use public only at module boundaries.| Element | Convention | Example |
|---|---|---|
| Type / Protocol | PascalCase | UserProfile, Fetchable |
| Function / Property | camelCase | fetchUser(), isActive |
| Constant (let at module scope) | camelCase | defaultTimeout |
| Enum case | camelCase | case loading, case success(Data) |
| Boolean | Prefix is, has, can, should | isValid, hasPermission |
| File name | PascalCase.swift | UserProfile.swift |
| Protocol | Adjective or -able/-ible suffix | Loadable, Configurable |
| Generic parameter | Descriptive or single uppercase | Element, T, Key, Value |
Follow the Swift API Design Guidelines:
distance(to:)), verb for mutating (sort()), -ed/-ing for non-mutating variant (sorted(), removing()).struct User { // Value type — prefer by default
let id: UUID
var name: String
}
class UserStore { // Reference type — when identity matters
private var users: [User] = []
}
Use struct by default. Use class when you need identity, inheritance, or reference semantics. Actors when you need thread-safe mutable state.
let name: String? = user?.name // safe chaining
let displayName = name ?? "Anonymous" // nil coalescing
// NEVER force-unwrap unless you have a provable invariant with a comment
guard let user = fetchUser(id) else { return } // early exit — preferred
// Optional binding
if let email = user.email {
sendConfirmation(to: email)
}
// map / flatMap
let uppercased = name.map { $0.uppercased() } // String?
let nested = fetchUser(id).flatMap { $0.address } // Address?
// Coalescing with throwing
let user = try optionalUser ?? { throw AppError.notFound }()
NEVER use ! to silence the compiler. Acceptable only with a provable invariant and a comment explaining why.
enum LoadingState<T> {
case idle
case loading
case loaded(T)
case failed(Error)
}
Prefer enums over boolean flags for state modeling. Enables exhaustive switch.
protocol Repository {
associatedtype Entity
func fetch(id: UUID) async throws -> Entity
func save(_ entity: Entity) async throws
}
extension Array where Element: Identifiable {
func element(withID id: Element.ID) -> Element? {
first { $0.id == id }
}
}
Rules:
Fetchable & Cacheable) over large monolithic protocols.For generics, opaque types, existentials, and advanced protocol patterns see references/type-system.md.
// Define domain errors
enum AppError: LocalizedError {
case networkUnavailable
case unauthorized
case notFound(resource: String)
var errorDescription: String? {
switch self {
case .networkUnavailable: "Network is unavailable"
case .unauthorized: "Authentication required"
case .notFound(let resource): "\(resource) not found"
}
}
}
// Use typed throws (Swift 6+)
func fetchUser(id: UUID) async throws(AppError) -> User { ... }
// Use Result for expected outcomes in callbacks
func validate(_ input: String) -> Result<ValidatedInput, ValidationError> { ... }
Rules:
guard for preconditions with early exit.Error broadly unless at a top-level boundary.async throws over Result for async operations.LocalizedError for user-facing error messages.// async/await
func fetchUser(id: UUID) async throws -> User {
let data = try await networkClient.get("users/\(id)")
return try decode(data)
}
// Structured concurrency — parallel execution
func loadDashboard() async throws -> Dashboard {
async let profile = fetchProfile()
async let notifications = fetchNotifications()
return Dashboard(profile: try await profile, notifications: try await notifications)
}
// Actor — thread-safe mutable state
actor Cache<Key: Hashable, Value> {
private var storage: [Key: Value] = [:]
func get(_ key: Key) -> Value? { storage[key] }
func set(_ key: Key, value: Value) { storage[key] = value }
}
Rules:
async let, TaskGroup. Avoid Task.detached unless truly needed.Task or actors.Sendable.Task.isCancelled or try Task.checkCancellation() to respond to cancellation.nonisolated explicitly when actor methods don't need isolation.For actors, task groups, async sequences, Sendable patterns, GCD migration, and Combine interop see references/concurrency.md.
// Prefer higher-order functions over manual loops
let activeUsers = users.filter { $0.isActive }
let names = users.map(\.name)
let totalAge = users.reduce(0) { $0 + $1.age }
// Lazy for large collections
let firstMatch = users.lazy.filter { $0.isActive }.first
// Dictionary grouping
let byDepartment = Dictionary(grouping: employees, by: \.department)
// Trailing closure syntax
let sorted = users.sorted { $0.name < $1.name }
// Multi-line closures — use named parameters
let transformed = items.map { item in
Item(
id: item.id,
name: item.name.uppercased()
)
}
// @escaping — when closure outlives the function
func fetch(completion: @escaping (Result<User, Error>) -> Void) { ... }
// @Sendable — when closure crosses concurrency boundaries
func execute(_ work: @Sendable () async -> Void) { ... }
Rules:
$0, $1 only for short, single-expression closures.async functions over completion handler closures in new code.MyPackage/
├── Package.swift
├── Sources/
│ ├── MyLibrary/
│ │ ├── Models/
│ │ ├── Services/
│ │ └── Extensions/
│ └── MyExecutable/
│ └── main.swift
├── Tests/
│ └── MyLibraryTests/
└── Plugins/
Rules:
For SPM setup, multi-target packages, build configurations, plugins, and testing see references/project-structure.md.
test_methodName_whenCondition_expectedResult.protocol UserRepository {
func fetch(id: UUID) async throws -> User
}
// Production
struct RemoteUserRepository: UserRepository {
let client: HTTPClient
func fetch(id: UUID) async throws -> User { ... }
}
// Test
struct FakeUserRepository: UserRepository {
var stubbedUser: User?
func fetch(id: UUID) async throws -> User {
guard let user = stubbedUser else { throw AppError.notFound(resource: "User") }
return user
}
}
import Testing
@Test("Fetches user by ID")
func fetchUser() async throws {
let repo = FakeUserRepository(stubbedUser: User(id: testID, name: "Alice"))
let user = try await repo.fetch(id: testID)
#expect(user.name == "Alice")
}
@Test("Throws when user not found")
func fetchUserNotFound() async {
let repo = FakeUserRepository(stubbedUser: nil)
await #expect(throws: AppError.self) {
try await repo.fetch(id: testID)
}
}
Prefer Swift Testing (@Test, #expect) over XCTest for new code. Use XCTest when the project requires it or for UI/integration tests on Apple platforms.
| Mistake | Fix |
|---|---|
| Force-unwrapping (!) without invariant | Use guard let, if let, ??, or optional chaining |
| Catching Error broadly | Catch specific error types at appropriate boundaries |
| Task { } without cancellation handling | Check Task.isCancelled or use Task.checkCancellation() |
| Using GCD (DispatchQueue) in new code | Use Swift Concurrency (async/await, actors) |
| Mutable var in struct properties without need | Default to let; use var only when mutation is required |
| Large protocols (>5 requirements) | Break into focused protocols; use composition |
| Ignoring Sendable warnings | Conform value types or use actor isolation |
| Completion handlers in new code | Use async/await; wrap legacy APIs with withCheckedContinuation |
| Stringly-typed APIs | Use enums, phantom types, or value types for type safety |
| Any / AnyObject without reason | Use generics or existentials with constraints |
| Double for money | Use Decimal with explicit rounding |
| Hard-coded dependencies | Protocol-based DI via init injection |
development
Insurance underwriting domain knowledge for building automated submission processing systems. Covers submission-to-bind lifecycle, document extraction patterns, compliance gates (sanctions, licensing, clearance), human-in-the-loop design for regulated financial services, confidence calibration for extracted fields, operating mode progression (manual to automated), and evidence traceability requirements. Use when designing or implementing underwriting pipelines, extraction agents, compliance workflows, HITL review systems, or decision package assembly for insurance or MGA operations.
development
This skill should be used when the user asks to "write TypeScript code", "create a TypeScript module", "define TypeScript types", "add type annotations", "use generics", "handle errors in TypeScript", "set up tsconfig", "organize TypeScript project", or when writing any TypeScript code that is not tied to a specific library or framework. Covers type system, strict mode, naming conventions, error handling, async patterns, and project structure.
development
Use when working with Terraform or OpenTofu - creating modules, writing tests (native test framework, Terratest), setting up CI/CD pipelines, reviewing configurations, choosing between testing approaches, debugging state issues, implementing security scanning (trivy, checkov), or making infrastructure-as-code architecture decisions. Enforces Provectus opinionated conventions (exact version pinning, etc.) on top of community best practices.
development
Enforces Feature-Sliced Design (FSD) architecture in React/TypeScript projects by scaffolding compliant folder structures, validating layer boundaries and import directions, detecting and fixing layer violations, and teaching FSD conventions during code generation and review. Use when asked to 'create a page', 'add an entity', 'build a widget', 'scaffold FSD structure', 'refactor to FSD', 'where should I put this code', 'what layer does X go in', 'organize my React code', 'fix layer violation', or 'review my FSD structure'. Triggers on any React/TypeScript task involving FSD layers, slices, segments, cross-layer imports, or public API boundaries.