internal/skills/content/swift-guide/SKILL.md
Swift language guardrails, patterns, and best practices for AI-assisted development. Use when working with Swift files (.swift), Package.swift, or when the user mentions Swift. Provides optionals handling, protocol-oriented patterns, concurrency with async/await, and testing standards specific to this project's coding standards.
npx skillsauth add ar4mirez/samuel swift-guideInstall 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.
Applies to: Swift 5.9+, iOS/macOS/Server-Side, SPM, Concurrency
guard let or if let; force-unwrap (!) is forbidden outside tests.upToNextMinor(from:) for librariesswift package resolve before committing after dependency changesPackage.resolved for applications; omit for librariesswift format or SwiftLint before every commitPascalCase for types, protocols, enums | camelCase for functions, properties, variablesSelf instead of repeating the type name inside type definitionsfinal by default; remove final only when subclassing is designed forguard let for early exit when the unwrapped value is needed afterwardif let for scoped unwrapping within a branch??) for default values; optional chaining (?.) to traverse!) outside of tests and IBOutlet declarationscompactMap to filter nil from collections; Optional.map/.flatMap to transformasync/await for all asynchronous operations (no completion handlers in new code)TaskGroup / ThrowingTaskGroup for parallel fan-out@MainActor; avoid DispatchQueue.main in new codeactor for mutable shared state; prefer actors over locksSendable-strict-concurrency=completeTask.isCancelled or Task.checkCancellation() in long-running workSomeProtocol & AnotherProtocol) for flexible constraintssome Protocol (opaque types) over any Protocol when the concrete type is fixedMyProject/
├── Package.swift # Manifest (targets, dependencies, platforms)
├── Package.resolved # Locked versions (commit for apps)
├── Sources/
│ ├── MyProject/ # Main library target
│ │ ├── Models/
│ │ ├── Services/
│ │ ├── Protocols/
│ │ └── Extensions/ # TypeName+Capability.swift
│ └── MyProjectCLI/ # Executable target (thin entry point)
│ └── main.swift
├── Tests/
│ └── MyProjectTests/
└── README.md
main.swift or @main struct should be thin: parse arguments, build dependencies, call library codefunc processUser(id: String?) -> User {
guard let id, !id.isEmpty else {
return User.anonymous
}
guard let user = userCache[id] else {
return fetchUser(id: id)
}
return user
}
func displayName(for user: User) -> String {
if let nickname = user.nickname { return nickname }
return "\(user.firstName) \(user.lastName)"
}
enum NetworkError: Error, Sendable {
case invalidURL(String)
case serverError(statusCode: Int)
case decodingFailed(underlying: Error)
}
func fetchData(from urlString: String) async -> Result<Data, NetworkError> {
guard let url = URL(string: urlString) else { return .failure(.invalidURL(urlString)) }
do {
let (data, response) = try await URLSession.shared.data(from: url)
guard let http = response as? HTTPURLResponse, (200..<300).contains(http.statusCode) else {
return .failure(.serverError(statusCode: 0))
}
return .success(data)
} catch {
return .failure(.decodingFailed(underlying: error))
}
}
protocol Timestamped {
var createdAt: Date { get }
var updatedAt: Date { get }
}
extension Timestamped {
var isRecent: Bool { updatedAt.timeIntervalSinceNow > -86_400 }
}
// Protocol composition for flexible constraints
func findRecent<T: Identifiable & Timestamped>(_ items: [T]) -> [T] {
items.filter(\.isRecent)
}
actor CacheStore<Key: Hashable & Sendable, Value: Sendable> {
private var storage: [Key: Value] = [:]
private let maxSize: Int
init(maxSize: Int = 1000) { self.maxSize = maxSize }
func get(_ key: Key) -> Value? { storage[key] }
func set(_ key: Key, value: Value) {
if storage.count >= maxSize { storage.removeAll() }
storage[key] = value
}
}
func fetchAllUsers(ids: [String]) async throws -> [User] {
try await withThrowingTaskGroup(of: User.self) { group in
for id in ids {
group.addTask { try await self.fetchUser(id: id) }
}
var users: [User] = []
for try await user in group { users.append(user) }
return users
}
}
// Value types: implicitly Sendable when all stored properties are Sendable
struct UserDTO: Sendable { let id: String; let name: String }
// Classes: must be final with immutable properties, or use @unchecked with a lock
final class AppConfig: Sendable { let apiBaseURL: URL; let maxRetries: Int
init(apiBaseURL: URL, maxRetries: Int = 3) { self.apiBaseURL = apiBaseURL; self.maxRetries = maxRetries }
}
@propertyWrapper
struct Clamped<Value: Comparable> {
private var value: Value
private let range: ClosedRange<Value>
var wrappedValue: Value {
get { value }
set { value = min(max(newValue, range.lowerBound), range.upperBound) }
}
init(wrappedValue: Value, _ range: ClosedRange<Value>) {
self.range = range
self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
}
struct AudioSettings {
@Clamped(0...100) var volume: Int = 50
@Clamped(0.5...2.0) var playbackSpeed: Double = 1.0
}
@resultBuilder
struct ArrayBuilder<Element> {
static func buildBlock(_ components: [Element]...) -> [Element] { components.flatMap { $0 } }
static func buildExpression(_ expression: Element) -> [Element] { [expression] }
static func buildOptional(_ component: [Element]?) -> [Element] { component ?? [] }
static func buildEither(first c: [Element]) -> [Element] { c }
static func buildEither(second c: [Element]) -> [Element] { c }
}
import XCTest
@testable import MyProject
final class UserServiceTests: XCTestCase {
private var sut: UserService!
private var mockRepo: MockUserRepository!
override func setUp() { super.setUp(); mockRepo = MockUserRepository(); sut = UserService(repository: mockRepo) }
override func tearDown() { sut = nil; mockRepo = nil; super.tearDown() }
func test_fetchUser_withValidID_returnsUser() async throws {
mockRepo.stubbedUser = User(id: "1", name: "Alice")
let user = try await sut.fetchUser(id: "1")
XCTAssertEqual(user.name, "Alice")
}
func test_fetchUser_withInvalidID_throwsNotFound() async {
mockRepo.stubbedError = .notFound
do {
_ = try await sut.fetchUser(id: "invalid")
XCTFail("Expected notFound error")
} catch let error as ServiceError {
XCTAssertEqual(error, .notFound)
} catch {
XCTFail("Unexpected error: \(error)")
}
}
}
func test_login_withExpiredToken_refreshesAutomatically()setUp() / tearDown() for shared test fixturesasync throws directly (no XCTestExpectation for async/await code)swift build # Build all targets
swift test # Run all tests
swift test --enable-code-coverage # With coverage
swift package resolve # Resolve dependencies
swift package update # Update dependencies
swift format . # Format (swift-format)
swiftlint # Lint (SwiftLint)
swiftlint --fix # Auto-fix lint issues
# .swiftlint.yml -- enforce these as errors
force_cast: error
force_unwrapping: error
force_try: error
function_body_length:
warning: 40
error: 50
cyclomatic_complexity:
warning: 8
error: 10
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "MyProject",
platforms: [.macOS(.v14), .iOS(.v17)],
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.0"),
.package(url: "https://github.com/apple/swift-log", from: "1.5.0"),
],
targets: [
.target(name: "MyProject", dependencies: [
.product(name: "Logging", package: "swift-log"),
], swiftSettings: [
.enableExperimentalFeature("StrictConcurrency"),
]),
.testTarget(name: "MyProjectTests", dependencies: ["MyProject"]),
]
)
For detailed patterns and examples, see:
development
Zig language guardrails, patterns, and best practices for AI-assisted development. Use when working with Zig files (.zig), build.zig, or when the user mentions Zig. Provides comptime patterns, allocator conventions, C interop guidelines, and testing standards specific to this project's coding standards.
tools
WordPress framework guardrails, patterns, and best practices for AI-assisted development. Use when working with WordPress projects, or when the user mentions WordPress. Provides theme development, plugin architecture, REST API, blocks, and security guidelines.
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs. Use when testing web apps, automating browser interactions, or debugging frontend issues.
tools
Suite of tools for creating elaborate, multi-component web applications using modern frontend technologies (React, Tailwind CSS, shadcn/ui). Use for complex projects requiring state management, routing, or shadcn/ui components - not for simple single-file HTML/JSX pages.