bundled-skills/super-code/swift/SKILL.md
Language-specific super-code guidelines for swift.
npx skillsauth add FrancoStino/opencode-skills-antigravity swiftInstall 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.
// ❌ Force unwrap
let name = user.name!
// ✅ — guard or if-let
guard let name = user.name else { return }
// ❌ Nested if-let pyramid
if let user = fetchUser() {
if let address = user.address {
if let city = address.city {
display(city)
}
}
}
// ✅ — chained optional binding
if let city = fetchUser()?.address?.city {
display(city)
}
// or guard-let for early exit
guard let city = fetchUser()?.address?.city else { return }
display(city)
// ❌ Ternary for default
let name = user.name != nil ? user.name! : "Unknown"
// ✅
let name = user.name ?? "Unknown"
// ❌ Optional map when if-let is clearer for side effects
user.name.map { display($0) }
// ✅ — map for transforms, if-let for side effects
let upper = user.name.map { $0.uppercased() }
if let name = user.name { display(name) }
// ❌ Imperative filter + map
var result: [String] = []
for item in items {
if item.isActive { result.append(item.name.uppercased()) }
}
// ✅
let result = items
.filter(\.isActive)
.map { $0.name.uppercased() }
// ❌ Manual dictionary construction
var dict: [String: User] = [:]
for user in users { dict[user.id] = user }
// ✅
let dict = Dictionary(uniqueKeysWithValues: users.map { ($0.id, $0) })
// or with possible duplicates:
let dict = Dictionary(grouping: users, by: \.department)
// ❌ Checking isEmpty then accessing first
if !items.isEmpty { process(items[0]) }
// ✅
if let first = items.first { process(first) }
// ❌ Index-based loop
for i in 0..<items.count { process(items[i]) }
// ✅
for item in items { process(item) }
// with index:
for (i, item) in items.enumerated() { process(i, item) }
Use key paths (\.isActive) as closure shorthand where supported.
// ❌ Class for plain data (reference semantics where value semantics suffice)
class Point {
var x: Double
var y: Double
init(x: Double, y: Double) { self.x = x; self.y = y }
}
// ✅
struct Point { var x, y: Double }
// ❌ Large struct copied repeatedly (performance hit)
struct HugeData { var buffer: [UInt8] /* thousands of elements */ }
func process(_ data: HugeData) { ... } // copies entire buffer
// ✅ — use class or pass inout for mutation
func process(_ data: inout HugeData) { ... }
// or use copy-on-write wrapper for large value types
Default to struct. Use class when you need identity, inheritance, or reference semantics.
// ❌ Using optionals to mask errors
func parse(_ input: String) -> Data? { ... } // caller doesn't know why it failed
// ✅
func parse(_ input: String) throws -> Data { ... }
// ❌ try! in production code
let data = try! JSONDecoder().decode(User.self, from: jsonData)
// ✅
do {
let data = try JSONDecoder().decode(User.self, from: jsonData)
} catch {
logger.error("decode failed: \(error)")
throw AppError.decodingFailed(underlying: error)
}
// ❌ Generic Error type
enum AppError: Error { case generic(String) }
// ✅ — specific, actionable error cases
enum AppError: Error {
case networkUnreachable
case invalidInput(field: String, reason: String)
case unauthorized
}
// ❌ Catching all errors and ignoring
do { try riskyOperation() } catch { }
// ✅
do {
try riskyOperation()
} catch let error as NetworkError {
handleNetworkError(error)
} catch {
throw error // rethrow unknown
}
// ❌ Callback-based async (pyramid of doom)
fetchUser { user in
fetchPosts(for: user) { posts in
fetchComments(for: posts.first!) { comments in
display(comments)
}
}
}
// ✅ (Swift 5.5+)
let user = try await fetchUser()
let posts = try await fetchPosts(for: user)
let comments = try await fetchComments(for: posts[0])
display(comments)
// ❌ Sequential awaits for independent work
let a = try await fetchA()
let b = try await fetchB()
// ✅
async let a = fetchA()
async let b = fetchB()
let (resultA, resultB) = try await (a, b)
// ❌ DispatchQueue.main.async for UI updates in async context
DispatchQueue.main.async { label.text = result }
// ✅
await MainActor.run { label.text = result }
// or mark the function/class @MainActor
Use actor for mutable shared state instead of manual locks/queues.
// ❌ Deep class inheritance hierarchy
class Animal { ... }
class Dog: Animal { ... }
class GuideDog: Dog { ... }
// ✅ — protocols + composition
protocol Animal { var name: String { get } }
protocol Trainable { func train() }
struct Dog: Animal, Trainable { ... }
// ❌ Protocol with default implementations for everything
protocol Renderable {
func render()
}
extension Renderable {
func render() { /* default */ }
}
// Every conformer uses default — protocol serves no purpose
// ✅ — only default implementations that provide genuine shared logic
// ❌ Associated type when generic parameter suffices
protocol Container {
associatedtype Element
func get() -> Element
}
// ✅ — use `some` or generic parameter for simple cases
func process(_ item: some Equatable) { ... }
| Anti-pattern | Preferred |
|---|---|
| Force unwrap ! in production code | guard let / if let / ?? |
| try! outside tests | do/catch |
| class for plain data | struct |
| Deep inheritance hierarchies | protocol composition |
| @objc when pure Swift works | native Swift types |
| NSArray / NSDictionary | Array / Dictionary |
| DispatchQueue in async/await code | actor / MainActor |
| Implicitly unwrapped optionals as fields | regular optionals or non-optional with init |
| Any / AnyObject everywhere | generics with protocol constraints |
| Massive switch over string values | enum with raw values |
| Singleton pattern (global mutable state) | dependency injection |
tools
Authorized security assessment of LLM applications and AI agents: prompt injection, tool abuse, RAG exposure, memory poisoning, system-prompt extraction, and agent-compliance engineering per OWASP LLM/ASI Top 10.
development
Builds two parameterized UI modes—流光溢彩白 (iridescent white) and 五彩斑斓黑 (colorful black)—with OKLCH, WebGL/CSS fallback, vision gating, screenshot QA, and total/per-color intensity reports. Use when a UI request names either mode or needs measured color parameters.
tools
Delegate coding tasks to the Kimi Code CLI (`kimi`) only when the user explicitly requests it, while the orchestrator retains review and landing responsibility.
development
Front-end JavaScript reverse engineering: locate signature chains, analyze encrypted request parameters, sample runtime behavior, and reproduce logic locally in Node for evidence-based output.