Deploy iOS App - NowStack Mobile
SkillCloud & infraThis skill does not use EAS Submit for Apple uploads. The target flow is:
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Deploy iOS App - NowStack Mobile skill
About this capability
One-shot NowStack Mobile iOS deployment with asc App Store Connect CLI. Use when preparing TestFlight/App Store releases, uploading IPAs, syncing screenshots/metadata, validating review readiness, or submitting the iOS app without EAS Submit.
What this skill tells your AI
The instructions your AI receives, as published by melvynx/saveit.now in .agents/skills/ns-deploy-ios-app/SKILL.md and read by ahel’s review.
This skill does not use EAS Submit for Apple uploads. The target flow is:
- Build or obtain a signed production
.ipa. - Authenticate
ascwith App Store Connect. - Use
ascto resolve the app, upload/publish the build, sync screenshots/metadata where possible, validate readiness, and submit.
EAS may appear only as an optional fallback to produce an .ipa if the user explicitly asks for it. App Store Connect automation belongs to asc.
<when_to_use> Use this workflow when:
- Shipping NowStack Mobile to TestFlight or App Review.
- Preparing the first iOS App Store release.
- Re-running an iOS submit after metadata, screenshots, IAP, privacy, or build changes.
- The user says: "deploy iOS", "publish iOS", "submit to App Store", "use asc", "asccli", "App Store Connect CLI", or asks for the iOS store deployment skill.
Do NOT use this for:
- Android/Google Play submissions (use
ns-deploy-android-app). - Local simulator/dev builds (
npm run ios,npx expo start). - EAS Submit unless the user explicitly overrides this skill.
- Creating or submitting real App Store resources without a dry run and explicit confirmation. </when_to_use>
<state_variables> Persist these values across the workflow:
| Variable | Type | Description |
|---|---|---|
{app_name} | string | App name from SiteConfig.title / Expo config. |
{slug} | string | Expo slug and URL scheme from SiteConfig.slug. |
{bundle_id} | string | iOS bundle identifier from SiteConfig.bundleId and ios.bundleIdentifier. |
{apple_team_id} | string | Apple Developer Team ID from SiteConfig.appleTeamId. |
{app_store_app_id} | string | Numeric App Store Connect app ID / Apple ID. |
{version} | string | App Store version string, usually from mobile-app/package.json / Expo config. |
{build_id} | string | App Store Connect build ID after upload/processing. |
{ipa_path} | string | Signed production .ipa path to upload. |
{convex_prod_url} | string | Production Convex cloud URL for EXPO_PUBLIC_CONVEX_URL. |
{convex_prod_site_url} | string | Production Convex site URL for EXPO_PUBLIC_CONVEX_SITE_URL. |
{iap_product_id} | string | Apple IAP product ID from SiteConfig.payment.iapProductId. |
{asc_key_id} | string | App Store Connect API key ID. Secret metadata; do not commit. |
{asc_issuer_id} | string | App Store Connect API issuer ID. Secret metadata; do not commit. |
{asc_p8_path} | string | Local path to the .p8 API private key. Never commit. |
{dry_run} | boolean | If true, print plans and run dry-run commands only. |
| </state_variables> |
<critical_safety>
- Never commit App Store Connect
.p8keys, Apple account passwords, app-specific passwords, certificates, provisioning profiles, export option files with secrets, or.envfiles containing secrets. - Never print full secret values. Mask key IDs, issuer IDs, tokens, and file paths when summarizing.
- Do not run
asc publish appstore --submit --confirm,asc review submit --confirm, or anyasc web ... --confirmcommand until the user explicitly confirms the app ID, bundle ID, Apple team, version, IPA path, production Convex URLs, screenshots, metadata, and IAP product. - Prefer
ascdry runs and validation before mutation. - Treat
asc web ...commands as optional escape hatches for App Store Connect web-only gaps. Use them only when the user is knowingly operating with their Apple session. </critical_safety>
gh repo view --json nameWithOwner,defaultBranchRef || true
git status --short --branch
node --version
npm --version
command -v asc && asc version
asc auth status --validate || asc auth doctor || true
cd mobile-app && npx expo config --type public
Read and verify these files:
site-config.ts
mobile-app/app.config.ts
mobile-app/package.json
mobile-app/lib/iap.ts
convex/payments/iap.ts
docs/templates/app-store-metadata.example.json
docs/templates/store-screenshot-manifest.example.json
Confirm:
SiteConfig.bundleIdequalsios.bundleIdentifierin generated Expo config.SiteConfig.slugequals the Expo scheme used by screenshot/deep-link automation.SiteConfig.appleTeamIdbelongs to the intended Apple Developer team.SiteConfig.easProjectIdbeing placeholder is not a blocker if this flow is not using EAS.- Production Convex URLs are known before the IPA is built.
SiteConfig.payment.iapProductId, StoreKit config, andconvex/payments/iap.tsare aligned.- Screenshots exist, are fresh, and passed AI visual QA.
- App Store metadata/review details/privacy/IAP status are ready enough for
asc validate.
<install_and_auth>
If asc is missing, install it:
brew install asc
or:
curl -fsSL https://asccli.sh/install | bash
If {asc_key_id}, {asc_issuer_id}, or {asc_p8_path} are unknown, run the ns-find-asc-credentials skill first — it locates .p8 keys on disk, reads the issuer ID from the user's signed-in browser session (App Store Connect web UI, via dev-browser CDP), and verifies the key is active before login.
Authenticate with an App Store Connect API key:
asc auth login \
--name "NowStack" \
--key-id "KEY_ID" \
--issuer-id "ISSUER_ID" \
--private-key "/secure/local/AuthKey_KEY_ID.p8" \
--network
For CI/headless shells where keychain access is not available:
asc auth login \
--bypass-keychain \
--name "NowStack CI" \
--key-id "KEY_ID" \
--issuer-id "ISSUER_ID" \
--private-key "/secure/local/AuthKey_KEY_ID.p8"
Then validate:
asc auth status --validate
asc auth doctor
asc apps list --output table
</install_and_auth>
<app_store_connect_setup>
Use asc as the Apple control plane:
asc apps list --output tableto resolve{app_store_app_id}.asc status --app "{app_store_app_id}" --output tablefor release state.asc localizations list --app "{app_store_app_id}"for metadata/localization status.asc screenshots list --app "{app_store_app_id}"for store media status.asc validate --app "{app_store_app_id}" --version "{version}" --platform IOS --output tablefor readiness.asc validate iap --app "{app_store_app_id}" --output tablewhen IAP is enabled.asc validate subscriptions --app "{app_store_app_id}" --output tableif subscriptions are used.
Manual or web-session gates that may still exist:
- Apple Developer enrollment and team/legal agreements.
- First app record creation if no public/API path is available for the current account.
- App Privacy publish state if public API validation cannot prove it.
- First-review IAP selection if Apple requires selecting the IAP on the app-version page. </app_store_connect_setup>
<metadata_and_screenshot_automation>
Before binary publish or review submission, run .agents/skills/ns-generate-store-screenshots and require its manifest to be upload-ready.
Automation target:
ns-generate-store-screenshotscreates iOS PNGs andmanifest.json.docs/templates/app-store-metadata.example.jsonremains the repo source template for copy/review details.ascis the preferred tool for App Store Connect metadata, localizations, screenshots, build upload, validation, and submission.- Keep raw screenshots separate from framed marketing screenshots. Upload only the user-approved set. </metadata_and_screenshot_automation>
<build_ipa>
This skill needs a signed production .ipa. Prefer local/Xcode or Xcode Cloud when the user wants no EAS.
Local Expo/Xcode path:
cd mobile-app
npm run env:prod
npx expo prebuild --clean --platform ios
Then archive/export with Xcode or xcodebuild. Keep ExportOptions.plist and signing material free of secrets and confirm the exact workspace/scheme before running destructive clean/archive steps.
Optional Xcode Cloud path:
asc xcode-cloud run --app "{app_store_app_id}" --workflow "CI" --branch "main" --wait
Optional fallback only if the user explicitly allows EAS for build artifact generation:
cd mobile-app
npm run env:prod
npx eas build --platform ios --profile production --non-interactive
Do not use npx eas submit. Once the .ipa exists, deployment continues with asc.
</build_ipa>
<asc_publish_flow> Before any mutation, run a dry run:
asc publish appstore \
--app "{app_store_app_id}" \
--ipa "{ipa_path}" \
--version "{version}" \
--submit \
--dry-run \
--output table
If the dry run is clean and the user confirms:
asc publish appstore \
--app "{app_store_app_id}" \
--ipa "{ipa_path}" \
--version "{version}" \
--submit \
--confirm
Add --wait when the command should wait for build processing before attaching/submitting:
asc publish appstore \
--app "{app_store_app_id}" \
--ipa "{ipa_path}" \
--version "{version}" \
--submit \
--wait \
--confirm
If the user wants a checkpoint before review submission, stage first:
asc release stage \
--app "{app_store_app_id}" \
--version "{version}" \
--build "{build_id}" \
--metadata-dir "./metadata/version/{version}" \
--dry-run \
--output table
asc release stage \
--app "{app_store_app_id}" \
--version "{version}" \
--build "{build_id}" \
--metadata-dir "./metadata/version/{version}" \
--confirm
Then submit explicitly:
asc review submit --app "{app_store_app_id}" --version "{version}" --build "{build_id}" --dry-run --output table
asc review submit --app "{app_store_app_id}" --version "{version}" --build "{build_id}" --confirm
</asc_publish_flow>
<post_submit_checklist>
After asc publish appstore or asc review submit succeeds:
- Run
asc status --app "{app_store_app_id}" --output table. - Run
asc submit status --version-id "{version_id}"orasc submit status --id "{submission_id}"if available. - Confirm the build appears in TestFlight/App Store Connect.
- Resolve processing, export compliance, App Privacy, age rating, pricing/availability, screenshot, review-detail, IAP, or subscription warnings.
- Test Apple Sign In, onboarding, Convex connectivity, paywall, purchase restore/finish behavior, and account deletion.
- Record the app ID, version, build ID, submission ID, IPA path, release notes, and
asccommand outputs in the release summary. - Restore dev env if
npm run env:prodchanged local files:
cd mobile-app
npm run env:dev
</post_submit_checklist>
<failure_modes>
ascis missing: install withbrew install ascor the install script.asc auth status --validatefails: API key ID, issuer ID, private key path, keychain storage, or network access is wrong.- Build uploads to the wrong app:
{app_store_app_id}, bundle ID, or Apple team is mismatched. asc publish appstorecannot attach/submit: build processing is incomplete; rerun with--waitor monitor withasc status.asc validateblocks submission: fix metadata, screenshots, review details, content rights, encryption, app availability, App Privacy, IAP, or subscription readiness.- App Review rejects payments: iOS production uses Stripe instead of Apple IAP, or IAP/subscription products are incomplete.
- First-review IAP/subscription gaps: use
asc validate iap,asc validate subscriptions, and the relevant attach/review commands; some first-time selections may still require App Store Connect UI orasc web ...with user approval. - Production app points at dev backend: the IPA was built before production Convex URLs were set.
- Credentials leak risk:
.p8, passwords, app-specific passwords, or signing materials were stored in tracked files. </failure_modes>
<success_metrics>
- A signed production
.ipaexists for the intended bundle ID/team. asc auth status --validatesucceeds.asc publish appstore --dry-runorasc review submit --dry-runis clean before mutation.asc publish appstore --submit --confirmorasc review submit --confirmcompletes for the intended app/version.- App Store Connect/TestFlight shows the build under the intended app/version.
- IAP product ID, bundle ID, Convex prod URLs, privacy/support URLs, screenshots, review details, and metadata are aligned.
- No secrets are committed or printed. </success_metrics>
Signals
- GitHub stars
- 31
- Forks
- 5
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
ns-deploy-ios-app- Source
- github.com/melvynx/saveit.now