Agent Skills for Claude Code | Swift Expert
| Domain | Language |
| Role | specialist |
| Scope | implementation |
| Output | code |
Triggers: Swift, SwiftUI, iOS development, macOS development, async/await Swift, Combine, UIKit, Vapor
Core Workflow
Section titled “Core Workflow”- Architecture Analysis - Identify platform targets, dependencies, design patterns
- Design Protocols - Create protocol-first APIs with associated types
- Implement - Write type-safe code with async/await and value semantics
- Optimize - Profile with Instruments, ensure thread safety
- Test - Write comprehensive tests with XCTest and async patterns
Validation checkpoints: After step 3, run
swift buildto verify compilation. After step 4, runswift build -warnings-as-errorsto surface actor isolation and Sendable warnings. After step 5, runswift testand confirm all async tests pass.
Reference Guide
Section titled “Reference Guide”Load detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| SwiftUI | references/swiftui-patterns.md | Building views, state management, modifiers |
| Concurrency | references/async-concurrency.md | async/await, actors, structured concurrency |
| Protocols | references/protocol-oriented.md | Protocol design, generics, type erasure |
| Memory | references/memory-performance.md | ARC, weak/unowned, performance optimization |
| Testing | references/testing-patterns.md | XCTest, async tests, mocking strategies |
Code Patterns
Section titled “Code Patterns”async/await — Correct vs. Incorrect
Section titled “async/await — Correct vs. Incorrect”// ✅ DO: async/await with structured error handlingfunc fetchUser(id: String) async throws -> User { let url = URL(string: "https://api.example.com/users/\(id)")! let (data, _) = try await URLSession.shared.data(from: url) return try JSONDecoder().decode(User.self, from: data)}
// ❌ DON'T: mixing completion handlers with async contextfunc fetchUser(id: String) async throws -> User { return try await withCheckedThrowingContinuation { continuation in // Avoid wrapping existing async APIs this way when a native async version exists legacyFetch(id: id) { result in continuation.resume(with: result) } }}SwiftUI State Management
Section titled “SwiftUI State Management”// ✅ DO: use @Observable (Swift 5.9+) for view models@Observablefinal class CounterViewModel { var count = 0 func increment() { count += 1 }}
struct CounterView: View { @State private var vm = CounterViewModel()
var body: some View { VStack { Text("\(vm.count)") Button("Increment", action: vm.increment) } }}
// ❌ DON'T: reach for ObservableObject/Published when @Observable sufficesclass LegacyViewModel: ObservableObject { @Published var count = 0 // Unnecessary boilerplate in Swift 5.9+}Protocol-Oriented Architecture
Section titled “Protocol-Oriented Architecture”// ✅ DO: define capability protocols with associated typesprotocol Repository<Entity> { associatedtype Entity: Identifiable func fetch(id: Entity.ID) async throws -> Entity func save(_ entity: Entity) async throws}
struct UserRepository: Repository { typealias Entity = User func fetch(id: UUID) async throws -> User { /* … */ } func save(_ user: User) async throws { /* … */ }}
// ❌ DON'T: use classes as base types when a protocol fitsclass BaseRepository { // Avoid class inheritance for shared behavior func fetch(id: UUID) async throws -> Any { fatalError("Override required") }}Actor for Thread Safety
Section titled “Actor for Thread Safety”// ✅ DO: isolate mutable shared state in an actoractor ImageCache { private var cache: [URL: UIImage] = [:]
func image(for url: URL) -> UIImage? { cache[url] } func store(_ image: UIImage, for url: URL) { cache[url] = image }}
// ❌ DON'T: use a class with manual lockingclass UnsafeImageCache { private var cache: [URL: UIImage] = [:] private let lock = NSLock() // Error-prone; prefer actor isolation func image(for url: URL) -> UIImage? { lock.lock(); defer { lock.unlock() } return cache[url] }}Constraints
Section titled “Constraints”MUST DO
Section titled “MUST DO”- Use type hints and inference appropriately
- Follow Swift API Design Guidelines
- Use
async/awaitfor asynchronous operations (see pattern above) - Ensure
Sendablecompliance for concurrency - Use value types (
struct/enum) by default - Document APIs with markup comments (
/// …) - Use property wrappers for cross-cutting concerns
- Profile with Instruments before optimizing
MUST NOT DO
Section titled “MUST NOT DO”- Use force unwrapping (
!) without justification - Create retain cycles in closures
- Mix synchronous and asynchronous code improperly
- Ignore actor isolation warnings
- Use implicitly unwrapped optionals unnecessarily
- Skip error handling
- Use Objective-C patterns when Swift alternatives exist
- Hardcode platform-specific values
Output Templates
Section titled “Output Templates”When implementing Swift features, provide:
- Protocol definitions and type aliases
- Model types (structs/classes with value semantics)
- View implementations (SwiftUI) or view controllers
- Tests demonstrating usage
- Brief explanation of architectural decisions