Skip to content

Build prescan checks

Before Capgo Cloud Build uploads your project, the CLI runs a prescan that catches credential, project, and store-config problems locally.

It also runs standalone:

Terminal window
npx @capgo/cli@latest build prescan <appId> --platform ios

There are 80 checks today. Prefer ignoring individual check ids over turning the whole scan off.

Terminal window
# Skip one check entirely (example: intentional Capacitor server.url / Next.js shell)
npx @capgo/cli@latest build request <appId> --platform ios \
--prescan-skip ios/capacitor-server-url-shipped
# Run the check but never block on it (error becomes warning)
npx @capgo/cli@latest build request <appId> --platform ios \
--prescan-warn ios/capacitor-server-url-shipped
# Repeatable or comma-separated
npx @capgo/cli@latest build request <appId> --platform ios \
--prescan-skip ios/capacitor-server-url-shipped \
--prescan-warn ios/capacitor-allow-navigation-wildcard,ios/plist-ats-arbitrary-loads

Standalone aliases on build prescan:

Terminal window
npx @capgo/cli@latest build prescan <appId> --platform ios \
--skip ios/capacitor-server-url-shipped \
--warn ios/capacitor-server-cleartext

Unknown check ids fail fast with a clear error.

FlagEffect
--no-prescanSkip the entire scan
--prescan-ignore-fatal (or --ignore-fatal on build prescan)Run scan, print report, never block
--fail-on-warningsTreat warnings as fatal (CI)

--no-prescan and --prescan-ignore-fatal hide or bypass all remaining checks. Use per-check overrides instead when you only disagree with one rule.

Use the exact id in --prescan-skip / --prescan-warn.

Gradual enforce means the finding is information-only until 2026-08-14, then it can block builds.

