swiftship/internal/skills/data/features/asc-testflight-orchestration/SKILL.md
End-to-end release workflows for TestFlight and App Store including build, archive, export, upload, and distribution. Use when asked to publish, submit, distribute to TestFlight, or submit to App Store.
npx skillsauth add abdullah4ai/apple-dev-docs asc-testflight-orchestrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
If the user only asks to add/invite a beta tester (NOT build + upload), skip the full workflow. Follow these steps in exact order:
# 1. Check if there are any builds available
asc builds list --app "APP_ID" --limit 3 --output json
If NO builds exist: Tell the user they need to upload a build first. Offer to run the full build+upload workflow (Step 1-9 below). Do NOT add testers without a build.
If builds exist: Continue with external testing below.
External testing works for any email — the tester does NOT need to be an App Store Connect team member. However, external testing requires Beta App Review before the tester can install.
# 2. List existing external groups, or create one
asc testflight beta-groups list --app "APP_ID" --output json
asc testflight beta-groups create --app "APP_ID" --name "Beta Testers"
# 3. Assign the latest build to the external group
asc builds add-groups --build "BUILD_ID" --group "GROUP_ID"
# 4. Add the tester to the group (works for any email)
asc testflight beta-testers add --app "APP_ID" --email "[email protected]" --group "Beta Testers"
Now you MUST ask the user for confirmation before submitting for Beta App Review. Say:
"I've added [email protected] to the Beta Testers group. To complete the invitation, this build needs to be submitted for Beta App Review (Apple reviews it, typically < 24 hours). Once approved, the tester will automatically receive a TestFlight invitation email. Shall I submit for Beta App Review?"
Wait for the user's response. Only proceed if they confirm:
# 5. Submit for Beta App Review (only after user confirms)
asc testflight review submit --build "BUILD_ID" --confirm
# 6. Check review status
asc testflight review submissions list --build "BUILD_ID"
Do NOT call asc testflight beta-testers invite for external testers — it will fail with "Tester has no installable build" until Beta App Review is approved. Once approved, the tester automatically receives the invitation.
Internal testing is only for people who are already App Store Connect team members. Internal groups auto-receive all builds and testers get instant access (no review). Use this only when the user explicitly asks for internal testing or the tester is a known team member.
asc testflight beta-groups create --app "APP_ID" --name "Internal Testers" --internal
asc testflight beta-testers add --app "APP_ID" --email "[email protected]" --group "Internal Testers"
asc testflight beta-testers invite --app "APP_ID" --email "[email protected]"
Do NOT use asc builds add-groups for internal groups — they auto-receive all processed builds.
xcodebuild archive + xcodebuild -exportArchive (see asc-xcode-build skill).asc auth login or ASC_* env vars).ASC_APP_ID or pass --app explicitly.asc publish testflight --app <APP_ID> --ipa <PATH> --group <GROUP_ID>[,<GROUP_ID>]--wait, --notify, --platform, --poll-interval, --timeoutasc publish appstore --app <APP_ID> --ipa <PATH> --version <VERSION>--wait, --submit --confirm, --platform, --poll-interval, --timeoutThis is a MANDATORY step-by-step workflow. When the user asks to publish/build/upload to TestFlight, you MUST execute ALL steps below in order. Do NOT skip any step. Do NOT claim the app is "already on TestFlight" without verifying. Do NOT stop after planning — execute the commands.
# Find .xcodeproj or .xcworkspace
find . -maxdepth 2 -name "*.xcworkspace" -o -name "*.xcodeproj" | head -5
If a project.yml exists (XcodeGen project), always regenerate the .xcodeproj first:
xcodegen generate
This ensures all build settings (CFBundleIconName, icon assets, etc.) are current in the .xcodeproj.
If a .xcworkspace exists, use -workspace flag. Otherwise use -project flag.
# List available schemes
xcodebuild -list
Pick the main app scheme (not tests, not UI tests).
# Get current build settings
xcodebuild -showBuildSettings -scheme "SCHEME" | grep -E "CURRENT_PROJECT_VERSION|MARKETING_VERSION"
Also check the latest build on ASC:
asc builds list --app "APP_ID" --limit 3 --output json
If the local build number is not higher than the latest uploaded build, increment it:
# Find the project.pbxproj or xcconfig and update CURRENT_PROJECT_VERSION
Check if ITSAppUsesNonExemptEncryption is set. If not, add it to avoid encryption compliance issues:
# Check in Info.plist or build settings
grep -r "ITSAppUsesNonExemptEncryption" . --include="*.plist" --include="*.pbxproj"
If missing, add ITSAppUsesNonExemptEncryption = NO to the app's Info.plist.
xcodebuild clean archive \
-scheme "SCHEME" \
-configuration Release \
-archivePath /tmp/APP_NAME.xcarchive \
-destination "generic/platform=iOS" \
-allowProvisioningUpdates \
AUTHENTICATION_KEY_PATH AUTH_FLAGS_IF_AVAILABLE
If API key authentication flags are provided in the system prompt, include them:
-authenticationKeyPath <path>-authenticationKeyID <id>-authenticationKeyIssuerID <issuer>This step MUST succeed. If it fails, diagnose the error and fix it before proceeding.
cat > /tmp/ExportOptions.plist << 'PLIST'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store-connect</string>
<key>destination</key>
<string>upload</string>
</dict>
</plist>
PLIST
If you know the team ID, add it:
<key>teamID</key>
<string>TEAM_ID</string>
xcodebuild -exportArchive \
-archivePath /tmp/APP_NAME.xcarchive \
-exportPath /tmp/APP_NAME_Export \
-exportOptionsPlist /tmp/ExportOptions.plist \
-allowProvisioningUpdates \
AUTHENTICATION_KEY_PATH AUTH_FLAGS_IF_AVAILABLE
This step MUST succeed. The IPA file will be at /tmp/APP_NAME_Export/APP_NAME.ipa.
asc builds upload --app "APP_ID" --ipa "/tmp/APP_NAME_Export/APP_NAME.ipa"
Wait for the upload to complete.
After upload, the build needs time to process on Apple's servers:
# Check if the build is processed
asc builds latest --app "APP_ID" --output json
If the build is still processing, wait and check again. Use asc builds info --build BUILD_ID to check status.
# 1. Create an external group and assign the build
asc testflight beta-groups create --app "APP_ID" --name "Beta Testers"
asc builds add-groups --build "BUILD_ID" --group "GROUP_ID"
# 2. Add tester to the group (works for any email)
asc testflight beta-testers add --app "APP_ID" --email "[email protected]" --group "Beta Testers"
Now ask the user for confirmation before submitting for Beta App Review:
"I've added the tester to the Beta Testers group. To complete the invitation, this build needs to be submitted for Beta App Review (typically < 24h). Once approved, the tester will automatically receive a TestFlight invitation. Shall I submit?"
# 3. Submit for Beta App Review (only after user confirms)
asc testflight review submit --build "BUILD_ID" --confirm
# 4. Check submission status
asc testflight review submissions list --build "BUILD_ID"
Do NOT call beta-testers invite for external testers — it fails with "Tester has no installable build" until review is approved. Once approved, testers automatically receive the TestFlight invitation.
# Verify the build is on TestFlight
asc builds info --build "BUILD_ID" --output json
Report to the user:
For App Store (not TestFlight), attach the build to a version and submit:
# Attach build to version
asc versions attach-build --version-id <VERSION_ID> --build <BUILD_ID>
# Submit for review
asc submit create --app <APP_ID> --version <VERSION> --build <BUILD_ID> --confirm
# Check or cancel submission
asc submit status --id <SUBMISSION_ID>
asc submit cancel --id <SUBMISSION_ID> --confirm
macOS apps are distributed as .pkg files, not .ipa.
asc builds upload \
--app <APP_ID> \
--pkg <PATH_TO_PKG> \
--version <VERSION> \
--build-number <BUILD_NUMBER> \
--wait
Notes:
--pkg automatically sets platform to MAC_OS..pkg, use asc builds upload --pkg + attach/submit steps.Same as iOS flow:
asc builds list --app <APP_ID> --limit 5
asc versions attach-build --version-id <VERSION_ID> --build <BUILD_ID>
asc review submissions-create --app <APP_ID> --platform MAC_OS
asc review items-add --submission <SUBMISSION_ID> --item-type appStoreVersions --item-id <VERSION_ID>
asc review submissions-submit --id <SUBMISSION_ID> --confirm
Same as iOS flow, use appropriate --platform: VISION_OS or TV_OS.
Before submitting to App Store, verify:
VALID (not processing)See asc-submission-health skill for detailed preflight checks.
After distribution, these commands manage TestFlight access:
asc testflight beta-groups list --app "APP_ID" --paginateasc testflight beta-groups create --app "APP_ID" --name "Beta Testers" (external, default)asc testflight beta-groups create --app "APP_ID" --name "Internal Testers" --internal (team members only)asc testflight beta-testers list --app "APP_ID" --paginateasc testflight beta-testers add --app "APP_ID" --email "[email protected]" --group "Beta Testers"asc testflight beta-testers remove --app "APP_ID" --email "[email protected]"asc builds test-notes create --build "BUILD_ID" --locale "en-US" --whats-new "Test instructions"asc builds test-notes update --id "LOCALIZATION_ID" --whats-new "Updated notes"asc testflight review submit).beta-testers invite for external testers — it fails before review approval. Testers are auto-invited once approved.asc builds add-groups for internal groups — they auto-receive builds.--paginate on large groups/tester lists.--help to verify flags for the exact command.tools
Apple platform skill for docs, WWDC lookup, App Store Connect work, and SwiftUI app generation. Use repo-local `node cli.js` for Apple docs and WWDC search, `appledev store` for App Store Connect workflows, and `appledev build` for app scaffolding or fix loops on macOS. USE WHEN: Apple APIs, WWDC sessions, TestFlight/App Store tasks, or building/fixing Apple-platform apps. DON'T USE WHEN: non-Apple platforms, generic backend work, or general web research. EDGE CASES: docs-only queries use `node cli.js` in this repo, not `appledev`; release workflows use `appledev store`; app scaffolding uses `appledev build`; rules-only requests can read `references/ios-rules/` or `references/swiftui-guides/` progressively without invoking binaries.
tools
All-in-one Apple developer skill with three integrated tools shipped as a single unified binary. (1) Documentation search across Apple frameworks, symbols, and 1,267 WWDC sessions from 2014-2025. No credentials needed. (2) App Store Connect CLI with 120+ commands covering builds (find/wait/upload), TestFlight, pre-submission validate, submissions, signing, subscriptions (family-sharable), IAP, analytics, Xcode Cloud, metadata workflows, release pipeline dashboard, insights, win-back offers, promoted purchases, product pages, nominations, accessibility declarations, pre-orders, pricing filters, localizations update, diff, webhooks with local receiver, workflow automation, and more. Requires App Store Connect API key. (3) Multi-platform app builder (iOS/watchOS/tvOS/iPad/macOS/visionOS) that generates complete Swift/SwiftUI apps from natural language with auto-fix, simulator launch, interactive chat mode, and open-in-Xcode. Requires an LLM API key and Xcode. Includes 38 iOS development rules and 12 SwiftUI best practice guides for Liquid Glass, navigation, state management, and modern APIs. All three tools ship as one binary (appledev). USE WHEN: Apple API docs, App Store Connect management, WWDC lookup, or building iOS/watchOS/tvOS/macOS/visionOS apps from scratch. DON'T USE WHEN: non-Apple platforms or general coding.
testing
watchOS complications: WidgetKit complication families, accessory sizes, timeline providers for watch face. Use when implementing watchOS-specific patterns related to widgets.
development
watchOS haptic feedback: WKInterfaceDevice preset haptic types for wrist-based feedback. Use when implementing watchOS-specific patterns related to haptics.