Capawesome Cloud Set up and manage native builds, live updates, and app store publishing for Capacitor apps using Capawesome Cloud. Prerequisites 1. A Capawesome Cloud account and organization. 2. A Capacitor 6, 7, or 8 app. 3. Node.js and npm installed. 4. For Native Builds : The app must be in a Git repository (GitHub, GitLab, Bitbucket, or Azure DevOps). 5. For Apple App Store Publishing : An active Apple Developer Program membership and an app created in App Store Connect. 6. For Google Play Store Publishing : A Google Play Developer account and an app created in Google Play Console with…

; echo; done\n```\n\nCopy the desired profile:\n\n```bash\ncp ~/Library/MobileDevice/Provisioning\\ Profiles/\u003cprofile-uuid>.mobileprovision ~/Desktop/\n```\n\n### Create in Apple Developer Portal\n\nIf no provisioning profile exists, print the following steps for the user and ask them to confirm when done:\n\n1. Sign in to [Apple Developer](https://developer.apple.com/account).\n2. Navigate to **Certificates, Identifiers & Profiles > Profiles**.\n3. Click **+** to create a new profile.\n4. Select type:\n - **iOS App Development** for development\n - **App Store** for App Store/TestFlight\n - **Ad Hoc** for enterprise/beta distribution\n5. Select App ID, certificates, and (for dev profiles) devices.\n6. Name the profile and click **Generate**.\n7. Download the `.mobileprovision` file.\n\nRepeat for each app extension (each requires its own provisioning profile matching its bundle identifier).\n\n**Note:** Provisioning profiles expire (typically after one year). Regenerate and re-upload if builds fail due to expired profiles.\n\n## Upload via CLI\n\n```bash\nnpx @capawesome/cli apps:certificates:create \\\n --app-id \u003cAPP_ID> \\\n --name \"Production iOS Certificate\" \\\n --platform ios \\\n --type production \\\n --file /path/to/certificate.p12 \\\n --password \u003cCERTIFICATE_PASSWORD> \\\n --provisioning-profile /path/to/profile.mobileprovision\n```\n\nFor apps with extensions, specify multiple provisioning profiles:\n\n```bash\nnpx @capawesome/cli apps:certificates:create \\\n --app-id \u003cAPP_ID> \\\n --name \"Production iOS Certificate\" \\\n --platform ios \\\n --type production \\\n --file /path/to/certificate.p12 \\\n --password \u003cCERTIFICATE_PASSWORD> \\\n --provisioning-profile /path/to/app.mobileprovision \\\n --provisioning-profile /path/to/widget.mobileprovision\n```\n\nOptions:\n- `--type`: `development` or `production`\n- `--file`: Path to `.p12` file\n- `--password`: Password for the `.p12` file\n- `--provisioning-profile`: Path to `.mobileprovision` file (repeatable for multiple targets)\n\n## Upload via Console\n\nNavigate to [Signing Certificates](https://console.cloud.capawesome.io/apps/_/certificates) and provide:\n\n- **Name**: Descriptive name (e.g., \"Production iOS Certificate\")\n- **Platform**: `iOS`\n- **Type**: `Development` or `Production`\n- **Certificate File**: The `.p12` file\n- **Certificate Password**: Password for the `.p12` file\n- **Provisioning Profiles**: One or more `.mobileprovision` files\n\n## Custom Provisioning Profile Mapping\n\nFor apps with multiple targets using non-standard bundle ID patterns, set the `IOS_PROVISIONING_PROFILE_MAP` environment variable to a JSON object mapping bundle IDs to target names:\n\n```json\n{\"com.example.wireguard\":\"WireGuardExtension\",\"com.example.tunnelprovider\":\"PacketTunnel\"}\n```\n\nSet this variable in the build environment. Capawesome Cloud uses these mappings in addition to automatic detection for the main app target.\n\n## List Certificates\n\n```bash\nnpx @capawesome/cli apps:certificates:list --app-id \u003cAPP_ID> --platform ios --json\n```\n\n## Delete a Certificate\n\n```bash\nnpx @capawesome/cli apps:certificates:delete --app-id \u003cAPP_ID> --name \"Production iOS Certificate\" --platform ios --yes\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":11736,"content_sha256":"dd3198b0a03e925f93484e2d01265bdda4eb4e14b1005e92c2db27e35e6a8a42"},{"filename":"references/cli-commands.md","content":"# CLI Commands Reference\n\nInstall: `npm install -g @capawesome/cli@latest`\nUsage: `npx @capawesome/cli \u003ccommand> [options]`\n\n## Contents\n\n- Authentication\n- App Management\n- Build Commands\n- Certificate Commands\n- Environment Commands\n- Destination Commands\n- Deployment Commands\n- Live Update Bundle Commands\n- Channel Commands\n- Device Commands\n- Utility\n\n## Authentication\n\n### login\n\n```bash\nnpx @capawesome/cli login\nnpx @capawesome/cli login --token \u003ctoken> # CI/CD\n```\n\n### logout\n\n```bash\nnpx @capawesome/cli logout\n```\n\n### whoami\n\n```bash\nnpx @capawesome/cli whoami\n```\n\n## App Management\n\n### apps:create\n\n```bash\nnpx @capawesome/cli apps:create [--name \u003cname>] [--organization-id \u003cid>]\n```\n\n### apps:delete\n\n```bash\nnpx @capawesome/cli apps:delete [--app-id \u003cid>] [--yes]\n```\n\n## Build Commands\n\n### apps:builds:create\n\nCreate a new native or web build.\n\n```bash\nnpx @capawesome/cli apps:builds:create [options]\n```\n\nOptions:\n- `--app-id`: App ID\n- `--platform`: `android`, `ios`, or `web`\n- `--type`: Build type\n - Android: `debug`, `release`\n - iOS: `simulator`, `development`, `ad-hoc`, `app-store`, `enterprise`\n- `--git-ref`: Git branch, tag, or commit SHA\n- `--certificate`: Name of the signing certificate to use\n- `--environment`: Name of the environment to use\n- `--destination`: Deployment destination (Android/iOS only)\n- `--channel`: Channel to deploy to (Web only)\n- `--stack`: Build stack (`macos-sequoia` or `macos-tahoe`)\n- `--apk`: Download APK after build (Android, optional file path)\n- `--aab`: Download AAB after build (Android, optional file path)\n- `--ipa`: Download IPA after build (iOS, optional file path)\n- `--zip`: Download zip after build (Web, optional file path)\n- `--json`: Output in JSON format (includes build ID)\n- `--detached`: Exit immediately without waiting for build to complete\n- `--yes, -y`: Skip confirmation prompts\n\n### apps:builds:cancel\n\n```bash\nnpx @capawesome/cli apps:builds:cancel --app-id \u003cAPP_ID> --build-id \u003cBUILD_ID>\n```\n\n### apps:builds:download\n\nDownload build artifacts.\n\n```bash\nnpx @capawesome/cli apps:builds:download [options]\n```\n\nOptions:\n- `--app-id`: App ID\n- `--build-id`: Build ID\n- `--apk`: Download APK (Android, optional file path)\n- `--aab`: Download AAB (Android, optional file path)\n- `--ipa`: Download IPA (iOS, optional file path)\n- `--zip`: Download zip (Web, optional file path)\n\n### apps:builds:logs\n\nDisplay build logs.\n\n```bash\nnpx @capawesome/cli apps:builds:logs --app-id \u003cAPP_ID> --build-id \u003cBUILD_ID>\n```\n\n## Certificate Commands\n\n### apps:certificates:create\n\n```bash\nnpx @capawesome/cli apps:certificates:create [options]\n```\n\nOptions:\n- `--app-id`: App ID\n- `--name`: Certificate name\n- `--platform`: `android`, `ios`, or `web`\n- `--type`: `development` or `production`\n- `--file`: Path to certificate file (`.jks`/`.keystore` for Android, `.p12` for iOS)\n- `--password`: Certificate/keystore password\n- `--key-alias`: Key alias (Android only)\n- `--key-password`: Key password (Android only)\n- `--provisioning-profile`: Path to `.mobileprovision` file (iOS, repeatable)\n- `--yes, -y`: Skip optional prompts\n\n### apps:certificates:list\n\n```bash\nnpx @capawesome/cli apps:certificates:list [--app-id \u003cid>] [--platform \u003cplatform>] [--type \u003ctype>] [--json]\n```\n\n### apps:certificates:get\n\n```bash\nnpx @capawesome/cli apps:certificates:get [--app-id \u003cid>] [--certificate-id \u003cid>] [--name \u003cname>] [--platform \u003cplatform>] [--json]\n```\n\n### apps:certificates:update\n\n```bash\nnpx @capawesome/cli apps:certificates:update [--app-id \u003cid>] [--certificate-id \u003cid>] [--name \u003cname>] [--type \u003ctype>] [--password \u003cpw>] [--key-alias \u003calias>] [--key-password \u003cpw>]\n```\n\n### apps:certificates:delete\n\n```bash\nnpx @capawesome/cli apps:certificates:delete [--app-id \u003cid>] [--certificate-id \u003cid>] [--name \u003cname>] [--platform \u003cplatform>] [--yes]\n```\n\n## Environment Commands\n\n### apps:environments:create\n\n```bash\nnpx @capawesome/cli apps:environments:create --app-id \u003cAPP_ID> --name \u003cNAME>\n```\n\n### apps:environments:list\n\n```bash\nnpx @capawesome/cli apps:environments:list --app-id \u003cAPP_ID> [--json]\n```\n\n### apps:environments:set\n\n```bash\nnpx @capawesome/cli apps:environments:set [options]\n```\n\nOptions:\n- `--app-id`: App ID\n- `--environment-id`: Environment ID\n- `--variable`: `key=value` (repeatable)\n- `--variable-file`: Path to `.env` file\n- `--secret`: `key=value` (repeatable)\n- `--secret-file`: Path to `.env` file with secrets\n\n### apps:environments:unset\n\n```bash\nnpx @capawesome/cli apps:environments:unset [options]\n```\n\nOptions:\n- `--app-id`: App ID\n- `--environment-id`: Environment ID\n- `--variable`: Key to unset (repeatable)\n- `--secret`: Key to unset (repeatable)\n\n### apps:environments:delete\n\n```bash\nnpx @capawesome/cli apps:environments:delete --app-id \u003cAPP_ID> [--environment-id \u003cid> | --name \u003cname>] [--yes]\n```\n\n## Destination Commands\n\n### apps:destinations:create\n\nCreate a new destination for an app.\n\n```bash\nnpx @capawesome/cli apps:destinations:create [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--name` | The name of the destination. |\n| `--platform` | The platform (`android` or `ios`). |\n| `--android-build-artifact-type` | Android build artifact type (`aab` or `apk`). |\n| `--android-package-name` | Android package name. |\n| `--android-release-status` | Android release status (`completed` or `draft`). |\n| `--google-play-track` | Google Play track (`internal`, `alpha`, `beta`, or `production`). |\n| `--google-service-account-key-file` | Path to the Google service account key JSON file. |\n| `--apple-api-key-file` | Path to the Apple API key (`.p8`) file. |\n| `--apple-app-id` | Apple App ID (numeric). |\n| `--apple-app-password` | Apple app-specific password. |\n| `--apple-id` | Apple ID email address. |\n| `--apple-issuer-id` | Apple Issuer ID. |\n| `--apple-team-id` | Apple Team ID. |\n\n### apps:destinations:list\n\n```bash\nnpx @capawesome/cli apps:destinations:list [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--json` | Output in JSON format. |\n| `--limit` | Maximum number of destinations to return. |\n| `--offset` | Offset to start returning destinations from. |\n| `--platform` | Filter by platform (`android` or `ios`). |\n\n### apps:destinations:get\n\n```bash\nnpx @capawesome/cli apps:destinations:get [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--destination-id` | The ID of the destination. |\n| `--json` | Output in JSON format. |\n| `--name` | The name of the destination. |\n| `--platform` | The platform (`android` or `ios`). |\n\n### apps:destinations:update\n\n```bash\nnpx @capawesome/cli apps:destinations:update [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--destination-id` | The ID of the destination. |\n| `--name` | The name of the destination. |\n| `--android-build-artifact-type` | Android build artifact type (`aab` or `apk`). |\n| `--android-package-name` | Android package name. |\n| `--android-release-status` | Android release status (`completed` or `draft`). |\n| `--google-play-track` | Google Play track. |\n| `--apple-api-key-id` | Apple API Key ID. |\n| `--apple-app-id` | Apple App ID. |\n| `--apple-app-password` | Apple app-specific password. |\n| `--apple-id` | Apple ID email. |\n| `--apple-issuer-id` | Apple Issuer ID. |\n| `--apple-team-id` | Apple Team ID. |\n\n### apps:destinations:delete\n\n```bash\nnpx @capawesome/cli apps:destinations:delete [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--destination-id` | The ID of the destination. |\n| `--name` | The name of the destination. |\n| `--platform` | The platform (`android` or `ios`). |\n| `--yes, -y` | Skip confirmation prompt. |\n\n## Deployment Commands\n\n### apps:deployments:create\n\nCreate a new app deployment.\n\n```bash\nnpx @capawesome/cli apps:deployments:create [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--build-id` | The ID of the build to deploy. Alternative to `--build-number`. |\n| `--build-number` | The build number to deploy. Alternative to `--build-id`. |\n| `--channel` | The name of the channel to deploy to (Web only). |\n| `--destination` | The name of the destination to deploy to (Android/iOS). |\n| `--detached` | Exit immediately without waiting for completion. |\n\n### apps:deployments:cancel\n\n```bash\nnpx @capawesome/cli apps:deployments:cancel [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--deployment-id` | The ID of the deployment to cancel. |\n\n### apps:deployments:logs\n\n```bash\nnpx @capawesome/cli apps:deployments:logs [options]\n```\n\nOptions:\n\n| Option | Description |\n|--------|-------------|\n| `--app-id` | The ID of the app. |\n| `--deployment-id` | The ID of the deployment. |\n\n## Live Update Bundle Commands\n\n### apps:liveupdates:upload\n\nUpload a locally built bundle and deploy to a channel.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:upload [options]\n```\n\nOptions:\n- `--app-id`: App ID\n- `--path`: Path to web assets folder or zip\n- `--channel`: Channel to deploy to\n- `--artifact-type`: `zip` (default) or `manifest`\n- `--private-key`: Private key file for code signing\n- `--rollout-percentage`: 0-100 for gradual rollout\n- `--android-min`, `--android-max`, `--android-eq`: Android version code constraints\n- `--ios-min`, `--ios-max`, `--ios-eq`: iOS version constraints\n- `--custom-property`: `key=value` pairs (repeatable)\n- `--git-ref`: Git reference to associate\n- `--expires-in-days`: Auto-delete after N days\n- `--yes`: Skip prompts\n\n### apps:liveupdates:register\n\nRegister a self-hosted bundle URL.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:register [options]\n```\n\nOptions: Same as `upload` plus `--url \u003chttps://...>` (required).\n\n### apps:liveupdates:bundle\n\nGenerate manifest and compress web assets into a zip.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:bundle [--input-path \u003cpath>] [--output-path \u003cpath>] [--overwrite] [--skip-manifest]\n```\n\n### apps:liveupdates:generatemanifest\n\nGenerate a manifest file for delta updates.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:generatemanifest --path \u003cweb-assets-path>\n```\n\n### apps:liveupdates:generatesigningkey\n\nGenerate RSA key pair for code signing.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:generatesigningkey [--key-size 2048|3072|4096] [--public-key-path \u003cpath>] [--private-key-path \u003cpath>]\n```\n\n### apps:liveupdates:rollback\n\nRollback to a previous deployment in a channel.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:rollback [--app-id \u003cid>] [--channel \u003cname>] [--steps 1-5]\n```\n\n### apps:liveupdates:rollout\n\nUpdate rollout percentage for active build in a channel.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:rollout [--app-id \u003cid>] [--channel \u003cname>] [--percentage 0-100]\n```\n\n### apps:liveupdates:setnativeversions\n\nSet native version constraints on a web build.\n\n```bash\nnpx @capawesome/cli apps:liveupdates:setnativeversions [--app-id \u003cid>] [--build-id \u003cid>] [--android-min \u003ccode>] [--android-max \u003ccode>] [--ios-min \u003cver>] [--ios-max \u003cver>]\n```\n\n## Channel Commands\n\n### apps:channels:create\n\n```bash\nnpx @capawesome/cli apps:channels:create [--app-id \u003cid>] [--name \u003cname>] [--protected] [--ignore-errors]\n```\n\n### apps:channels:delete\n\n```bash\nnpx @capawesome/cli apps:channels:delete [--app-id \u003cid>] [--name \u003cname>] [--yes]\n```\n\n### apps:channels:get\n\n```bash\nnpx @capawesome/cli apps:channels:get [--app-id \u003cid>] [--name \u003cname>] [--json]\n```\n\n### apps:channels:list\n\n```bash\nnpx @capawesome/cli apps:channels:list [--app-id \u003cid>] [--json] [--limit \u003cn>] [--offset \u003cn>]\n```\n\n### apps:channels:pause\n\n```bash\nnpx @capawesome/cli apps:channels:pause [--app-id \u003cid>] [--channel \u003cname>]\n```\n\n### apps:channels:resume\n\n```bash\nnpx @capawesome/cli apps:channels:resume [--app-id \u003cid>] [--channel \u003cname>]\n```\n\n### apps:channels:update\n\n```bash\nnpx @capawesome/cli apps:channels:update [--app-id \u003cid>] [--channel-id \u003cid>] [--name \u003cname>] [--protected]\n```\n\n## Device Commands\n\n### apps:devices:delete\n\n```bash\nnpx @capawesome/cli apps:devices:delete [--app-id \u003cid>] [--device-id \u003cid>] [--yes]\n```\n\n### apps:devices:forcechannel\n\n```bash\nnpx @capawesome/cli apps:devices:forcechannel [--app-id \u003cid>] [--device-id \u003cid>] [--channel \u003cname>]\n```\n\n### apps:devices:unforcechannel\n\n```bash\nnpx @capawesome/cli apps:devices:unforcechannel [--app-id \u003cid>] [--device-id \u003cid>]\n```\n\n## Utility\n\n### doctor\n\n```bash\nnpx @capawesome/cli doctor\n```\n\nPrint environment and CLI diagnostic information.\n\n## CI/CD Usage\n\nFor CI/CD pipelines, authenticate with a token:\n\n```bash\nnpx @capawesome/cli login --token $CAPAWESOME_CLOUD_TOKEN\n```\n\nUse `--detached` to exit immediately after creating a build (useful for non-blocking pipelines):\n\n```bash\nnpx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform android --type release --git-ref main --certificate \"Release Key\" --detached --yes\n```\n\nUse `--json` to capture the build ID for downstream steps:\n\n```bash\nBUILD_OUTPUT=$(npx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform android --type release --git-ref main --json --yes)\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":13282,"content_sha256":"0d0e8a6fe62209bf3bb1e8b8a31b68131307fb0344cf2d0da7667aa280a3ea56"},{"filename":"references/environments.md","content":"# Environments\n\nEnvironment variables customize native builds by providing configuration values, secrets, and build parameters.\n\n## Default CI Variables\n\nAutomatically set for every build. Cannot be overridden.\n\n| Name | Type | Description |\n| ----------------------- | --------- | ---------------------------------------------------- |\n| `CI` | `boolean` | Always `true` in CI builds. |\n| `CI_APP_ID` | `string` | The app ID. |\n| `CI_BUILD_ID` | `string` | Unique build identifier. |\n| `CI_BUILD_NUMBER` | `string` | Sequential build number (auto-increments). |\n| `CI_GIT_COMMIT_SHA` | `string` | SHA hash of the Git commit. |\n| `CI_GIT_COMMIT_MESSAGE` | `string` | Commit message. |\n| `CI_GIT_REFERENCE` | `string` | Git branch or tag name. |\n| `CI_PLATFORM` | `string` | Target platform (`ios` or `android`). |\n\n## Reserved Environment Variables\n\nCan be set to customize build behavior.\n\n| Name | Type | Description |\n| ------------------------------ | -------- | -------------------------------------------------------------------------- |\n| `ANDROID_BUILD_TYPE` | `string` | Custom Android build type (e.g., `staging`). |\n| `ANDROID_FLAVOR` | `string` | Android product flavor. |\n| `IOS_PROVISIONING_PROFILE_MAP` | `string` | JSON mapping bundle IDs to target names for multi-target apps. |\n| `IOS_SCHEME` | `string` | iOS scheme name. |\n| `NODE_VERSION` | `int` | Node.js major version (e.g., `22` or `24`). |\n| `JAVA_VERSION` | `int` | Java major version (e.g., `17` or `21`). |\n| `XCODE_VERSION` | `int` | Xcode major version (e.g., `16` or `26`). |\n\n## Custom Environments\n\nCustom environments group variables/secrets for different build scenarios (e.g., development, staging, production).\n\n### Create via CLI\n\n```bash\nnpx @capawesome/cli apps:environments:create --app-id \u003cAPP_ID> --name staging\n```\n\n### Set Variables via CLI\n\n```bash\nnpx @capawesome/cli apps:environments:set \\\n --app-id \u003cAPP_ID> \\\n --environment-id \u003cENV_ID> \\\n --variable \"API_URL=https://api.staging.example.com\" \\\n --variable \"FEATURE_FLAG=true\"\n```\n\nBulk import from a `.env` file:\n\n```bash\nnpx @capawesome/cli apps:environments:set \\\n --app-id \u003cAPP_ID> \\\n --environment-id \u003cENV_ID> \\\n --variable-file .env\n```\n\n### Set Secrets via CLI\n\n```bash\nnpx @capawesome/cli apps:environments:set \\\n --app-id \u003cAPP_ID> \\\n --environment-id \u003cENV_ID> \\\n --secret \"API_KEY=sk-abc123\" \\\n --secret \"NPM_TOKEN=npm_xyz\"\n```\n\nBulk import from a `.env` file:\n\n```bash\nnpx @capawesome/cli apps:environments:set \\\n --app-id \u003cAPP_ID> \\\n --environment-id \u003cENV_ID> \\\n --secret-file .env.secrets\n```\n\nSecrets are encrypted at rest and in transit and never displayed in build logs.\n\n### Unset Variables/Secrets\n\n```bash\nnpx @capawesome/cli apps:environments:unset \\\n --app-id \u003cAPP_ID> \\\n --environment-id \u003cENV_ID> \\\n --variable API_URL \\\n --secret API_KEY\n```\n\n### List Environments\n\n```bash\nnpx @capawesome/cli apps:environments:list --app-id \u003cAPP_ID> --json\n```\n\n### Delete an Environment\n\n```bash\nnpx @capawesome/cli apps:environments:delete --app-id \u003cAPP_ID> --name staging --yes\n```\n\n### Set Default Environment\n\nTo auto-select an environment for every build, navigate to [App Settings](https://console.cloud.capawesome.io/apps/_/settings), enable **Default Environment** in the \"Builds\" section, select the environment, and save.\n\n## Ad-hoc Environment Variables\n\nTemporary variables set when creating a single build. Not persisted.\n\nUseful for:\n- Troubleshooting (e.g., testing a different `NODE_VERSION`)\n- Overriding native configuration values for a single build\n\nSet via Console when creating a build: enter `KEY=VALUE` pairs in the \"Ad-hoc Environment\" field.\n\nSet via CLI using the `--ad-hoc-env` flag on `apps:builds:create` (if available).\n\n**Warning:** Ad-hoc variables are **not encrypted** and may appear in build logs. Do not use for sensitive data — use environment secrets instead.\n\n## Reserved Name Restrictions\n\nThe variable name `CI` and any name starting with `CI_` are reserved and cannot be overridden by custom or ad-hoc environments.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4825,"content_sha256":"786b46a1935ad8fc62985c07d43a193817bb142e8b09c884fa4f77e20ba01e0a"},{"filename":"references/google-play-store-credentials.md","content":"# Google Play Store Credentials\n\n## Prerequisites\n\n- A [Google Play Developer](https://play.google.com/console) account.\n- An app already created in Google Play Console.\n- The first version of the app must have been uploaded manually to Google Play Console. This is a Google Play requirement, not a Capawesome Cloud limitation.\n\n## Required Information\n\n- **Package Name**: The Android application ID (e.g., `com.example.app`), defined in `android/app/build.gradle` as `applicationId`.\n- **Service Account JSON Key File**: Generated from Google Cloud Console and linked in Google Play Console.\n\n## Obtaining the Service Account JSON Key File\n\nIf the Google Cloud Console or Google Play Console appears in a non-English language, append `?hl=en` to the URL to switch to English.\n\n1. Sign in to the [Google Cloud Console](https://console.cloud.google.com/).\n2. Navigate to **IAM & Admin** > **Service Accounts**.\n3. Click **Create Service Account**.\n 1. In step 1, fill in the service account details (e.g., name: \"Capawesome Cloud\") and click **Create and Continue**.\n 2. In step 2, assign the role **Service Account User** and click **Continue**.\n 3. In step 3, leave the fields empty and click **Done**.\n4. In the list of service accounts, locate the newly created service account. Copy its **email address** (needed in step 8). Then click the menu in the **Actions** column and select **Manage keys**.\n5. In the **Keys** tab, click **Add Key** > **Create new key**.\n6. Select **JSON** as the key type and click **Create**. Save the downloaded JSON key file securely.\n7. Sign in to the [Google Play Console](https://play.google.com/console).\n8. Navigate to **Users and Permissions** and click **Invite new user**. Enter the service account email address copied in step 4.\n9. Click on the invited user and go to the **App permissions** tab. Add the desired applications to grant access to.\n10. In the permissions dialog, check at least all permissions in the **Release** section, then click **Apply**.\n11. Click **Invite User** to complete the setup.\n\n## Troubleshooting\n\n- **Deployment fails with permission error** → ensure the service account has at least **Release** permissions in Google Play Console for the specific app.\n- **\"First version must be uploaded manually\" error** → upload the first APK or AAB directly through the Google Play Console before using automated deployments.\n- **Service account email not accepted** → ensure the email address is the one from Google Cloud Console (ends with `@*.iam.gserviceaccount.com`), not a personal email.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2570,"content_sha256":"d15ee96d44c889975d733f217de887fe7fe37ffcd3c15dbc23249bc9d1723c91"},{"filename":"references/live-update-advanced-topics.md","content":"# Advanced Topics\n\n## Channels\n\nChannels distribute different bundles to different user groups (e.g., `production`, `staging`, `beta`). A `default` channel is created automatically.\n\nCreate a channel:\n\n```bash\nnpx @capawesome/cli apps:channels:create\n```\n\nSet a channel in the app:\n\n```typescript\nawait LiveUpdate.setChannel({ channel: \"beta\" });\n```\n\nOr pass it to `sync()`:\n\n```typescript\nawait LiveUpdate.sync({ channel: \"production\" });\n```\n\nRead `cli-commands.md` for all channel management commands.\n\n## Versioned Channels\n\nRestrict bundles to specific native versions by tying channel names to version codes.\n\n**Android** (`android/app/build.gradle`):\n\n```groovy\nandroid {\n defaultConfig {\n resValue \"string\", \"capawesome_live_update_default_channel\", \"production-\" + defaultConfig.versionCode\n }\n}\n```\n\n**iOS** (`ios/App/App/Info.plist`):\n\n```xml\n\u003ckey>CapawesomeLiveUpdateDefaultChannel\u003c/key>\n\u003cstring>production-$(CURRENT_PROJECT_VERSION)\u003c/string>\n```\n\n## Bundle Versioning\n\nRestrict bundles to native version ranges when uploading:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:upload --android-min 1 --android-max 5 --ios-min 1.0.0 --ios-max 1.0.5\n```\n\n## Rollbacks\n\nManual rollback via CLI:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:rollback --channel production --steps 1\n```\n\nEnable auto-blocking of rolled-back bundles:\n\n```typescript\nLiveUpdate: {\n autoBlockRolledBackBundles: true,\n readyTimeout: 10000,\n}\n```\n\n## Gradual Rollouts\n\nUpload a bundle with a rollout percentage:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:upload --rollout-percentage 10\n```\n\nUpdate the rollout:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:rollout --channel production --percentage 50\n```\n\n## Code Signing\n\nGenerate a signing key pair:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:generatesigningkey\n```\n\nUpload a signed bundle:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:upload --private-key private.pem\n```\n\nConfigure the plugin with the public key:\n\n```typescript\nLiveUpdate: {\n publicKey: \"-----BEGIN PUBLIC KEY-----\\n...\\n-----END PUBLIC KEY-----\",\n}\n```\n\n## Self-Hosting\n\nRegister a self-hosted bundle URL:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:register --url https://example.com/bundle.zip\n```\n\n## CI/CD Integration\n\nRead `live-update-ci-cd-integrations.md` for GitHub Actions, GitLab CI, Azure DevOps, and Bitbucket Pipelines examples.\n\n## Delta Updates\n\nUse manifest artifact type to download only changed files:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:upload --artifact-type manifest\n```\n\nGenerate a manifest first if needed:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:generatemanifest --path dist\n```\n\n## Debugging\n\nThe Live Update SDK logs to Android Logcat and iOS Xcode console. View server-side logs in the [Capawesome Cloud Console](https://console.cloud.capawesome.io) under the \"Logs\" section of the app.\n\n## Limitations\n\n- Live updates only support **binary-compatible changes** (HTML, CSS, JS, images). Native code changes (Java, Swift, CocoaPods, Gradle) require a full app store submission.\n- Maximum bundle size on Capawesome Cloud is **1 GB**. Use `manifest` artifact type for larger bundles.\n- Live updates are compliant with both Apple App Store and Google Play policies.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3238,"content_sha256":"c56a8a6c0519458cd4c946af3dfe81fa31c037dc69f387a6d9d54befc4dd1a33"},{"filename":"references/live-update-ci-cd-integrations.md","content":"# CI/CD Integrations\n\n## GitHub Actions\n\n```yaml\nname: Deploy Live Update\n\non:\n workflow_dispatch:\n inputs:\n channel:\n description: \"Channel to deploy to\"\n required: true\n default: \"default\"\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: 20\n - run: npm ci\n - run: npm run build\n - run: npx @capawesome/cli login --token ${{ secrets.CAPAWESOME_CLOUD_TOKEN }}\n - run: |\n npx @capawesome/cli apps:channels:create \\\n --name ${{ github.event.inputs.channel }} \\\n --ignore-errors\n - run: |\n npx @capawesome/cli apps:liveupdates:upload \\\n --channel ${{ github.event.inputs.channel }} \\\n --path dist \\\n --yes\n```\n\nStore `CAPAWESOME_CLOUD_TOKEN` as a repository secret.\n\n## GitLab CI/CD\n\n```yaml\ndeploy-live-update:\n image: node:20\n stage: deploy\n rules:\n - when: manual\n variables:\n CHANNEL:\n value: \"default\"\n description: \"Channel to deploy to\"\n script:\n - npm ci\n - npm run build\n - npx @capawesome/cli login --token $CAPAWESOME_CLOUD_TOKEN\n - npx @capawesome/cli apps:channels:create --name $CHANNEL --ignore-errors\n - npx @capawesome/cli apps:liveupdates:upload --channel $CHANNEL --path dist --yes\n```\n\nStore `CAPAWESOME_CLOUD_TOKEN` as a masked CI/CD variable.\n\n## Azure DevOps\n\n```yaml\ntrigger: none\n\npool:\n vmImage: \"ubuntu-latest\"\n\nparameters:\n - name: channel\n displayName: \"Channel\"\n type: string\n default: \"default\"\n\nsteps:\n - task: NodeTool@0\n inputs:\n versionSpec: \"20.x\"\n - script: npm ci\n - script: npm run build\n - script: npx @capawesome/cli login --token $(CAPAWESOME_CLOUD_TOKEN)\n - script: npx @capawesome/cli apps:channels:create --name ${{ parameters.channel }} --ignore-errors\n - script: npx @capawesome/cli apps:liveupdates:upload --channel ${{ parameters.channel }} --path dist --yes\n```\n\nStore `CAPAWESOME_CLOUD_TOKEN` as a secure pipeline variable.\n\n## Bitbucket Pipelines\n\n```yaml\npipelines:\n custom:\n deploy-live-update:\n - variables:\n - name: CHANNEL\n default: \"default\"\n - step:\n name: Deploy Live Update\n image: node:20\n script:\n - npm ci\n - npm run build\n - npx @capawesome/cli login --token $CAPAWESOME_CLOUD_TOKEN\n - npx @capawesome/cli apps:channels:create --name $CHANNEL --ignore-errors\n - npx @capawesome/cli apps:liveupdates:upload --channel $CHANNEL --path dist --yes\n```\n\nStore `CAPAWESOME_CLOUD_TOKEN` as a repository variable.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2686,"content_sha256":"60fe1f14e1d37d2dd938eff3cfa7c9c54882bacdb82a1660819b6dac76dc9ec6"},{"filename":"references/live-update-configuration.md","content":"# Plugin Configuration\n\nAll options are set under `plugins.LiveUpdate` in `capacitor.config.ts` or `capacitor.config.json`.\n\n| Option | Type | Default | Since | Description |\n| ------------------------------ | ----------------------------- | ------------------------------ | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `appId` | `string` | — | 5.0.0 | The Capawesome Cloud app ID (UUID). Not the native app identifier. |\n| `autoBlockRolledBackBundles` | `boolean` | `false` | 7.3.0 | Automatically block bundles that caused a rollback (up to 100). No effect if `readyTimeout` is `0`. Android/iOS only. |\n| `autoDeleteBundles` | `boolean` | `false` | 5.0.0 | Automatically delete unused bundles after `ready()` is called. |\n| `autoUpdateStrategy` | `'none'` \\| `'background'` | `'none'` | 7.3.0 | `none`: No automatic updates. `background`: Auto-download and apply at startup and resume (if last check >15 min ago). Android/iOS only. |\n| `defaultChannel` | `string` | — | 6.3.0 | Default channel. Can be overridden by `setChannel()`, `sync()` channel param, or native config. |\n| `httpTimeout` | `number` | `60000` | 6.4.0 | Timeout in milliseconds for HTTP requests. |\n| `publicKey` | `string` | — | 6.1.0 | PEM-encoded RSA public key for bundle integrity verification. |\n| `readyTimeout` | `number` | `0` | 5.0.0 | Timeout in ms to wait for `ready()` before rolling back. Set to e.g. `10000` for rollback protection. `0` disables. |\n| `serverDomain` | `string` | `'api.cloud.capawesome.io'` | 7.0.0 | API domain without scheme or path. Use `'api.cloud.capawesome.eu'` for EU servers. |\n\n## Example Configuration\n\n```typescript\nimport { CapacitorConfig } from \"@capacitor/cli\";\n\nconst config: CapacitorConfig = {\n plugins: {\n LiveUpdate: {\n appId: \"6e351b4f-69a7-415e-a057-4567df7ffe94\",\n autoUpdateStrategy: \"background\",\n readyTimeout: 10000,\n autoDeleteBundles: true,\n autoBlockRolledBackBundles: true,\n defaultChannel: \"production\",\n },\n },\n};\n\nexport default config;\n```\n\n## Channel Priority\n\nThe channel is resolved in the following order (highest priority first):\n\n1. **Forced channel** (set via Capawesome Cloud Console or CLI per device — highest priority)\n2. **`sync()` channel parameter** (not persisted, single-call override)\n3. **`setChannel()`** (persisted in SharedPreferences/UserDefaults)\n4. **Native config** (`CapawesomeLiveUpdateDefaultChannel` in `Info.plist` on iOS, `capawesome_live_update_default_channel` in `strings.xml` on Android)\n5. **Capacitor config** `defaultChannel` (lowest priority)\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":4650,"content_sha256":"6e28fbb8c8f1f2e68cd27d05b5419c9bbb3d576372821a402b2e6ff709f62dd4"},{"filename":"references/live-update-faq.md","content":"# Frequently Asked Questions\n\n## Compliance\n\n### Are Live Updates compliant with Apple App Store policies?\n\nYes. The Apple Developer Program License Agreement allows interpreted code to be downloaded as long as it does not change the primary purpose of the app or bypass OS security features. Live Updates only update the web layer.\n\n### Are Live Updates compliant with Google Play policies?\n\nYes. Google Play's Device and Network Abuse policy restriction on self-updating does not apply to JavaScript running in a webview or browser. Live Updates only modify the web layer.\n\n## Updates\n\n### What are binary-compatible changes?\n\nChanges that only affect web assets (HTML, CSS, JS, images) and do not require a native update. Native code changes (Java, Swift, CocoaPods, Gradle) are NOT binary-compatible and require an app store submission.\n\n### What is the maximum bundle size?\n\n1 GB on Capawesome Cloud. To work with larger bundles:\n1. Reduce bundle size by removing source maps and optimizing assets.\n2. Use `manifest` artifact type (1 GB limit applies per file, not the whole bundle).\n3. Self-host the bundle.\n\n### What happens when a bundle is deleted?\n\nDevices that already downloaded the bundle continue using it. The previous bundle becomes the latest in the channel.\n\n### How to automatically delete old bundles?\n\n1. Set a bundle limit per channel (oldest auto-deleted when limit reached).\n2. Set an expiration date per bundle with `--expires-in-days`.\n\n## Channels\n\n### What happens when a channel is deleted?\n\nAll bundles in the channel are deleted. Devices with existing bundles continue using them.\n\n## Devices\n\n### How are Monthly Active Users (MAU) counted?\n\nA MAU is a unique device that has synced with Capawesome Cloud in the current month, identified by a plugin-generated unique ID.\n\n### What happens at the MAU limit?\n\nNew devices stop receiving updates. Existing devices continue receiving updates. An email notification is sent.\n\n### What happens at the storage limit?\n\nNew uploads are blocked. Delete old bundles or upgrade the plan.\n\n## Privacy\n\n### Is PII collected?\n\nNo. Only device-generated identifiers are sent to Capawesome Cloud for MAU counting.\n\n## Development\n\n### Why are local changes not visible after installing a live update?\n\nOnce a live update bundle is active, it takes precedence over the default bundle. Options:\n1. Call `LiveUpdate.reset()` then reload.\n2. Reinstall the app.\n3. Increase the native version code (Capacitor auto-resets on native update).\n\n### Do not use Live Reload during testing\n\nThe Live Reload development feature uses a dev server, not the local file system. Disable Live Reload when testing live updates:\n\n```bash\nnpx ionic cap run android --open\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2719,"content_sha256":"e6db0ea9b104d28f8fc90a9a85f4bdde84563d31211fa108c81623a1fe035094"},{"filename":"references/live-update-plugin-api.md","content":"# Live Update Plugin API Reference\n\nImport: `import { LiveUpdate } from \"@capawesome/capacitor-live-update\";`\n\n## Methods\n\n### ready()\n\n```typescript\nready() => Promise\u003cReadyResult>\n```\n\nNotify the plugin that the app is ready. Call as early as possible to prevent rollback. Returns `{ currentBundleId, previousBundleId, rollback }`.\n\n### sync(options?)\n\n```typescript\nsync(options?: { channel?: string }) => Promise\u003c{ nextBundleId: string | null }>\n```\n\nFetch the latest bundle from Capawesome Cloud, download it, and set it as the next bundle. Call `reload()` or restart the app to apply. Returns `null` if up-to-date.\n\n### reload()\n\n```typescript\nreload() => Promise\u003cvoid>\n```\n\nReload the app to apply the next bundle immediately.\n\n### reset()\n\n```typescript\nreset() => Promise\u003cvoid>\n```\n\nReset to the default (built-in) bundle. Call `reload()` or restart to apply.\n\n### fetchLatestBundle(options?)\n\n```typescript\nfetchLatestBundle(options?: { channel?: string }) => Promise\u003cFetchLatestBundleResult>\n```\n\nFetch metadata about the latest bundle without downloading. Returns `{ bundleId, artifactType, downloadUrl, customProperties, channel, checksum, signature }`. `bundleId` is `null` if no bundle available.\n\n### downloadBundle(options)\n\n```typescript\ndownloadBundle(options: {\n url: string;\n bundleId: string;\n artifactType?: 'zip' | 'manifest';\n checksum?: string;\n signature?: string;\n}) => Promise\u003cvoid>\n```\n\nDownload a bundle from a URL.\n\n### setNextBundle(options)\n\n```typescript\nsetNextBundle(options: { bundleId: string | null }) => Promise\u003cvoid>\n```\n\nSet the bundle to use after next reload/restart. Pass `null` to use the default bundle.\n\n### deleteBundle(options)\n\n```typescript\ndeleteBundle(options: { bundleId: string }) => Promise\u003cvoid>\n```\n\nDelete a downloaded bundle.\n\n### getBundles()\n\n```typescript\ngetBundles() => Promise\u003c{ bundleIds: string[] }>\n```\n\nGet all available bundle identifiers.\n\n### getDownloadedBundles()\n\n```typescript\ngetDownloadedBundles() => Promise\u003c{ bundleIds: string[] }>\n```\n\nGet all downloaded bundle identifiers. Since 7.4.0.\n\n### getCurrentBundle()\n\n```typescript\ngetCurrentBundle() => Promise\u003c{ bundleId: string | null }>\n```\n\nGet the current active bundle ID. `null` means default bundle.\n\n### getNextBundle()\n\n```typescript\ngetNextBundle() => Promise\u003c{ bundleId: string | null }>\n```\n\nGet the next bundle ID. `null` means default bundle.\n\n### setChannel(options)\n\n```typescript\nsetChannel(options: { channel: string | null }) => Promise\u003cvoid>\n```\n\nSet the update channel. Persisted across restarts. Pass `null` to remove.\n\n### getChannel()\n\n```typescript\ngetChannel() => Promise\u003c{ channel: string | null }>\n```\n\nGet the currently resolved channel.\n\n### fetchChannels(options?)\n\n```typescript\nfetchChannels(options?: { limit?: number; offset?: number; query?: string }) => Promise\u003c{ channels: Array\u003c{ id: string; name: string }> }>\n```\n\nFetch available channels (requires channel discovery enabled). Since 8.2.0.\n\n### setCustomId(options)\n\n```typescript\nsetCustomId(options: { customId: string | null }) => Promise\u003cvoid>\n```\n\nSet a custom device identifier.\n\n### getCustomId()\n\n```typescript\ngetCustomId() => Promise\u003c{ customId: string | null }>\n```\n\n### getDeviceId()\n\n```typescript\ngetDeviceId() => Promise\u003c{ deviceId: string }>\n```\n\nGet the unique device identifier.\n\n### getVersionCode()\n\n```typescript\ngetVersionCode() => Promise\u003c{ versionCode: string }>\n```\n\nGet the native version code (`versionCode` on Android, `CFBundleVersion` on iOS).\n\n### getVersionName()\n\n```typescript\ngetVersionName() => Promise\u003c{ versionName: string }>\n```\n\nGet the native version name (`versionName` on Android, `CFBundleShortVersionString` on iOS).\n\n### isSyncing()\n\n```typescript\nisSyncing() => Promise\u003c{ syncing: boolean }>\n```\n\nCheck if a sync is in progress. Since 7.4.0.\n\n### setConfig(options)\n\n```typescript\nsetConfig(options: { appId?: string | null }) => Promise\u003cvoid>\n```\n\nUpdate plugin config at runtime. Persisted across restarts. Auto-reset on native app update. Since 7.4.0.\n\n### getConfig()\n\n```typescript\ngetConfig() => Promise\u003c{ appId: string | null; autoUpdateStrategy: 'none' | 'background' }>\n```\n\nGet current runtime config. Since 7.4.0.\n\n### resetConfig()\n\n```typescript\nresetConfig() => Promise\u003cvoid>\n```\n\nReset runtime config to Capacitor config values. Since 7.4.0.\n\n### getBlockedBundles()\n\n```typescript\ngetBlockedBundles() => Promise\u003c{ bundleIds: string[] }>\n```\n\nGet blocked bundle IDs. Since 7.4.0.\n\n### clearBlockedBundles()\n\n```typescript\nclearBlockedBundles() => Promise\u003cvoid>\n```\n\nClear all blocked bundles. Since 7.4.0.\n\n## Event Listeners\n\n### downloadBundleProgress\n\n```typescript\nLiveUpdate.addListener('downloadBundleProgress', (event) => {\n // event: { bundleId, progress, downloadedBytes, totalBytes }\n console.log(`Download: ${Math.round(event.progress * 100)}%`);\n});\n```\n\n### nextBundleSet\n\n```typescript\nLiveUpdate.addListener('nextBundleSet', (event) => {\n // event: { bundleId: string | null }\n console.log(`Next bundle set: ${event.bundleId}`);\n});\n```\n\n### reloaded\n\n```typescript\nLiveUpdate.addListener('reloaded', () => {\n console.log('App was reloaded');\n});\n```\n\n### removeAllListeners()\n\n```typescript\nLiveUpdate.removeAllListeners() => Promise\u003cvoid>\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":5254,"content_sha256":"0de6126564a723305fcb0f492a8935a161e4968bfa4406edd490a17121d2c3fe"},{"filename":"references/live-updates.md","content":"# Live Updates\n\nSet up OTA updates for Capacitor apps using Capawesome Cloud.\n\n## Contents\n\n- Install the Live Update Plugin\n- Configure the Plugin\n- Add Rollback Protection\n- Add Update Logic (Always Latest, Manual Sync)\n- Configure iOS Privacy Manifest\n- Configure Version Handling\n- Sync the Capacitor Project\n- Test the Setup\n- Advanced Topics\n\n## Install the Live Update Plugin\n\nDetermine Capacitor version from `package.json`, then install:\n\n- **Capacitor 8**: `npm install @capawesome/capacitor-live-update@latest`\n- **Capacitor 7**: `npm install @capawesome/capacitor-live-update@^7.3.0`\n- **Capacitor 6**: `npm install @capawesome/capacitor-live-update@^6.0.0`\n\n## Configure the Plugin\n\nAdd `LiveUpdate` config to `capacitor.config.ts` (or `.json`):\n\n```typescript\n// capacitor.config.ts\nimport { CapacitorConfig } from \"@capacitor/cli\";\n\nconst config: CapacitorConfig = {\n // ... existing config\n plugins: {\n LiveUpdate: {\n appId: \"\u003cAPP_ID_FROM_STEP_2>\",\n autoUpdateStrategy: \"background\", // Capacitor 7/8 only — omit for Capacitor 6\n },\n },\n};\n\nexport default config;\n```\n\nRead `live-update-configuration.md` for all available configuration options.\n\n## Add Rollback Protection (Recommended)\n\nSet `readyTimeout` and `autoBlockRolledBackBundles` in the plugin config:\n\n```typescript\nLiveUpdate: {\n appId: \"\u003cAPP_ID>\",\n autoUpdateStrategy: \"background\",\n readyTimeout: 10000,\n autoBlockRolledBackBundles: true,\n}\n```\n\nCall `ready()` as early as possible in app startup:\n\n```typescript\nimport { LiveUpdate } from \"@capawesome/capacitor-live-update\";\n\nvoid LiveUpdate.ready();\n```\n\nIf `ready()` is not called within `readyTimeout` ms, the plugin automatically rolls back.\n\n## Add Always Latest Update Logic (Recommended, Capacitor 7/8 Only)\n\nAdd a listener to prompt the user when a new update is ready. **Important:** Always show a confirmation dialog before reloading — never call `LiveUpdate.reload()` without user consent.\n\n```typescript\nimport { LiveUpdate } from \"@capawesome/capacitor-live-update\";\n\nLiveUpdate.addListener(\"nextBundleSet\", async (event) => {\n if (event.bundleId) {\n const shouldReload = confirm(\"A new update is available. Install now?\");\n if (shouldReload) {\n await LiveUpdate.reload();\n }\n }\n});\n```\n\nCopy this snippet exactly. Do not simplify or omit the `confirm()` dialog.\n\n## Add Manual Update Logic (Capacitor 6 Only)\n\nCapacitor 6 does not support `autoUpdateStrategy`. Implement manual sync:\n\n```typescript\nimport { App } from \"@capacitor/app\";\nimport { LiveUpdate } from \"@capawesome/capacitor-live-update\";\n\nvoid LiveUpdate.ready();\n\nApp.addListener(\"resume\", async () => {\n const { nextBundleId } = await LiveUpdate.sync();\n if (nextBundleId) {\n const shouldReload = confirm(\"A new update is available. Install now?\");\n if (shouldReload) {\n await LiveUpdate.reload();\n }\n }\n});\n```\n\nFor Capacitor 7/8 with `autoUpdateStrategy: \"background\"`, no additional code is required.\nRead `update-strategies.md` for alternative strategies.\n\n## Configure iOS Privacy Manifest\n\nAdd to `ios/App/PrivacyInfo.xcprivacy` inside the `NSPrivacyAccessedAPITypes` array:\n\n```xml\n\u003cdict>\n \u003ckey>NSPrivacyAccessedAPIType\u003c/key>\n \u003cstring>NSPrivacyAccessedAPICategoryUserDefaults\u003c/string>\n \u003ckey>NSPrivacyAccessedAPITypeReasons\u003c/key>\n \u003carray>\n \u003cstring>CA92.1\u003c/string>\n \u003c/array>\n\u003c/dict>\n```\n\n## Configure Version Handling\n\nLive updates only deliver web code (HTML, CSS, JS, images). If the app's native code changes (e.g., a new Capacitor plugin is added or a native dependency is updated), the live update bundle must match the native binary it runs on — otherwise the app may crash or behave unexpectedly. Version handling ensures that each live update bundle is only delivered to devices running a compatible native version.\n\nAsk the user which approach to use:\n\n1. **Versioned Channels (recommended):** Ties each channel to a native version code. Set at build time in native projects.\n2. **Versioned Bundles:** Sets version constraints on each upload. No native changes needed.\n3. **Skip for now:** Skip versioning for initial testing.\n\n### Option 1: Versioned Channels\n\n**Android** — add to `android/app/build.gradle` inside `android.defaultConfig`:\n\n```groovy\nresValue \"string\", \"capawesome_live_update_default_channel\", \"production-\" + defaultConfig.versionCode\n```\n\n**iOS** — add to `ios/App/App/Info.plist`:\n\n```xml\n\u003ckey>CapawesomeLiveUpdateDefaultChannel\u003c/key>\n\u003cstring>production-$(CURRENT_PROJECT_VERSION)\u003c/string>\n```\n\nRead the current native version code. Before uploading, create the matching channel if missing:\n\n```bash\nnpx @capawesome/cli apps:channels:create --app-id \u003cAPP_ID> --name production-\u003cVERSION_CODE>\n```\n\nWhen uploading, target this channel:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:upload --app-id \u003cAPP_ID> --channel production-\u003cVERSION_CODE>\n```\n\n### Option 2: Versioned Bundles\n\nRead the current native version code and pass constraints on every upload:\n\n```bash\nnpx @capawesome/cli apps:liveupdates:upload --android-min \u003cCODE> --android-max \u003cCODE> --ios-min \u003cCODE> --ios-max \u003cCODE>\n```\n\nUse `--android-eq` / `--ios-eq` to exclude a specific version code.\n\nSet `defaultChannel` in the Capacitor config:\n\n```typescript\nLiveUpdate: {\n appId: \"\u003cAPP_ID>\",\n defaultChannel: \"production\",\n}\n```\n\nEnsure a channel with that name exists before uploading.\n\n### Option 3: Skip\n\nSet `defaultChannel` in the Capacitor config:\n\n```typescript\nLiveUpdate: {\n appId: \"\u003cAPP_ID>\",\n defaultChannel: \"default\",\n}\n```\n\n## Sync the Capacitor Project\n\n```bash\nnpx cap sync\n```\n\n## Test the Setup\n\nAsk the user whether they would like to test the live update functionality. If declined, skip.\n\n### Make a Visible Change\n\nPick an easily noticeable element in the app's web source (e.g., a heading, label, or background color). Apply a small, obvious change so the update is easy to spot. For example, append \" - Live Update Test\" to a heading.\n\n### Build and Upload the Updated Bundle\n\nCheck which channels exist for the app:\n\n```bash\nnpx @capawesome/cli apps:channels:list --app-id \u003cAPP_ID> --json\n```\n\nIf no channel exists or the desired channel (including versioned channels) is missing, create one:\n\n```bash\nnpx @capawesome/cli apps:channels:create --app-id \u003cAPP_ID> --name \u003cNAME>\n```\n\nBuild the web assets and upload them:\n\n```bash\nnpm run build\nnpx @capawesome/cli apps:liveupdates:upload\n```\n\n### Revert the Visible Change\n\nRevert the change made above so the app source is back to its original state.\n\n### Rebuild and Prepare the Native Project\n\n```bash\nnpm run build\nnpx cap sync\n```\n\nThen open the native project:\n\n- **iOS:** `npx cap open ios`\n- **Android:** `npx cap open android`\n\n### Verify on Device\n\nTell the user to perform the following steps:\n\n1. Run the app on a real device or emulator from Xcode or Android Studio.\n2. **For Always Latest / `autoUpdateStrategy: \"background\"` (Capacitor 7/8):** Wait for the update prompt to appear and accept it. The visible change from the uploaded bundle should appear after reload. If no prompt appears, force-close and reopen the app to trigger a check.\n3. **For manual sync (Capacitor 6):** Switch away from the app and return to it. Accept the update prompt when it appears, and the change should be visible immediately after reload.\n4. If the change does not appear, check Android Logcat or iOS Xcode console for Live Update SDK log output and refer to `live-update-advanced-topics.md` (Debugging section).\n\nAfter testing, tell the user: Once a live update bundle has been applied, the app points to that bundle instead of the default one. To use the development server again, completely uninstall and reinstall the app. This is only relevant during development — in production, the default bundle is automatically restored on each native app update.\n\n## Advanced Topics\n\nRead `live-update-advanced-topics.md` for channels, versioned channels, rollbacks, code signing, gradual rollouts, self-hosting, delta updates, debugging, and limitations.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":8010,"content_sha256":"01af1b441fc59f30b67026286ba68d728120c69fa69278131cd882e77ff783b0"},{"filename":"references/native-builds.md","content":"# Native Builds\n\nBuild native iOS and Android apps in the cloud using Capawesome Cloud.\n\n## Contents\n\n- Connect Git Repository\n- Upload Signing Certificates\n- Configure Environments\n- Configure Build Settings\n- Trigger a Build\n- Monitor and Download Build Artifacts\n- Configure Native Configuration Overwriting\n- Set Up CI/CD\n\n## Connect Git Repository\n\n**This step requires the Capawesome Cloud Console** — no CLI command is available for Git connection.\n\nInstruct the user to:\n\n1. Navigate to the [Git](https://console.cloud.capawesome.io/apps/_/git) page of the app in the Capawesome Cloud Console.\n2. In the **Git Providers** section, select the Git provider (GitHub, GitLab, Bitbucket, etc.) and click **Connect** to authorize access. Skip if already connected.\n3. In the **Git Repositories** section, select the Git provider from the dropdown, choose the repository owner, and select the repository.\n4. Click **Save**.\n\n## Upload Signing Certificates\n\nSkip this step if the user only wants to create unsigned builds (`debug` on Android, `simulator` on iOS).\n\n### Android\n\nUpload a Java Keystore for signed Android builds:\n\n```bash\nnpx @capawesome/cli apps:certificates:create \\\n --app-id \u003cAPP_ID> \\\n --name \"Production Android Key\" \\\n --platform android \\\n --type production \\\n --file /path/to/my-release-key.jks \\\n --password \u003cKEYSTORE_PASSWORD> \\\n --key-alias my-key-alias \\\n --key-password \u003cKEY_PASSWORD>\n```\n\nIf the user does not have a keystore, read `certificates-android.md` for creation instructions.\n\n### iOS\n\nUpload a `.p12` certificate and provisioning profile for signed iOS builds:\n\n```bash\nnpx @capawesome/cli apps:certificates:create \\\n --app-id \u003cAPP_ID> \\\n --name \"Production iOS Certificate\" \\\n --platform ios \\\n --type production \\\n --file /path/to/certificate.p12 \\\n --password \u003cCERTIFICATE_PASSWORD> \\\n --provisioning-profile /path/to/profile.mobileprovision\n```\n\nRead `certificates-ios.md` to determine if the user already has a `.p12` file and provisioning profile, and guide them through obtaining the missing files if needed.\n\n## Configure Environments (Optional)\n\nSkip unless the user needs custom environment variables, secrets, or reserved variable overrides.\n\nCreate an environment:\n\n```bash\nnpx @capawesome/cli apps:environments:create --app-id \u003cAPP_ID> --name production\n```\n\nSet variables and secrets:\n\n```bash\nnpx @capawesome/cli apps:environments:set \\\n --app-id \u003cAPP_ID> \\\n --environment-id \u003cENV_ID> \\\n --variable \"API_URL=https://api.example.com\" \\\n --secret \"API_KEY=sk-abc123\"\n```\n\nRead `environments.md` for default CI variables, reserved variables (`JAVA_VERSION`, `NODE_VERSION`, `XCODE_VERSION`, etc.), secrets, and ad-hoc environments.\n\n## Configure Build Settings (Optional)\n\nSkip for standard project setups where the app is in the repo root and uses `npm install` + `npm run build`.\n\nFor monorepos, subdirectory apps, or custom build commands, create `capawesome.config.json` in the project root:\n\n```json\n{\n \"cloud\": {\n \"apps\": [\n {\n \"appId\": \"\u003cAPP_ID>\",\n \"baseDir\": \"apps/my-app\",\n \"dependencyInstallCommand\": \"npm install\",\n \"webBuildCommand\": \"npm run build\"\n }\n ]\n }\n}\n```\n\nRead `build-configuration.md` for all options including pnpm/Yarn setup and web build script priority.\n\n## Trigger a Build\n\n```bash\nnpx @capawesome/cli apps:builds:create \\\n --app-id \u003cAPP_ID> \\\n --platform \u003candroid|ios> \\\n --type \u003cBUILD_TYPE> \\\n --git-ref \u003cBRANCH_OR_TAG> \\\n --certificate \"\u003cCERTIFICATE_NAME>\"\n```\n\nExamples:\n\n```bash\n# Android debug (no certificate needed)\nnpx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform android --type debug --git-ref main\n\n# Android release\nnpx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform android --type release --git-ref main --certificate \"Production Android Key\"\n\n# iOS simulator (no certificate needed)\nnpx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform ios --type simulator --git-ref main\n\n# iOS App Store\nnpx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform ios --type app-store --git-ref main --certificate \"Production iOS Certificate\"\n```\n\nAdd `--environment \u003cNAME>` to use a custom environment. Add `--stack \u003cSTACK>` to select a build stack.\n\nRead `build-types.md` for all available build types. Read `build-stacks.md` for available stacks and software versions.\n\n## Monitor and Download Build Artifacts\n\nView build logs:\n\n```bash\nnpx @capawesome/cli apps:builds:logs --app-id \u003cAPP_ID> --build-id \u003cBUILD_ID>\n```\n\nDownload artifacts after the build completes:\n\n```bash\n# Android\nnpx @capawesome/cli apps:builds:download --app-id \u003cAPP_ID> --build-id \u003cBUILD_ID> --apk\nnpx @capawesome/cli apps:builds:download --app-id \u003cAPP_ID> --build-id \u003cBUILD_ID> --aab\n\n# iOS\nnpx @capawesome/cli apps:builds:download --app-id \u003cAPP_ID> --build-id \u003cBUILD_ID> --ipa\n```\n\nAlternatively, use inline download flags on `apps:builds:create`:\n\n```bash\nnpx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform android --type release --git-ref main --certificate \"Production Android Key\" --apk ./app-release.apk\n```\n\n## Configure Native Configuration Overwriting (Optional)\n\nSkip unless the user needs to modify native project settings (app ID, display name, version numbers) dynamically per build.\n\n1. Install Trapeze:\n\n```bash\nnpm install --save-dev @trapezedev/configure\n```\n\n2. Create `capawesome.yml` in the project root:\n\n```yaml\nvars:\n CI_BUILD_NUMBER:\n default: 1\n\nplatforms:\n android:\n versionCode: $CI_BUILD_NUMBER\n ios:\n buildNumber: $CI_BUILD_NUMBER\n```\n\n3. Add the build script to `package.json`:\n\n```json\n{\n \"scripts\": {\n \"capawesome:build\": \"if [ \\\"$CI_PLATFORM\\\" = \\\"ios\\\" ] || [ \\\"$CI_PLATFORM\\\" = \\\"android\\\" ]; then npx trapeze run capawesome.yml -y --$CI_PLATFORM; fi && npm run build\"\n }\n}\n```\n\nRead `build-configuration.md` for full Trapeze setup and environment variable usage. Read `build-guides.md` for auto-incrementing build numbers with version name management.\n\n## Set Up CI/CD (Optional)\n\nSkip unless the user wants automated builds from CI/CD pipelines.\n\n1. Generate a token in the [Capawesome Cloud Console](https://console.cloud.capawesome.io).\n2. Store as a secret in the CI/CD platform (e.g., `CAPAWESOME_CLOUD_TOKEN`).\n3. Authenticate and trigger builds:\n\n```bash\nnpx @capawesome/cli login --token $CAPAWESOME_CLOUD_TOKEN\nnpx @capawesome/cli apps:builds:create \\\n --app-id \u003cAPP_ID> \\\n --platform android \\\n --type release \\\n --git-ref main \\\n --certificate \"Production Android Key\" \\\n --yes\n```\n\nUse `--detached` to exit immediately without waiting for the build to complete:\n\n```bash\nnpx @capawesome/cli apps:builds:create --app-id \u003cAPP_ID> --platform android --type release --git-ref main --detached --yes\n```\n\nRead `cli-commands.md` for the full CLI reference including `--json` output for capturing build IDs.\n\n## Advanced Topics\n\nRead `build-guides.md` for:\n- Auto-incrementing build numbers\n- Custom iOS provisioning profiles for multi-target apps\n- Private npm package configuration\n- Overriding Java version\n- Web build script configuration\n\nRead `build-troubleshooting.md` for common errors and fixes.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":7172,"content_sha256":"6916375782ee590b06740c68cc6d6abd504a95f623fdfdb30a8cdc96a7c74fcf"},{"filename":"references/update-strategies.md","content":"# Update Strategies\n\n## Background\n\nSet `autoUpdateStrategy: \"background\"` in the plugin config. No additional code needed.\n\nBehavior:\n- Checks for updates at app startup and on resume (if last check >15 min ago).\n- Downloads in the background.\n- Applies on next app launch.\n\nTo force a check during development, force-close and restart the app.\n\n## Always Latest (Recommended)\n\nCombines background updates with a user prompt when an update is ready.\n\n```typescript\nimport { LiveUpdate } from \"@capawesome/capacitor-live-update\";\n\nvoid LiveUpdate.ready();\n\nLiveUpdate.addListener(\"nextBundleSet\", async (event) => {\n if (event.bundleId) {\n const shouldReload = confirm(\"A new update is available. Install now?\");\n if (shouldReload) {\n await LiveUpdate.reload();\n }\n }\n});\n```\n\nSet `autoUpdateStrategy: \"background\"` in the config.\n\n## Force Update\n\nShow a splash/loading screen while downloading, then reload immediately.\n\n```typescript\nimport { LiveUpdate } from \"@capawesome/capacitor-live-update\";\nimport { SplashScreen } from \"@capacitor/splash-screen\";\n\nvoid LiveUpdate.ready();\n\nconst checkForUpdate = async () => {\n const { nextBundleId } = await LiveUpdate.sync();\n if (nextBundleId) {\n await SplashScreen.show();\n await LiveUpdate.reload();\n }\n};\n\nvoid checkForUpdate();\n```\n\nSet `autoUpdateStrategy: \"none\"` in the config.\n\n## Manual Sync (Capacitor 6)\n\nCapacitor 6 does not support `autoUpdateStrategy`. Implement sync manually:\n\n```typescript\nimport { App } from \"@capacitor/app\";\nimport { LiveUpdate } from \"@capawesome/capacitor-live-update\";\n\nvoid LiveUpdate.ready();\n\nApp.addListener(\"resume\", async () => {\n const { nextBundleId } = await LiveUpdate.sync();\n if (nextBundleId) {\n const shouldReload = confirm(\"A new update is available. Install now?\");\n if (shouldReload) {\n await LiveUpdate.reload();\n }\n }\n});\n```\n\n## Advanced: Manual Fetch + Download\n\nFor full control over the update flow without using `sync()`:\n\n```typescript\nimport { LiveUpdate } from \"@capawesome/capacitor-live-update\";\n\nconst checkAndApply = async () => {\n const { bundleId, downloadUrl, artifactType, checksum, signature } =\n await LiveUpdate.fetchLatestBundle();\n\n if (!bundleId) return;\n\n const { bundleId: currentId } = await LiveUpdate.getCurrentBundle();\n if (bundleId === currentId) return;\n\n await LiveUpdate.downloadBundle({\n url: downloadUrl,\n bundleId,\n artifactType,\n checksum,\n signature,\n });\n\n await LiveUpdate.setNextBundle({ bundleId });\n await LiveUpdate.reload();\n};\n```\n\nSet `autoUpdateStrategy: \"none\"` when using this approach.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":2612,"content_sha256":"244cad03ae14aeed5332410a8be7a9707ba4e6098a054402547b126875f441ab"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Capawesome Cloud","type":"text"}]},{"type":"paragraph","content":[{"text":"Set up and manage native builds, live updates, and app store publishing for Capacitor apps using Capawesome Cloud.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Prerequisites","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A ","type":"text"},{"text":"Capawesome Cloud","type":"text","marks":[{"type":"link","attrs":{"href":"https://console.cloud.capawesome.io","title":null}}]},{"text":" account and organization.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A ","type":"text"},{"text":"Capacitor 6, 7, or 8","type":"text","marks":[{"type":"strong"}]},{"text":" app.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Node.js and npm installed.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"For ","type":"text"},{"text":"Native Builds","type":"text","marks":[{"type":"strong"}]},{"text":": The app must be in a Git repository (GitHub, GitLab, Bitbucket, or Azure DevOps).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"For ","type":"text"},{"text":"Apple App Store Publishing","type":"text","marks":[{"type":"strong"}]},{"text":": An active ","type":"text"},{"text":"Apple Developer Program","type":"text","marks":[{"type":"link","attrs":{"href":"https://developer.apple.com/programs/","title":null}}]},{"text":" membership and an app created in ","type":"text"},{"text":"App Store Connect","type":"text","marks":[{"type":"link","attrs":{"href":"https://appstoreconnect.apple.com","title":null}}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"For ","type":"text"},{"text":"Google Play Store Publishing","type":"text","marks":[{"type":"strong"}]},{"text":": A ","type":"text"},{"text":"Google Play Developer","type":"text","marks":[{"type":"link","attrs":{"href":"https://play.google.com/console","title":null}}]},{"text":" account and an app created in Google Play Console with at least one version uploaded manually.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"General Rules","type":"text"}]},{"type":"paragraph","content":[{"text":"Before running any ","type":"text"},{"text":"@capawesome/cli","type":"text","marks":[{"type":"code_inline"}]},{"text":" command for the first time, run it with the ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to review all available options.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Procedures","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Authenticate with Capawesome Cloud","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"npx @capawesome/cli login","type":"text"}]},{"type":"paragraph","content":[{"text":"For CI/CD, use token-based auth:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"npx @capawesome/cli login --token \u003ctoken>","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Create an App in Capawesome Cloud","type":"text"}]},{"type":"paragraph","content":[{"text":"Skip if the user already has an app ID.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"npx @capawesome/cli apps:create","type":"text"}]},{"type":"paragraph","content":[{"text":"The CLI prompts for organization and app name, then outputs the ","type":"text"},{"text":"app ID","type":"text","marks":[{"type":"strong"}]},{"text":" (UUID). Save for subsequent steps.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: Identify Required Feature(s)","type":"text"}]},{"type":"paragraph","content":[{"text":"Ask the user which Capawesome Cloud feature(s) to set up:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Native Builds","type":"text","marks":[{"type":"strong"}]},{"text":" — Build iOS and Android apps in the cloud.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Live Updates","type":"text","marks":[{"type":"strong"}]},{"text":" — Push OTA web updates to deployed apps.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"App Store Publishing","type":"text","marks":[{"type":"strong"}]},{"text":" — Automate submissions to Apple App Store or Google Play Store.","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"The user may select one or more features. Proceed to the corresponding sections below.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Native Builds","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/native-builds.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full native builds setup and usage procedure. This covers:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Connecting a Git repository","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Uploading signing certificates (Android keystores, iOS .p12 + provisioning profiles)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Configuring environments and secrets","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Configuring build settings (monorepos, custom build commands)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Triggering builds","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Monitoring and downloading build artifacts","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Configuring native configuration overwriting with Trapeze","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Setting up CI/CD pipelines","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Live Updates","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/live-updates.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full live updates setup and usage procedure. This covers:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Installing the ","type":"text"},{"text":"@capawesome/capacitor-live-update","type":"text","marks":[{"type":"code_inline"}]},{"text":" plugin","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Configuring the plugin in Capacitor config","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Adding rollback protection","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Adding update logic (Always Latest, Manual Sync, Force Update)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Configuring iOS Privacy Manifest","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Configuring version handling (versioned channels, versioned bundles)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Testing the setup","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"App Store Publishing","type":"text"}]},{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/app-store-publishing.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full app store publishing setup and usage procedure. This covers:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Creating Apple App Store destinations (API Key or Apple ID auth)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Creating Google Play Store destinations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Deploying builds to destinations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Building and deploying in one step","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Error Handling","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Native Builds","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"invalid source release: 21","type":"text","marks":[{"type":"code_inline"}]},{"text":" → Set ","type":"text"},{"text":"JAVA_VERSION","type":"text","marks":[{"type":"code_inline"}]},{"text":" env var to ","type":"text"},{"text":"17","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"21","type":"text","marks":[{"type":"code_inline"}]},{"text":". Read ","type":"text"},{"text":"references/build-troubleshooting.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"JavaScript heap out of memory","type":"text","marks":[{"type":"code_inline"}]},{"text":" → Set ","type":"text"},{"text":"NODE_OPTIONS","type":"text","marks":[{"type":"code_inline"}]},{"text":" env var to ","type":"text"},{"text":"--max-old-space-size=4096","type":"text","marks":[{"type":"code_inline"}]},{"text":". Read ","type":"text"},{"text":"references/build-troubleshooting.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Authentication errors → Re-run ","type":"text"},{"text":"npx @capawesome/cli login","type":"text","marks":[{"type":"code_inline"}]},{"text":". For CI/CD, verify the token.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Missing signing certificate → Upload via ","type":"text"},{"text":"apps:certificates:create","type":"text","marks":[{"type":"code_inline"}]},{"text":". Read ","type":"text"},{"text":"references/certificates-android.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"references/certificates-ios.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Expired provisioning profile → Regenerate in Apple Developer Portal and re-upload. Read ","type":"text"},{"text":"references/certificates-ios.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Web build step fails → Ensure ","type":"text"},{"text":"package.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" has ","type":"text"},{"text":"capawesome:build","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"build","type":"text","marks":[{"type":"code_inline"}]},{"text":" script. Read ","type":"text"},{"text":"references/build-configuration.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Live Updates","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"npx cap sync","type":"text","marks":[{"type":"code_inline"}]},{"text":" fails → Verify plugin version matches Capacitor version in ","type":"text"},{"text":"package.json","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Bundles not applied → Ensure ","type":"text"},{"text":"LiveUpdate.ready()","type":"text","marks":[{"type":"code_inline"}]},{"text":" is called before ","type":"text"},{"text":"readyTimeout","type":"text","marks":[{"type":"code_inline"}]},{"text":" expires.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"App reverts to default bundle after restart → ","type":"text"},{"text":"ready()","type":"text","marks":[{"type":"code_inline"}]},{"text":" likely not called. Add it early in app init.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Upload auth errors → Re-run ","type":"text"},{"text":"npx @capawesome/cli login","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Updates not detected with ","type":"text"},{"text":"autoUpdateStrategy: \"background\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" → Updates only checked if last check was >15 min ago. Force-close and restart.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/live-update-plugin-api.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for the full SDK API reference.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/live-update-faq.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for compliance, billing, and limitations.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"App Store Publishing","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Authentication errors → Re-run ","type":"text"},{"text":"npx @capawesome/cli login","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Destination creation fails → Verify credentials. Read ","type":"text"},{"text":"references/apple-app-store-credentials.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"references/google-play-store-credentials.md","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"iOS build not appearing in TestFlight → Build processing may take time. Common causes: build number not incremented, missing Privacy Descriptions in ","type":"text"},{"text":"Info.plist","type":"text","marks":[{"type":"code_inline"}]},{"text":", insufficient permissions.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Google Play deployment fails → Ensure first version was uploaded manually. Verify service account has Release permissions.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Deployment timeout → Use ","type":"text"},{"text":"--detached","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag and check logs with ","type":"text"},{"text":"apps:deployments:logs","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"apps:deployments:create","type":"text","marks":[{"type":"code_inline"}]},{"text":" fails with \"build not found\" → Ensure the build completed successfully.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Cancel a stuck deployment → ","type":"text"},{"text":"npx @capawesome/cli apps:deployments:cancel --app-id \u003cAPP_ID> --deployment-id \u003cDEPLOYMENT_ID>","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Related Skills","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"capacitor-app-development","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — For general Capacitor development topics, CI/CD patterns, and troubleshooting.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"capawesome-cli","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — For the full Capawesome CLI command reference, project configuration, and CI/CD integration details.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"capacitor-plugins","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — For installing and configuring Capacitor plugins, including the ","type":"text"},{"text":"@capawesome/capacitor-live-update","type":"text","marks":[{"type":"code_inline"}]},{"text":" plugin.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"ionic-appflow-migration","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — For migrating existing Ionic Appflow projects to Capawesome Cloud.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"capacitor-in-app-purchases","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" — For setting up in-app purchases and subscriptions before publishing to app stores.","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"capawesome-cloud","author":"@skillopedia","source":{"stars":24,"repo_name":"skills","origin_url":"https://github.com/capawesome-team/skills/blob/HEAD/skills/capawesome-cloud/SKILL.md","repo_owner":"capawesome-team","body_sha256":"754e40919438397f9a04eafc5af00b52483b398b792912ad5dbe0f54a4625479","cluster_key":"d3a9296cfb0aecd72103f00a4db36f682f9a9286eb22a07f57cb94dc22489aa3","clean_bundle":{"format":"clean-skill-bundle-v1","source":"capawesome-team/skills/skills/capawesome-cloud/SKILL.md","attachments":[{"id":"1faff5b1-5073-5fa8-a056-f83ae66e85ec","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1faff5b1-5073-5fa8-a056-f83ae66e85ec/attachment.md","path":"references/app-store-publishing.md","size":5786,"sha256":"4680e609418bf228cb94c7a45b06c2dd6776ba00dd0fae01c70a790b92a34414","contentType":"text/markdown; charset=utf-8"},{"id":"1bd018e4-fcf0-55b0-8b07-96de127c84f5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1bd018e4-fcf0-55b0-8b07-96de127c84f5/attachment.md","path":"references/apple-app-store-credentials.md","size":2389,"sha256":"5fec2ff34f940d07b29b844500c543c0a3a8600012876cfef5054e44dafa63e2","contentType":"text/markdown; charset=utf-8"},{"id":"7e9c2e7b-2d00-511f-9dad-ce540bf11642","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7e9c2e7b-2d00-511f-9dad-ce540bf11642/attachment.md","path":"references/build-configuration.md","size":3312,"sha256":"0483e35fde630442c3e77b04d79c5783825dfc52f0e5c290ed29782e0aba8e83","contentType":"text/markdown; charset=utf-8"},{"id":"775c570f-d87a-55e4-b30a-20161dbf5a51","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/775c570f-d87a-55e4-b30a-20161dbf5a51/attachment.md","path":"references/build-guides.md","size":3635,"sha256":"45597b46419ebd9f035cc1d6686c47107ca45a24ccb0e97257ab5ce7cb13093a","contentType":"text/markdown; charset=utf-8"},{"id":"b00e005d-7a4c-538f-b185-5c0c0d7652ed","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b00e005d-7a4c-538f-b185-5c0c0d7652ed/attachment.md","path":"references/build-stacks.md","size":1714,"sha256":"8be1ade2d1640f569c51b2c6e77c7bc91f789fb47581397151665c282e089071","contentType":"text/markdown; charset=utf-8"},{"id":"c32e99c9-545d-5691-aedd-41836e0e8acc","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c32e99c9-545d-5691-aedd-41836e0e8acc/attachment.md","path":"references/build-troubleshooting.md","size":2797,"sha256":"90c3e26ac93bfde307c64201545ca03f4cb05d77bea70c82c214b2a72c5795a0","contentType":"text/markdown; charset=utf-8"},{"id":"7c152d9e-e0ed-58e3-9731-eef99443bfc4","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/7c152d9e-e0ed-58e3-9731-eef99443bfc4/attachment.md","path":"references/build-types.md","size":2487,"sha256":"1f5f6172d67bc2c8649ba239a5bdb3304b99bedcc76dfbfd4601c71b76141e4f","contentType":"text/markdown; charset=utf-8"},{"id":"bbdb43d3-6e60-5884-9673-d3b5f8eb5504","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/bbdb43d3-6e60-5884-9673-d3b5f8eb5504/attachment.md","path":"references/certificates-android.md","size":2344,"sha256":"7c857cc1ddf9b8d5593312922d0042b671cecca2117adc100aa91738f458daed","contentType":"text/markdown; charset=utf-8"},{"id":"ef436155-46f2-5ae2-a99d-735ee20a1bc5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ef436155-46f2-5ae2-a99d-735ee20a1bc5/attachment.md","path":"references/certificates-ios.md","size":11736,"sha256":"dd3198b0a03e925f93484e2d01265bdda4eb4e14b1005e92c2db27e35e6a8a42","contentType":"text/markdown; charset=utf-8"},{"id":"a2792968-3d61-5213-a9b6-1c297ce1599d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/a2792968-3d61-5213-a9b6-1c297ce1599d/attachment.md","path":"references/cli-commands.md","size":13282,"sha256":"0d0e8a6fe62209bf3bb1e8b8a31b68131307fb0344cf2d0da7667aa280a3ea56","contentType":"text/markdown; charset=utf-8"},{"id":"2b1d64f0-e15a-5e6f-a0aa-98d1ab5c7851","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/2b1d64f0-e15a-5e6f-a0aa-98d1ab5c7851/attachment.md","path":"references/environments.md","size":4825,"sha256":"786b46a1935ad8fc62985c07d43a193817bb142e8b09c884fa4f77e20ba01e0a","contentType":"text/markdown; charset=utf-8"},{"id":"0e551879-b81a-5fa7-b3e3-12795f210d15","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/0e551879-b81a-5fa7-b3e3-12795f210d15/attachment.md","path":"references/google-play-store-credentials.md","size":2570,"sha256":"d15ee96d44c889975d733f217de887fe7fe37ffcd3c15dbc23249bc9d1723c91","contentType":"text/markdown; charset=utf-8"},{"id":"55f0dee5-58db-5deb-9af0-3324cc251c53","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/55f0dee5-58db-5deb-9af0-3324cc251c53/attachment.md","path":"references/live-update-advanced-topics.md","size":3238,"sha256":"c56a8a6c0519458cd4c946af3dfe81fa31c037dc69f387a6d9d54befc4dd1a33","contentType":"text/markdown; charset=utf-8"},{"id":"ee6fe74c-c47a-5083-988b-a7a36c765733","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/ee6fe74c-c47a-5083-988b-a7a36c765733/attachment.md","path":"references/live-update-ci-cd-integrations.md","size":2686,"sha256":"60fe1f14e1d37d2dd938eff3cfa7c9c54882bacdb82a1660819b6dac76dc9ec6","contentType":"text/markdown; charset=utf-8"},{"id":"1ed1efaa-80af-55fd-89f4-130d61790ffd","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/1ed1efaa-80af-55fd-89f4-130d61790ffd/attachment.md","path":"references/live-update-configuration.md","size":4650,"sha256":"6e28fbb8c8f1f2e68cd27d05b5419c9bbb3d576372821a402b2e6ff709f62dd4","contentType":"text/markdown; charset=utf-8"},{"id":"e37848ba-49a6-5b83-9d43-9cf7d4807866","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/e37848ba-49a6-5b83-9d43-9cf7d4807866/attachment.md","path":"references/live-update-faq.md","size":2719,"sha256":"e6db0ea9b104d28f8fc90a9a85f4bdde84563d31211fa108c81623a1fe035094","contentType":"text/markdown; charset=utf-8"},{"id":"d5760b38-bdf4-5d10-8364-ef664240bcc5","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d5760b38-bdf4-5d10-8364-ef664240bcc5/attachment.md","path":"references/live-update-plugin-api.md","size":5254,"sha256":"0de6126564a723305fcb0f492a8935a161e4968bfa4406edd490a17121d2c3fe","contentType":"text/markdown; charset=utf-8"},{"id":"aa4bc85b-12ba-534d-877b-1063f0188803","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/aa4bc85b-12ba-534d-877b-1063f0188803/attachment.md","path":"references/live-updates.md","size":8010,"sha256":"01af1b441fc59f30b67026286ba68d728120c69fa69278131cd882e77ff783b0","contentType":"text/markdown; charset=utf-8"},{"id":"c3db1572-45a6-59b5-84b3-3267de8a5eb1","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c3db1572-45a6-59b5-84b3-3267de8a5eb1/attachment.md","path":"references/native-builds.md","size":7172,"sha256":"6916375782ee590b06740c68cc6d6abd504a95f623fdfdb30a8cdc96a7c74fcf","contentType":"text/markdown; charset=utf-8"},{"id":"17909252-c1b3-5a22-bf44-0512ad41f1d6","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/17909252-c1b3-5a22-bf44-0512ad41f1d6/attachment.md","path":"references/update-strategies.md","size":2612,"sha256":"244cad03ae14aeed5332410a8be7a9707ba4e6098a054402547b126875f441ab","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"3d1830097853f85239d113b14e0453640d2511822f0fbf5f95bbc553d6aeff2e","attachment_count":20,"text_attachments":20,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/capawesome-cloud/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"testing-qa","category_label":"Testing"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"testing-qa","metadata":{"author":"capawesome-team","source":"https://github.com/capawesome-team/skills/tree/main/skills/capawesome-cloud"},"import_tag":"clean-skills-v1","description":"Guides the agent through setting up and using Capawesome Cloud for Capacitor apps. Covers three core workflows: (1) Native Builds — cloud builds for iOS and Android, signing certificates, environments, Trapeze configuration, and build artifacts; (2) Live Updates — OTA updates via the @capawesome/capacitor-live-update plugin, channels, versioning, rollbacks, and code signing; (3) App Store Publishing — automated submissions to Apple App Store (TestFlight) and Google Play Store. Includes CI/CD integration for all workflows. Do not use for non-Capacitor mobile frameworks."}},"renderedAt":1782986934988}

Capawesome Cloud Set up and manage native builds, live updates, and app store publishing for Capacitor apps using Capawesome Cloud. Prerequisites 1. A Capawesome Cloud account and organization. 2. A Capacitor 6, 7, or 8 app. 3. Node.js and npm installed. 4. For Native Builds : The app must be in a Git repository (GitHub, GitLab, Bitbucket, or Azure DevOps). 5. For Apple App Store Publishing : An active Apple Developer Program membership and an app created in App Store Connect. 6. For Google Play Store Publishing : A Google Play Developer account and an app created in Google Play Console with…