home / skills / vladimirbrejcha / ios-ai-skills / ios-xcodegen
This skill helps automate iOS XcodeGen workflows to generate projects, fix destinations, wire assets, manage SwiftPM in CI, and resolve packaging issues.
npx playbooks add skill vladimirbrejcha/ios-ai-skills --skill ios-xcodegenReview the files below or copy the command above to add this skill to your agents.
---
name: ios-xcodegen
description: "XcodeGen workflows for iOS/iPadOS apps: generate projects from project.yml/project.yaml, fix build/test destination issues, wire asset catalogs, configure test hosts, manage SwiftPM resolution in CI, and resolve App Store packaging errors related to embedded static libraries."
---
# XcodeGen iOS workflow
## Quick start
- Treat `project.yml` (or `project.yaml`) as the source of truth; regenerate with `xcodegen generate` before building.
- Do not edit the generated `.xcodeproj` directly; delete and regenerate as needed.
## Build / Run
- For “Designed for iPad on Mac” builds, use a macOS destination with `variant=Designed for iPad` when available.
- For tests, prefer an iOS Simulator if any vendor frameworks lack Mac Catalyst support.
## Tests
- Ensure the test target is added to the scheme and has a host app if required.
- If tests show 0 cases, recheck the scheme and any test plan configuration.
- If `@testable import` fails, confirm the host app module name and that tests build for the same destination as the host.
## Resources / Assets
- Asset catalogs and storyboards must be in the resources build phase. In XcodeGen, add them under `sources` with `buildPhase: resources`.
- Enable asset symbol generation when code uses generated `ColorAsset`/`ImageAsset` symbols:
- `ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOLS=YES`
- `ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS=YES`
## SwiftPM in CI
- If CI disables automatic dependency resolution, ensure `Package.resolved` is committed or copied to the expected location (usually `.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved`) before build.
- Keep versions pinned in `project.yml` when deterministic builds are required.
## App Store Connect packaging issues
- Static `.a` files must never appear under `*.app/Frameworks`.
- XcodeGen does not support a `library:` dependency key; to link a `.a` file, use:
- `framework: path/to/libSomething.a`
- `embed: false`
- XCFrameworks that contain static libs should also be linked only:
- set `embed: false` for those XCFrameworks to avoid `.a` slices being copied into `Frameworks/`.
- Verify the generated project’s “Embed Frameworks” build phase contains only dynamic frameworks that must be embedded.
## Diagnostics / sanity checks
- Regenerate and clean Derived Data after changing `project.yml`.
- After archiving, inspect the app bundle’s `Frameworks/` directory; it should contain only dynamic frameworks and Swift runtime libraries.
This skill provides XcodeGen-focused workflows and fixes for building Swift iOS/iPadOS apps. It enforces project.yml as the source of truth, automates common project generation tasks, and eliminates packaging and CI issues that break builds or App Store uploads. The goal is reliable, reproducible Xcode projects that behave the same in local and CI environments.
It regenerates .xcodeproj files from project.yml/project.yaml and applies sanity checks for build phases, resource wiring, test hosts, and embedding rules. The skill also prepares SwiftPM resolution for CI, configures asset symbol generation, and inspects generated app bundles to detect forbidden static libraries in Frameworks. It outputs concrete actions and remediation steps based on the project.yml configuration.
Why do my tests show 0 cases after generating the project?
Check that the test target is included in the scheme, has the correct host app if needed, and that any test plan configuration references the correct targets and destinations.
How do I prevent static .a files from being embedded in the app bundle?
Link .a files with `framework: path/to/libSomething.a` and set `embed: false`. For XCFrameworks that include static slices, also set `embed: false` so they aren’t copied into Frameworks/.