/swift6-fix
**Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase
$ npx -y skills add carloshpdoc/ios-workflow-claude --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/swift6-fix
Context preview
What this command does when you run it.
**Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase
Command definition
swift6-fix.mdSwift 6 Fix: $ARGUMENTS
> **Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase search for flag/font files), or ask if they cannot be inferred. This plugin ships no per-project config.
Apply Swift 6 strict concurrency fixes for the specified category.
**Valid categories:** `config`, `mainactor`, `singletons`, `dispatch-queue`, `completion-handlers`, `sendable`, `delegates`
If `$ARGUMENTS` is empty, show usage and recommend next category based on `docs/swift6-migration-status.md`.
Prerequisites
1. Read `docs/swift6-migration-status.md` to understand current progress 2. Run `/swift6-check $ARGUMENTS` mentally — verify that the category has remaining items 3. If the category shows 0 remaining, inform the user and suggest the next category
Category: `config`
Foundation changes — run this FIRST before any other category.
Steps
1. Update `Project.swift`: change `"SWIFT_VERSION": "5.3"` → `"SWIFT_VERSION": "6.0"` (all occurrences) 2. Update all `Modules/*/Package.swift`: change `swiftLanguageMode(.v5)` → `swiftLanguageMode(.v6)` 3. Add `SWIFT_STRICT_CONCURRENCY` build setting:
- If first time: set to `targeted`
- If `targeted` already done: set to `complete`
4. Lock any dependency versions still pinned to `master` / a moving branch (Swift 6 will break on unexpected upstream changes) 5. Run `tuist generate --no-open` 6. Build: `xcodebuild -scheme <scheme> -destination 'platform=iOS Simulator,name=iPhone 11,OS=latest' -quiet build` 7. If build fails, fix errors iteratively (max 10 iterations) 8. Update `docs/swift6-migration-status.md` config checklist 9. Commit with message: `[CHORE] Swift 6 migration: update Swift version and concurrency settings`
Category: `mainactor`
Add `@MainActor` to ViewModels that are `ObservableObject` subclasses.
Rules
- Add `@MainActor` annotation to the class declaration
- Do NOT change any method signatures or property types
- If a method is explicitly `nonisolated`, leave it as-is
- If a class already has `@MainActor`, skip it
- Work in batches of 20-30 files per session to keep PRs reviewable
Steps
1. Find all unannotated ViewModels:
grep -rl "class.*ViewModel.*ObservableObject" <scheme>/ --include="*.swift" | while read f; do
grep -L "@MainActor" "$f"
done2. For each file, add `@MainActor` before the class declaration:
// BEFORE
final class SomeViewModel: ObservableObject {
// AFTER
@MainActor
final class SomeViewModel: ObservableObject {3. Build after every 10 files. If errors appear:
- `@MainActor`-isolated property accessed from non-isolated context → add `@MainActor` to the caller or mark the access as `MainActor.assumeIsolated`
- Protocol conformance issues → add `@MainActor` to the protocol if it's internal
- Test files referencing the ViewModel → add `@MainActor` to the test class or use `await`
4. Run tests for affected modules 5. Update `docs/swift6-migration-status.md`:
- Increment "Done" count
- Decrement "Remaining" count
- Add entry to Execution Log
6. Format changed files with `swiftformat` 7. Commit with message: `[CHORE] Swift 6 migration: add @MainActor to ViewModels (batch N)`
Category: `singletons`
Protect mutable singletons with actor isolation or `@MainActor`.
Rules
- `static let shared` with mutable properties → add `@MainActor` to the class
- `static var shared` (mutable reference) → change to `static let shared` + add `@MainActor`
- If the singleton is accessed from background threads intentionally, wrap in an actor instead
- The session/user singleton typically gets special treatment — it's usually the most critical one
Critical Singletons (priority order)
1. Session/user managers — many mutable properties, accessed everywhere 2. Any `static var shared` (mutable reference!) — convert first 3. Analytics/tracking singletons with mutable internal state 4. Shared ViewModels exposed as `static var` 5. All remaining `static let shared` with mutable internal state
Steps
1. List all singletons:
grep -rn "static let shared\|static var shared" <scheme>/ --include="*.swift"
2. For each singleton: a. Read the file to understand thread access patterns b. If mainly UI-bound: add `@MainActor` to the class c. If accessed from background threads: convert to actor or use `nonisolated(unsafe)` as escape hatch d. Change `static var shared` → `static let shared` where possible 3. Build after every 5 changes 4. Fix cascading errors (callers may need `await` or `@MainActor`) 5. Run tests 6. Update `docs/swift6-migration-status.md` 7. Commit with message: `[CHORE] Swift 6 migration: protect singletons with actor isolation`
Category: `dispatch-queue`
Replace `DispatchQueue.main.async` with structured concurrency.
Rules
- `DispatchQueue.main.async { ... }` in a `@MainActor` context → remove the dispatch, code already runs on main
- `DispatchQueue.main.async { ... }` in a non-MainActor context → use `Task { @MainActor in ... }` or `await MainActor.run { ... }`
- `DispatchQueue.main.sync` → evaluate carefully, may indicate a design issue
- `DispatchQueue.global().async` → use `Task.detached` or `Task { ... }` with appropriate priority
- Work in batches of 30-50 replacements per session
Steps
1. Find all occurrences:
grep -rn "DispatchQueue\.main\.async" <scheme>/ --include="*.swift"
2. Group by file and context:
- In ViewModels (already `@MainActor` after mainactor phase) → remove dispatch wrapper
- In Services/Repositories → use `Task { @MainActor in ... }`
- In UIKit delegates/callbacks → use `Task { @MainActor in ... }`
3. Apply changes per file 4. Build after every 15 files 5. Run tests 6. Update `docs/swift6-migration-status.
Read more
Swift 6 Fix: $ARGUMENTS
> **Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase search for flag/font files), or ask if they cannot be inferred. This plugin ships no per-project config.
Apply Swift 6 strict concurrency fixes for the specified category.
**Valid categories:** `config`, `mainactor`, `singletons`, `dispatch-queue`, `completion-handlers`, `sendable`, `delegates`
If `$ARGUMENTS` is empty, show usage and recommend next category based on `docs/swift6-migration-status.md`.
Prerequisites
1. Read `docs/swift6-migration-status.md` to understand current progress 2. Run `/swift6-check $ARGUMENTS` mentally — verify that the category has remaining items 3. If the category shows 0 remaining, inform the user and suggest the next category
Category: `config`
Foundation changes — run this FIRST before any other category.
Steps
1. Update `Project.swift`: change `"SWIFT_VERSION": "5.3"` → `"SWIFT_VERSION": "6.0"` (all occurrences) 2. Update all `Modules/*/Package.swift`: change `swiftLanguageMode(.v5)` → `swiftLanguageMode(.v6)` 3. Add `SWIFT_STRICT_CONCURRENCY` build setting:
- If first time: set to `targeted`
- If `targeted` already done: set to `complete`
4. Lock any dependency versions still pinned to `master` / a moving branch (Swift 6 will break on unexpected upstream changes) 5. Run `tuist generate --no-open` 6. Build: `xcodebuild -scheme <scheme> -destination 'platform=iOS Simulator,name=iPhone 11,OS=latest' -quiet build` 7. If build fails, fix errors iteratively (max 10 iterations) 8. Update `docs/swift6-migration-status.md` config checklist 9. Commit with message: `[CHORE] Swift 6 migration: update Swift version and concurrency settings`
Category: `mainactor`
Add `@MainActor` to ViewModels that are `ObservableObject` subclasses.
Rules
- Add `@MainActor` annotation to the class declaration
- Do NOT change any method signatures or property types
- If a method is explicitly `nonisolated`, leave it as-is
- If a class already has `@MainActor`, skip it
- Work in batches of 20-30 files per session to keep PRs reviewable
Steps
1. Find all unannotated ViewModels:
grep -rl "class.*ViewModel.*ObservableObject" <scheme>/ --include="*.swift" | while read f; do
grep -L "@MainActor" "$f"
done2. For each file, add `@MainActor` before the class declaration:
// BEFORE
final class SomeViewModel: ObservableObject {
// AFTER
@MainActor
final class SomeViewModel: ObservableObject {3. Build after every 10 files. If errors appear:
- `@MainActor`-isolated property accessed from non-isolated context → add `@MainActor` to the caller or mark the access as `MainActor.assumeIsolated`
- Protocol conformance issues → add `@MainActor` to the protocol if it's internal
- Test files referencing the ViewModel → add `@MainActor` to the test class or use `await`
4. Run tests for affected modules 5. Update `docs/swift6-migration-status.md`:
- Increment "Done" count
- Decrement "Remaining" count
- Add entry to Execution Log
6. Format changed files with `swiftformat` 7. Commit with message: `[CHORE] Swift 6 migration: add @MainActor to ViewModels (batch N)`
Category: `singletons`
Protect mutable singletons with actor isolation or `@MainActor`.
Rules
- `static let shared` with mutable properties → add `@MainActor` to the class
- `static var shared` (mutable reference) → change to `static let shared` + add `@MainActor`
- If the singleton is accessed from background threads intentionally, wrap in an actor instead
- The session/user singleton typically gets special treatment — it's usually the most critical one
Critical Singletons (priority order)
1. Session/user managers — many mutable properties, accessed everywhere 2. Any `static var shared` (mutable reference!) — convert first 3. Analytics/tracking singletons with mutable internal state 4. Shared ViewModels exposed as `static var` 5. All remaining `static let shared` with mutable internal state
Steps
1. List all singletons:
grep -rn "static let shared\|static var shared" <scheme>/ --include="*.swift"
2. For each singleton: a. Read the file to understand thread access patterns b. If mainly UI-bound: add `@MainActor` to the class c. If accessed from background threads: convert to actor or use `nonisolated(unsafe)` as escape hatch d. Change `static var shared` → `static let shared` where possible 3. Build after every 5 changes 4. Fix cascading errors (callers may need `await` or `@MainActor`) 5. Run tests 6. Update `docs/swift6-migration-status.md` 7. Commit with message: `[CHORE] Swift 6 migration: protect singletons with actor isolation`
Category: `dispatch-queue`
Replace `DispatchQueue.main.async` with structured concurrency.
Rules
- `DispatchQueue.main.async { ... }` in a `@MainActor` context → remove the dispatch, code already runs on main
- `DispatchQueue.main.async { ... }` in a non-MainActor context → use `Task { @MainActor in ... }` or `await MainActor.run { ... }`
- `DispatchQueue.main.sync` → evaluate carefully, may indicate a design issue
- `DispatchQueue.global().async` → use `Task.detached` or `Task { ... }` with appropriate priority
- Work in batches of 30-50 replacements per session
Steps
1. Find all occurrences:
grep -rn "DispatchQueue\.main\.async" <scheme>/ --include="*.swift"
2. Group by file and context:
- In ViewModels (already `@MainActor` after mainactor phase) → remove dispatch wrapper
- In Services/Repositories → use `Task { @MainActor in ... }`
- In UIKit delegates/callbacks → use `Task { @MainActor in ... }`
3. Apply changes per file 4. Build after every 15 files 5. Run tests 6. Update `docs/swift6-migration-status.
Reusable Claude Code slash-commands, skills, and workflows extracted from real iOS / backend projects. Packaged as three installable plugins - register the marketplace and /plugin install what you need.
Repo: carloshpdoc/ios-workflow-claude
Other commands on ios-workflow-claude.
- /apollo-check
**Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase
Open command - /apollo-migrate
**Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase
Open command - /apollo-review
**Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase
Open command - /apollo-status
**Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase
Open command - /apollo-tasks
**Project context:** Values in angle brackets below (e.g. `<scheme>`, `<JIRA_KEY>`, `<flag-key-enum>`) are resolved at runtime — detect them from the project (`xcodebuild -list -json` for the scheme, `git`/`gh` for repo & owner, the branch name for the Jira key, a codebase
Open command - /bump
Bump the app version or build number across all targets in the current project.
Open command

