10 KiB
| name | description |
|---|---|
| appstore-first-release | Step-by-step first (and later) App Store release of a mobile app or game - App Store Connect API key, bundle id, app record, signing, build and upload with the API key (apple signing, apple build, apple upload), TestFlight, version + listing text in many locales, screenshots, age rating, App Privacy, review details, in-app purchases with the first version, and submitting for review. Use when the user wants to publish, release, upload or set up an iOS app or game on the App Store or TestFlight, or hits App Store Connect API errors. |
App Store: first release
The CLI is storebound (on PATH while the plugin is enabled; otherwise bunx storebound in a project that has it,
or bun <toolchain>/cli/index.ts; agents can also use the storebound mcp tools).
Config: storebound.config.ts; credentials: ASC_KEY_ID, ASC_ISSUER_ID, ASC_P8 (env or
.storebound/credentials.json, gitignored). All commands are idempotent and have --dry. Run storebound check first.
Do it, don't ask (first rule in AGENTS.md / docs/agents-core.md of the toolchain): you run every step below
yourself, API steps with storebound and UI steps in App Store Connect with your browser tool, and verify each. The
owner only presses Submit for Review, Release, App Privacy Publish, cancels a submission or accepts agreements, and
answers the compliance facts no file proves, all in one batch at the start.
Steps (API = storebound, UI = App Store Connect, driven by you with your browser tool; Local = this machine)
- UI · API key. App Store Connect > Users and Access > Integrations > App Store Connect API > Team Keys > +
(Admin or App Manager). Download
AuthKey_<KEYID>.p8once, keep it in~/.appstoreconnect/private_keys/, note the Key ID and Issuer ID. The same key signs builds (-allowProvisioningUpdates). - API · Bundle id.
storebound apple bundleregisters it (Certificates, Identifiers & Profiles). - UI · App record. Apps > + > New App: iOS, name, primary language, the bundle id, SKU. No API for this.
The name is unique on the App Store: when App Store Connect says it is "already being used", ask the owner for a
longer App Store name (30 characters at most, e.g. "STAR DASH: Stone Age to 2100"), set it as
apple.nameand fill again (storebound console fill apple-app-record).app.namestays the Play and on-device name;apple listingsendsapple.namefor every locale without its own### nameblock, andstorebound checkflags a name over 30 characters. Thenstorebound apple statusfinds it (put the Apple ID inapple.appIdto skip the lookup). - Local · Info.plist.
ITSAppUsesNonExemptEncryptionwith the true answer (export-complianceskill;NOonly when the app uses nothing beyond OS / HTTPS encryption) so builds arrive answered;NSUserTrackingUsageDescriptionif ads use the IDFA; privacy policy reachable inside the app (guideline 5.1.1). - Local · Sign, build + upload (Mac with Xcode; the API key signs, no Xcode account login needed). Details and
the manual-signing route:
build-and-signskill.storebound apple signing status # capabilities, certificate with a key on this Mac, profiles storebound apple build --version 1.0.0 --dry # project + scheme found, next build number, ExportOptions.plist storebound apple build --version 1.0.0 # xcodebuild archive + exportArchive -> build/ios/export/<version>-<build>/*.ipa storebound apple upload --dry # then without --dry (asks): API build upload, waits for VALIDapple buildtakes the build number fromstorebound apple next-buildunless--build-number Nis given, and prints it at the end: note it, every later step selects that exact build, never "the latest". The generated ExportOptions.plist usesmethodapp-store-connect,destinationexport, your team and the signing style ofapple.signing.style(automatic by default). Processing takes 5-30 min;apple uploadwaits for it. - API · TestFlight. Put an internal group with
allBuilds: trueinapple.testflight.groupsand runstorebound apple testflight groups sync: every new build reaches the team automatically. External testers, What to Test, Test Information and Beta App Review: the testflight skill. Sandbox testers stay UI: Users and Access > Sandbox. - API · Version + text. Fill
store/appstore.md, thenstorebound apple listing --version 1.0.0 --build 3(version, copyright, MANUAL release, the build with exactly that number, name / subtitle / privacy URL, description / keywords / promo / URLs). Run it with--dryfirst and show the owner the plan: the version decision (keep, update the editable version's string, create, or refuse with the reason), the build, and per locale create / update with old -> new per field. Locales still markedstatus=draft/status=translateare skipped untillisting reviewed(--include-draftsonly when the owner says so). Then run it yourself with--yes: it applies exactly that plan. Thenstorebound apple release --phased on: manual release + phased release is the default for every version (release-management). - API · Screenshots.
store-screenshotsskill, thenstorebound apple screenshots > .storebound/asc-shots.log 2>&1 &(6.9" + 6.5" per locale, MD5-idempotent). - API · App info.
storebound apple appinfo(--dryfirst: old -> new per field): categories, age rating declaration, content rights, Free price, all territories. The first availability record of a new app may be refused by the public API (an error on POST /v2/appAvailabilities); then set it once in App Store Connect > Pricing and Availability with your browser tool and re-run (later runs only read it). - API · Review details.
storebound apple review-details(contact from.storebound/credentials.jsonreviewContact, or--contact-from <Apple ID of another app of the team>; notes from the config). Apps behind a sign-in: the demo account from.storebound/(review-accessskill). Apps with accounts: in-app deletion (account-deletionskill). - API · In-app purchases and subscriptions.
store-iap-setupandstore-subscriptionsskills. First IAPs and subscriptions go to review with this version:storebound apple iap-submit --with-version --dry, then (after the owner's yes, since it submits)storebound apple iap-submit --with-version --yes. On a real first release (2026-10-12) it added the IAPs to the draft submission that already held version 1.0.0 and submitted them, first try. Not the console: its IAP "Add for Review" menu did not react to scripted clicks, and the version page no longer has an "In-App Purchases and Subscriptions" section. - UI · App Privacy.
store-declarationsskill (nutrition labels; you fill and save them), then the owner presses Publish. - Preflight.
storebound validate --appleuntil it shows no blocker (store-preflight). - Submit.
storebound apple submit --build <n>(dry run: the plan table with the build you uploaded, by its number, the version and the ready IAPs in one review submission), then the owner's yes for the same command with--yes; with IAPsapple iap-submit --with-version --yesdoes the same without attaching a build (step 11). In the desktop app the owner presses Releases > Submit for review (plan, then a system dialog). Release type MANUAL means the owner presses "Release" after approval. - Verify + wait.
storebound apple status: version WAITING_FOR_REVIEW, IAPs WAITING_FOR_REVIEW, one review submission.storebound apple status --wait-reviewpolls until approved (exit 0) or rejected (exit 1,review-rejections). Approved: the owner releases (release-management).
Gotchas
- The app record cannot be created via API; the bundle id can.
- First consumable / non-consumable IAPs must be submitted together with an app version. The deprecated
inAppPurchaseSubmissionsanswersFIRST_*_MUST_BE_SUBMITTED_ON_VERSION;storebound apple iap-submit --with-versionputs both into one review submission throughreviewSubmissionItems(worked on a real first release, 2026-10-12). The console route is broken for agents: the IAP "Add for Review" menu ignored scripted clicks and the version page has no "In-App Purchases and Subscriptions" section any more. If the version was already submitted without them: cancel the review submission (storebound apple status --cancel-submission <id>, the owner's yes), wait a minute, thenapple iap-submit --with-version(pitfall 28). - Rejected (Invalid Binary, a crash, ...): the review submission stays open with UNRESOLVED_ISSUES and keeps the
version and its IAPs. Upload a fixed build, then
storebound apple resubmit --build <n>(dry run with the plan table), and after the owner's yes--build <n> --yes: it attaches build n, reuses that submission (no second draft), adds only missing items, marks the REJECTED version item resolved (Apple refuses every submit with "not ready to be submitted yet" until it is; IAP items with--resolve-iaps) and resubmits, retrying only while nothing is left REJECTED (pitfall 30,review-rejections).apple iap-submitreuses it the same way. An empty draft (0 items) cannot be canceled and is harmless. - App Privacy (data types, purposes, linked, tracking) is UI-only and must be published, not just saved.
- Export compliance unanswered = "Missing Compliance":
storebound apple encryption(export-compliance). - ITMS-91053 / 91061 privacy manifest emails after upload:
privacy-manifestskill. - Screenshot sizes: 6.9" 1320 x 2868 (
APP_IPHONE_67) is required; 6.5" 1284 x 2778 (APP_IPHONE_65) recommended. PNG without alpha. Up to 10 per set. Apple processes uploads async; failures show as FAILED later. - App Store icon (1024) must have no alpha channel (
storebound iconswrites rgb24). - Limits: name 30, subtitle 30, promotional text 170, keywords 100 characters (not bytes; no spaces after commas), description 4000. No "What's New" on a first version.
- Guideline 5.1.1: the privacy policy link must be inside the app too (Settings > Privacy), not only in the listing.
xcodebuildwith Capacitor needs a UTF-8 locale (export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8).- 500 / 503 from the API happen; storebound retries with backoff.