| name | app-store-release |
| description | Build, archive, validate, upload, and submit iOS/iPadOS/macOS/visionOS apps to App Store Connect via fastlane (match/gym/pilot/deliver), xcrun altool, or EAS (eas build / eas submit) for native Swift, React Native, Expo, Flutter, and Capacitor projects. Covers .xcarchive, ExportOptions.plist, code signing, PrivacyInfo.xcprivacy, TestFlight, ASC REST API metadata and screenshots, JWT-signed API keys, App Review submission, rejections, ITMS-XXXXX errors, macOS notarization (notarytool), and Xcode Cloud. Use when asked to submit to the App Store, ship to TestFlight, archive and upload, fastlane release, eas submit, fix code signing or ITMS-90xxx, notarize a Mac app, or respond to a rejection. |
App Store Release
The solo-developer pipeline for shipping an iOS app to the App Store: build → archive
→ validate → upload → TestFlight → metadata → submit → post-review. Three pipeline
shapes — pick one before touching anything:
- Bare-bones (
xcrun altool + ASC web UI) — no tooling beyond Xcode. Best for the
first submission and TestFlight-only flows on native / Flutter / RN / Capacitor.
Often shorter than fastlane setup for a single ship.
- Fastlane — own-your-pipeline, runs locally or in CI. Best once you're shipping
repeat releases and want screenshot/metadata automation and 2FA-free CI.
- EAS Build + Submit — Expo's hosted pipeline. Best for Expo and bare-RN-on-EAS
projects. Collapses Phases 1–4 into two CLI commands.
Framework-aware build routing collapses every project to one Xcode workspace (or a
remote EAS build) before Phase 2; everything after that is framework-agnostic.
Scope and siblings. This skill owns the mechanical release act. For the deep
pre-upload guideline-compliance audit (Sign in with Apple, account deletion,
ATT, usage strings, IAP rules), use the app-review-preflight skill first — it
catches rejections while they're cheap. For keyword research, listing copywriting,
and store-screenshot design, use app-store-optimization. For icon
generation / validation, use app-icons. This skill cross-references those but
does not duplicate them; it keeps only the slices that are mechanically part of
pushing a binary live (the ASC REST upload protocols, device-size enums, age-rating
field discovery, and a post-rejection response loop).
Kernel: 12 axioms
Full axiom text (war stories, exact error strings, OP cross-references):
kernel-axioms. The headlines:
- Apple changes the rules constantly — the live ASC UI / guidelines / Xcode release notes are the source of truth, never this skill.
- The
.xcarchive is the choke point — after a Distribution-signed archive with dSYMs, every framework's pipeline is identical.
- Signing failures masquerade as build failures — read the exact log error; cloud signing breaks on the second archive (OP-4 → OP-6).
- Build wrappers hide the truth — find the raw
xcodebuild/altool/EAS-dashboard error before retrying anything.
- Validate before upload, every time —
--validate-app catches ITMS errors in ~30s vs a 5–30 min processing round-trip.
- TestFlight is the only honest validation — a build proves itself by installing and launching on a real device.
- First-time submission ≠ update — route the mode before doing any work.
- Privacy manifest is load-bearing —
PrivacyInfo.xcprivacy + signed SDK manifests, verified at validation time (references/PRIVACY-MANIFEST.md).
- Rejections cite a guideline number for a reason — read the cited clause verbatim, fix, scan for repeats, then reply (references/REJECTIONS.md).
- ASC's REST API is an undocumented discovery surface — PATCH-and-read-errors beats trusting last year's schema (OP-17/18/20/26).
- TestFlight is not independent of version state — an approved version closes its train; bump before every post-release upload (ITMS-90062/90186, OP-30).
- ASC credentials are radioactive — never print/commit the
.p8/JWT; every mutating ASC call needs explicit user confirmation (references/ASC-API.md).
Mode router (read before processing)
First-submission strategy: fill metadata/screenshots/age-rating/review-info once in the
ASC web UI (faster than a Deliverfile from scratch); adopt fastlane after the first ship.
Pick exactly one. Each routes to a different subset of phases.
| Mode | Trigger | Phases run |
|---|
first-submission | App not yet in ASC, never released | 0 → 8 (full) |
update | Existing app, new build/version | 0 → 8, skip ASC record creation + agreements + age rating in 6 |
testflight-only | Internal beta, no Store release this cycle | 0 → 5, stop |
metadata-only | Description / screenshots / keywords / privacy change only | 6 → 7, skip 0–5 |
resubmission-after-rejection | Apple rejected the previous build | start at references/REJECTIONS.md, then resume from the earliest affected phase |
xcode-version-rebuild | New Xcode/SDK forces re-archive (annual iOS bump) | 0 → 8 + Xcode-compat audit at Phase 0 |
Framework router (Phase 1 only)
Each framework collapses to a buildable Xcode workspace or a remote EAS build. After
Phase 1, every later phase is framework-agnostic.
| Framework | Pipeline | Pre-Xcode step | Workspace path |
|---|
| Native (Swift/SwiftUI/UIKit) | fastlane / altool | bundle exec pod install if a Podfile exists; for XcodeGen repos xcodegen generate first (OP-39) | MyApp.xcworkspace (or .xcodeproj if no Pods, or generated from project.yml) |
| React Native (bare, no EAS) | fastlane | cd ios && bundle exec pod install | ios/MyApp.xcworkspace |
| Expo (managed) | EAS | eas build --platform=ios --profile=production | n/a (cloud build) |
| Expo (bare) / RN with EAS | EAS (recommended) or fastlane | eas build or npx expo prebuild && cd ios && pod install | n/a or ios/<App>.xcworkspace |
| Flutter | fastlane / altool | flutter build ios --release --no-codesign | ios/Runner.xcworkspace |
| Capacitor | fastlane | npx cap sync ios | ios/App/App.xcworkspace |
Detection: if app.config.js / app.json has an expo: key, or eas.json exists
at project root, treat it as an Expo project and prefer EAS unless you have a strong
reason for fastlane (custom CI runners, air-gapped builds). Otherwise default to
bare-bones for the first submission and graduate to fastlane when repeat-release pain
justifies it.
→ See references/FRAMEWORK-BUILDS.md for per-framework command sequences;
references/EAS-SUBMISSION.md for the full EAS pipeline.
Quick start
Copy-paste command sequences for all three paths live in
quick-start: A. bare-bones (4 commands — build,
IPA-content verify, altool validate, upload — plus the ASC web-UI pass and the
VALID poll), B. fastlane (fastlane init, the minimal release lane, the
per-framework one-liners), C. EAS (eas build + eas submit with the
ascAppId pre-flight), and the one-time ASC API key setup (where to generate,
.p8 storage convention, Key ID vs Issuer ID 401 trap, App Manager vs Admin role).
Automation coverage
Know the CLI-vs-web-UI boundary before you start — don't hunt for a fastlane action
that doesn't exist. Builds, signing sync, build-number bumps, upload, metadata,
screenshots, and the review submit recur via fastlane/EAS; Developer Program enrollment,
Agreements/Tax/Banking, first app-record creation (no public POST /v1/apps — OP-42),
privacy nutrition labels, export compliance, and age rating are one-time web-UI items
(Phase 0). Full per-step fastlane/EAS table + the web-UI-only list + Xcode Cloud / macOS
pointers: PRE-FLIGHT — Automation coverage, plus the
one-time setup walkthrough in the same file.
Pipeline
Each phase has a hard gate; do not proceed without the listed evidence.
Phase 0 — Pre-flight
Gate: every checklist item verified in ASC / the Apple Developer portal — program
membership paid, agreements/tax/banking, ASC record, bundle-ID consistency,
ITSAppUsesNonExemptEncryption (OP-24), version strictly above the latest approved train
(OP-30); plus per-path items (local Distribution cert in the keychain — OP-4, profile,
ASC key for fastlane; eas whoami + ascAppId for EAS). Full per-path checklists:
PRE-FLIGHT — Phase 0 gate checklists; also
references/FASTLANE-SETUP.md, references/EAS-SUBMISSION.md.
Phase 1 — Framework build
Gate: Xcode opens the workspace and builds the Release scheme without errors. Plus:
app icon and launch screen are not framework defaults.
Apply the framework router. Fail fast on dependency-install errors before touching
Xcode — they're cheaper to diagnose than archive failures.
Critical placeholder-asset check (the silent App Review rejection trap):
- App icon:
flutter create / RN / Capacitor scaffolds ship default placeholder
icons that pass binary validation but get rejected at App Review under Guideline 4.0
(OP-1). Visually inspect the 1024×1024 source before Phase 2. Verify size + no-alpha
with sips -g pixelWidth -g pixelHeight -g hasAlpha <icon> (OP-46). If it's the
framework default, regenerate (see the app-icons skill, or
flutter_launcher_icons).
- Launch screen: verify
LaunchScreen.storyboard is customized — default storyboards
reference a 68-byte placeholder (OP-2). If hand-writing a storyboard for Xcode 26,
stay in the legacy format or Xcode's IB compiler may throw an internal error (OP-7).
→ references/FRAMEWORK-BUILDS.md.
Phase 2 — Archive (fastlane gym / xcodebuild / eas build)
Gate: valid .xcarchive with embedded dSYMs at a known path, Distribution-signed
(fastlane/altool); or FINISHED build with a downloadable IPA URL (EAS).
fastlane gym \
--workspace ios/MyApp.xcworkspace \
--scheme MyApp --configuration Release \
--export_method app-store \
--output_directory build --include_symbols true
EAS path: eas build --platform=ios --profile=production --non-interactive --no-wait,
then poll eas build:view <id> --json until status=FINISHED (5–10 min).
→ references/GYM-AND-ARCHIVE.md for ExportOptions.plist templates (use
method: app-store-connect — OP-38), manual-signing variants, and the two-stage
archive/export signing model (OP-40). For native/XcodeGen, put signing in project.yml,
never the .xcodeproj (OP-39).
Phase 3 — Validate
Gate: validation returns success; all ITMS errors resolved.
xcrun altool --validate-app -f build/MyApp.ipa -t ios \
--apiKey <KEY_ID> --apiIssuer <ISSUER_ID>
gym runs validation by default. Common failures: missing privacy manifest, missing
usage descriptions, encryption-export gaps, wrong provisioning profile, deprecated APIs.
→ references/PRIVACY-MANIFEST.md, references/ITMS-ERRORS.md.
Phase 4 — Upload (fastlane pilot / xcrun altool / eas submit)
Gate: build appears in ASC → TestFlight → Builds, processing complete (~5–30 min).
fastlane pilot upload --ipa build/MyApp.ipa \
--skip_waiting_for_build_processing false --skip_submission true
eas submit --platform=ios --latest --non-interactive
Use the ASC API key over Apple-ID + app-specific-password (required in CI). EAS surfaces
Apple-side errors only at the submission URL (OP-29).
⚠ Version-train constraint: the version in this build must be higher than the latest
approved App Store version — TestFlight-only included (ITMS-90062 + ITMS-90186, OP-30).
Bump before re-uploading after an approval.
→ references/PILOT-AND-TESTFLIGHT.md (fastlane + altool), references/EAS-SUBMISSION.md.
Phase 5 — TestFlight verification
Gate: build installs and launches on at least one real device via TestFlight.
- Internal testing (≤100 testers, no review) — use first.
- External testing (≤10K, Beta App Review for the first build of a version) — only when needed.
- Verify launch, primary flow, no immediate crash. Crash reports: ASC → TestFlight → Crashes.
→ references/PILOT-AND-TESTFLIGHT.md.
Phase 6 — Metadata
Gate: all required ASC fields populated.
For keyword research, listing copywriting, and store-screenshot design, use the
app-store-optimization skill — that's where the ASO craft lives. This phase
covers only the mechanics of getting the fields and assets into ASC.
Three paths — pick once and stick with it: A fastlane deliver (committed source of
truth, repeat releases / CI), B ASC REST API direct (JWT script — mind the 3-step
screenshot protocol OP-22, annual age-rating expansion OP-17/18, the APP_IPHONE_67
device-size enum OP-21), C ASC web UI (recommended first submission; sole
authoritative privacy-label + age-rating questionnaire). EAS builds are garbage-collected
after 30 days (OP-32) — don't sit on metadata. Per-path detail + the full required-field
list (name/subtitle/keywords limits, screenshots, privacy labels, copyright):
DELIVER-AND-METADATA — Phase 6.
Phase 7 — Submit for Review
Gate: submission accepted; state moves PREPARE_FOR_SUBMISSION → WAITING_FOR_REVIEW.
Note: a build showing "Ready to Submit" in TestFlight is not "Submitted" — the
review submission is a separate action (OP-13).
Attach demo-account credentials, review notes, and the phased/manual release choices,
then submit via fastlane deliver --submit_for_review true or the ASC REST 3-call
sequence — the submit is a PATCH … {submitted:true}, not an actions/submit (OP-47),
and a stale UNRESOLVED_ISSUES submission must be cancelled first (OP-48). Exact
commands + REST calls + post-submit state verification:
DELIVER-AND-METADATA — Phase 7 and
references/ASC-REST-RESOURCES.md.
This is the irreversible action. ALWAYS require explicit user authorization before
firing the final submit — never submit programmatically without confirmation (axiom 12).
Phase 8 — Post-review
Gate: approved + released, OR rejection handled and resubmission queued.
On rejection, references/REJECTIONS.md is the entry point: read the cited guideline
verbatim, reproduce locally against the exact build the reviewer saw, fix the root
cause, scan for the same pattern elsewhere, then resubmit. Do all four before replying.
References
-
kernel-axioms.md — the 12 operating axioms in full (war stories, exact error strings, OP cross-references).
-
quick-start.md — copy-paste bare-bones / fastlane / EAS command sequences + one-time ASC API key setup.
-
PRE-FLIGHT.md — Apple Developer / ASC setup, certs, provisioning, bundle-ID hygiene, credential sanity-check, CLI-vs-web-UI automation coverage.
-
FRAMEWORK-BUILDS.md — Native / RN / Expo / Flutter / Capacitor pre-iOS-build steps + dependency-install errors.
-
FASTLANE-SETUP.md — Bundler-managed install, Appfile, lane structure, recommended lanes.
-
EAS-SUBMISSION.md — EAS Build + Submit for Expo: config, polling, error reading, fastlane migration.
-
MATCH-AND-SIGNING.md — fastlane match, cert storage/sync, manual-signing fallback, common signing errors.
-
GYM-AND-ARCHIVE.md — gym config, ExportOptions.plist templates, raw xcodebuild archive/-exportArchive.
-
PILOT-AND-TESTFLIGHT.md — pilot/altool upload, JWT minting, the 3-state poll loop, tester groups, Beta App Review, version-train semantics, ASC state verification.
-
DELIVER-AND-METADATA.md — deliver layout, screenshot capture (3 paths) + upload/reorder/replace protocols, age-rating, the submit (PATCH {submitted:true}), phased-release curve, idempotent diff-before-write, ASC enum/limit reference.
-
PRIVACY-MANIFEST.md — PrivacyInfo.xcprivacy, required-reason APIs + reason codes, the enumerated "commonly used SDK" list, the iOS-26/Xcode-26 SDK floor-version table, third-party SDK signatures.
-
ITMS-ERRORS.md — Catalog of common ITMS-XXXXX errors/warnings (incl. 90475, 90348, the iOS-17 split permission keys, non-ITMS archive errors) with cause / fix / prevention.
-
ASC-API.md — Secrets-hygiene model, ~/.asc_secrets, the safe JWT client, the 401/403 troubleshooting table, OpenAPI-template script, asc-mcp + the asc community CLI.
-
ASC-REST-RESOURCES.md — ongoing-management REST: customer reviews + AI summaries, gzip-TSV sales/finance reports, in-app-events/custom-product-pages/app-clips, recovering a stuck submission.
-
MACOS-DISTRIBUTION.md — MAS .pkg (cert pools, embed profile, SwiftPM 409, actool 90546/90236), Developer-ID notarization (hardened runtime, notarytool, staple+re-zip, broken-trust repair), SwiftPM .app packaging, Sparkle appcast.
-
XCODE-CLOUD.md — Apple-native CI: the three ci_scripts/, the CI_* env table, the two release scripts (WhatToTest, version↔tag), workflows, troubleshooting, the compute-hour cost model.
-
REJECTIONS.md — App Review Guideline routing (2.1 / 4.0 / 4.3 / 5.1.1 / 3.1.1 …), the four-step response loop, fix-time/strategy/seasonal tables, named-AI consent, Resolution Center templates, appeals.
-
OPERATOR-PATTERNS.md — Session-mined gotchas in OP-N format (OP-1 … OP-63). Placeholder-icon traps, cloud-signing fragility, ASC API quirks, screenshot upload protocol, age-rating discovery, EAS traps, zero-fastlane Flutter flow, XcodeGen/native-Swift signing, the correct submit endpoint (OP-47), cancel-stale-submission (OP-48), server-authoritative build numbers (OP-61), extension 90348, locale crash, and more.
Reading order by project type:
- Any first submission: OP-1, OP-4, OP-7, OP-17, OP-22, OP-47, axiom 12 +
ASC-API.md
- Flutter /
altool zero-fastlane: OP-34, OP-35, OP-36, OP-37, OP-38, OP-46, OP-52, OP-60
- Expo / EAS: OP-28, OP-29, OP-30, OP-31, OP-32, OP-33
- Native Swift / XcodeGen: OP-39 → OP-46, OP-54, OP-55, OP-57, OP-61, OP-62
- Resubmit after rejection: OP-47, OP-48, OP-49 +
REJECTIONS.md
- macOS / Xcode Cloud:
MACOS-DISTRIBUTION.md, XCODE-CLOUD.md