Agent skill
ios-workflow
iOS-specific workflow activated automatically when platform-context.json reports primary_platform=ios. Handles toolchain verification, Swift Testing patterns, XcodeBuildMCP integration, and SwiftLint.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/ios-workflow
SKILL.md
iOS Workflow
Activated automatically when the Platform Detection Engine identifies an iOS/Swift project. Never activate this manually in non-iOS projects.
Phase 1: Toolchain verification
When iOS is detected, check and report tool availability:
๐ iOS project detected. Checking toolchain...
โ
swift โ found (Swift 6.0.3)
โ
xcodebuild โ found (Xcode 16.2)
โ
swiftlint โ found (0.57.0)
โ
XcodeBuildMCP โ found (~/.claude/skills/xcodebuildmcp/SKILL.md)
โ ๏ธ xcbeautify โ not found (optional: brew install xcbeautify)
iOS toolchain ready.
Checks to perform:
swift --versionโ report Swift versionxcodebuild -versionโ report Xcode versioncommand -v swiftlint && swiftlint versionโ report version or "not found"ls ~/.claude/skills/xcodebuildmcp/SKILL.md 2>/dev/nullโ XcodeBuildMCP presencecommand -v xcbeautifyโ optional, just report
None of these checks are blockers โ missing tools generate warnings, not errors.
Phase 2: Test Framework Detection
Determine whether the project uses Swift Testing or XCTest:
# Count test files using each framework
swift_testing_count=$(grep -r "import Testing" . --include="*.swift" -l 2>/dev/null | wc -l)
xctest_count=$(grep -r "import XCTest" . --include="*.swift" -l 2>/dev/null | wc -l)
swift_testing_count > 0ANDxctest_count == 0โ use Swift Testingxctest_count > 0ANDswift_testing_count == 0โ use XCTest (legacy)- Both present โ use Swift Testing for new tests, keep existing XCTest tests
- None found โ default to Swift Testing (modern standard)
Report to user:
๐งช Test framework: Swift Testing (@Test, @Suite, #expect)
or:
๐งช Test framework: XCTest (existing project uses XCTest โ maintaining consistency)
Phase 3: iOS Test Pipeline
Execute in this exact order:
Step 1 โ Unit tests (swift test or xcodebuild)
# Option A: Swift Package Manager project
swift test --parallel
# Option B: Xcode project/workspace (if .xcodeproj/.xcworkspace found)
xcodebuild test \
-scheme {detected_scheme} \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-resultBundlePath .claude/feature-state/{slug}/test-results.xcresult \
| xcbeautify 2>/dev/null || cat
Detect which to use: if Package.swift exists without .xcodeproj โ use swift test.
Step 2 โ SwiftLint (files modified by this feature only)
Run SwiftLint only on modified files โ not the whole project:
# Get files modified since the feature branch started
modified_files=$(git diff --name-only HEAD~1 -- "*.swift" 2>/dev/null)
# Run swiftlint on those files only (if swiftlint is available)
if command -v swiftlint > /dev/null 2>&1 && [ -n "$modified_files" ]; then
swiftlint lint $modified_files --reporter json > .claude/feature-state/{slug}/swiftlint.json
swiftlint lint $modified_files # human-readable output
fi
If swiftlint not found: skip with โ ๏ธ swiftlint not found โ skipping lint.
Step 3 โ XcodeBuildMCP build + simulator (optional, non-blocking)
Only if capabilities.xcodebuildmcp_available == true in platform-context.json:
1. /xcodebuildmcp discover_projs
โ find .xcodeproj or .xcworkspace
2. /xcodebuildmcp session_set_defaults
โ configure scheme, destination, configuration
3. /xcodebuildmcp build_run_sim
โ build + launch on iOS Simulator
โ capture build output and simulator status
Result reporting:
โ
App running on iPhone 16 Simulator (iOS 18.3)
or:
โ ๏ธ Simulator build failed: [error summary] โ tests passed, continuing to commit
XcodeBuildMCP failure is non-blocking. Unit tests passing is sufficient for the workflow.
Swift Testing patterns for iOS
When generating new tests (Test Only mode or per-task test generation), always use Swift Testing โ never XCTest โ unless the project exclusively uses XCTest.
Required imports and structure
import Testing
@testable import {ModuleName}
@Suite("ViewModel or UseCase Name")
struct PersonalTrainerViewModelTests {
@Test("describe the behavior, not the method name")
func loadsTrainerOnAppear() async throws {
// Arrange
let viewModel = PersonalTrainerViewModel(
discoverTrainersUseCase: MockDiscoverTrainersUseCase(),
featureFlagChecker: MockFeatureFlagChecker(enabled: true)
)
// Act
await viewModel.onAppear()
// Assert
#expect(viewModel.isFeatureEnabled == true)
#expect(viewModel.currentTrainer != nil)
}
@Test("does not load trainer when feature flag is disabled")
func doesNotLoadWhenDisabled() async {
let viewModel = PersonalTrainerViewModel(
featureFlagChecker: MockFeatureFlagChecker(enabled: false)
)
await viewModel.onAppear()
#expect(viewModel.currentTrainer == nil)
}
// Parameterized test
@Test("requestConnection returns true for valid trainer IDs",
arguments: ["trainer-alpha", "trainer-beta", "trainer-gamma"])
func requestConnectionSucceeds(trainerId: String) async {
let viewModel = PersonalTrainerViewModel(
connectTrainerUseCase: MockConnectTrainerUseCase(shouldSucceed: true)
)
let result = await viewModel.requestConnection(trainerId: trainerId)
#expect(result == true)
}
}
Rules for iOS tests
- Use
@Suiteto group related tests (one suite per ViewModel/UseCase/Repository) - Use
@Test("behavior description")โ describe what it does, not the method - Use
#expect(condition)for assertions โ neverXCTAssert - Use
#require(value)to unwrap optionals that must exist - Use
throwsfor tests that can throw,async throwsfor async tests - Use
arguments:for data-driven tests (replaces XCTestparametrize) - Use
.tags()trait for categorization:@Test("...", .tags(.unit, .viewModel)) - Never use
XCTest,XCTAssert*, orclass FooTests: XCTestCase
File structure for iOS tests
Follow the existing project convention. If no convention exists, use:
{ProjectName}/
โโโ {ProjectName}Tests/
โโโ Domain/
โ โโโ UseCases/
โ โโโ {UseCase}Tests.swift โ one file per use case
โโโ Data/
โ โโโ Repositories/
โ โ โโโ {Repository}Tests.swift
โ โโโ Services/
โ โโโ {Service}Tests.swift
โโโ Presentation/
โโโ Features/
โโโ {Feature}/
โโโ {Feature}ViewModelTests.swift
Test file naming
- One test file per production file:
PersonalTrainerViewModel.swiftโPersonalTrainerViewModelTests.swift - Place in mirror directory under
{ProjectName}Tests/
Test Only mode โ iOS
When --mode test-only is invoked on an iOS project:
- Detect test framework (Swift Testing vs XCTest)
- Find Swift files without corresponding test files:
bash
find . -name "*.swift" \ ! -name "*Tests.swift" \ ! -name "*Mock*" \ ! -path "*/Tests/*" \ -type f 2>/dev/null - For each file without tests, check if it's testable (ViewModels, UseCases, Repositories, Services)
- Present to user:
Found 3 files without test coverage: - Presentation/Features/PersonalTrainer/PersonalTrainerViewModel.swift - Domain/UseCases/ConnectTrainerUseCase.swift - Data/Repositories/TrainerRepository.swift Generate Swift Testing tests for these files? [yes/no/select] - Generate tests following Swift Testing patterns above
- Run
swift test --parallel - If XcodeBuildMCP available: optionally run build on simulator
- Report coverage delta
Configuration in platform-context.json
The iOS entry in platform-context.json includes:
{
"type": "ios",
"test_framework": "swift-testing",
"capabilities": {
"swiftlint_available": true,
"xcodebuildmcp_available": true,
"swift_testing_available": true
}
}
This configuration is ignored completely on non-iOS projects.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?