IdPlatformsWhat it checksGradual enforce
shared/apikey-permissionios, androidAPI key can request native buildsβ€”
shared/app-existsios, androidApp id exists and is visible to the API keyβ€”
shared/credentials-savedios, androidRequired iOS/Android credentials are saved locallyβ€”
shared/cap-sync-staleios, androidWeb assets built and Capacitor plugins syncedβ€”
shared/node-linker-layoutios, androidnode_modules layout works with Capacitor native pathsβ€”
shared/bundle-id-consistencyios, androidCapacitor appId matches native bundle id / applicationIdβ€”
IdPlatformsWhat it checksGradual enforce
ios/p12-opensiosiOS .p12 opens with the provided passwordβ€”
ios/p12-expiryiosiOS signing certificate is not expiredβ€”
ios/profile-expiryiosProvisioning profile is not expiredβ€”
ios/profile-bundle-matchiosProvisioning profile bundle id matches the appβ€”
ios/profile-type-vs-modeiosProfile type matches app_store / ad_hoc modeβ€”
ios/cert-profile-pairingiosCertificate is embedded in the provisioning profileβ€”
ios/targets-coverediosAll iOS targets have a provisioning profileβ€”
ios/infoplist-sanityiosInfo.plist has required version / identity keysβ€”
ios/asc-key-validiosApp Store Connect API key fields look validβ€”
ios/asc-key-accessiosASC API key can access the app (remote)β€”
ios/plist-bundle-id-formatiosCFBundleIdentifier format is validYes
ios/plist-version-short-formatiosCFBundleShortVersionString format is validYes
ios/plist-version-build-formatiosCFBundleVersion format is validYes
ios/plist-encryption-complianceiosITSAppUsesNonExemptEncryption is declaredYes
ios/plist-ats-arbitrary-loadsiosNSAllowsArbitraryLoads is not enabled for productionYes
ios/plist-launch-storyboardiosLaunch screen is declaredYes
ios/plist-orientations-multitaskingiosOrientation / multitasking settings are consistentYes
ios/plist-orientations-presentiosUISupportedInterfaceOrientations is declaredYes
ios/plist-display-nameiosDisplay name is setYes
ios/plist-background-modes-sanityiosUIBackgroundModes values look validYes
ios/xcode-deployment-target-capacitoriosiOS deployment target meets Capacitor requirementsYes
ios/xcode-signing-teamiosSigning team is setYes
ios/xcode-bundle-id-mismatch-across-configsiosBundle id is consistent across Xcode configsYes
ios/xcode-enable-bitcode-leftoveriosENABLE_BITCODE leftover is removedYes
ios/xcode-swift-version-sanityiosSwift version setting looks saneYes
ios/xcode-no-app-targetiosXcode project has an application targetYes
ios/xcode-multiple-app-targetsiosMultiple app targets are handled intentionallyYes
ios/entitlements-vs-profile-capabilityiosEntitlements match profile capabilitiesYes
ios/entitlements-aps-environment-vs-modeiosaps-environment matches distribution modeYes
ios/entitlements-associated-domains-formatiosAssociated Domains format is validYes
ios/entitlements-app-groups-formatiosApp Groups format is validYes
ios/capacitor-server-url-shippediosserver.url is not left as a live-reload / remote shell endpoint for store buildsYes
ios/capacitor-server-cleartextiosserver.cleartext is not enabled for productionYes
ios/capacitor-allow-navigation-wildcardiosserver.allowNavigation is not a blanket wildcardYes
ios/pods-not-installediosCocoaPods Pods / workspace are present when using PodsYes
ios/pods-lock-missingiosPodfile.lock pins pod versionsYes
ios/pods-capacitor-missingiosPodfile wires CapacitorYes
ios/spm-package-resolved-missingiosSPM Package.resolved is presentYes
ios/spm-capacitor-dependency-missingiosPackage.swift declares CapacitorYes
ios/appicon-empty-or-placeholderiosAppIcon.appiconset exists and is not emptyYes
ios/appicon-referenced-file-missingiosContents.json icon files exist on diskYes
ios/appicon-marketing-missingios1024Γ—1024 marketing icon existsYes
ios/spm-deployment-target-consistencyiosSPM deployment target is consistentYes
IdPlatformsWhat it checksGradual enforce
android/keystore-opensandroidAndroid keystore opens with provided passwordsβ€”
android/keystore-expiryandroidAndroid signing cert is not expiredβ€”
android/cordova-vars-presentandroidcordova.variables.gradle is present after cap syncβ€”
android/gradle-props-heuristicsandroidgradle.properties heuristics for common build breaksβ€”
android/play-sa-jsonandroidPlay service-account JSON is present when configuredβ€”
android/flavor-existsandroidRequested product flavor existsβ€”
android/agp8-package-attrandroidManifest package= attribute removed for AGP 8+β€”
android/manifest-well-formedandroidAndroidManifest.xml parsesβ€”
android/manifest-tag-typoandroidCommon manifest tag typosβ€”
android/manifest-namespace-uriandroidxmlns:android namespace URI is correctβ€”
android/manifest-missing-prefixandroidAndroid attributes use the android: prefixβ€”
android/manifest-exported-missingandroidandroid:exported is set where requiredβ€”
android/manifest-multiple-uses-sdkandroidOnly one uses-sdk elementβ€”
android/manifest-duplicate-componentandroidNo duplicate componentsβ€”
android/manifest-unique-permissionandroidCustom permissions are uniqueβ€”
android/manifest-hardcoded-debuggableandroiddebuggable=true not shippedβ€”
android/manifest-mock-locationandroidACCESS_MOCK_LOCATION not shippedβ€”
android/manifest-exported-unprotectedandroidExported components are protectedβ€”
android/manifest-query-all-packagesandroidQUERY_ALL_PACKAGES justificationβ€”
android/manifest-deeplink-validandroidDeeplink intent-filters look validβ€”
android/applicationid-presentandroidapplicationId is declared in app/build.gradleβ€”
android/capacitor-build-gradle-appliedandroidcapacitor.build.gradle exists when appliedβ€”
android/gradle-wrapper-presentandroidGradle wrapper files are presentβ€”
android/flavor-dimensionsandroidFlavor dimensions are declared when flavors existβ€”
android/google-services-fileandroidgoogle-services.json present when plugin appliedβ€”
android/local-properties-committedandroidlocal.properties is not committed with secretsβ€”
android/sdk-floorsandroidmin/compile/target SDK floors look validβ€”
android/target-sdk-playandroidtargetSdk meets Play requirementsβ€”
android/min-sdk-capacitorandroidminSdk meets Capacitor requirementsβ€”
android/version-fieldsandroidversionCode / versionName are presentβ€”
android/play-sa-accessandroidPlay service account can access the app (remote)β€”

Shipping a native shell that loads a production server.url is a supported Capacitor pattern. Prescan flags ios/capacitor-server-url-shipped because it is often a live-reload leftover.

Acknowledge it without disabling other checks:

Terminal window
npx @capgo/cli@latest build request <appId> --platform ios \
--prescan-skip ios/capacitor-server-url-shipped

Or keep visibility as a warning:

Terminal window
npx @capgo/cli@latest build request <appId> --platform ios \
--prescan-warn ios/capacitor-server-url-shipped