/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
$ 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
/apollo-migrate
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
apollo-migrate.mdApollo Repository Migration
> **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.
Migrate the Apollo repository **$ARGUMENTS** to the new `GraphQLClientProtocol` pattern.
Pre-Migration: Read the Investigation
**MANDATORY:** Before writing any code, read the investigation file:
docs/apollo-removal/issues/$ARGUMENTS.md
If the investigation file does NOT exist, tell the user to run `/apollo-check $ARGUMENTS` first and stop. Do not proceed without an investigation.
If the investigation file exists, read it completely. It contains:
- The design decisions already made (pattern, fragment handling, PR splitting)
- The exact files to create, modify, and delete
- The consumers to update
- The tests to write
- Any risks or special considerations
**Follow the investigation.** The migration steps are always the same (see CLAUDE.md). What changes per repo is the target files and consumers identified in the investigation. If you need to deviate from it, note the deviation and the reason — you will need to explain this in the report.
Reference
Read `docs/apollo-migration-guide.md` for the full migration guide.
**Gold standard reference files (read before writing code):**
- `<scheme>/Repositories/<ReferenceRepo>/Queries/<ReferenceRepo>Query.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>GraphQLDataSource.swift`
- `<scheme>/Repositories/<ReferenceRepo>/Models/<ReferenceRepo>GraphQLResponse.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>ResponseMapper.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>Repository.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>RepositoryFactory.swift`
Migration Steps
The steps are always the same (defined in CLAUDE.md). Use the investigation file for repo-specific details:
Step 1: Gather Information
Read the source files listed in the investigation. Verify the investigation is still accurate (no files changed since it was written).
Step 2: Create Query File
Create `Queries/<Name>Query.swift` in the repository directory:
enum <Name>Query {
static let query = """
<paste the exact query from the .graphql file>
"""
static let operationName = "<OperationName>"
}- Copy the query **exactly** from the `.graphql` file
- The operation name is the name after `query` or `mutation` keyword
Step 3: Create GraphQL Response Models
Create `Models/<Name>GraphQLResponse.swift`:
- Define `Codable` structs matching the GraphQL response JSON structure
- Use `__typename` mapped via CodingKeys where needed
- Match the field names from the `.graphql` query
- Study the `.graphql.swift` generated types to understand the shape and nullability
Step 4: Create GraphQL DataSource
Create `<Name>GraphQLDataSource.swift`:
- Define protocol `<Name>GraphQLDataSourceProtocol` with async throws methods
- Implement using `GraphQLClientProtocol` from `import Services`
- Use `InputEncodable` for query parameters
- Use `withCheckedThrowingContinuation` to bridge the callback-based client to async/await
- Include mock loading support (following <ReferenceRepo> pattern)
Step 5: Create Response Mapper
Create `<Name>ResponseMapper.swift`:
- Define protocol `<Name>ResponseMapperProtocol`
- Map from `*GraphQLResponse` types to domain models
- Handle optional fields and type discriminators (`__typename`)
- Reuse existing domain models from `SharedModels` when they exist
Step 6: Create/Update Repository
Create or update `<Name>Repository.swift`:
- Keep the existing protocol if consumers already depend on it
- If the protocol signature needs to change, update all consumers
- Implementation delegates to DataSource + Mapper
- Constructor takes `dataSource` and `mapper` parameters
- **MANDATORY: All completion handlers MUST dispatch to `DispatchQueue.main.async`**
// ✅ CORRECT pattern for repository methods
func fetchData(completion: @escaping (Model?) -> Void) {
Task {
do {
let response = try await dataSource.fetch()
let model = mapper.map(response)
DispatchQueue.main.async { completion(model) }
} catch {
Log.error(message: error.localizedDescription)
DispatchQueue.main.async { completion(nil) }
}
}
}Step 7: Create Factory
Create `<Name>RepositoryFactory.swift` following the standard pattern from `docs/apollo-migration-guide.md`.
Step 8: Update Consumers
For each consumer listed in the investigation:
1. Replace `import Apollo` with `import Services` (if needed) 2. Replace `Network<Name>Repository()` with `<Name>RepositoryFactory.makeRepository()` 3. Remove any direct Apollo type usage (`<Query>.Data`, fragments, etc.) 4. Update method calls if the protocol signature changed 5. Verify the consumer still compiles
Step 9: Delete Old Files
Remove the files listed in the investigation's "Files to Delete" section: 1. The `.graphql` file (unless it has shared fragments — check the plan) 2. The `.graphql.swift` file from `<scheme>/Services/Apollo/API/` 3. The old `Network*Repository.swift` (only if fully replaced) 4. Any Apollo-specific extensions or helpers only used by this repo
Step 10: Regenerate Project
**MANDATORY after adding or deleting files.** Run:
tuist generate --no-open
This regenerates `<scheme>.xcodeproj/project.pbxproj` and removes orphaned references to deleted files. Skipping this step causes build failures ("file not found" errors for deleted files that are still referenced in the project).
Step 11: Build and Verify
Build the project to verify compilation:
xcodebuild -works
Read more
Apollo Repository Migration
> **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.
Migrate the Apollo repository **$ARGUMENTS** to the new `GraphQLClientProtocol` pattern.
Pre-Migration: Read the Investigation
**MANDATORY:** Before writing any code, read the investigation file:
docs/apollo-removal/issues/$ARGUMENTS.md
If the investigation file does NOT exist, tell the user to run `/apollo-check $ARGUMENTS` first and stop. Do not proceed without an investigation.
If the investigation file exists, read it completely. It contains:
- The design decisions already made (pattern, fragment handling, PR splitting)
- The exact files to create, modify, and delete
- The consumers to update
- The tests to write
- Any risks or special considerations
**Follow the investigation.** The migration steps are always the same (see CLAUDE.md). What changes per repo is the target files and consumers identified in the investigation. If you need to deviate from it, note the deviation and the reason — you will need to explain this in the report.
Reference
Read `docs/apollo-migration-guide.md` for the full migration guide.
**Gold standard reference files (read before writing code):**
- `<scheme>/Repositories/<ReferenceRepo>/Queries/<ReferenceRepo>Query.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>GraphQLDataSource.swift`
- `<scheme>/Repositories/<ReferenceRepo>/Models/<ReferenceRepo>GraphQLResponse.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>ResponseMapper.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>Repository.swift`
- `<scheme>/Repositories/<ReferenceRepo>/<ReferenceRepo>RepositoryFactory.swift`
Migration Steps
The steps are always the same (defined in CLAUDE.md). Use the investigation file for repo-specific details:
Step 1: Gather Information
Read the source files listed in the investigation. Verify the investigation is still accurate (no files changed since it was written).
Step 2: Create Query File
Create `Queries/<Name>Query.swift` in the repository directory:
enum <Name>Query {
static let query = """
<paste the exact query from the .graphql file>
"""
static let operationName = "<OperationName>"
}- Copy the query **exactly** from the `.graphql` file
- The operation name is the name after `query` or `mutation` keyword
Step 3: Create GraphQL Response Models
Create `Models/<Name>GraphQLResponse.swift`:
- Define `Codable` structs matching the GraphQL response JSON structure
- Use `__typename` mapped via CodingKeys where needed
- Match the field names from the `.graphql` query
- Study the `.graphql.swift` generated types to understand the shape and nullability
Step 4: Create GraphQL DataSource
Create `<Name>GraphQLDataSource.swift`:
- Define protocol `<Name>GraphQLDataSourceProtocol` with async throws methods
- Implement using `GraphQLClientProtocol` from `import Services`
- Use `InputEncodable` for query parameters
- Use `withCheckedThrowingContinuation` to bridge the callback-based client to async/await
- Include mock loading support (following <ReferenceRepo> pattern)
Step 5: Create Response Mapper
Create `<Name>ResponseMapper.swift`:
- Define protocol `<Name>ResponseMapperProtocol`
- Map from `*GraphQLResponse` types to domain models
- Handle optional fields and type discriminators (`__typename`)
- Reuse existing domain models from `SharedModels` when they exist
Step 6: Create/Update Repository
Create or update `<Name>Repository.swift`:
- Keep the existing protocol if consumers already depend on it
- If the protocol signature needs to change, update all consumers
- Implementation delegates to DataSource + Mapper
- Constructor takes `dataSource` and `mapper` parameters
- **MANDATORY: All completion handlers MUST dispatch to `DispatchQueue.main.async`**
// ✅ CORRECT pattern for repository methods
func fetchData(completion: @escaping (Model?) -> Void) {
Task {
do {
let response = try await dataSource.fetch()
let model = mapper.map(response)
DispatchQueue.main.async { completion(model) }
} catch {
Log.error(message: error.localizedDescription)
DispatchQueue.main.async { completion(nil) }
}
}
}Step 7: Create Factory
Create `<Name>RepositoryFactory.swift` following the standard pattern from `docs/apollo-migration-guide.md`.
Step 8: Update Consumers
For each consumer listed in the investigation:
1. Replace `import Apollo` with `import Services` (if needed) 2. Replace `Network<Name>Repository()` with `<Name>RepositoryFactory.makeRepository()` 3. Remove any direct Apollo type usage (`<Query>.Data`, fragments, etc.) 4. Update method calls if the protocol signature changed 5. Verify the consumer still compiles
Step 9: Delete Old Files
Remove the files listed in the investigation's "Files to Delete" section: 1. The `.graphql` file (unless it has shared fragments — check the plan) 2. The `.graphql.swift` file from `<scheme>/Services/Apollo/API/` 3. The old `Network*Repository.swift` (only if fully replaced) 4. Any Apollo-specific extensions or helpers only used by this repo
Step 10: Regenerate Project
**MANDATORY after adding or deleting files.** Run:
tuist generate --no-open
This regenerates `<scheme>.xcodeproj/project.pbxproj` and removes orphaned references to deleted files. Skipping this step causes build failures ("file not found" errors for deleted files that are still referenced in the project).
Step 11: Build and Verify
Build the project to verify compilation:
xcodebuild -works
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-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 - /code-review
Review code quality applying DRY, SOLID, naming, and formatting standards
Open command

