dbmrq/agent-skills/ios-app-store-release
Claude Code and agent skill by dbmrq/agent-skills
- community
Checking that the SKILL.md file is still in the repository.
Ship iOS apps to App Store Connect end-to-end — Xcode Cloud, ASC API metadata and screenshots, release manifests, TestFlight, and prepare-for-submission without auto-submit. Use when publishing an iOS app, setting up App Store automation, ASC API scripts, store screenshots, Xcode Cloud release workflows, or preparing a version for App Review.
Install
npx vskill@latest install dbmrq/agent-skills/ios-app-store-releaseSKILL.md
iOS App Store Release
Agent playbook for repeatable, mostly-automated iOS releases. Assumes Swift/SwiftUI, optional XcodeGen, Python ASC client, and Xcode Cloud for archives.
Out of scope (agent already knows): creating Apple Developer accounts, basic xcodebuild, writing App Store copy from scratch, generic git tagging.
Hard rules (never violate)
These are stop-and-ask constraints. Convenience (unblocking asc-sync, bumping a marketing version, “fixing” a stuck ship) does not override them.
- Never blind-overwrite ASC listing or review data. Live App Store Connect is the source of truth when it differs from the repo or from what an agent “remembers.” Always GET before PATCH; merge per ASC metadata merge; prefer ASC (or the richer side) for review notes, description, keywords, contact, etc. Local
review-notes.txt/ YAML being non-empty is not permission to replace a longer ASC value. After merge, write winners back intostore-assets/so the next ship does not regress.
- Never remove a version from App Review (no
DELETE /appStoreVersionSubmissions, no “Cancel Review” / withdraw, no developer-reject-to-edit) unless the human explicitly asks in this conversation. Canceling restarts the review clock and can add days of wait. If a version is alreadyWAITING_FOR_REVIEW/IN_REVIEW/PENDING_APPLE_RELEASE, follow Version selection — upload the binary only and warn; do not cancel, rename, or re-attach builds on that version.
- Do not invent a workaround that mutates an in-review version (rename
1.0→1.1, swap the attached build, rewrite notes) without explicit human approval. Prefer waiting for approval/release, or uploading a new TestFlight/App Store build while leaving the review queue alone.
Before starting
Collect per-app constants (store in scripts/asc/constants.py or equivalent):
| Constant | Example | Notes | |
|---|---|---|---|
APP_ID | ASC apps resource id | Not bundle id | |
BUNDLE_ID | co.example.app | ||
DEFAULT_LOCALE | en-US | ||
CI_PRODUCT_NAME | App name in Xcode Cloud | May lag in ASC API after first workflow setup | |
| Screenshot display types | APP_IPHONE_67, APP_IPAD_PRO_3GEN_129 | Validate against ASC — invalid enums fail upload | |
| Composed pixel sizes | iPhone 1290×2796, iPad 2064×2752 | Must match display type |
Credentials: ~/.config/app-store-connect/credentials.json with issuer_id, key_id, private_key_path, optional team_id.
Target architecture (per app repo)
Design choices that paid off:
- Tests local, archive in Cloud — saves Cloud compute; only Release workflow on tag.
- YAML manifest per release — agents edit ship intent, not ASC UI.
- `submit_for_review: false` default for first ship — human presses Submit after visual check.
- `.release-state.json` + `--resume` — idempotent recovery; skip completed steps with strict
<ordering (failed step must re-run). - Legal/support URLs — separate public repo + GitHub Pages; app repo stays private.
Reference templates and API traps: reference.md.
End-to-end ship workflow
Copy and track:
1. Release manifest
whats_new required for validator even when ASC rejects it on first release (handle in metadata sync — see reference).
2. Orchestrator steps
Typical order:
- validate — manifest + required metadata fields
- tests — unit tests locally (
GregorTests-style, not full UI suite) - bump —
MARKETING_VERSION+ incrementCURRENT_PROJECT_VERSIONinproject.yml, runxcodegen - commit + tag —
v{version}, push branch + tag (triggers Cloud) - wait-build — poll Xcode Cloud product or ASC builds API until
processingState: VALID - assets (if
refresh_assets) — capture → compose → upload screenshots - asc-sync — metadata, review detail, export compliance, attach build
- submit (optional) — create submission; often blocked by API role or left to human
3. Build wait fallback
If find_ci_product() returns nothing (common right after first workflow setup), poll ASC builds:
Trap: build.attributes.version is the build number (e.g. 3), not marketing version. Match via included preReleaseVersions.attributes.version.
Trap: Xcode Cloud builds can be buildAudienceType: INTERNAL_ONLY (TestFlight-only) depending on the workflow's distribution setting. Only APP_STORE_ELIGIBLE builds can attach to an appStoreVersion; an internal build fails with 409 ENTITY_ERROR.RELATIONSHIP.INVALID — "The specified pre-release build could not be added." Filter on `buildAudienceType == APP_STORE_ELIGIBLE` inside the build selector, not only at attach time: Beta/TestFlight builds are usually the newest ones, so an unfiltered “latest VALID build” will always pick the wrong one. Prefer newer_than_build_id=<previous eligible build> over min_build_number — Xcode Cloud may stamp its own CI run number (28) while project.yml says 101, so a project-number floor can reject the real release build.
Workflow contract (enforce it before tagging): keep two workflows per app — Release on tag v* with APP_STORE_ELIGIBLE, and Beta on push to main with INTERNAL_ONLY for TestFlight/FeedbackLoop. Beta must never be App Store-eligible: a feedback-loop build must not be attachable to a version. Audit both via the ASC API (GET /ciProducts/{id}/workflows) or a scripts/asc/workflows.py audit helper; a missing Release workflow is the usual reason every build picker entry is grayed out. Creating a workflow is possible via POST /v1/ciWorkflows (needs product, primary repository, ciXcodeVersions “Latest Release”, and ciMacOsVersions “Latest Release” relationships). PATCHing a workflow replaces the start conditions you omit — to add manualBranchStartCondition, send tagStartCondition and manualTagStartCondition in the same PATCH or tag releases silently stop triggering.
Diagnosing “most builds are grayed out”: query /v1/builds and look at buildAudienceType. If the recent ones are all INTERNAL_ONLY and there is no Release workflow, the app has only a Beta/TestFlight pipeline. Add the Release workflow, run it from the tag/branch, wait for processingState: VALID, then attach that build. Do not try to attach a Beta build.
Local archive fallback when Cloud is broken: xcodebuild archive → exportArchive → xcrun altool --upload-app. Copy .p8 to ~/.appstoreconnect/private_keys/AuthKey_{KEY_ID}.p8 — altool ignores custom --apiKeyPath unless file is in that directory.
After upload, PATCH build: usesNonExemptEncryption: false (and set ITSAppUsesNonExemptEncryption = NO in Info.plist for future uploads).
Submitting for review (current API)
POST /v1/appStoreVersionSubmissions is not available to API keys anymore: it returns 403 FORBIDDEN_ERROR — The resource 'appStoreVersionSubmissions' does not allow 'CREATE'. Allowed operation is: DELETE. Use review submissions instead:
POST /v1/reviewSubmissionswithplatform: IOSand the app relationship.POST /v1/reviewSubmissionItemswithreviewSubmission+appStoreVersion.PATCH /v1/reviewSubmissions/{id}withsubmitted: true.
Trap — an open submission may not contain your app version. Creative assets (header/search images and videos) can be submitted separately and sit in WAITING_FOR_REVIEW while the version is still PREPARE_FOR_SUBMISSION. Before deciding “already submitted” or reusing a draft, list items with GET /reviewSubmissions/{id}/items?include=appStoreVersion and check for a matching appStoreVersion id. Multiple submissions can coexist; create a new one for the version if the open one only contains assets. Do not cancel the asset submission.
`whatsNew` is required for updates. ASC localizations are often empty while the release manifest has the notes. Merge/patch whatsNew before submitting (the manifest is the source for shipping copy); for a first release it may be non-editable and can be skipped.
A 409 STATE_ERROR.ENTITY_STATE_INVALID on item-create hides readiness blockers in meta.associatedErrors — surface them. Common current blockers:
STATE_ERROR.CANNOT_SUBMIT_MISSING_REGULATED_MEDICAL_DEVICE_APP_DECLARATION→ App Store
Connect → App Information → Declare Regulated Medical Device (select No for a non-medical app). Required for apps with a primary/secondary Health & Fitness or Medical category, or frequent medical content in the age rating. UI-only, no public API.
- App Privacy questionnaire (also UI-only).
Screenshots (non-obvious)
Deep capture / compose / ASC upload workflow: [ios-app-store-screenshots](../ios-app-store-screenshots/SKILL.md).
Summary for ship pipelines: raw simulator capture → compose_store_assets.py (Pillow + scenes.yaml) → upload_store_assets.py --version X.Y. Use XCTest attachments + SCREENSHOT_BASENAME export (do not rely on xcodebuild shell env for launch args). Pin simulator names; gate DemoMode with #if DEBUG.
Demo / mock data (critical)
Store screenshots need content; App Store builds must not.
- Gate all demo vault seeding behind
#if DEBUGand launch args (e.g.-UITestDemo). - Production: empty journal only (
JournalBootstrap.ensureDefaultJournal— directories, no notes). - Review notes must describe real first-launch behavior (empty journal), not screenshot fixtures. First submissions follow the common-questions template in reference.md; the physical-device screen recording attachment is human-only in the ASC UI.
- Never symlink or ship bundled sample markdown in the app target.
Xcode Cloud
`ci_post_clone.sh`: install/run xcodegen generate when .xcodeproj is generated from spec.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/ios-app-store-release/SKILL.md
Popularity
- 7-day trend score
- 5
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/dbmrq/agent-skills/ios-app-store-release)