swift-concurrency
Resolve Swift concurrency compiler errors, adopt approachable concurrency (SE-0466), and write data-race-safe async code. Use when fixing Sendable conformance errors, actor isolation warnings, or strict concurrency diagnostics; when adopting default MainActor isolation, @concurrent, nonisolated(nonsending), or Task.immediate; when designing actor-based architectures, structured concurrency with TaskGroup, or background work offloading; or when migrating from @preconcurrency to full Swift 6 strict concurrency.
What this skill does
# Swift Concurrency
Review, fix, and write concurrent Swift code targeting Swift 6.3+. Apply actor
isolation, Sendable safety, and modern concurrency patterns with minimal
behavior changes.
## Contents
- [Triage Workflow](#triage-workflow)
- [Swift 6.2 Language Changes](#swift-62-language-changes)
- [Actor Isolation Rules](#actor-isolation-rules)
- [Sendable Rules](#sendable-rules)
- [Structured Concurrency Patterns](#structured-concurrency-patterns)
- [Task Cancellation](#task-cancellation)
- [Actor Reentrancy](#actor-reentrancy)
- [AsyncSequence and AsyncStream](#asyncsequence-and-asyncstream)
- [`@Observable and Concurrency`](#observable-and-concurrency)
- [Synchronization Primitives](#synchronization-primitives)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)
- [References](#references)
## Triage Workflow
When diagnosing a concurrency issue, follow this sequence:
### Step 1: Capture context
- Copy the exact compiler diagnostic(s) and the offending symbol(s).
- Identify the project's concurrency settings:
- Swift language version (must be 6.2+).
- Whether Approachable Concurrency is enabled.
- Whether Default Actor Isolation is set to `MainActor`.
- Swift 6 strict concurrency status: complete/errors in Swift 6 language mode;
Complete / Targeted / Minimal only when auditing Swift 5 migration settings.
- Determine the current actor context of the code (`@MainActor`, custom `actor`,
`nonisolated`) and whether a default isolation mode is active.
- Confirm whether the code is UI-bound or intended to run off the main actor.
### Step 2: Apply the smallest safe fix
Prefer edits that preserve existing behavior while satisfying data-race safety.
| Situation | Recommended fix |
|---|---|
| UI-bound type | Annotate the type or relevant members with `@MainActor`. |
| Protocol conformance on MainActor type | Use an isolated conformance: `extension Foo: @MainActor Proto`. |
| Global / static state | Protect with `@MainActor` or move into an actor. |
| Background work needed | Use a `@concurrent` async function on a `nonisolated` type. |
| Sendable error | Prefer immutable value types. Add `Sendable` only when correct. |
| Cross-isolation callback | Use `sending` parameters (SE-0430) for finer control. |
### Step 3: Verify
- Rebuild and confirm the diagnostic is resolved.
- Check for new warnings introduced by the fix.
- Ensure no unnecessary `@unchecked Sendable` or `nonisolated(unsafe)` was added.
## Swift 6.2 Language Changes
Swift 6.2 introduces "approachable concurrency" -- a set of language changes
that make concurrent code safer by default while reducing annotation burden.
In Xcode, Approachable Concurrency and Default Actor Isolation are separate
build settings: use Approachable Concurrency for the bundled upcoming-feature
flags, and set Default Actor Isolation to `MainActor` when you want unannotated
code inferred as `@MainActor`.
### SE-0466: Default MainActor Isolation
With the `-default-isolation MainActor` compiler flag, SwiftPM
`.defaultIsolation(MainActor.self)`, or Xcode's `Default Actor Isolation`
setting set to `MainActor`, unannotated declarations in the module are inferred
as `@MainActor` unless explicitly opted out.
**Effect:** Eliminates most data-race safety errors for UI-bound code and
global/static state without writing `@MainActor` everywhere.
```swift
// With default MainActor isolation enabled, these are implicitly @MainActor:
final class StickerLibrary {
static let shared = StickerLibrary() // safe -- on MainActor
var stickers: [Sticker] = []
}
final class StickerModel {
let photoProcessor = PhotoProcessor()
var selection: [PhotosPickerItem] = []
}
// Conformances are also implicitly isolated:
extension StickerModel: Exportable {
func export() {
photoProcessor.exportAsPNG()
}
}
```
**When to use:** Recommended for apps, scripts, and other executable targets
where most code is UI-bound. Not recommended for library targets that should
remain actor-agnostic.
### SE-0461: nonisolated(nonsending)
Nonisolated async functions now stay on the caller's actor by default instead
of hopping to the global concurrent executor. This is the
`nonisolated(nonsending)` behavior.
```swift
class PhotoProcessor {
func extractSticker(data: Data, with id: String?) async -> Sticker? {
// In Swift 6.2+, this runs on the caller's actor (e.g., MainActor)
// instead of hopping to a background thread.
// ...
}
}
@MainActor
final class StickerModel {
let photoProcessor = PhotoProcessor()
func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? {
guard let data = try await item.loadTransferable(type: Data.self) else {
return nil
}
// No data race -- photoProcessor stays on MainActor
return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
}
}
```
Use `@concurrent` to explicitly request background execution when needed.
### `@concurrent` Attribute
`@concurrent` ensures a function always runs on the concurrent thread pool,
freeing the calling actor to run other tasks.
```swift
class PhotoProcessor {
var cachedStickers: [String: Sticker] = [:]
func extractSticker(data: Data, with id: String) async -> Sticker {
if let sticker = cachedStickers[id] { return sticker }
let sticker = await Self.extractSubject(from: data)
cachedStickers[id] = sticker
return sticker
}
@concurrent
static func extractSubject(from data: Data) async -> Sticker {
// Expensive image processing -- runs on background thread pool
// ...
}
}
```
To move a function to a background thread:
1. Ensure the containing type is `nonisolated` (or the function itself is).
2. Add `@concurrent` to the function.
3. Add `async` if not already asynchronous.
4. Add `await` at call sites.
```swift
nonisolated struct PhotoProcessor {
@concurrent
func process(data: Data) async -> ProcessedPhoto? { /* ... */ }
}
// Caller:
processedPhotos[item.id] = await PhotoProcessor().process(data: data)
```
### SE-0472: Task.immediate
`Task.immediate` starts executing synchronously on the current actor before
any suspension point, rather than being enqueued.
```swift
Task.immediate { await handleUserInput() }
```
Use for latency-sensitive work that should begin without delay. There is also
`Task.immediateDetached` which combines immediate start with detached semantics.
### SE-0475: Transactional Observation (Observations)
`Observations { }` provides async observation of `@Observable` types via
`AsyncSequence`, enabling transactional change tracking.
```swift
for await _ in Observations { model.count } {
print("Count changed to \(model.count)")
}
```
### Isolated Conformances
A conformance that needs MainActor state is called an *isolated conformance*.
The compiler ensures it is only used in a matching isolation context.
```swift
protocol Exportable {
func export()
}
// Isolated conformance: only usable on MainActor
extension StickerModel: @MainActor Exportable {
func export() {
photoProcessor.exportAsPNG()
}
}
@MainActor
struct ImageExporter {
var items: [any Exportable]
mutating func add(_ item: StickerModel) {
items.append(item) // OK -- ImageExporter is on MainActor
}
}
```
If `ImageExporter` were `nonisolated`, adding a `StickerModel` would fail:
"Main actor-isolated conformance of 'StickerModel' to 'Exportable' cannot be
used in nonisolated context."
### Clock Epochs
`ContinuousClock` and `SuspendingClock` now expose `.epoch` (SE-0473), enabling instant comparison and conversion between clock types.
```swift
let continuous = ContinuousClock()
let elapsed = continuous.now - continuous.epoch // Duration since system boot
```
## Actor Isolation Rules
1. All mutable shared state MUST be protected by an actor or global actor.
2. `@MainActor` for all UI-tRelated in Productivity
gitea-workflow
IncludedOrchestrate agile development workflows for Gitea repositories using the tea CLI. Use when working with Gitea-hosted repos and asking to 'run the workflow', 'continue working', 'what's next', 'complete the task cycle', 'start my day', 'end the sprint', 'implement the next task', or wanting guided step-by-step development assistance. Keywords: workflow, orchestrate, agile, task cycle, sprint, daily, implement, review, PR, standup, retrospective, gitea, tea.
microsoft-graph-gateway
IncludedRoute Microsoft Graph work in this workspace. Use when users want to read or write Outlook mail, calendar events, contacts, OneDrive or SharePoint files, Teams, Planner, To Do, users, groups, directory data, or arbitrary Microsoft Graph endpoints from VS Code. Prefer WorkIQ for common read scenarios. Use Microsoft Graph for write actions and gap-read scenarios that need exact Graph properties, filters, permissions, or endpoints.
copilotkit
IncludedUse when building with CopilotKit — setup, development, integrations, debugging, upgrading, or contributing. Routes to the appropriate specialized skill based on the task.
wordly-wisdom
IncludedProvides calibrated decision analysis using Charlie Munger-style multiple mental models, inversion, incentive mapping, circle-of-competence checks, misjudgment audits, second-order effects, and forecast updates. Use when the user asks for an oracle take, a hard call, a decision memo, a premortem, an outside view, a red-team, a sanity-check, what am I missing, think this through, or wants a strategy, hire, investment, plan, product, partnership, or major life choice analysed. Avoid for simple factual lookups or time-sensitive legal, medical, or market questions without fresh evidence.
swain-session
IncludedSession management and project status dashboard. Owns the full session lifecycle (start/work/close/resume), focus lane, bookmarks, worktree detection, and tab naming. Also serves as the project status dashboard — shows active epics, progress, actionable next steps, blocked items, tasks, GitHub issues, and recommendations. Worktree creation is deferred to swain-do task dispatch (SPEC-195). Triggers on: 'session', 'status', 'what's next', 'dashboard', 'overview', 'where are we', 'what should I work on', 'show me priorities', 'bookmark', 'focus on', 'session info'.
gandi
IncludedComprehensive Gandi domain registrar integration for domain and DNS management. Register and manage domains, create/update/delete DNS records (A, AAAA, CNAME, MX, TXT, SRV, and more), configure email forwarding and aliases, check SSL certificate status, create DNS snapshots for safe rollback, bulk update zone files, and monitor domain expiration. Supports multi-domain management, zone file import/export, and automated DNS backups. Includes both read-only and destructive operations with safety controls.