ns-ios-deploy-app - App Store Connect deployment for NowStack Mobile

SkillCloud & infra

This skill does not use EAS Submit for Apple uploads. The target flow is:

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the ns-ios-deploy-app - App Store Connect deployment for 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-ios-deploy-app/SKILL.md and read by ahel’s review.

This skill does not use EAS Submit for Apple uploads. The target flow is:

  1. Build or obtain a signed production .ipa.
  2. Authenticate asc with App Store Connect.
  3. Use asc to resolve the app, upload/publish the build, sync screenshots/metadata where possible, validate readiness, and submit.

Build artifact generation is OS-aware: macOS may use local Xcode or local EAS, while Windows/Linux must load ns-setup-expo and use EAS cloud to produce the .ipa. 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:

VariableTypeDescription
{app_name}stringApp name from SiteConfig.title / Expo config.
{slug}stringExpo slug and URL scheme from SiteConfig.slug.
{bundle_id}stringiOS bundle identifier from SiteConfig.bundleId and ios.bundleIdentifier.
{apple_team_id}stringApple Developer Team ID from SiteConfig.appleTeamId.
{app_store_app_id}stringNumeric App Store Connect app ID / Apple ID.
{version}stringApp Store version string, usually from mobile-app/package.json / Expo config.
{build_id}stringApp Store Connect build ID after upload/processing.
{ipa_path}stringSigned production .ipa path to upload.
{convex_prod_url}stringProduction Convex cloud URL for EXPO_PUBLIC_CONVEX_URL.
{convex_prod_site_url}stringProduction Convex site URL for EXPO_PUBLIC_CONVEX_SITE_URL.
{iap_product_id}stringApple IAP product ID from SiteConfig.payment.iapProductId.
{asc_key_id}stringApp Store Connect API key ID. Secret metadata; do not commit.
{asc_issuer_id}stringApp Store Connect API issuer ID. Secret metadata; do not commit.
{asc_p8_path}stringLocal path to the .p8 API private key. Never commit.
{dry_run}booleanIf true, print plans and run dry-run commands only.
</state_variables>

<critical_safety>

  • Never commit App Store Connect .p8 keys, Apple account passwords, app-specific passwords, certificates, provisioning profiles, export option files with secrets, or .env files 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 any asc web ... --confirm command until the user explicitly confirms the app ID, bundle ID, Apple team, version, IPA path, production Convex URLs, screenshots, metadata, and IAP product.
  • Prefer asc dry 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.bundleId equals ios.bundleIdentifier in generated Expo config.
  • SiteConfig.slug equals the Expo scheme used by screenshot/deep-link automation.
  • SiteConfig.appleTeamId belongs to the intended Apple Developer team.
  • SiteConfig.easProjectId being 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, and convex/payments/iap.ts are 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 table to resolve {app_store_app_id}.
  • asc status --app "{app_store_app_id}" --output table for 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 table for readiness.
  • asc validate iap --app "{app_store_app_id}" --output table when IAP is enabled.
  • asc validate subscriptions --app "{app_store_app_id}" --output table if 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-screenshots creates iOS PNGs and manifest.json.
  • docs/templates/app-store-metadata.example.json remains the repo source template for copy/review details.
  • asc is 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. Detect the OS before choosing the build path:

uname -s || node -p "process.platform"
  • macOS / Darwin: local Xcode/Expo or local EAS builds are allowed when signing/tooling are ready. Prefer local/Xcode or Xcode Cloud when the user wants no EAS cloud credits.
  • Windows/Linux: do not attempt local iOS production builds. Load/follow .agents/skills/ns-setup-expo/SKILL.md, verify eas-cli, eas whoami, linked easProjectId, and expo-doctor, then use EAS cloud to produce the .ipa.

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

Windows/Linux required cloud path, and optional macOS fallback only if the user explicitly allows EAS cloud 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}" or asc 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 asc command outputs in the release summary.
  • Restore dev env if npm run env:prod changed local files:
cd mobile-app
npm run env:dev

</post_submit_checklist>

<failure_modes>

  • asc is missing: install with brew install asc or the install script.
  • asc auth status --validate fails: 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 appstore cannot attach/submit: build processing is incomplete; rerun with --wait or monitor with asc status.
  • asc validate blocks 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 or asc 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 .ipa exists for the intended bundle ID/team.
  • asc auth status --validate succeeds.
  • asc publish appstore --dry-run or asc review submit --dry-run is clean before mutation.
  • asc publish appstore --submit --confirm or asc review submit --confirm completes 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-ios-deploy-app
Source
github.com/melvynx/saveit.now