App Store Release skill for Claude Code
Signed, reviewed and rolled out without surprises. Claude runs mobile releases like a release manager: CI-signed builds with unambiguous version and build numbers, testers on the exact binary that ships, metadata and privacy disclosures that match every SDK, and reviewer notes with demo credentials. Rollouts are phased with crash and ANR halt thresholds set in advance, and bad releases are halted and fixed forward because neither store can roll back.
- name
app-store-release - size178 lines · ≈2,200 tokens
- files2
- licenseMIT
- updated
What Claude sees before loading it
This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.
description: Ships iOS and Android app releases through App Store Connect and Google Play — version and build numbers, code signing (certificates, provisioning, Play App Signing, upload keys), TestFlight and Play testing tracks, store metadata and screenshots, privacy labels, privacy manifests and Data safety, review guideline pitfalls, phased and staged rollouts, monitoring, and fix-forward when a release goes bad. Use when preparing a store submission, a build is rejected, signing fails in CI, setting up fastlane or EAS Submit, or planning a rollout. Try asking
- Prepare our 2.4 release for the App Store and Play Store — what do we still need?
- Apple rejected the build under guideline 5.1.1 — help me fix and respond
- Set up fastlane so CI signs and uploads both apps to TestFlight and internal testing
Use it when
- Preparing a store submission or first public launch
- A build was rejected by App Review or flagged by Play policy
- Code signing or uploads fail in CI
- Planning a phased or staged rollout and halt criteria
Skip it when
- You are cutting releases for a web service or library — use release-management
- You only need OTA JavaScript updates in Expo — use react-native-expo
How to check the result
The submitted build numbers match what testers approved, both consoles show no missing compliance items, and crash and ANR rates are checked against halt thresholds at each rollout step.
The common mistake it prevents
Assuming a bad release can be rolled back, when both stores only allow halting and shipping a new build with a higher build number.
A release is done well when the build is reproducible and signed by CI, version numbers are unambiguous, testers used the exact binary that ships, metadata and privacy disclosures match what the app actually does, rollout is gradual with crash and ANR thresholds that trigger a halt, and the team knows there is no rollback — only halt and fix forward.
Before starting
Confirm with the user before anything irreversible: submitting for review, releasing to production, increasing a rollout to 100%, or changing signing keys. Then gather:
- App identifiers: iOS bundle ID + Team ID; Android
applicationId. - Current live versions on both stores and the last build numbers uploaded.
- Signing setup: Xcode automatic signing, fastlane match, or EAS credentials; Play App Signing status and where the upload keystore lives (and its backup).
- CI credentials: App Store Connect API key (issuer ID, key ID, .p8), Google Play service account JSON with release permissions.
- Platform requirements currently in force: Apple’s minimum Xcode/SDK for uploads (Xcode 26 with the iOS 26 SDK from April 2026) and Google Play’s target API level (API 35 since August 2025; the next level is enforced each August). Check both stores’ latest announcements before release planning.
Versioning
| Platform | User-facing | Build identifier | Rule |
|---|---|---|---|
| iOS | CFBundleShortVersionString (MARKETING_VERSION), e.g. 2.4.0 | CFBundleVersion (CURRENT_PROJECT_VERSION), e.g. 241 | Build number must increase for every upload of the same version |
| Android | versionName, e.g. 2.4.0 | versionCode integer | Must increase for every upload; max 2100000000; never reused |
- Use semver for the marketing version; derive build numbers from CI (run number or a
remote counter such as EAS
appVersionSource: remote) so two branches never collide. - Keep iOS and Android marketing versions in step for support sanity; build numbers can differ.
- Tag the commit:
git tag v2.4.0-ios-241(or one tag per marketing version).
Signing
iOS:
- Distribution needs an Apple Distribution certificate and an App Store provisioning profile containing the app’s capabilities (push, associated domains, app groups). Capability mismatch is the most common archive/upload failure.
- In CI use fastlane
match(certificates in an encrypted repo/bucket) or EAS credentials; avoid personal machines holding the only private key. - Authenticate tools with an App Store Connect API key, not an Apple ID with 2FA.
Android:
- Use Play App Signing: Google holds the app signing key; you sign uploads with an upload key. Back up the upload keystore and passwords in a secrets manager. A lost upload key can be reset through Play Console support; a lost app signing key without Play App Signing cannot be recovered.
- Build an Android App Bundle:
./gradlew bundleRelease→app/build/outputs/bundle/release/app-release.aab. - Deep links and Google sign-in need the app signing SHA-256 from Play Console, not
the upload key (see
deep-links).
Release workflow
- [ ] 1. Freeze scope; bump marketing version; changelog drafted
- [ ] 2. CI builds signed release artifacts (IPA / AAB) from a tagged commit
- [ ] 3. Upload to TestFlight (internal → external) and Play internal → closed track
- [ ] 4. Regression pass on the uploaded binaries (not local builds)
- [ ] 5. Metadata, screenshots, What's New, privacy disclosures updated
- [ ] 6. Submit for review with reviewer notes and demo credentials (confirm with user)
- [ ] 7. Release with phased/staged rollout (confirm with user)
- [ ] 8. Monitor crash-free and ANR rates; widen, halt, or fix forward
- [ ] 9. Post-release: tag, close milestone, update release notes, archive dSYMs/mapping files
Upload commands (pick the project’s tool):
# fastlane
fastlane match appstore --readonly
fastlane gym --scheme App --export_method app-store
fastlane pilot upload --skip_waiting_for_build_processing
fastlane supply --aab app-release.aab --track internal
# Expo
eas build --platform all --profile production
eas submit --platform ios --latest && eas submit --platform android --latest
Upload debug symbols for crash reporting: iOS dSYMs and the Android R8 mapping.txt
(Play Console and your crash tool, e.g. Sentry or Crashlytics).
Testing tracks
| Store | Track | Notes |
|---|---|---|
| Apple | TestFlight internal | Up to 100 team members; no review; available after processing |
| Apple | TestFlight external | Up to 10,000 testers; first build of a version needs Beta App Review; builds expire after 90 days |
| Internal testing | Up to 100 testers; available within minutes | |
| Closed / open testing | Larger groups; new personal developer accounts must run a closed test with at least 12 opted-in testers for 14 days before production access |
Metadata and privacy
- Text limits: iOS name 30, subtitle 30, keywords 100 (comma-separated, no spaces needed), promotional text 170, description 4000. Play title 30, short description 80, full description 4000.
- Screenshots must show the real app UI for the current version. Apple accepts the largest iPhone size (6.9-inch) and scales down; iPad apps need iPad screenshots. Play needs at least two phone screenshots and a 1024×500 feature graphic.
- Privacy: App Store privacy “nutrition label” and Play Data safety form must cover your code and every SDK (analytics, ads, crash reporting). Mismatches are a rejection and policy risk.
- iOS privacy manifest (
PrivacyInfo.xcprivacy) declaring required-reason APIs (UserDefaults, file timestamps, disk space, system boot time) for your app and third-party SDKs; listed SDKs must ship their own signed manifests. - Account deletion: apps that allow account creation must let users delete the account from within the app (Google also requires a web deletion link).
- Purpose strings (
NS*UsageDescription) must explain the user benefit specifically.
Review
- Provide a working demo account and any required setup in App Review Information / Play’s app access section; most “incomplete” rejections are login walls.
- Explain non-obvious features, hardware requirements, or region-limited content in the notes.
- Digital goods and subscriptions generally require in-app purchase; storefront-specific exceptions (US external purchase links, EU alternative terms) change — check the current guidelines before relying on them.
- If rejected, reply in Resolution Center with specifics or fix and resubmit; request an expedited review only for critical fixes.
For the common rejection reasons with concrete fixes, read references/review-rejections.md when a build is rejected or before submitting a first release.
Rollout
| Store | Mechanism | Controls |
|---|---|---|
| App Store | Phased release for automatic updates: 1%, 2%, 5%, 10%, 20%, 50%, 100% over 7 days | Pause (up to 30 days total), release to all; users can still update manually |
| Google Play | Staged rollout percentage you choose | Increase, halt, resume; halted users stay on the old version |
Halt thresholds (set before release, adjust to your baseline):
- Crash-free users drop more than 0.5 percentage points below the previous version.
- Android vitals: user-perceived crash rate above 1.09% or ANR rate above 0.47% (Play’s bad-behavior thresholds affect store visibility).
- A spike in a specific crash signature, payment failures, or support tickets.
There is no store rollback. Fix forward: halt the rollout, ship a new build with a higher
build number/versionCode (reverting code if needed), and use feature flags or OTA updates
(Expo) to disable broken features immediately.
Release notes template
## 2.4.0 (iOS build 241 / Android versionCode 20400)
**What's New (store text, ≤ 4000 chars, user language):**
- Split a bill with friends directly from a receipt
- Faster search on large order histories
- Fixed: totals could show the wrong currency after switching regions
**Internal:**
- Rollout: iOS phased release; Android staged 5% → 20% → 50% → 100% (48 h per step if crash-free ≥ 99.5%)
- Flags: `bill_split` on for 100%; kill switch documented
- Symbols: dSYMs and mapping.txt uploaded to Sentry release 2.4.0
- Owner on call: @dana
Verification
- The binaries testers approved are the ones submitted (same build number / versionCode).
- App Store Connect and Play Console show no missing compliance items (export compliance, content rating, privacy forms, target API).
- After release, crash and ANR dashboards are checked at each rollout step against the halt thresholds, and symbolicated crashes are readable.
Bundled files
Loaded only when a step in the skill needs them. Review them here before installing.
references/review-rejections.md
# Common store rejections and fixes
Read this when a build is rejected or before submitting a first release. Guideline numbers
refer to Apple's App Review Guidelines; Google Play equivalents are named by policy.
Guidelines change — confirm wording in the current documents before quoting them to a
reviewer.
## Apple
| Guideline | Typical rejection | Fix |
|---|---|---|
| 2.1 App Completeness | Crash on launch, broken login, placeholder content, reviewer could not sign in | Test the exact TestFlight build on a clean device and the latest iOS; provide a working demo account and steps; remove "coming soon" screens |
| 2.3 Accurate Metadata | Screenshots show features not in the app, or are marketing images only; keywords stuffed with competitor names | Use real screenshots of this version; remove trademarked/competitor keywords; describe only shipped features |
| 2.3.10 | Mentions of other platforms ("also on Android") in metadata | Remove references to other platforms |
| 2.5.1 Software Requirements | Private APIs or deprecated frameworks | Replace the API; check third-party SDKs for private API use |
| 3.1.1 In-App Purchase | Digital content or subscriptions sold via external payment or unlock codes | Use StoreKit IAP for digital goods; physical goods and person-to-person services may use other payments; follow storefront-specific link entitlements if used |
| 3.1.2 Subscriptions | Missing terms, price, duration, or restore purchases | Show price, period, auto-renewal terms, links to terms and privacy, and a Restore button on the paywall |
| 4.0 Design / 4.2 Minimum Functionality | Thin web wrapper, app duplicates the website without native value | Add native functionality (offline, push, device features) or ship as a website |
| 4.3 Spam | Many near-identical apps or template apps | Consolidate into one app with in-app configuration |
| 4.8 Login Services | Third-party social login without an equivalent privacy-focused option | Offer Sign in with Apple or another login meeting the guideline's privacy requirements |
| 5.1.1 Data Collection | Vague purpose strings, requiring personal data not needed for core function, forced registration before showing value | Specific purpose strings; make registration optional when features do not need an account |
| 5.1.1(v) Account Deletion | Account creation without in-app deletion | Add an in-app path that deletes the account (not just deactivates), with clear confirmation |
| 5.1.2 Data Use and Sharing | Tracking without App Tracking Transparency prompt, or privacy label mismatch | Request ATT before tracking; update the privacy label for all SDKs |
| Guideline 1.2 User-Generated Content | UGC without reporting, blocking, and moderation | Add report and block, a moderation process, and terms users accept |
Responding: in Resolution Center, quote the guideline, state precisely what changed or why
the reviewer's understanding differs, and attach a screen recording when the feature is hard
to reach. Appeals go to the App Review Board when you believe the guideline was misapplied.
## Google Play
| Policy area | Typical rejection or warning | Fix |
|---|---|---|
| Target API level | Update targets an API level below the current requirement | Raise `targetSdk`, handle behavior changes (permissions, edge-to-edge, foreground service types), retest |
| Data safety | Form does not match observed data collection (SDKs) | Audit SDKs, update the form, add disclosures in-app where required |
| Permissions | Sensitive permissions (SMS, call log, all files access, background location, exact alarms) without approved use case | Remove the permission or submit the declaration with a video of the core feature |
| Foreground services | Missing or wrong foreground service type declarations | Declare `android:foregroundServiceType` and the matching permission; justify in the declaration form |
| Account deletion | No in-app deletion or missing web deletion URL | Add both and enter the URL in Play Console |
| Metadata | Misleading title/icon, keyword stuffing, ratings prompts in title | Clean metadata; follow store listing guidelines |
| Payments | Digital goods sold outside Google Play Billing where not permitted | Use Play Billing or a permitted alternative billing program for the region |
| Families / Ads | Ads SDKs not certified for children's apps, or wrong target audience | Set target audience accurately; use certified SDKs |
| Pre-launch report | Crashes on Firebase Test Lab devices | Fix crashes reported in the pre-launch report before promoting |
## Before every first submission
- [ ] Demo account works on a fresh install; any 2FA bypass for reviewers documented
- [ ] Every permission prompt has a specific purpose string and appears only when needed
- [ ] Privacy label / Data safety reviewed against the full SDK list
- [ ] In-app account deletion present if accounts exist
- [ ] Paywall shows price, period, renewal terms, restore, terms and privacy links
- [ ] UGC: report, block, moderation
- [ ] No placeholder text, test endpoints, or debug menus in the release build
- [ ] Metadata and screenshots match the shipped build
About this skill
Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.