swift-concurrency-pro
Reviews Swift code for concurrency correctness, modern API usage, and common async/await pitfalls. Use when reading, writing, or reviewing Swift concurrency code.
install
source · Clone the upstream repo
git clone https://github.com/twostraws/Swift-Concurrency-Agent-Skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/twostraws/Swift-Concurrency-Agent-Skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/swift-concurrency-pro" ~/.claude/skills/twostraws-swift-concurrency-agent-skill-swift-concurrency-pro && rm -rf "$T"
manifest:
swift-concurrency-pro/SKILL.mdsource content
Review Swift concurrency code for correctness, modern API usage, and adherence to project conventions. Report only genuine problems - do not nitpick or invent issues.
Review process:
- Scan for known-dangerous patterns using
to prioritize what to inspect.references/hotspots.md - Check for recent Swift 6.2 concurrency behavior using
.references/new-features.md - Validate actor usage for reentrancy and isolation correctness using
.references/actors.md - Ensure structured concurrency is preferred over unstructured where appropriate using
.references/structured.md - Check unstructured task usage for correctness using
.references/unstructured.md - Verify cancellation is handled correctly using
.references/cancellation.md - Validate async stream and continuation usage using
.references/async-streams.md - Check bridging code between sync and async worlds using
.references/bridging.md - Review any legacy concurrency migrations using
.references/interop.md - Cross-check against common failure modes using
.references/bug-patterns.md - If the project has strict-concurrency errors, map diagnostics to fixes using
.references/diagnostics.md - If reviewing tests, check async test patterns using
.references/testing.md
If doing a partial review, load only the relevant reference files.
Core Instructions
- Target Swift 6.2 or later with strict concurrency checking.
- If code spans multiple targets or packages, compare their concurrency build settings before assuming behavior should match.
- Prefer structured concurrency (task groups) over unstructured (
).Task {} - Prefer Swift concurrency over Grand Central Dispatch for new code. GCD is still acceptable in low-level code, framework interop, or performance-critical synchronous work where queues and locks are the right tool – don't flag these as errors.
- If an API offers both
/async
and closure-based variants, always preferawait
/async
.await - Do not introduce third-party concurrency frameworks without asking first.
- Do not suggest
to fix compiler errors. It silences the diagnostic without fixing the underlying race. Prefer actors, value types, or@unchecked Sendable
parameters instead. The only legitimate use is for types with internal locking that are provably thread-safe.sending
Output Format
Organize findings by file. For each issue:
- State the file and relevant line(s).
- Name the rule being violated.
- Show a brief before/after code fix.
Skip files with no issues. End with a prioritized summary of the most impactful changes to make first.
Example output:
DataLoader.swift
Line 18: Actor reentrancy – state may have changed across the
.await
// Before actor Cache { var items: [String: Data] = [:] func fetch(_ key: String) async throws -> Data { if items[key] == nil { items[key] = try await download(key) } return items[key]! } } // After actor Cache { var items: [String: Data] = [:] func fetch(_ key: String) async throws -> Data { if let existing = items[key] { return existing } let data = try await download(key) items[key] = data return data } }
Line 34: Use
instead of creating tasks in a loop.withTaskGroup
// Before for url in urls { Task { try await fetch(url) } } // After try await withThrowingTaskGroup(of: Data.self) { group in for url in urls { group.addTask { try await fetch(url) } } for try await result in group { process(result) } }
Summary
- Correctness (high): Actor reentrancy bug on line 18 may cause duplicate downloads and a force-unwrap crash.
- Structure (medium): Unstructured tasks in loop on line 34 lose cancellation propagation.
End of example.
References
- Grep targets for code review: known-dangerous patterns and what to check for each.references/hotspots.md
- Swift 6.2 changes that alter review advice: default actor isolation, isolated conformances, caller-actor async behavior,references/new-features.md
,@concurrent
, task naming, and priority escalation.Task.immediate
- Actor reentrancy, shared-state annotations, global actor inference, and isolation patterns.references/actors.md
- Task groups over loops, discarding task groups, concurrency limits.references/structured.md
- Task vs Task.detached, when Task {} is a code smell.references/unstructured.md
- Cancellation propagation, cooperative checking, broken cancellation patterns.references/cancellation.md
- AsyncStream factory, continuation lifecycle, back-pressure.references/async-streams.md
- Checked continuations, wrapping legacy APIs,references/bridging.md
.@unchecked Sendable
- Migrating from GCD,references/interop.md
/locks, completion handlers, delegates, and Combine.Mutex
- Common concurrency failure modes and their fixes.references/bug-patterns.md
- Strict-concurrency compiler errors, protocol conformance fixes, and likely remedies.references/diagnostics.md
- Async test strategy with Swift Testing, race detection, avoiding timing-based tests.references/testing.md