This is the full developer documentation for Capgo # Welcome to Capgo Documentation > Master Capgo Cloud for instant app updates and explore our comprehensive collection of Capacitor plugins to enhance your mobile development ## 🚀 Capgo Cloud - Live Updates Made Simple [Section titled “🚀 Capgo Cloud - Live Updates Made Simple”](#-capgo-cloud---live-updates-made-simple) Instant Updates Deploy JavaScript, HTML, and CSS updates directly to users without app store delays. Fix bugs and ship features in minutes, not days. 3-Step Integration Get started with just `npx @capgo/cli@latest init [APIKEY]` and start pushing updates immediately with our simple integration. Mobile & Desktop Same live update system for Capacitor mobile apps and Electron desktop apps. One platform, all your apps. Complete Guide Learn everything from [quick setup](/docs/getting-started/quickstart/) to advanced deployment strategies in our comprehensive documentation. ## 📚 What’s in This Documentation [Section titled “📚 What’s in This Documentation”](#-whats-in-this-documentation) [Capgo Cloud Setup ](/docs/getting-started/quickstart/)Complete guides for integrating live updates, managing channels, CI/CD integration, and monitoring your deployments. [Electron Updater ](/docs/plugins/electron-updater/)Live updates for Electron desktop apps. Same powerful system, now for desktop applications. [150+ Capacitor Plugins ](/docs/plugins/)Explore our collection of production-ready plugins for biometrics, purchases, camera, storage, and more native features. [CLI & Public API ](/docs/cli/)Automate your workflow with our CLI tools and integrate Capgo into your existing systems with our REST API. [Enterprise Solutions ](/enterprise/)Dedicated support, SLAs, custom features, and advanced security options for teams that need more. ## 🎯 Quick Links [Section titled “🎯 Quick Links”](#-quick-links) * **First time?** Start with the [5-minute quickstart](/docs/getting-started/quickstart/) * **Need a plugin?** Browse our [plugin collection](/docs/plugins/) or request [custom development](/consulting/) * **Having issues?** Check the [FAQ](/docs/faq/) or join our [Discord](https://discord.capgo.app) * **Enterprise needs?** Check our [enterprise solutions](/enterprise/) or [contact us](mailto:support@capgo.app) ## Keep going from Welcome to Capgo Documentation [Section titled “Keep going from Welcome to Capgo Documentation”](#keep-going-from-welcome-to-capgo-documentation) If you are using **Welcome to Capgo Documentation** to plan native plugin work, connect it with [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives, and [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds. # Introduction to Capgo Build > Build iOS and Android apps in the cloud without local setup. No local Mac required for iOS builds. Capgo Build is a cloud-based native app compilation service for Capacitor apps. It lets you build iOS and Android apps without maintaining local development environments - no Xcode, no Android Studio, no Mac hardware required on your own machine. ## What Capgo Build Does [Section titled “What Capgo Build Does”](#what-capgo-build-does) Capgo Build compiles the **native parts** of your Capacitor app in the cloud: iOS Builds Run on dedicated Mac Mini Silicon M4 machines — no Mac of your own required. Android Builds Build on the same M4 fleet, with Android Studio 2025 available. Automatic Code Signing Certificates, provisioning profiles, and keystores are all handled for you. Direct Store Submission Signed apps upload straight to App Store Connect and Google Play. You trigger builds with a single CLI command that works from anywhere - your local machine, GitHub Actions, GitLab CI, or any CI/CD pipeline. ## Build Machines and Toolchain [Section titled “Build Machines and Toolchain”](#build-machines-and-toolchain) Capgo Build runs native jobs on dedicated Mac Mini Silicon M4 machines: | Component | Specification | | ------------- | -------------------------------------------------------- | | Machine | Mac Mini Silicon M4 | | CPU | 10-core M4 CPU (4 performance cores, 6 efficiency cores) | | GPU | 10-core GPU | | Neural Engine | 16-core Neural Engine | | Memory | 16GB of RAM | | OS image | macOS Tahoe 26.2 | The build image supports Xcode 26.2 and Android Studio 2025 for native build pipelines. ## When to Use Capgo Build vs Live Updates [Section titled “When to Use Capgo Build vs Live Updates”](#when-to-use-capgo-build-vs-live-updates) Capgo offers two complementary features for updating your app. Here’s when to use each: | Scenario | Live Updates | Capgo Build | | --------------------------------------------------------- | :----------: | :---------: | | Bug fix in JavaScript/TypeScript code | ✓ | | | UI changes (HTML, CSS, images) | ✓ | | | Updating web dependencies | ✓ | | | Adding or removing a Capacitor plugin | | ✓ | | Updating a native SDK version | | ✓ | | Changing native permissions (Info.plist, AndroidManifest) | | ✓ | | Updating Capacitor version | | ✓ | | Modifying native code (Swift, Kotlin, Java) | | ✓ | | Changing app icon or splash screen | | ✓ | | First app store submission | | ✓ | Note **Live Updates** push JavaScript changes instantly without app store review. **Capgo Build** creates new native binaries when you change native code. Most teams use Live Updates daily and Capgo Build occasionally when native changes are needed. ## Why Use Capgo Build [Section titled “Why Use Capgo Build”](#why-use-capgo-build) No Local Mac Required for iOS Build and ship iOS apps without owning Mac hardware. Anyone on Windows, Linux, or any CI/CD system can trigger iOS builds and publish to TestFlight. Skip Local Environment Setup No need to install Xcode, Android Studio, or manage SDK versions. Capgo Build handles all native tooling - you just run the CLI command. Centralized Credentials Store your certificates and keystores in your CI/CD secrets once. Any team member can trigger builds without needing signing credentials on their local machine. Works With Any CI/CD A single CLI command integrates with any pipeline. GitHub Actions, GitLab CI, Jenkins - trigger builds as part of your existing workflow. Real-Time Build Logs Watch your build progress live in your terminal. Logs stream via Server-Sent Events so you can debug issues instantly as they happen. Direct Store Submission Signed apps upload directly to App Store Connect and Google Play. No manual steps between build completion and store submission. ## How It Works [Section titled “How It Works”](#how-it-works) When you run the build command: 1. **Upload** - The CLI zips only what’s needed (native platform folder + native dependencies) and uploads to secure cloud storage 2. **Build** - Your app compiles on dedicated infrastructure using Fastlane 3. **Sign** - Certificates and keystores are applied (they exist only in memory during the build) 4. **Submit** - Signed apps are uploaded directly to App Store Connect or Google Play 5. **Cleanup** - All build artifacts and credentials are automatically deleted Your source code stays on your machine. Only the platform-specific native code is uploaded. ## Security Model [Section titled “Security Model”](#security-model) Capgo Build is designed with zero credential storage: * **Runtime-only credentials** - Certificates and keystores are never stored in Capgo. They are uploaded and removed immediately after the build finishes. * **Ephemeral environments** - Each build runs in isolation and is destroyed after completion * **No log storage** - Build logs stream to your terminal only, never stored on Capgo servers * **Minimal upload** - Only the native platform you request is uploaded, not your full codebase. [See exactly what gets uploaded](/docs/builder/getting-started/#what-gets-built) ## Pricing [Section titled “Pricing”](#pricing) Build time is the only cost: * Build minutes are included in your Capgo plan * Extra minutes available via credit system * Builds run on Mac Mini Silicon M4 machines with the native toolchains already installed * No storage fees ## Next Steps [Section titled “Next Steps”](#next-steps) [Getting Started ](/docs/builder/getting-started/)Create your first build and see Capgo Build in action. [Credentials Setup ](/docs/builder/credentials/)Configure certificates for iOS and keystores for Android. [Auto OTA or Native ](/docs/builder/ci-ota-or-native/)CI that picks live update vs Capgo Build automatically. [Trigger from CI UI ](/docs/builder/ci-ui-trigger/)Start a native build from GitHub, GitLab, Bitbucket, or Azure. [Build Webhooks ](/docs/builder/webhooks/)Fire Capgo Build from an admin dashboard over HTTP. [Prescan checks ](/docs/builder/prescan/)Full list of pre-build checks and how to skip or warn on specific rules. [GitHub Actions ](/docs/builder/github-actions/)Full Capgo Build CI setup with secrets and release workflows. # AI Build Diagnosis > When a native build fails, Capgo's AI reads the build log and tells you the likely cause, the evidence, and how to fix it. Native build logs are long. When an iOS (Xcode / Fastlane) or Android (Gradle / Fastlane) build fails, Capgo can run the log through an AI build engineer that pinpoints **what went wrong and how to fix it** — so you don’t have to scroll thousands of lines yourself. ## Enable it [Section titled “Enable it”](#enable-it) Add `--ai-analytics` to your build: ```bash bunx @capgo/cli@latest build request com.example.app --platform android --ai-analytics ``` The diagnosis only kicks in when a build **fails** — successful builds are untouched. ## When it runs [Section titled “When it runs”](#when-it-runs) What happens on a failed build depends on where you run it and whether you passed the flag: | Environment | `--ai-analytics` | Behavior | | -------------------- | :--------------: | ----------------------------------------------------- | | Interactive terminal | yes | Diagnoses the failure immediately | | Interactive terminal | no | Asks first, then offers the diagnosis | | CI / non-interactive | yes | Runs automatically and prints the diagnosis to stderr | | CI / non-interactive | no | Skipped — nothing is sent | So in CI you must opt in with `--ai-analytics`; in a terminal you’re always asked first unless the flag pre-opts you in. ## What you get [Section titled “What you get”](#what-you-get) A short, focused markdown report: * **Likely cause** — one sentence. * **Evidence** — the 1–3 most relevant lines quoted from your log. * **Suggested fix** — numbered steps to change in *your* project (signing config, a missing capability, a Gradle or CocoaPods issue, a plugin conflict, 
). If the logs are ambiguous it says so and lists the top hypotheses, rather than inventing an error that isn’t there. ## Your logs, your choice [Section titled “Your logs, your choice”](#your-logs-your-choice) AI diagnosis is **opt-in** — nothing is sent unless you pass `--ai-analytics` or confirm the prompt. * **Capgo AI (default):** your build log is trimmed and sent to Capgo’s analysis endpoint (which runs on Cloudflare Workers AI) just long enough to produce the diagnosis. Build logs aren’t part of normal storage — they stream to your terminal during the build. * **Keep logs on your machine:** in an interactive terminal you can instead have the CLI **write a local prompt file** — the same diagnosis instructions plus your log — that you paste into your own LLM. Your logs never leave your machine. Note The analysis treats your build log as untrusted data, so a log line that looks like an instruction (a prompt-injection attempt) can’t hijack the diagnosis. # Android Builds > Configure and build Android apps with Capgo Cloud Build Build and submit Android apps to Google Play Store using Capgo’s dedicated infrastructure. ## What you will learn [Section titled “What you will learn”](#what-you-will-learn) * You will learn how to upload your app via Capgo Native build * You will learn how to configure the credentials for Capgo Native Build ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * You need to have an active Google Developer account * You need to have Android Studio installed * Your app must be able to build successfully with Android Studio Note I will use the following app for the tutorial: Recommended: automated onboarding You don’t have to do any of this by hand. Capgo’s onboarding creates and configures your Android signing credentials (keystore + Google Play service account) for you — this is the recommended path: ```bash bunx @capgo/cli@latest build init --platform android ``` The manual walkthrough below is only for those who prefer to set up credentials themselves, or want to understand exactly what Capgo does under the hood. ## The first manual build [Section titled “The first manual build”](#the-first-manual-build) Before we can start thinking about building the app with Capgo, we should first set it up, and do a first Android build by hand. There are some advantages to doing a manual build first: * You will prepare the credentials for the later Capgo build * You will create a record on the Play Store Console ### Building the app manually with Android Studio [Section titled “Building the app manually with Android Studio”](#building-the-app-manually-with-android-studio) Before we can start building the app with Capgo, we need to build the app manually with Android Studio. 1. Open Android Studio Run `bunx cap open android` to open the Android Studio project. 2. Click on `Build` -> `Generate Signed App Bundles / APKs` ![Android Studio generate signed app bundles / APKs](/native-build-assets/android-studio-generate-signed-app-bundles-apks.webp) 3. Select `Android App Bundle` and click on `Next` ![Android Studio select Android App Bundle](/native-build-assets/android-studio-select-android-app-bundle.webp) ### Creating a Keystore [Section titled “Creating a Keystore”](#creating-a-keystore) Right now, you are missing the keystore file. This file is used to sign your app, which lets Google know that it’s you who built the app. To generate it, we will use the GUI method provided by Android Studio. There is also a way to do this with the command line, but we will not cover that in this tutorial. 1. Click on `Create new` ![Android Studio create new keystore](/native-build-assets/android-studio-create-new-keystore.webp) 2. Fill in the Key Store path ![Android Studio fill in key store path](/native-build-assets/android-studio-fill-in-key-store-path.webp) Caution This **IS TO BE SAVED** - it will be used later 3. Set the Key Store password ![Android Studio set key store password](/native-build-assets/android-studio-set-key-store-password.webp) Note I recommend using the same password for the Key Store and the Key Alias. Caution This **IS TO BE SAVED** - it will be used later 4. Fill the rest of the form 1. Keep the Key Alias as is (key0) 2. Fill the certificate details. I have filled it with fake details, but you should fill it with your own details. ![Android Studio fill rest of the form](/native-build-assets/android-studio-fill-rest-of-the-form.webp) 5. Click on `OK` ![Android Studio click on OK](/native-build-assets/android-studio-click-on-ok.webp) ### Finishing the manual build [Section titled “Finishing the manual build”](#finishing-the-manual-build) 1. Make sure all of the details for the keystore have been filled in correctly and click on `Next` ![Android Studio make sure all of the details for the keystore have been filled in correctly](/native-build-assets/android-studio-make-sure-all-of-the-details-for-the-keystore-have-been-filled-in-correctly.webp) 2. Select the `release` build variant and click on `Create` ![Android Studio select release build variant](/native-build-assets/android-studio-select-release-build-variant.webp) 3. After the build succeeds, you should see the following screen ![Android Studio after build succeed](/native-build-assets/android-studio-after-build-succeed.webp) 1. This popup indicates that the build succeeded. 2. Click on the `locate` button - this will open the file explorer and you should see the build there. 4. Make sure you can see the build in the file explorer ![Android Studio make sure you can see the build in the file explorer](/native-build-assets/android-studio-make-sure-you-can-see-the-build-in-the-file-explorer.webp) ### Creating the app on the Play Store Console [Section titled “Creating the app on the Play Store Console”](#creating-the-app-on-the-play-store-console) 1. Go to [Google Play Console](https://play.google.com/console/) 2. Select the correct developer account ![Google Play Console select correct developer account](/native-build-assets/google-play-console-select-correct-developer-account.webp) 3. Click on `Create app` ![Google Play Console create app](/native-build-assets/google-play-console-create-app.webp) 4. Choose the app name and the language ![Google Play Console choose the app name and the language](/native-build-assets/google-play-console-choose-the-app-name-and-the-language.webp) 5. Select the app category and if the app is paid or free ![Google Play Console select the app category and if the app is paid or free](/native-build-assets/google-play-console-select-the-app-category-and-if-the-app-is-paid-or-free.webp) 6. Accept the terms and conditions ![Google Play Console accept the terms and conditions](/native-build-assets/google-play-console-accept-the-terms-and-conditions.webp) Caution Make sure you read the terms and conditions before accepting them. 7. Click on `Create` ![Google Play Console click on create](/native-build-assets/google-play-console-click-on-create.webp) ### Creating the internal testing group [Section titled “Creating the internal testing group”](#creating-the-internal-testing-group) Now that you have created the app, you can create an internal testing group. Since I won’t actually publish the app for everyone on Play Store, I will need to create an internal testing group. Note Internal testing is still the fastest way to smoke-test your Play-distributed build before a real launch. If your developer account is a personal account created after November 13, 2023, internal testing does **not** replace the closed-testing requirement for production access. You will still need a closed test with at least 12 opted-in testers for 14 consecutive days before production. 1. Go to `internal testing` Click on `Test and release` -> `Testing` -> `Internal testing` ![Google Play Console internal testing](/native-build-assets/google-play-console-internal-testing.webp) 2. Click on `Testers` ![Google Play Console testers](/native-build-assets/google-play-console-testers.webp) 3. Click on `Create email list` ![Google Play Console create email list](/native-build-assets/google-play-console-create-email-list.webp) 4. Name the email list ![Google Play Console name the email list](/native-build-assets/google-play-console-name-the-email-list.webp) 5. Add the email addresses of the testers ![Google Play Console add the email addresses of the testers](/native-build-assets/google-play-console-add-the-email-addresses-of-the-testers.webp) 6. Press `Enter` and click on `Save` ![Google Play Console press enter and click on save](/native-build-assets/google-play-console-press-enter-and-click-on-save.webp) 7. Click on `Create group` ![Google Play Console create group](/native-build-assets/google-play-console-create-group.webp) 8. Make sure that the new list is selected and click on `Save` ![Google Play Console make sure that the new list is selected and click on save](/native-build-assets/google-play-console-make-sure-that-the-new-list-is-selected-and-click-on-save.webp) ### Uploading the app to the internal testing group [Section titled “Uploading the app to the internal testing group”](#uploading-the-app-to-the-internal-testing-group) Now that you have created the internal testing group, you can upload the app to the internal testing group. 1. Go to `Test and release` -> `Testing` -> `Internal testing` ![Google Play Console internal testing](/native-build-assets/google-play-console-internal-testing.webp) 2. Click on the `Releases` button ![Google Play Console releases button](/native-build-assets/google-play-console-releases-button.webp) 3. Click on `Create new release` ![Google Play Console create new release](/native-build-assets/google-play-console-create-new-release.webp) 4. Click on `Upload` ![Google Play Console upload](/native-build-assets/google-play-console-upload.webp) 5. Select the AAB file ![Google Play Console select AAB file](/native-build-assets/google-play-console-select-apk-file.webp) Caution Make sure you select the AAB file that you built manually with Android Studio. If this file doesn’t use the same keystore as the one you will use for the Capgo build, the Capgo Native Build will fail. 6. Wait for the AAB file to be uploaded 7. Click on `Next` ![Google Play Console next](/native-build-assets/google-play-console-next-step.webp) 8. Fix the errors Personally, at this stage I see this error ![Google Play Console big scary warning](/native-build-assets/google-play-console-big-scary-warning.webp) This is because I haven’t verified my phone number yet. I will do that and continue the tutorial. 9. Click on `Save and publish` This will publish the app to the internal testing group. ![Google Play Console save and publish](/native-build-assets/google-play-console-save-and-publish.webp) 10. Confirm the publication ![Google Play Console confirm publication](/native-build-assets/google-play-console-confirm-publication.webp) 11. Make sure the app is published ![Google Play Console make sure the app is published](/native-build-assets/google-play-console-make-sure-the-app-is-published.webp) 12. Get your temporary app name ![Google Play Console get your temporary app name](/native-build-assets/google-play-console-get-your-temporary-app-name.webp) ### Accept the invitation to internal testing group [Section titled “Accept the invitation to internal testing group”](#accept-the-invitation-to-internal-testing-group) Now that you have uploaded the app to the internal testing group, you can accept the invitation to the internal testing group. 1. Go to `Test and release` -> `Testing` -> `Internal testing` ![Google Play Console internal testing](/native-build-assets/google-play-console-internal-testing.webp) 2. Click on `Testers` ![Google Play Console testers](/native-build-assets/google-play-console-testers.webp) 3. Click on `Copy link` ![Google Play Console copy link](/native-build-assets/google-play-console-copy-link.webp) 4. Send the link to your phone, open it in the browser and click on `Accept` ![Google Play Console accept invitation](/native-build-assets/google-play-console-accept-invitation.webp) 5. Confirm the invitation has been accepted and click on “download it on Play Store” ![Google Play Console download it on Play Store](/native-build-assets/google-play-console-download-it-on-play-store.webp) 6. Install the app 1. If you had installed the app before using Android Studio, click on the `uninstall` button ![Google Play Console uninstall app](/native-build-assets/google-play-console-uninstall-app.webp) 2. Click on the `install` button ![Google Play Console install app](/native-build-assets/google-play-console-install-app.webp) 3. Open the app and confirm it has downloaded successfully [](/native-build-assets/screen-20260215-072439-1771136671038.mp4 "App downloaded successfully from Play Store internal testing") Caution If you do not see the app in Play Store, make sure you have selected the correct account in Play Store. ## Configuring Capgo Native Build (Android) [Section titled “Configuring Capgo Native Build (Android)”](#configuring-capgo-native-build-android) Now, you are ready to start the setup of Capgo Native Build. Congratulations 🎉! | Requirement | Flag | Description | Required | | --------------------------- | -------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------- | | Keystore file | `--keystore ` | Path to your `.jks`/`.keystore` file used to sign the APK/AAB. | Yes | | Keystore alias | `--keystore-alias ` | Alias name of the key inside the keystore. | Yes | | Keystore key password | `--keystore-key-password ` | Password for the key. If key/store passwords match, you can provide only one. | Look at the note below | | Keystore store password | `--keystore-store-password ` | Password for the keystore. If key/store passwords match, you can provide only one. | Look at the note below | | Google Play service account | `--play-config ` | JSON service account file for Play Store uploads. | Yes | ```bash bunx @capgo/cli@latest build credentials save --platform android \ --keystore ./path/to/keystore.jks \ --keystore-alias "your-alias" \ --keystore-key-password "key-password" \ --keystore-store-password "store-password" \ --play-config ./play-store-service-account.json ``` Note If key and store passwords are identical, provide only one of `--keystore-key-password` or `--keystore-store-password`. ### Keystore, keystore password, keystore key password, keystore alias [Section titled “Keystore, keystore password, keystore key password, keystore alias”](#keystore-keystore-password-keystore-key-password-keystore-alias) If you have followed the [manual build instructions](/docs/builder/android/#building-the-app-manually-with-android-studio), you should have the keystore already generated. If you have not followed the instructions, please follow them to generate the keystore. ### Google Play service account [Section titled “Google Play service account”](#google-play-service-account) Generating the Google Play service account is a manual and complex process. Yet, it is required to upload your app to Google Play. Please keep in mind the following things: * You **NEED** to be the [owner of the Developer Account](https://support.google.com/googleplay/android-developer/thread/238025575?hl=en\&msgid=238033420). Otherwise, you will not be able to setup the service account. * You will need to create a new Google Cloud Project (separate from your Google Play Account) Let’s begin. 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 2. Click on the project selector ![Google Console Project Selector](/social-login-assets/google_cons_project_selector.png) 3. If you already have a project, select it. Otherwise, create a new project: Note The screenshots below are illustrative - use a name appropriate for your project. 1. Click on `New project` ![New Project button in Google Console](/social-login-assets/google_cons_new_project_btn.png) 2. Name your project and click `Create` ![Project naming screen showing name field and Create button](/social-login-assets/google_cons_name_projec.png) 3. Ensure that you are on the right project ![Project name showing in the selector indicating correct project selection](/social-login-assets/google_cons_right_proj.png) 4. Let’s click on the search bar and search for `service accounts` and click on it ![Google Console search bar](/native-build-assets/google-console-search-bar.webp) 5. Let’s click on `Create service account` ![Create Service Account button in Google Console](/native-build-assets/google_cons_create_service_account_btn.webp) 6. Fill in the form for the service account and click on `Done` 1. I recommend setting the name to `Capgo Native Build Service Account` 2. For the Service Account ID, I recommend setting it to `capgo-native-build-service-acc` 3. As for the description, you don’t have to fill it in, but I recommend filling it with `Allows Capgo Native Build to build and submit the app to the Play Store` ![Google Console fill in the form for the service account](/native-build-assets/google-console-fill-in-the-form-for-the-service-account.webp) 7. Click on the newly created service account You should now see the newly created service account in the list. Click on it. ![Google Console newly created service account](/native-build-assets/google-console-newly-created-service-account.webp) Note Copy this email address as well, you will need it later. 8. Click on the `Keys` tab ![Keys tab in Google Console](/native-build-assets/google_cons_keys_tab.webp) 9. Click on `Add Key` and `Create new key` ![Google Console add key and create new key](/native-build-assets/google-console-add-key-and-create-new-key.webp) 10. Click on `JSON` and `Create` ![Create Key button in Google Console](/native-build-assets/google_cons_create_key_btn.webp) Caution Clicking on `Create` will create a new key and it will download the JSON file to your local machine. You need to save the JSON file in a safe place. It **WILL** be used later. 11. Download the JSON file The JSON file should have been downloaded automatically. You can click on `close` to close the window. ![Google Console download key](/native-build-assets/google-console-download-key.webp) ### Granting Play Store API access to the service account [Section titled “Granting Play Store API access to the service account”](#granting-play-store-api-access-to-the-service-account) The newly created service account does not yet have access to the Play Store API. To grant it, head to the Play Store Console. 1. Go to [Google Play Console](https://play.google.com/console/) 2. Select the correct developer account ![Google Play Console select correct developer account](/native-build-assets/google-play-console-select-correct-developer-account.webp) 3. Click on `Users and permissions` ![Google Play Console users and permissions](/native-build-assets/google-play-console-users-and-permissions.webp) 4. Click on `Invite new users` ![Google Play Console invite new users](/native-build-assets/google-play-console-invite-new-users.webp) 5. Copy the email address of the service account ![Google Play Console copy email address of the service account](/native-build-assets/google-play-console-copy-email-address-of-the-service-account.webp) 6. Go to `Account permissions` and grant the minimum required permissions: * In `App permissions`, grant access to your app. * In `Releases`, enable `Create, edit, and roll out releases`. * If your workflow uses Play App Signing, enable the related signing permission. * If you are unsure, use `Admin` only during setup, then reduce permissions afterward. ![Google Play Console grant permissions](/native-build-assets/google-play-console-grant-permissions.webp) 7. Click on `Invite user` ![Google Play Console invite user](/native-build-assets/google-play-console-invite-user.webp) 8. Confirm the invitation ![Google Play Console confirm invitation](/native-build-assets/google-play-console-confirm-invitation.webp) 9. Confirm that the user has been invited ![Google Play Console confirm that the user has been invited](/native-build-assets/google-play-console-confirm-that-the-user-has-been-invited.webp) ### Saving the credentials [Section titled “Saving the credentials”](#saving-the-credentials) You are now ready to save the credentials and run your first build. You can save the credentials using the following command: ```bash bunx @capgo/cli@latest build credentials save --platform android \ --keystore ./path/to/keystore.jks \ --keystore-alias "your-alias" \ --keystore-key-password "key-password" \ --keystore-store-password "store-password" \ --play-config ./play-store-service-account.json ``` ### CI/CD setup (GitHub Actions) [Section titled “CI/CD setup (GitHub Actions)”](#cicd-setup-github-actions) If you already completed [Keystore, keystore password, keystore key password, keystore alias](#keystore-keystore-password-keystore-key-password-keystore-alias) and [Google Play service account](#google-play-service-account), you already have everything needed for CI/CD. This section only covers how to pass those values as GitHub Actions secrets and environment variables. #### 1) Convert credential files to single-line base64 [Section titled “1) Convert credential files to single-line base64”](#1-convert-credential-files-to-single-line-base64) ```bash # Android keystore (.jks or .keystore) base64 -i ./path/to/keystore.jks | tr -d '\n' > keystore_base64.txt # Google Play service account JSON base64 -i ./play-store-service-account.json | tr -d '\n' > play_config_base64.txt ``` Tip GitHub secrets should be single-line values. `tr -d '\n'` removes line breaks from base64 output. #### 2) Create repository secrets [Section titled “2) Create repository secrets”](#2-create-repository-secrets) In `GitHub > Repository > Settings > Secrets and variables > Actions`, add: | Secret name | Value | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | `CAPGO_TOKEN` | Your Capgo API token | | `APP_ID` | Your Capgo app ID (example: `com.example.app`) | | `ANDROID_KEYSTORE_FILE` | Content of `keystore_base64.txt` | | `KEYSTORE_KEY_ALIAS` | Keystore alias from [Keystore, keystore password, keystore key password, keystore alias](#keystore-keystore-password-keystore-key-password-keystore-alias) | | `KEYSTORE_KEY_PASSWORD` | Keystore key password | | `KEYSTORE_STORE_PASSWORD` | Keystore store password | | `PLAY_CONFIG_JSON` | Content of `play_config_base64.txt` | Note If key and store passwords are the same, you can provide just one of `KEYSTORE_KEY_PASSWORD` or `KEYSTORE_STORE_PASSWORD`. #### 3) Use env vars in your GitHub Actions workflow [Section titled “3) Use env vars in your GitHub Actions workflow”](#3-use-env-vars-in-your-github-actions-workflow) .github/workflows/android-build.yml ```yaml name: Android Cloud Build on: workflow_dispatch: push: branches: [main] jobs: android-build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Request Android build with Capgo run: bunx @capgo/cli@latest build request ${{ secrets.APP_ID }} --platform android env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} ``` Tip With this setup, CI sends credentials through environment variables only. You do not need to commit signing files or upload them as workflow artifacts. ### Running the build [Section titled “Running the build”](#running-the-build) Congratulations 🎉! You are now ready to run your first build. Run: ```bash bunx @capgo/cli@latest build request com.example.app --platform android ``` And this will start the build process đŸŸđŸ„‚ ### Submit the Play release for review [Section titled “Submit the Play release for review”](#submit-the-play-release-for-review) By default, Android release builds upload to Google Play and can remain inactive until you finish the release in Play Console. If your CI release should submit the Play release automatically, pass `--submit-to-store-review` with a release build: ```bash npx @capgo/cli@latest build request com.example.app \ --platform android \ --build-mode release \ --submit-to-store-review \ --android-track production \ --store-release-name "1.2.3" \ --store-release-notes "General improvements" \ --store-release-notes-locale "en-US=General improvements" \ --store-release-notes-locale "nl-NL=Algemene verbeteringen" \ --store-release-notes-locale "fr-FR=Ameliorations generales" ``` Caution On Android, `--submit-to-store-review` defaults to the **production** track with `release_status: completed` when you do not set a track. That can go live to 100% of users. Pass `--android-track internal` (or `alpha` / `beta`) — or set `PLAY_STORE_TRACK` in CI — to keep the completed release on a non-production track. Use `--android-release-status` / `PLAY_STORE_RELEASE_STATUS` when you need a different status than `completed`. This requires the same Google Play service account setup as the normal upload path (`PLAY_CONFIG_JSON` in CI or saved Android credentials locally). `--store-release-name` is used as the Google Play `version_name`. `--store-release-notes` is the fallback Play changelog, and each `--store-release-notes-locale "locale=notes"` entry writes a localized Play changelog for that locale. Capgo sends the Play release as `completed` unless you override `--android-release-status`; if Managed publishing is enabled in Play Console, Google can still wait for your manual publish after approval. ## Keep going from Android Builds [Section titled “Keep going from Android Builds”](#keep-going-from-android-builds) If you are using **Android Builds** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # Auto Choose Live Update or Native Build > Set up CI/CD that detects whether a change can ship as a Capgo live update or needs a Capgo Build native binary, then runs the right path automatically. Most Capacitor releases are JavaScript-only and should ship as a [live update](/docs/live-updates/). Some changes touch native code and need a new binary from [Capgo Build](/docs/builder/). This guide shows how to make GitHub Actions, GitLab CI, or any other CI/CD platform pick the correct path on every push — without a human deciding. ## The Decision [Section titled “The Decision”](#the-decision) Capgo already knows which path is safe. After your web build (and before you upload or request a native build), run: ```bash npx @capgo/cli@latest bundle releaseType com.example.app --channel production # → OTA ship with bundle upload # → native ship with Capgo Build ``` `OTA` means the native packages match what is already live on the channel. `native` means a plugin, Capacitor version, or other native dependency changed — an over-the-air bundle alone cannot update those devices safely. `releaseType` compares **native package metadata** (Capacitor/Cordova plugins and versions). It does **not** see every edit under `ios/`, `android/`, or `capacitor.config.*`. Gate those paths in git first, then use `releaseType` for dependency compatibility — the examples below do both. See [Native Compatibility](/docs/live-updates/compatibility/) for the full rules and the manual `bundle compatibility` table. Tip Gate every production pipeline on `releaseType`. It is cheaper than guessing, and it avoids shipping a live update that crashes devices still on the older native binary. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * Capgo app registered and a [Capgo API key](/docs/webapp/api-keys/) in CI secrets as `CAPGO_TOKEN` * Live Updates upload working (`bundle upload`) — see [CI/CD Integration](/docs/getting-started/cicd-integration/) * Capgo Build credentials in CI if you expect native jobs — see [GitHub Actions](/docs/builder/github-actions/) or [Credentials](/docs/builder/credentials/) * A channel that already exists and matches production (examples use `production`) * Channel on the `metadata` strategy so every upload can carry `--auto-min-update-version` (one-time): ```bash npx @capgo/cli@latest channel set production com.example.app --disable-auto-update metadata ``` ## How the Pipeline Should Work [Section titled “How the Pipeline Should Work”](#how-the-pipeline-should-work) ``` flowchart TD A[Push / merge] --> B[Install + web build] B --> C["bundle releaseType"] C -->|OTA| D["bundle upload"] C -->|native| E["build request iOS + Android"] E --> F[Store / TestFlight / Play] ``` 1. Build web assets as usual. 2. If the commit touches `ios/`, `android/`, or `capacitor.config.*`, force the native path. 3. Otherwise ask Capgo `releaseType` whether the commit is OTA-safe. 4. If `OTA`, upload with `--fail-on-incompatible` and `--auto-min-update-version`. 5. If `native`, run Capgo Build, then upload the matching bundle with `--auto-min-update-version` so the channel’s native metadata advances. Do **not** use `--fail-on-incompatible` for that baseline upload — the new native packages are supposed to differ. See [Native + OTA Channel Workflow](/docs/live-updates/native-ota-channel-workflow/) for the channel-level FAQ. ## GitHub Actions [Section titled “GitHub Actions”](#github-actions) One workflow that gates native paths, then branches on `releaseType`: .github/workflows/capgo-release.yml ```yaml name: Capgo Release on: push: branches: [main] jobs: decide: runs-on: ubuntu-latest outputs: release_type: ${{ steps.verdict.outputs.type }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: npm ci - run: npm run build - name: Decide OTA vs native id: verdict env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} run: | BEFORE="${{ github.event.before }}" if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then BEFORE="$(git rev-parse HEAD~1 2>/dev/null || echo '')" fi if [ -z "$BEFORE" ] || git diff --name-only "$BEFORE" "${{ github.sha }}" \ | grep -qE '^(ios/|android/|capacitor\.config\.)'; then TYPE=native echo "Native path/config changed (or no prior commit) — forcing native" else TYPE=$(npx @capgo/cli@latest bundle releaseType com.example.app --channel production | tr -d '[:space:]') fi echo "type=$TYPE" >> "$GITHUB_OUTPUT" echo "Capgo release type: $TYPE" live_update: needs: decide if: needs.decide.outputs.release_type == 'OTA' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: npm ci - run: npm run build - name: Upload live update env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} run: | npx @capgo/cli@latest bundle upload com.example.app \ --channel production \ --fail-on-incompatible \ --auto-min-update-version native_build: needs: decide if: needs.decide.outputs.release_type == 'native' runs-on: ubuntu-latest strategy: fail-fast: false matrix: platform: [ios, android] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: npm ci - run: npm run build - run: npx cap sync ${{ matrix.platform }} - name: Capgo Build ${{ matrix.platform }} env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | npx @capgo/cli@latest build request com.example.app \ --platform ${{ matrix.platform }} \ --build-mode release native_bundle: needs: [decide, native_build] if: needs.decide.outputs.release_type == 'native' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: npm ci - run: npm run build - name: Upload bundle for new native baseline env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} run: | # Channel must already be on metadata (see Prerequisites above) npx @capgo/cli@latest bundle upload com.example.app \ --channel production \ --auto-min-update-version ``` Replace `com.example.app` and wire the signing secrets as described in [GitHub Actions for Capgo Build](/docs/builder/github-actions/). Note `--fail-on-incompatible` belongs on the OTA job only. After you put the channel on the `metadata` strategy, keep `--auto-min-update-version` on every upload (OTA and native baseline). After a native binary ships, upload the matching bundle with `--auto-min-update-version` and without `--fail-on-incompatible` so later `releaseType` checks see the new native packages. ## GitLab CI [Section titled “GitLab CI”](#gitlab-ci) GitLab evaluates `rules` when the pipeline is created, so branch with a shell `if` inside one deploy job (or generate a [dynamic child pipeline](https://docs.gitlab.com/ee/ci/pipelines/downstream_pipelines.html#dynamic-child-pipelines) if you need separate native matrix jobs): .gitlab-ci.yml ```yaml image: node:24 stages: - build - deploy variables: APP_ID: com.example.app CHANNEL: production build_web: stage: build script: - npm ci - npm run build artifacts: paths: - dist/ - node_modules/ expire_in: 1 hour only: - main deploy: stage: deploy needs: [build_web] script: - | BEFORE="${CI_COMMIT_BEFORE_SHA:-}" if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then BEFORE="$(git rev-parse HEAD~1 2>/dev/null || echo '')" fi if [ -z "$BEFORE" ] || git diff --name-only "$BEFORE" "$CI_COMMIT_SHA" \ | grep -qE '^(ios/|android/|capacitor\.config\.)'; then TYPE=native else TYPE=$(npx @capgo/cli@latest bundle releaseType "$APP_ID" --channel "$CHANNEL" | tr -d '[:space:]') fi echo "Capgo release type: $TYPE" if [ "$TYPE" = "OTA" ]; then npx @capgo/cli@latest bundle upload "$APP_ID" \ --channel "$CHANNEL" \ --fail-on-incompatible \ --auto-min-update-version elif [ "$TYPE" = "native" ]; then npx cap sync npx @capgo/cli@latest build request "$APP_ID" --platform ios --build-mode release npx @capgo/cli@latest build request "$APP_ID" --platform android --build-mode release npx @capgo/cli@latest bundle upload "$APP_ID" \ --channel "$CHANNEL" \ --auto-min-update-version else echo "Unexpected release type: $TYPE" >&2 exit 1 fi only: - main ``` Store `CAPGO_TOKEN` and Capgo Build signing variables as masked/protected CI/CD variables. ## Other CI Platforms [Section titled “Other CI Platforms”](#other-ci-platforms) The same three steps work anywhere: | Step | Command | | ----------- | ------------------------------------------------------------------------------------------------------------------ | | Verdict | `npx @capgo/cli@latest bundle releaseType APP_ID --channel production` | | OTA path | `npx @capgo/cli@latest bundle upload APP_ID --channel production --fail-on-incompatible --auto-min-update-version` | | Native path | `npx @capgo/cli@latest build request APP_ID --platform ios` (or `android`) `--build-mode release` | Map the shell exit / stdout into your platform’s conditionals (or keep a single job with a shell `if`, like GitLab above): * **Azure Pipelines** — set an output variable from a script step, then use `condition: eq(variables['releaseType'], 'OTA')` * **Bitbucket Pipelines** — write `RELEASE_TYPE=
` to `$BITBUCKET_PIPELINES_VARIABLES_PATH`, declare it under `output-variables`, and branch later steps with `condition: state: RELEASE_TYPE == "OTA"` (file artifacts alone cannot drive `condition`) * **CircleCI** — `when` is evaluated at config-compile time, so branch with a runtime shell `if` (or dynamic config / continuation), not a workspace value in `when` * **Jenkins** — capture stdout into an env var and use `when { environment name: 'RELEASE_TYPE', value: 'OTA' }` ## Paths Filters (Optional Speedup) [Section titled “Paths Filters (Optional Speedup)”](#paths-filters-optional-speedup) Path filters are a cost optimization, not a substitute for the Capgo check. Prefer excluding docs-only paths rather than maintaining a fragile allowlist — web builds often also depend on `vite.config.*`, `tsconfig*.json`, and framework config files: ```yaml on: push: branches: [main] paths-ignore: - '**.md' - 'docs/**' - '.github/**' ``` If you use an allowlist instead, include every input your web and native builds read, not only `src/` and `package.json`. ## After a Native Verdict [Section titled “After a Native Verdict”](#after-a-native-verdict) When CI chooses native: 1. Capgo Build produces signed binaries and can submit to TestFlight / Play (see [configuration](/docs/builder/configuration/)). 2. Upload the matching JS bundle with `--auto-min-update-version` (metadata strategy) so the channel records the new native packages — otherwise the next JS-only commit still returns `native`. 3. Once users install the new binary, later JavaScript-only commits return to `OTA` again. ## Related Guides [Section titled “Related Guides”](#related-guides) [Native Compatibility ](/docs/live-updates/compatibility/)Why Capgo returns OTA vs native and how to block bad uploads. [Native + OTA Channel Workflow ](/docs/live-updates/native-ota-channel-workflow/)Dev/production channels and when to drop --fail-on-incompatible for an intentional native baseline. [GitHub Actions (Capgo Build) ](/docs/builder/github-actions/)Signing secrets and full native build workflows. [Trigger Builds from the CI UI ](/docs/builder/ci-ui-trigger/)Run a native build on demand from GitHub, GitLab, or Bitbucket. [Trigger Builds via Webhook ](/docs/builder/webhooks/)Fire Capgo Build from an admin dashboard or any HTTP client. # Trigger Native Builds from the CI UI > Run Capgo Build on demand from the GitHub Actions, GitLab, Bitbucket, or Azure DevOps UI — no git tag or push required. Sometimes you need a signed iOS or Android binary without merging a PR or cutting a release tag — a QA build, a store resubmit, or a one-off TestFlight. Every major code host can start a pipeline from its web UI. This guide shows how to wire that UI to Capgo Build. ## What You Get [Section titled “What You Get”](#what-you-get) No Git Ceremony Click Run workflow / Run pipeline. Capgo Build compiles from the branch you pick. Safe Inputs Platform and build mode use constrained choices where the host supports them (GitHub / Bitbucket / Azure). GitLab variables remain editable per run unless you define [pipeline inputs](https://docs.gitlab.com/ee/ci/yaml/#specinputs) with `options`. Same Secrets as CI Reuse the Capgo Build credentials already in your repo. Nothing new on laptops. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * Capgo Build working once locally or in CI — see [Getting Started](/docs/builder/getting-started/) * Signing secrets already in the host (for GitHub, [export with the CLI and `gh secret set -f`](/docs/builder/github-actions/#setup)) * `CAPGO_TOKEN` stored as a masked secret / CI variable ## GitHub Actions [Section titled “GitHub Actions”](#github-actions) GitHub’s **Actions** tab can start any workflow that declares `workflow_dispatch`. ### 1. Add the workflow [Section titled “1. Add the workflow”](#1-add-the-workflow) .github/workflows/capgo-build-manual.yml ```yaml name: Capgo Build (Manual) on: workflow_dispatch: inputs: platform: description: Platform to build required: true default: both type: choice options: [ios, android, both] mode: description: Build mode required: true default: debug type: choice options: [debug, release] ref_note: description: Optional note for the run summary required: false type: string jobs: build: runs-on: ubuntu-latest environment: ${{ inputs.mode == 'release' && 'production' || 'build-debug' }} strategy: fail-fast: false matrix: platform: ${{ fromJSON(inputs.platform == 'both' && '["ios","android"]' || format('["{0}"]', inputs.platform)) }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: npm ci - run: npm run build - run: npx cap sync ${{ matrix.platform }} - name: Capgo Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | EXTRA="" if [ "${{ inputs.mode }}" = "debug" ] && [ "${{ matrix.platform }}" = "android" ]; then EXTRA="--no-playstore-upload --output-upload" fi npx @capgo/cli@latest build request com.example.app \ --platform ${{ matrix.platform }} \ --build-mode ${{ inputs.mode }} \ $EXTRA ``` ### 2. Run it from the UI [Section titled “2. Run it from the UI”](#2-run-it-from-the-ui) 1. Open the GitHub repository in the browser 2. Go to **Actions** 3. Select **Capgo Build (Manual)** 4. Click **Run workflow** 5. Pick the branch, platform, and mode 6. Confirm **Run workflow** Anyone with **write** access can start a build. The sample maps `release` runs to a GitHub Environment named `production` — create that environment and add required reviewers so store builds wait for approval. Without `environment:` on the job, environment protection rules never apply. Tip Prefer the API or another tool to click the button? Use [`gh workflow run`](https://cli.github.com/manual/gh_workflow_run) or see [Trigger Builds via Webhook](/docs/builder/webhooks/) for `repository_dispatch`. ## GitLab CI [Section titled “GitLab CI”](#gitlab-ci) GitLab can run a job from **Build → Pipelines → Run pipeline** when the job is available for that branch. ```yaml # Job fragment for .gitlab-ci.yml stages: - build variables: APP_ID: com.example.app PLATFORM: android # override from Run pipeline UI BUILD_MODE: debug capgo_native_manual: stage: build when: manual script: - npm ci - npm run build - npx cap sync "$PLATFORM" - | npx @capgo/cli@latest build request "$APP_ID" \ --platform "$PLATFORM" \ --build-mode "$BUILD_MODE" rules: # Actions / Pipelines UI → manual play button - if: '$CI_PIPELINE_SOURCE == "web"' when: manual # Pipeline trigger token / webhook → run automatically - if: '$CI_PIPELINE_SOURCE == "trigger"' when: on_success - when: never ``` 1. Open the GitLab project 2. Go to **Build → Pipelines → Run pipeline** 3. Choose the branch 4. Optionally set `PLATFORM` / `BUILD_MODE` variables for this run 5. Start the pipeline, then click the play button on **capgo\_native\_manual** `when: manual` keeps the job from firing on every push; the web UI (or a [pipeline trigger token](/docs/builder/webhooks/#gitlab-pipeline-trigger)) starts it on demand. ## Bitbucket Pipelines [Section titled “Bitbucket Pipelines”](#bitbucket-pipelines) Use a custom pipeline so the Bitbucket UI can pass variables: bitbucket-pipelines.yml ```yaml pipelines: custom: capgo-native-build: - variables: - name: PLATFORM default: android allowed-values: - ios - android - name: BUILD_MODE default: debug allowed-values: - debug - release - step: name: Capgo Build image: node:24 script: - npm ci - npm run build - npx cap sync "$PLATFORM" - npx @capgo/cli@latest build request com.example.app --platform "$PLATFORM" --build-mode "$BUILD_MODE" ``` Run it from **Pipelines → Run pipeline → Custom: capgo-native-build**. Store `CAPGO_TOKEN` and signing material under **Repository settings → Pipelines → Repository variables**. ## Azure DevOps [Section titled “Azure DevOps”](#azure-devops) azure-pipelines-capgo-manual.yml ```yaml trigger: none # disable CI push triggers pr: none # also disable PR triggers (GitHub/Bitbucket-backed projects) parameters: - name: platform displayName: Platform type: string default: android values: - ios - android - name: buildMode displayName: Build mode type: string default: debug values: - debug - release pool: vmImage: ubuntu-latest steps: - task: NodeTool@0 inputs: versionSpec: '24.x' - script: | npm ci npm run build npx cap sync ${{ parameters.platform }} npx @capgo/cli@latest build request com.example.app \ --platform ${{ parameters.platform }} \ --build-mode ${{ parameters.buildMode }} env: CAPGO_TOKEN: $(CAPGO_TOKEN) # map other signing secrets from Library → Variable groups ``` `trigger: none` and `pr: none` keep the pipeline off automatic CI/PR runs so it starts from **Pipelines → Run pipeline** (or a webhook). If the project uses Azure Repos branch policies that queue this pipeline, disable that policy separately. Add `CAPGO_TOKEN` and signing values to a variable group marked secret. ## Recommended Inputs [Section titled “Recommended Inputs”](#recommended-inputs) | Input | Suggested values | Notes | | ---------------- | ------------------------ | -------------------------------------- | | Platform | `ios`, `android`, `both` | Matrix when `both` | | Mode | `debug`, `release` | Debug + `--output-upload` for QA links | | iOS distribution | `app_store`, `ad_hoc` | Ad-hoc never submits to App Store | For downloadable QA artifacts, combine debug Android with `--no-playstore-upload --output-upload` and read the URL with [`build last-output`](/docs/builder/github-actions/#read-the-build-output-url-and-qr-code). ## Security Notes [Section titled “Security Notes”](#security-notes) * Prefer environment protection rules (GitHub) or protected variables (GitLab) for `release` builds that submit to stores. * Do not put signing passwords in workflow `inputs` — only in secrets/variables. * Limit who can run workflows with repository roles and team permissions (write access is required on GitHub). Branch protection alone does not control **Run workflow**; add an in-workflow authorization check if only a narrower group may start builds. ## Related Guides [Section titled “Related Guides”](#related-guides) [GitHub Actions (full setup) ](/docs/builder/github-actions/)Export credentials and push/tag workflows. [Auto OTA or Native ](/docs/builder/ci-ota-or-native/)Let CI choose live update vs Capgo Build on every push. [Trigger via Webhook ](/docs/builder/webhooks/)Call the same pipelines from an admin dashboard over HTTP. # Configuration Options > Complete reference for all Cloud Build CLI flags, environment variables, and credential keys Complete reference for every Cloud Build configuration option. Use this page to find the CLI flag, environment variable, or credential key for any build setting. ## Configuration Precedence [Section titled “Configuration Precedence”](#configuration-precedence) Every build option can be set in multiple ways. When the same option is set in multiple places, higher-priority sources win: ``` flowchart LR A["🔧 CLI Flag"] -->|overrides| B["🌍 Environment Variable"] B -->|overrides| C["📁 Local Credentials"] C -->|overrides| D["🏠 Global Credentials"] style A fill:#6366f1,color:#fff,stroke:#4f46e5 style B fill:#8b5cf6,color:#fff,stroke:#7c3aed style C fill:#a78bfa,color:#fff,stroke:#8b5cf6 style D fill:#c4b5fd,color:#1e1b4b,stroke:#a78bfa ``` **Example:** If your saved credentials have `SKIP_BUILD_NUMBER_BUMP=true` but you pass `--no-skip-build-number-bump` on the CLI, the CLI flag wins and build numbers will be auto-incremented. Tip For CI/CD pipelines, environment variables are usually the most convenient. For local development, saved credentials (via `build credentials save`) avoid repeating flags every time. *** ## iOS Options [Section titled “iOS Options”](#ios-options) ### Code Signing [Section titled “Code Signing”](#code-signing) | CLI Flag | Env Variable | Credential Key | Default | Description | | ----------------------------------- | ---------------------------- | ---------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `--build-certificate-base64 ` | `BUILD_CERTIFICATE_BASE64` | `BUILD_CERTIFICATE_BASE64` | — | Base64-encoded `.p12` distribution certificate | | `--ios-provisioning-profile ` | `CAPGO_IOS_PROVISIONING_MAP` | `CAPGO_IOS_PROVISIONING_MAP` | — | Provisioning profile as a `path` or `bundleId=path` mapping. Repeatable for multi-target apps (app + extensions); the profile name is auto-extracted. | | `--p12-password ` | `P12_PASSWORD` | `P12_PASSWORD` | — | Password for the `.p12` certificate (omit if certificate has no password) | ### App Store Connect Authentication [Section titled “App Store Connect Authentication”](#app-store-connect-authentication) | CLI Flag | Env Variable | Credential Key | Default | Description | | ---------------------------------- | --------------------------- | --------------------------- | ------- | ----------------------------------------------------- | | `--apple-key-id ` | `APPLE_KEY_ID` | `APPLE_KEY_ID` | — | App Store Connect API Key ID | | `--apple-issuer-id ` | `APPLE_ISSUER_ID` | `APPLE_ISSUER_ID` | — | App Store Connect Issuer ID (UUID) | | `--apple-key-content ` | `APPLE_KEY_CONTENT` | `APPLE_KEY_CONTENT` | — | Base64-encoded App Store Connect API key (`.p8` file) | | `--app-store-connect-team-id ` | `APP_STORE_CONNECT_TEAM_ID` | `APP_STORE_CONNECT_TEAM_ID` | — | App Store Connect Team ID | Not recommended **App-specific password authentication is discouraged and its use is advised against.** It exists only as a compatibility path for teams migrating from Ionic Appflow (which relied on it). It is tied to a personal Apple ID with no granular permissions, cannot query App Store Connect (so build numbers fall back to a timestamp), and only covers the TestFlight upload itself. Prefer an App Store Connect API key (`.p8`) instead: it is the recommended, more capable, and more secure option for CI/CD. #### App-specific password authentication (not recommended) [Section titled “App-specific password authentication (not recommended)”](#app-specific-password-authentication-not-recommended) | CLI Flag | Env Variable | Credential Key | Default | Description | | ------------------------------------------ | ---------------------------------------------- | ---------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------- | | `--apple-id ` | `FASTLANE_USER` | `FASTLANE_USER` | — | Apple ID email of the account that owns the app | | `--apple-app-specific-password ` | `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` | `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` | — | App-specific password (`xxxx-xxxx-xxxx-xxxx`) generated at [appleid.apple.com](https://appleid.apple.com) | | `--apple-app-id ` | `APPLE_APP_ID` | `APPLE_APP_ID` | — | Numeric App Store Connect app ID (e.g. `1234567890`) | Caution All three fields are required together. The numeric `APPLE_APP_ID` (found in App Store Connect → your app → App Information → Apple ID) is mandatory: without it fastlane falls back to an interactive 2FA login that cannot complete on the build runner. When this method is used the build number falls back to a timestamp-based value, because App Store Connect is not queried for the latest build number. ### iOS Build Settings [Section titled “iOS Build Settings”](#ios-build-settings) | CLI Flag | Env Variable | Credential Key | Default | Description | | --------------------------- | ------------------------ | ------------------------ | ----------- | ------------------------------------------ | | `--ios-scheme ` | `CAPGO_IOS_SCHEME` | `CAPGO_IOS_SCHEME` | `App` | Xcode scheme to build | | `--ios-target ` | `CAPGO_IOS_TARGET` | `CAPGO_IOS_TARGET` | `App` | Xcode target for reading build settings | | `--ios-distribution ` | `CAPGO_IOS_DISTRIBUTION` | `CAPGO_IOS_DISTRIBUTION` | `app_store` | Distribution mode: `app_store` or `ad_hoc` | *** ## Android Options [Section titled “Android Options”](#android-options) ### Keystore Signing [Section titled “Keystore Signing”](#keystore-signing) | CLI Flag | Env Variable | Credential Key | Default | Description | | -------------------------------------- | ------------------------- | ------------------------- | ------- | --------------------------------------------------------------- | | `--android-keystore-file ` | `ANDROID_KEYSTORE_FILE` | `ANDROID_KEYSTORE_FILE` | — | Base64-encoded keystore file (`.keystore` or `.jks`) | | `--keystore-key-alias ` | `KEYSTORE_KEY_ALIAS` | `KEYSTORE_KEY_ALIAS` | `key0` | Keystore key alias | | `--keystore-key-password ` | `KEYSTORE_KEY_PASSWORD` | `KEYSTORE_KEY_PASSWORD` | — | Keystore key password (falls back to store password if not set) | | `--keystore-store-password ` | `KEYSTORE_STORE_PASSWORD` | `KEYSTORE_STORE_PASSWORD` | — | Keystore store password | ### Google Play Configuration [Section titled “Google Play Configuration”](#google-play-configuration) | CLI Flag | Env Variable | Credential Key | Default | Description | | ----------------------------------- | --------------------------- | --------------------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `--play-config-json ` | `PLAY_CONFIG_JSON` | `PLAY_CONFIG_JSON` | — | Base64-encoded Google Play service account JSON key | | `--android-track ` | `PLAY_STORE_TRACK` | `PLAY_STORE_TRACK` | `internal` (or `production` with `--submit-to-store-review`) | Google Play release track (`internal`, `alpha`, `beta`, `production`). Forwarded from CI env / CLI into the build runner. | | `--android-release-status ` | `PLAY_STORE_RELEASE_STATUS` | `PLAY_STORE_RELEASE_STATUS` | `draft` (or `completed` with `--submit-to-store-review`) | Release status on the chosen track (`draft`, `completed`, `inProgress`, `halted`). Explicit values override the `--submit-to-store-review` default. | ### Android Build Settings [Section titled “Android Build Settings”](#android-build-settings) | CLI Flag | Default | Description | | ----------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `--android-flavor ` | — | Product flavor to build (e.g. `production`). **Required** if your project defines multiple flavors. | | `--android-track ` | `internal` | Google Play track for this upload. With `--submit-to-store-review` and no track set, Capgo defaults to `production`. | | `--android-release-status ` | `draft` | Google Play release status. With `--submit-to-store-review` and no status set, Capgo defaults to `completed`. | | `--in-app-update-priority <0–5>` | — | Google Play in-app update priority for this release (higher = more urgent). | | `--no-playstore-upload` | — | Build and sign, but skip the Play Store upload (requires `--output-upload`). | *** ## Build Control Options [Section titled “Build Control Options”](#build-control-options) These options work for both iOS and Android builds. ### Build Mode [Section titled “Build Mode”](#build-mode) | CLI Flag | Default | Description | | ----------------------- | --------- | --------------------------------------------------------------------------------------------------------- | | `--platform ` | — | **Required.** `ios` or `android` | | `--build-mode ` | `release` | `debug` or `release` | | `--path ` | `.` | Project directory | | `--verbose` | `false` | Enable verbose build logging | | `--ai-analytics` | `false` | On build failure, send logs to Capgo AI for diagnosis — see [AI Build Diagnosis](/docs/builder/ai-debug/) | ### Build Number Control [Section titled “Build Number Control”](#build-number-control) | CLI Flag | Env Variable | Credential Key | Default | Description | | ----------------------------- | ------------------------ | ------------------------ | ------- | ----------------------------------------------------------------- | | `--skip-build-number-bump` | `SKIP_BUILD_NUMBER_BUMP` | `SKIP_BUILD_NUMBER_BUMP` | `false` | Skip automatic build number / version code incrementing | | `--no-skip-build-number-bump` | — | — | — | Explicitly re-enable auto-increment (overrides saved credentials) | By default, Capgo Cloud Build automatically increments build numbers: * **iOS:** Fetches latest build number from App Store Connect, increments by 1 * **Android:** Fetches max `versionCode` from Google Play, increments by 1 When `--skip-build-number-bump` is set, the build uses whatever version is already in your project files (Xcode project or `build.gradle`). ### Output Upload [Section titled “Output Upload”](#output-upload) | CLI Flag | Env Variable | Credential Key | Default | Description | | ------------------------------- | -------------------------------- | -------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | `--output-upload` | `BUILD_OUTPUT_UPLOAD_ENABLED` | `BUILD_OUTPUT_UPLOAD_ENABLED` | `false` | Upload build outputs (IPA/APK/AAB) to Capgo storage. When set via env var, use `BUILD_OUTPUT_UPLOAD_ENABLED=true`. | | `--no-output-upload` | `BUILD_OUTPUT_UPLOAD_ENABLED` | — | — | Disable output upload. When set via env var, use `BUILD_OUTPUT_UPLOAD_ENABLED=false`. | | `--output-retention ` | `BUILD_OUTPUT_RETENTION_SECONDS` | `BUILD_OUTPUT_RETENTION_SECONDS` | `1h` | How long download links remain active | | `--output-record ` | — | — | — | After a successful build, write a JSON record (job ID, status, download URL, QR code) to `` — read it back with `build last-output`. | **Retention format:** Use human-readable durations like `1h`, `6h`, `2d`, `7d`. Minimum is 1 hour, maximum is 7 days. When set via env var, use seconds (e.g., `3600` for 1 hour). ### Authentication [Section titled “Authentication”](#authentication) | CLI Flag | Env Variable | Default | Description | | -------------------- | ------------- | ------- | -------------------------------------------- | | `-a, --apikey ` | `CAPGO_TOKEN` | — | Capgo API key for authentication | | `--supa-host ` | — | — | Custom Supabase host (self-hosting only) | | `--supa-anon ` | — | — | Custom Supabase anon key (self-hosting only) | *** ## Environment Variable Quick Reference [Section titled “Environment Variable Quick Reference”](#environment-variable-quick-reference) Copy-paste ready for your CI/CD pipeline. All variables are optional — only set what you need. ### iOS [Section titled “iOS”](#ios) ```bash # Code signing (required for iOS builds) BUILD_CERTIFICATE_BASE64="" CAPGO_IOS_PROVISIONING_MAP="" P12_PASSWORD="" # App Store Connect (required for store submission) APPLE_KEY_ID="ABC1234567" APPLE_ISSUER_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" APPLE_KEY_CONTENT="" APP_STORE_CONNECT_TEAM_ID="TEAM123456" # Alternative to the App Store Connect API key above: Apple ID + app-specific # password (e.g. when migrating from Ionic Appflow). All three are required. # FASTLANE_USER="apple-id@example.com" # FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD="xxxx-xxxx-xxxx-xxxx" # APPLE_APP_ID="1234567890" # Optional iOS settings CAPGO_IOS_SCHEME="App" CAPGO_IOS_TARGET="App" ``` ### Android [Section titled “Android”](#android) ```bash # Keystore signing (required for Android builds) ANDROID_KEYSTORE_FILE="" KEYSTORE_KEY_ALIAS="my-key-alias" KEYSTORE_KEY_PASSWORD="" KEYSTORE_STORE_PASSWORD="" # Google Play (required for store submission) PLAY_CONFIG_JSON="" # Optional Android settings PLAY_STORE_TRACK="internal" PLAY_STORE_RELEASE_STATUS="draft" ``` ### Build Control [Section titled “Build Control”](#build-control) ```bash # Build behavior SKIP_BUILD_NUMBER_BUMP="true" # Skip auto-increment BUILD_OUTPUT_UPLOAD_ENABLED="true" # Upload IPA/APK/AAB BUILD_OUTPUT_RETENTION_SECONDS="3600" # 1 hour download link # Authentication CAPGO_TOKEN="your-api-key" ``` *** ## Credential Storage [Section titled “Credential Storage”](#credential-storage) ### Save Credentials Locally [Section titled “Save Credentials Locally”](#save-credentials-locally) Instead of passing flags or env vars every time, save credentials once: ```bash # Save iOS credentials bunx @capgo/cli@latest build credentials save \ --platform ios \ --certificate ./dist_cert.p12 \ --ios-provisioning-profile ./profile.mobileprovision \ --p12-password "cert-password" \ --apple-key ./AuthKey.p8 \ --apple-key-id ABC1234567 \ --apple-issuer-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ --apple-team-id TEAM123456 # Save Android credentials bunx @capgo/cli@latest build credentials save \ --platform android \ --keystore ./release.keystore \ --keystore-alias my-key \ --keystore-key-password "key-pass" \ --keystore-store-password "store-pass" \ --play-config ./play-service-account.json ``` ### Storage Locations [Section titled “Storage Locations”](#storage-locations) | Flag | Location | Use Case | | ----------- | ----------------------------------------- | --------------------------------------------------- | | *(default)* | `~/.capgo-credentials/credentials.json` | Global — shared across all projects on your machine | | `--local` | `.capgo-credentials.json` in project root | Per-project — overrides global when both exist | Credentials are keyed by **app ID** (e.g. `com.example.myapp`), so a single credentials file can store settings for multiple apps without conflicts. Each app’s credentials are further split by platform (`ios` / `android`). Caution Add `.capgo-credentials.json` to your `.gitignore` if using local credentials. Never commit credentials to version control. ### Manage Saved Credentials [Section titled “Manage Saved Credentials”](#manage-saved-credentials) ```bash # List saved credentials bunx @capgo/cli@latest build credentials list # Update a specific option without re-entering everything bunx @capgo/cli@latest build credentials update --skip-build-number-bump # Clear saved credentials bunx @capgo/cli@latest build credentials clear --platform ios ``` *** ## Examples [Section titled “Examples”](#examples) ### GitHub Actions [Section titled “GitHub Actions”](#github-actions) ```yaml name: Build and Submit on: push: branches: [main] jobs: build-ios: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bunx cap sync ios - run: bunx @capgo/cli@latest build request --platform ios env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.IOS_CERTIFICATE }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} build-android: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bunx cap sync android - run: bunx @capgo/cli@latest build request --platform android env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} ``` ### Using CLI Flags Directly [Section titled “Using CLI Flags Directly”](#using-cli-flags-directly) ```bash # Build iOS with all options inline bunx @capgo/cli@latest build request \ --platform ios \ --build-mode release \ --skip-build-number-bump \ --output-retention 6h \ --apikey YOUR_API_KEY # Build Android, skip version bump, no output upload bunx @capgo/cli@latest build request \ --platform android \ --skip-build-number-bump \ --no-output-upload \ --apikey YOUR_API_KEY ``` ### Mixed Configuration [Section titled “Mixed Configuration”](#mixed-configuration) Combine saved credentials with CLI overrides: ```bash # Save base credentials once bunx @capgo/cli@latest build credentials save --platform ios \ --certificate ./cert.p12 \ --ios-provisioning-profile ./profile.mobileprovision \ --output-upload # Override specific options per-build bunx @capgo/cli@latest build request --platform ios \ --skip-build-number-bump \ --output-retention 2d ``` The saved credentials provide signing details while CLI flags override build behavior for this specific run. # Managing Credentials > Save and manage build credentials locally for iOS and Android builds Manage your iOS and Android build credentials locally for convenient cloud builds. ## Overview [Section titled “Overview”](#overview) Capgo CLI stores your build credentials **on your machine** — never on Capgo’s servers. By default they live in one **global** file, `~/.capgo-credentials/credentials.json`, shared across all your projects. Pass `--local` to keep them **per-project** in `.capgo-credentials.json` instead. When you run a build, the saved credentials are used automatically and sent securely to Capgo, then deleted after the build completes. Need Help Getting Credentials? If you don’t have your certificates and credentials yet, check these comprehensive guides: **iOS:** * [How to Get iOS Certificates](/docs/builder/ios/#how-to-get-ios-certificates-and-provisioning-profiles) - Step-by-step guide * [iOS Certificates Guide](/docs/builder/ios/) - Detailed step-by-step tutorial * [Blog: Automatic iOS Builds](https://capgo.app/blog/automatic-capacitor-ios-build-github-action/) - Complete CI/CD setup **Android:** * [Creating a Keystore](/docs/builder/android/#creating-a-keystore) - Step-by-step guide * [Android Certificates Guide](/docs/builder/android/) - Detailed step-by-step tutorial * [Blog: Automatic Android Builds](https://capgo.app/blog/automatic-capacitor-android-build-github-action/) - Complete CI/CD setup Security Guarantee **Your credentials are NEVER stored permanently on Capgo servers:** * ✅ Used ONLY during the active build process * ✅ Automatically deleted after build completion * ✅ Apps are sent directly to App Store/Play Store - we store NOTHING * ✅ Transmitted securely over HTTPS ## Commands [Section titled “Commands”](#commands) ### Manage Credentials Interactively [Section titled “Manage Credentials Interactively”](#manage-credentials-interactively) The quickest way to work with your saved credentials is the interactive manager. It opens a TUI (the same one `build init` uses) where you can browse what’s stored, see what’s configured per app and platform, export a CI/CD-ready `.env` file, or delete a platform’s credentials: ```bash bunx @capgo/cli@latest build credentials manage ``` | Option | Description | | --------------------------- | ------------------------------------------------------------------------ | | `--appId ` | App to manage (prompts you to pick if omitted) | | `--platform ` | Platform to manage (prompts if omitted) | | `--local` | Use the per-project `.capgo-credentials.json` instead of the global file | Prefer one-shot, scriptable commands? Use the individual commands below. ### Save Credentials [Section titled “Save Credentials”](#save-credentials) Store your build credentials locally for automatic use: ```bash bunx @capgo/cli@latest build credentials save --platform [options] ``` ### Update Credentials [Section titled “Update Credentials”](#update-credentials) Partially update existing credentials without re-providing everything: ```bash bunx @capgo/cli@latest build credentials update --platform [options] ``` The `update` command uses **additive merge** for provisioning profiles — new profiles are merged with existing ones. To replace the entire provisioning map instead, add `--overwrite-ios-provisioning-map`. Example — add an extension profile to existing credentials: ```bash bunx @capgo/cli@latest build credentials update \ --platform ios \ --ios-provisioning-profile "com.example.app.widget=./widget_profile.mobileprovision" ``` The update command accepts the same options as `save` but all are optional — only the fields you provide are updated. ### List Credentials [Section titled “List Credentials”](#list-credentials) View currently saved credentials (passwords are masked): ```bash bunx @capgo/cli@latest build credentials list # List credentials for a specific app bunx @capgo/cli@latest build credentials list --appId com.example.app ``` ### Clear Credentials [Section titled “Clear Credentials”](#clear-credentials) Remove saved credentials from your local machine: ```bash # Clear all credentials bunx @capgo/cli@latest build credentials clear # Clear credentials for a specific app + platform bunx @capgo/cli@latest build credentials clear --appId com.example.app --platform ios ``` ### Migrate Credentials [Section titled “Migrate Credentials”](#migrate-credentials) Convert legacy single-profile format to the new multi-target format: ```bash bunx @capgo/cli@latest build credentials migrate --platform ios ``` The migrate command detects old `BUILD_PROVISION_PROFILE_BASE64` credentials, converts them to `CAPGO_IOS_PROVISIONING_MAP`, and removes the legacy keys. See [Migration from Single Profile](/docs/builder/ios/#migration-from-single-profile) for details. ## Saving iOS Credentials [Section titled “Saving iOS Credentials”](#saving-ios-credentials) Note **Don’t have iOS certificates yet?** See the [iOS Builds guide](/docs/builder/ios/#how-to-get-ios-certificates-and-provisioning-profiles) for instructions on creating certificates and provisioning profiles. ### Complete Example [Section titled “Complete Example”](#complete-example) ```bash bunx @capgo/cli@latest build credentials save \ --platform ios \ --certificate ./cert.p12 \ --p12-password "YourP12Password" \ --ios-provisioning-profile "com.example.app=./profile.mobileprovision" \ --apple-key ./AuthKey_ABC1234567.p8 \ --apple-key-id "ABC1234567" \ --apple-issuer-id "00000000-0000-0000-0000-000000000000" \ --apple-team-id "TEAM123456" ``` ### iOS Options [Section titled “iOS Options”](#ios-options) | Option | Description | Required | | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | | `--certificate ` | Path to .p12 certificate file | Yes (release) | | `--p12-password ` | Password for the .p12 certificate | Yes (release) | | `--ios-provisioning-profile ` | Provisioning profile mapping (`bundleId=path`). Repeatable for multi-target apps. If only one profile and no bundleId prefix, CLI auto-infers from the profile. | Yes (release) | | `--apple-key ` | Path to App Store Connect API .p8 key | See noteÂč | | `--apple-key-id ` | App Store Connect API Key ID | See noteÂč | | `--apple-issuer-id ` | App Store Connect API Issuer ID (UUID) | See noteÂč | | `--apple-team-id ` | App Store Connect Team ID | Yes | | `--apple-id ` | Apple ID email for app-specific password upload (alternative to the API key) | See noteÂČ | | `--apple-app-specific-password ` | App-specific password (`xxxx-xxxx-xxxx-xxxx`) | See noteÂČ | | `--apple-app-id ` | Numeric App Store Connect app ID (e.g. `1234567890`) | See noteÂČ | | `--ios-distribution ` | Distribution mode: `app_store` (default) or `ad_hoc` | No | | `--output-upload` | Enable a time-limited Capgo download link for the build artifact | No (default: `false`) | | `--output-retention ` | How long to keep build outputs (e.g. `3600s`) | No (default: `3600s`) | | `--skip-build-number-bump` | Skip automatic build-number increment | No | Âč App Store Connect API Key Requirements * **`app_store` mode** (default): All three API key options are **required** unless you pass `--output-upload` or `--skip-build-number-bump` (which bypass the need for API-driven submission). * **`ad_hoc` mode**: These options are **not required** — no App Store submission takes place. See [Ad-Hoc Distribution Mode](/docs/builder/ios/#ad-hoc-distribution-mode) for details. ÂČ App-specific password (not recommended) **This method is discouraged and advised against.** It exists only as a compatibility path for teams migrating from Ionic Appflow. Prefer an App Store Connect API key (`.p8`), which is the recommended, more capable, and more secure option for CI/CD. If you must use it, all three options (`--apple-id`, `--apple-app-specific-password`, and `--apple-app-id`) are required together. The numeric `--apple-app-id` (App Store Connect → your app → App Information → Apple ID) lets the upload run without an interactive 2FA prompt; with this method the build number falls back to a timestamp because App Store Connect is not queried. ### What Gets Stored [Section titled “What Gets Stored”](#what-gets-stored) When you save iOS credentials, the CLI: 1. Reads the certificate and provisioning profile files 2. Converts them to base64 encoding 3. Saves them to `~/.capgo-credentials/credentials.json` (or `.capgo-credentials.json` with `--local`) 4. Stores passwords and IDs as plain text (local files only) The stored file structure: ```json { "ios": { "BUILD_CERTIFICATE_BASE64": "...", "CAPGO_IOS_PROVISIONING_MAP": "{\"com.example.app\":{\"profile\":\"...\",\"name\":\"match AppStore com.example.app\"}}", "APPLE_KEY_CONTENT": "...", "P12_PASSWORD": "...", "APPLE_KEY_ID": "ABC1234567", "APPLE_ISSUER_ID": "...", "APP_STORE_CONNECT_TEAM_ID": "TEAM123456", "CAPGO_IOS_DISTRIBUTION": "app_store" } } ``` ## Saving Android Credentials [Section titled “Saving Android Credentials”](#saving-android-credentials) Note **Don’t have a keystore yet?** See the [Android Builds guide](/docs/builder/android/#creating-a-keystore) for instructions on creating a keystore and setting up Play Store credentials. ### Complete Example [Section titled “Complete Example”](#complete-example-1) ```bash bunx @capgo/cli@latest build credentials save \ --platform android \ --keystore ./release.keystore \ --keystore-alias "my-key-alias" \ --keystore-key-password "KeyPassword123" \ --keystore-store-password "StorePassword123" \ --play-config ./play-store-service-account.json ``` ### Android Options [Section titled “Android Options”](#android-options) | Option | Description | Required | | -------------------------------------- | --------------------------------------- | ---------------- | | `--keystore ` | Path to .keystore or .jks file | Yes (release) | | `--keystore-alias ` | Key alias in the keystore | Yes (release) | | `--keystore-key-password ` | Password for the key alias | Yes (release) | | `--keystore-store-password ` | Password for the keystore | Yes (release) | | `--play-config ` | Path to Play Store service account JSON | Yes (submission) | ### What Gets Stored [Section titled “What Gets Stored”](#what-gets-stored-1) When you save Android credentials, the CLI: 1. Reads the keystore and service account JSON files 2. Converts them to base64 encoding 3. Saves them to `~/.capgo-credentials/credentials.json` (or `.capgo-credentials.json` with `--local`) 4. Stores passwords and alias as plain text (local files only) The stored file structure: ```json { "android": { "ANDROID_KEYSTORE_FILE": "...", "PLAY_CONFIG_JSON": "...", "KEYSTORE_KEY_ALIAS": "my-key-alias", "KEYSTORE_KEY_PASSWORD": "...", "KEYSTORE_STORE_PASSWORD": "..." } } ``` ## Using Saved Credentials [Section titled “Using Saved Credentials”](#using-saved-credentials) Once you’ve saved credentials, they’re automatically used when you build: ```bash # Credentials automatically loaded from ~/.capgo-credentials/credentials.json bunx @capgo/cli@latest build request com.example.app --platform ios ``` You can also override saved credentials using environment variables: ```bash # Environment variables take precedence over saved credentials BUILD_CERTIFICATE_BASE64="..." \ P12_PASSWORD="different-password" \ bunx @capgo/cli@latest build request com.example.app --platform ios ``` **Precedence order:** 1. Environment variables (highest priority) 2. Saved credentials (`~/.capgo-credentials/credentials.json`, or local `.capgo-credentials.json`) 3. No credentials (lowest priority) ## Viewing Saved Credentials [Section titled “Viewing Saved Credentials”](#viewing-saved-credentials) List what credentials you have saved: ```bash bunx @capgo/cli@latest build credentials list ``` Example output: ```plaintext 📋 Saved Build Credentials: iOS Credentials: ✓ Certificate (base64) ✓ Provisioning Map (JSON) ✓ Apple Key Content (base64) ✓ P12 Password: ******** ✓ Apple Key ID: ABC1234567 ✓ Apple Issuer ID: 00000000-0000-0000-0000-000000000000 ✓ Team ID: TEAM123456 Android Credentials: ✓ Keystore (base64) ✓ Play Store Config (base64) ✓ Keystore Alias: my-key-alias ✓ Key Password: ******** ✓ Store Password: ******** Location: ~/.capgo-credentials/credentials.json 🔒 These credentials are stored locally on your machine only. When building, they are sent to Capgo but NEVER stored there. They are auto-deleted after build completion. ``` ## Security Best Practices [Section titled “Security Best Practices”](#security-best-practices) ### Local Storage Security [Section titled “Local Storage Security”](#local-storage-security) 1. **File Permissions** ```bash # Global credentials directory + file chmod 700 ~/.capgo-credentials chmod 600 ~/.capgo-credentials/credentials.json # Local (per-project) credentials, if you use --local chmod 600 .capgo-credentials.json ``` 2. **Never Commit Credentials** ```bash # Ignore the per-project credentials file (used with --local) echo ".capgo-credentials.json" >> .gitignore ``` The global file lives in your home directory, outside the repo. 3. **Separate Credentials** * Use different credentials for local development vs CI/CD * Rotate credentials regularly * Don’t share credentials between team members ### CI/CD Usage [Section titled “CI/CD Usage”](#cicd-usage) For CI/CD environments, **prefer environment variables** over saved credentials. #### Export a ready-to-use `.env` (recommended) [Section titled “Export a ready-to-use .env (recommended)”](#export-a-ready-to-use-env-recommended) Instead of base64-encoding each credential file by hand (see [below](#preparing-base64-values)), let `build credentials manage` generate the file for you: ```bash bunx @capgo/cli@latest build credentials manage # pick your app → choose "Export to .env" ``` It writes a `.env.capgo..` file (permissions `0600`) containing every saved credential as an environment variable — each line is one secret to add to your CI/CD provider. Both platforms are combined by default; add `--platform ios` or `--platform android` to scope it to one. Caution The exported file holds your signing secrets — add it to `.gitignore` and never commit it. #### Complete Environment Variables Reference [Section titled “Complete Environment Variables Reference”](#complete-environment-variables-reference) The CLI reads the following environment variables for credentials: **iOS Credentials:** | Variable | Description | Format | Required | | ---------------------------- | ---------------------------------------------------- | --------------------------- | ------------- | | `BUILD_CERTIFICATE_BASE64` | P12/PKCS12 certificate for code signing | Base64 | Yes (release) | | `CAPGO_IOS_PROVISIONING_MAP` | JSON map of bundle IDs to provisioning profile data | JSON string | Yes (release) | | `P12_PASSWORD` | Password for the P12 certificate | Plain text | Optional | | `APPLE_KEY_ID` | App Store Connect API Key ID | String (e.g., “ABC1234567”) | See noteÂč | | `APPLE_ISSUER_ID` | App Store Connect API Issuer ID | UUID string | See noteÂč | | `APPLE_KEY_CONTENT` | App Store Connect API key (.p8 file content) | Base64 | See noteÂč | | `APP_STORE_CONNECT_TEAM_ID` | Apple Developer Team ID | String (e.g., “XXXXXXXXXX”) | Yes | | `CAPGO_IOS_DISTRIBUTION` | Distribution mode: `app_store` (default) or `ad_hoc` | String | No | **Android Credentials:** | Variable | Description | Format | Required | | ------------------------- | --------------------------------- | ---------- | ---------------- | | `ANDROID_KEYSTORE_FILE` | Keystore file for signing APK/AAB | Base64 | Yes (release) | | `KEYSTORE_KEY_ALIAS` | Key alias within the keystore | String | Yes (release) | | `KEYSTORE_KEY_PASSWORD` | Password for the key alias | Plain text | Yes\* | | `KEYSTORE_STORE_PASSWORD` | Password for the keystore file | Plain text | Yes\* | | `PLAY_CONFIG_JSON` | Google Play service account JSON | Base64 | Yes (submission) | \*If only one password is provided, it will be used for both `KEYSTORE_KEY_PASSWORD` and `KEYSTORE_STORE_PASSWORD`. #### GitHub Actions Example [Section titled “GitHub Actions Example”](#github-actions-example) .github/workflows/build.yml ```yaml name: Cloud Build on: push: branches: [main] jobs: build-ios: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bunx @capgo/cli@latest build request com.example.app --platform ios env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} build-android: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 - run: bun install - run: bunx @capgo/cli@latest build request com.example.app --platform android env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} ``` #### Preparing Base64 Values [Section titled “Preparing Base64 Values”](#preparing-base64-values) To convert your credential files to base64 for CI/CD secrets: ```bash # iOS Certificate (.p12) base64 -i certificate.p12 | tr -d '\n' > certificate_base64.txt # iOS Provisioning Profiles — use the CLI to generate CAPGO_IOS_PROVISIONING_MAP: bunx @capgo/cli@latest build credentials save --platform ios \ --ios-provisioning-profile "com.example.app=./profile.mobileprovision" \ # ... other options # Then copy CAPGO_IOS_PROVISIONING_MAP from ~/.capgo-credentials/credentials.json to your CI secrets # iOS App Store Connect Key (.p8) base64 -i AuthKey_XXXXXX.p8 | tr -d '\n' > apple_key_base64.txt # Android Keystore (.keystore or .jks) base64 -i release.keystore | tr -d '\n' > keystore_base64.txt # Google Play Service Account JSON base64 -i play-store-service-account.json | tr -d '\n' > play_config_base64.txt ``` Tip The `tr -d '\n'` removes newlines to create a single-line base64 string, which is easier to store as a CI/CD secret. #### Why Environment Variables Are More Secure [Section titled “Why Environment Variables Are More Secure”](#why-environment-variables-are-more-secure) This approach is more secure because: * Secrets are managed by your CI/CD platform * No credential files on runners * Easy rotation and access control * Audit trails for secret usage ### Credential Rotation [Section titled “Credential Rotation”](#credential-rotation) Regularly rotate your credentials: 1. **iOS**: Generate new certificates and API keys yearly 2. **Android**: Change keystore passwords annually 3. **After team changes**: Rotate when team members leave Update saved credentials: ```bash # Re-run save command with new credentials bunx @capgo/cli@latest build credentials save --platform ios --certificate ./new-cert.p12 ... ``` ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### ”No credentials found” [Section titled “”No credentials found””](#no-credentials-found) If the build says no credentials were found: 1. **Check if credentials are saved**: ```bash bunx @capgo/cli@latest build credentials list ``` 2. **Save credentials if missing**: ```bash bunx @capgo/cli@latest build credentials save --platform ios ... ``` 3. **Verify the credentials file exists**: ```bash ls -la ~/.capgo-credentials/credentials.json # global ls -la .capgo-credentials.json # local (--local) ``` ### “Permission denied” when reading credentials [Section titled ““Permission denied” when reading credentials”](#permission-denied-when-reading-credentials) Fix file permissions: ```bash chmod 600 ~/.capgo-credentials/credentials.json # global chmod 600 .capgo-credentials.json # local ``` ### Credentials not being used [Section titled “Credentials not being used”](#credentials-not-being-used) Check that the correct platform is specified: ```bash # Make sure --platform matches saved credentials bunx @capgo/cli@latest build request com.example.app --platform ios # Uses ios credentials bunx @capgo/cli@latest build request com.example.app --platform android # Uses android credentials ``` ### Clear and re-save credentials [Section titled “Clear and re-save credentials”](#clear-and-re-save-credentials) If credentials seem corrupted: ```bash # Clear all credentials bunx @capgo/cli@latest build credentials clear # Save again bunx @capgo/cli@latest build credentials save --platform ios ... ``` ## Migration from Environment Variables [Section titled “Migration from Environment Variables”](#migration-from-environment-variables) If you’re currently using environment variables, you can migrate to saved credentials: 1. **Extract your current environment variables** ```bash echo $BUILD_CERTIFICATE_BASE64 # Verify they exist ``` 2. **Decode base64 files back to original files** (if needed) ```bash echo "$BUILD_CERTIFICATE_BASE64" | base64 -d > cert.p12 echo "$BUILD_PROVISION_PROFILE_BASE64" | base64 -d > profile.mobileprovision ``` 3. **Save using the CLI** ```bash bunx @capgo/cli@latest build credentials save \ --platform ios \ --certificate ./cert.p12 \ --ios-provisioning-profile ./profile.mobileprovision \ --p12-password "$P12_PASSWORD" \ --apple-key-id "$APPLE_KEY_ID" \ --apple-issuer-id "$APPLE_ISSUER_ID" \ --apple-team-id "$APP_STORE_CONNECT_TEAM_ID" ``` If you have existing credentials saved in the old format (single `BUILD_PROVISION_PROFILE_BASE64`), run: ```bash bunx @capgo/cli@latest build credentials migrate --platform ios ``` This converts the legacy single-profile to a `CAPGO_IOS_PROVISIONING_MAP` and removes the old `BUILD_PROVISION_PROFILE_BASE64` and `APPLE_PROFILE_NAME` keys. 4. **Test the build** ```bash bunx @capgo/cli@latest build request com.example.app --platform ios ``` 5. **Remove environment variables** (optional) ```bash unset BUILD_CERTIFICATE_BASE64 BUILD_PROVISION_PROFILE_BASE64 ``` ## File Location [Section titled “File Location”](#file-location) Credentials are stored in a single JSON file: * **Global** (default): `~/.capgo-credentials/credentials.json` — shared across all your projects * **Local** (with `--local`): `.capgo-credentials.json` in your project root — overrides the global file for that project The file is created automatically the first time you save credentials. Add **`.capgo-credentials.json`** to your `.gitignore` so per-project credentials are never committed. ## Next Steps [Section titled “Next Steps”](#next-steps) * [Getting Started](/docs/builder/getting-started/) - Create your first build * [iOS Builds](/docs/builder/ios/) - iOS-specific build configuration * [Android Builds](/docs/builder/android/) - Android-specific build configuration * [Troubleshooting](/docs/builder/troubleshooting/) - Common issues and solutions ## Need Help? [Section titled “Need Help?”](#need-help) * 📚 [Troubleshooting guide](/docs/builder/troubleshooting/) * 💬 [Discord community](https://discord.com/invite/VnYRvBfgA6) * 📧 Email: ## Keep going from Managing Credentials [Section titled “Keep going from Managing Credentials”](#keep-going-from-managing-credentials) If you are using **Managing Credentials** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # Getting Started > Create your first native build with Capgo Cloud Build Get started with Capgo Cloud Build and create your first iOS or Android native build in minutes. ## What You’ll Need [Section titled “What You’ll Need”](#what-youll-need) Before you begin, ensure you have: * A Capacitor app that builds successfully locally * Node.js 20 or higher installed * A Capgo account (a free trial is enough to get started) * Your app already registered in Capgo (run `npx @capgo/cli@latest app add` if not) * *(No need to prepare signing credentials in advance — we’ll set them up in the next step.)* ## Configure your signing credentials [Section titled “Configure your signing credentials”](#configure-your-signing-credentials) Capgo needs signing credentials to build and submit your app — but you don’t have to wrangle them by hand. Answer a couple of questions and we’ll point you to the exact command to run: 1. **** 2. **** 3. **** 4. **** ## Run your first build [Section titled “Run your first build”](#run-your-first-build) You need to be authenticated with Capgo to build. If you haven’t already: ```bash npx @capgo/cli@latest login # or, in CI, set the token directly: export CAPGO_TOKEN=your_api_key ``` If you just ran **`build init`**, you’re already set — the onboarding offers to start a build for you at the end, so your first build may already be on its way. 🎉 Otherwise, start a build yourself with `build request` — set `--platform` to whichever you’re building: ```bash npx @capgo/cli@latest build request com.example.app --platform --build-mode debug ``` The CLI uploads the prepared native project and streams build logs live in your terminal. Capgo Build can return a signed artifact or submit it to App Store Connect or Google Play when you configure the appropriate release flow. ## Understanding the Build Process [Section titled “Understanding the Build Process”](#understanding-the-build-process) When you run the build command, here’s what happens: ``` flowchart LR A[Your CI] -->|1. Prepare Native Project| B[Prepared iOS / Android Project] B -->|2. Upload| C[Capgo Build] C -->|3. Compile and Sign| D[Dedicated Build Infrastructure] D -->|4. Stream Logs| E[Your Terminal] D -->|Return Signed Artifact or Store Delivery| F[Output] D -->|5. Clean Temporary Project Data| G[Cleanup] ``` 1. **Prepare in your CI** - Build the web layer, resolve private dependencies, and synchronize the completed assets into the native project. 2. **Upload** - The prepared native project is uploaded to secure cloud storage for the build. 3. **Build Execution** - Capgo compiles and signs the native project on dedicated infrastructure. 4. **Log Streaming** - Real-time logs stream to your terminal via Server-Sent Events. 5. **Cleanup** - The build environment and temporary project data are cleaned up after the build; output retention depends on the selected artifact and store-delivery options. ## Use Capgo Build with Bitrise or another CI [Section titled “Use Capgo Build with Bitrise or another CI”](#use-capgo-build-with-bitrise-or-another-ci) Capgo Build does not replace your existing CI. Keep the steps that need your private access in Bitrise or another CI system: install from private registries, resolve private CocoaPods over SSH, run custom native setup, build the web layer, and run `npx cap sync`. Then call Capgo Build with the prepared native project. Capgo receives the ready `ios/` or `android/` project to compile and sign, so it does not need your private Nexus, CocoaPods SSH, or web-build credentials. The compiled web assets are already inside that prepared native project; they are used for the build rather than retained as a source repository. ## What Gets Built [Section titled “What Gets Built”](#what-gets-built) Capgo Build receives the prepared native project required to compile your app. Your web source code, private dependency installation, and Capacitor sync remain in your CI. ### What Gets Uploaded [Section titled “What Gets Uploaded”](#what-gets-uploaded) | Included | Description | | ----------------------------------- | ---------------------------------------------------------------- | | `ios/` or `android/` | The native platform folder you’re building | | `package.json`, `package-lock.json` | Dependency manifest | | `capacitor.config.*` | Capacitor configuration | | `resources/` | App icons, splash screens | | Native plugin code | Only the `ios/` or `android/` subfolder of each Capacitor plugin | ### What’s NOT Uploaded [Section titled “What’s NOT Uploaded”](#whats-not-uploaded) | Excluded | Why | | -------------------------------------- | -------------------------------------------------------- | | `node_modules/` (most of it) | Only native plugin code is included, not JS dependencies | | `src/` | Your web source code stays local | | `dist/`, `www/`, `build/` (root level) | Already synced into the native folder via `cap sync` | | `.git/` | Version control history | | `.gradle/`, `.idea/`, `.swiftpm/` | Build caches and IDE settings | | `.env`, secrets | Never uploaded | Note Your built web assets (JS, CSS, and HTML) are uploaded only because `npx cap sync` has copied them into the native project. The web source and dependency-installation steps stay in your CI; the prepared native project is used to build the binary and then cleaned up. ### Your Responsibilities [Section titled “Your Responsibilities”](#your-responsibilities) Before running `npx @capgo/cli@latest build request`: 1. **Prepare in your CI** - Resolve private package registries, SSH-based CocoaPods, device SDKs, extensions, and any custom native preparation in Bitrise or your existing CI. 2. **Build your web assets** - Run `npm run build` (or your framework’s build command). 3. **Sync to native** - Run `npx cap sync` to copy the compiled web assets into the prepared native project. 4. **Request the native build** - Send the prepared `ios/` or `android/` project to Capgo Build. ### What Capgo Build Handles [Section titled “What Capgo Build Handles”](#what-capgo-build-handles) * Native iOS compilation (Xcode, Fastlane) * Native Android compilation (Gradle) * Code signing with your credentials * Optional App Store Connect or Google Play submission * Supported native build configuration and credential values passed as environment variables Capgo Build does not need access to your private Nexus registry or SSH credentials once your CI has prepared the native project. See [Build Configuration](/docs/builder/configuration/) for supported environment variables and store options. For a kiosk flavour distributed through MDM, configure the Android project/build to produce an APK. When requesting the build, use both flags to skip Google Play and retrieve the signed output: ```bash npx @capgo/cli@latest build request YOUR_APP_ID --platform android --no-playstore-upload --output-upload ``` `--no-playstore-upload` prevents Play Store upload even if Play credentials are saved; `--output-upload` provides a time-limited link to the signed output. Distribute that APK through your MDM. ## Next Steps [Section titled “Next Steps”](#next-steps) Now that you’ve created your first build: * [Configure iOS builds](/docs/builder/ios/) - Set up certificates and profiles * [Configure Android builds](/docs/builder/android/) - Set up keystores and Play Store * [Troubleshooting](/docs/builder/troubleshooting/) - Common issues and solutions * [CLI Reference](/docs/cli/reference/build/) - Complete command documentation ## Need Help? [Section titled “Need Help?”](#need-help) * Check the [troubleshooting guide](/docs/builder/troubleshooting/) * Join our [Discord community](https://discord.com/invite/VnYRvBfgA6) * Email support at # GitHub Actions > Set up CI/CD with Capgo Build using GitHub Actions to automate iOS and Android builds on push, tag, or manual trigger. Automate your iOS and Android builds directly from your GitHub repository. With one workflow file and a handful of repository secrets, every push, tag, or manual trigger can produce signed, store-ready apps — without anyone on the team needing a Mac, Xcode, or Android Studio installed. ## What You Get [Section titled “What You Get”](#what-you-get) Hands-off Releases Tag a release in Git and your signed iOS and Android binaries are submitted to TestFlight and Play Store automatically. No Local Setup Contributors on Windows or Linux can trigger iOS builds. No Xcode, no provisioning hassles, no shared signing certificates floating around laptops. Scoped Secrets Credentials live in GitHub repository secrets, scoped to your repo and visible only to the workflow runner. Easy to rotate, easy to audit. Parallel Builds Build iOS and Android at the same time with a matrix job. A typical release finishes in under 10 minutes. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) Before setting up the workflow, make sure you have: * A Capgo account with an active subscription and a [Capgo API key](/docs/webapp/api-keys/) * Your app registered in Capgo (`bunx @capgo/cli@latest app add` if not) * Build credentials configured locally with `bunx @capgo/cli@latest build init` — see [Managing Credentials](/docs/builder/credentials/) for the wizard walkthrough * A successful local build (`bunx @capgo/cli@latest build request com.example.app --platform android --build-mode debug`) — CI is not the place to debug your first build * The [GitHub CLI (`gh`)](https://cli.github.com/) installed and authenticated (`gh auth login`) Note The flow below assumes credentials already exist in your local credentials store (from `build init`). If you haven’t set them up yet, do that first — the wizard handles certificate creation, provisioning profiles, keystores, and Play Store service accounts interactively. ## Setup [Section titled “Setup”](#setup) The Capgo CLI can export your local credentials as a ready-to-use `.env` file. Combined with `gh secret set -f`, this turns the entire CI/CD setup into three commands — no manual base64 encoding, no JSON wrangling, no copy-paste-secret-by-secret. 1. **Add your Capgo API key as a repository secret** The API key isn’t part of the per-app credential store, so add it once manually: ```bash gh secret set CAPGO_TOKEN --body "your_capgo_api_key_here" ``` Generate the key in the [Capgo dashboard](https://web.capgo.app/app/account/apikeys) with **upload** permissions or higher. 2. **Export your credentials to a `.env` file** Run the interactive credentials manager: ```bash bunx @capgo/cli@latest build credentials manage --appId com.example.app ``` In the TUI, select **Export to .env**. The CLI writes `.env.capgo.` to your current directory with mode `0600` (owner-readable only) — for example, `.env.capgo.com.example.app`. When both iOS and Android are configured, both platforms’ secrets land in the same file under `# === IOS ===` and `# === ANDROID ===` section headers. iOS and Android env-var names are disjoint, so combining them is conflict-free. Need a per-platform file? Pass `--platform ios` (or `--platform android`) to scope the manager to one platform. The export then produces a per-platform file like `.env.capgo.com.example.app.ios`. Useful when iOS and Android secrets live in different repos or environments. Shared config keys A handful of config toggles (`BUILD_OUTPUT_UPLOAD_ENABLED`, `BUILD_OUTPUT_RETENTION_SECONDS`, `SKIP_BUILD_NUMBER_BUMP`, `CAPGO_IOS_DISTRIBUTION`) can be stored under each platform independently and may have drifted apart. If the manager finds drift, it prints the conflicting keys, asks for explicit confirmation before writing, and embeds the conflict list as a comment at the top of the file. Re-export with `--platform` if you need to preserve per-platform values. 3. **Push the `.env` file to GitHub Actions secrets** The `gh secret set -f` command reads a dotenv file and creates one repository secret per `KEY=value` line: ```bash gh secret set -f .env.capgo.com.example.app ``` That’s it — every secret your workflow needs is now in GitHub. Verify with `gh secret list`. Don't commit the .env file It contains plaintext signing material. Once you’ve pushed it to GitHub: ```bash echo '.env.capgo.*' >> .gitignore rm .env.capgo.* ``` Re-export anytime you need to rotate credentials — the file isn’t a long-lived artifact. 4. **Create the workflow file** Add `.github/workflows/capgo-build.yml` to your repository. Pick one of the three trigger patterns below depending on how you want to fire builds. ### What ends up in your secrets [Section titled “What ends up in your secrets”](#what-ends-up-in-your-secrets) For reference, `gh secret set -f` will create these repository secrets (your workflow YAML references them by these exact names): | Platform | Secrets created | | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | iOS | `BUILD_CERTIFICATE_BASE64`, `P12_PASSWORD`, `CAPGO_IOS_PROVISIONING_MAP_BASE64`, `APPLE_KEY_ID`, `APPLE_ISSUER_ID`, `APPLE_KEY_CONTENT`, `APP_STORE_CONNECT_TEAM_ID` | | Android | `ANDROID_KEYSTORE_FILE`, `KEYSTORE_KEY_ALIAS`, `KEYSTORE_KEY_PASSWORD`, `KEYSTORE_STORE_PASSWORD`, `PLAY_CONFIG_JSON` | | (added manually) | `CAPGO_TOKEN` | You don’t need to memorise these — the workflow examples below already reference all of them. ## Workflow Examples [Section titled “Workflow Examples”](#workflow-examples) The three examples below cover the most common patterns. They all use the same shape: check out the repo, install dependencies, build the web assets, sync to native, then call Capgo Build with credentials passed as environment variables. ### 1. Manual Trigger [Section titled “1. Manual Trigger”](#1-manual-trigger) Lets anyone with write access fire a build from the **Actions** tab in GitHub with a platform dropdown. Useful for ad-hoc test builds or kicking off a release on demand. .github/workflows/capgo-build-manual.yml ```yaml name: Capgo Build (Manual) on: workflow_dispatch: inputs: platform: description: 'Platform to build' required: true default: 'android' type: choice options: [ios, android, both] mode: description: 'Build mode' required: true default: 'debug' type: choice options: [debug, release] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: bun-version: latest - run: bun install --frozen-lockfile - run: bun run build - run: bunx cap sync - name: Trigger Capgo Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | bunx @capgo/cli@latest build request com.example.app \ --platform ${{ inputs.platform }} \ --build-mode ${{ inputs.mode }} ``` Replace `com.example.app` with your app ID. Once committed, go to **Actions → Capgo Build (Manual) → Run workflow** to trigger it. ### 2. Release on Tag [Section titled “2. Release on Tag”](#2-release-on-tag) Builds and ships both platforms in parallel whenever you push a version tag like `v1.4.0`. This is the most common production setup — `git tag v1.4.0 && git push --tags` becomes your release command. .github/workflows/capgo-build-release.yml ```yaml name: Capgo Build (Release) on: push: tags: - 'v*' jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: platform: [ios, android] steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: bun-version: latest - run: bun install --frozen-lockfile - run: bun run build - run: bunx cap sync ${{ matrix.platform }} - name: Build ${{ matrix.platform }} env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} # iOS BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} # Android ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | bunx @capgo/cli@latest build request com.example.app \ --platform ${{ matrix.platform }} \ --build-mode release ``` The matrix runs iOS and Android in parallel on separate runners. Setting `fail-fast: false` means a failed iOS build won’t cancel the in-progress Android build (and vice versa) — useful when one platform has a transient signing issue. Note **About the version number:** Capgo Build auto-increments your build number on every release build. If you’d rather pin it to the tag, see [Skip build number bumping](#skip-build-number-bumping) below. ### 3. Debug Build on Push to Main [Section titled “3. Debug Build on Push to Main”](#3-debug-build-on-push-to-main) Catches native build regressions early by producing a debug Android build on every push to `main`. Cheap to run, fast feedback, and you can skip Play Store upload to keep it purely a smoke test. .github/workflows/capgo-build-main.yml ```yaml name: Capgo Build (Main) on: push: branches: [main] paths: - 'src/**' - 'android/**' - 'ios/**' - 'package.json' - 'capacitor.config.*' jobs: smoke-build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 with: bun-version: latest - run: bun install --frozen-lockfile - run: bun run build - run: bunx cap sync android - name: Smoke build (Android debug) env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} run: | bunx @capgo/cli@latest build request com.example.app \ --platform android \ --build-mode debug \ --no-playstore-upload \ --output-upload ``` The `paths` filter ensures the workflow doesn’t run on doc-only changes. `--no-playstore-upload` skips Play Store submission (no `PLAY_CONFIG_JSON` needed), and `--output-upload` produces a download URL for the resulting APK so you can install it on a test device. ## Common Patterns [Section titled “Common Patterns”](#common-patterns) ### Skip Play Store / TestFlight upload [Section titled “Skip Play Store / TestFlight upload”](#skip-play-store--testflight-upload) For test builds, skip store submission: Android uses `--no-playstore-upload`; for iOS, build in ad-hoc mode with `--ios-distribution ad_hoc` (which never submits to the App Store). Combine either with `--output-upload` to get a time-limited download URL for the binary. ### Submit the store release for review [Section titled “Submit the store release for review”](#submit-the-store-release-for-review) By default, release builds upload the signed artifact and leave the final store action under your control. For CI releases that should move directly into the store review flow, add `--submit-to-store-review`. Android uses your `PLAY_CONFIG_JSON` service account. **Without an explicit track, `--submit-to-store-review` defaults to the production track with `release_status: completed`.** Prefer stating the track at the call site with `--android-track` (or `PLAY_STORE_TRACK`), and override status with `--android-release-status` / `PLAY_STORE_RELEASE_STATUS` when needed: ```yaml - name: Submit Android release for review env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | npx @capgo/cli@latest build request com.example.app \ --platform android \ --build-mode release \ --submit-to-store-review \ --android-track production \ --store-release-name "${GITHUB_REF_NAME}" \ --store-release-notes "Release ${GITHUB_REF_NAME}" \ --store-release-notes-locale "en-US=Release ${GITHUB_REF_NAME}" ``` For an internal completed release instead of production: ```yaml - name: Submit Android internal release env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} run: | npx @capgo/cli@latest build request com.example.app \ --platform android \ --build-mode release \ --submit-to-store-review \ --android-track internal \ --store-release-name "${GITHUB_REF_NAME}" ``` iOS uses the App Store Connect API key path and submits the processed TestFlight build to App Store review. It requires `app_store` distribution; `--ios-testflight-groups` is optional for external beta distribution and is not required for App Store review: ```yaml - name: Submit iOS build to App Store review env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} run: | npx @capgo/cli@latest build request com.example.app \ --platform ios \ --build-mode release \ --ios-distribution app_store \ --submit-to-store-review \ --store-release-name "${GITHUB_REF_NAME}" \ --store-release-notes "Release ${GITHUB_REF_NAME}" \ --store-release-notes-locale "en-US=Release ${GITHUB_REF_NAME}" \ --no-ios-automatic-release ``` Caution This path only submits the build artifact. Store listing metadata, tester groups, review contact details, compliance answers, and rollout choices still need to be ready in App Store Connect or Google Play Console before CI runs it. ### Read the build output URL and QR code [Section titled “Read the build output URL and QR code”](#read-the-build-output-url-and-qr-code) Pass `--output-record ` to persist the build artifact URL and QR code to disk when the build succeeds, then read it back in subsequent steps with `build last-output`. No log scraping, no regex. ```yaml - name: Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} # ...credentials... run: | bunx @capgo/cli@latest build request com.example.app \ --platform android --build-mode debug \ --output-upload --output-retention 1d \ --output-record /tmp/build.json - name: Comment on PR with build URL env: GH_TOKEN: ${{ github.token }} run: | URL=$(bunx @capgo/cli@latest build last-output --path /tmp/build.json --field outputUrl) if [ -n "$URL" ]; then gh pr comment ${{ github.event.pull_request.number }} \ --body "Debug build ready: $URL" fi ``` `--output-record /tmp/build.json` writes a JSON record (with `jobId`, `status`, `outputUrl`, `qrCodeAscii`, `qrCodePngPath`, `finishedAt`) and a PNG QR code alongside at `/tmp/build.json.qr.png`. `build last-output` reads it back: * `--field outputUrl` prints just the download URL (newline-terminated; safe for `URL=$(...)`). * `--field qrCodePngPath` prints the PNG path so you can upload it as a PR attachment. * `--qr` prints the rendered ASCII QR — drop it inside a Markdown code fence on the PR comment for inline scannability. Note The record is only written on a successful build. Unsupported `schemaVersion` and unknown `--field` values exit non-zero, so a stale CLI in the runner fails loudly instead of silently emitting an empty URL. ### Skip build number bumping [Section titled “Skip build number bumping”](#skip-build-number-bumping) By default each release build increments the build number. To pin it to a value you control (for example, the Git tag), pass `--skip-build-number-bump`: ```yaml - name: Set version from tag run: | VERSION="${GITHUB_REF#refs/tags/v}" # Update package.json or your version source here bun pm version "$VERSION" --no-git-tag-version - name: Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} # ...credentials... run: | bunx @capgo/cli@latest build request com.example.app \ --platform ios --build-mode release \ --skip-build-number-bump ``` ### Cache dependencies [Section titled “Cache dependencies”](#cache-dependencies) `bun install` is already fast enough that a JS-deps cache rarely pays off, but Capacitor’s native dependencies (CocoaPods, Gradle) are worth caching for larger projects: ```yaml - uses: actions/cache@v4 with: path: | ~/.bun/install/cache ios/App/Pods android/.gradle key: ${{ runner.os }}-capgo-${{ hashFiles('**/bun.lock', '**/Podfile.lock') }} ``` ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) | Symptom | Likely cause | | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `CAPGO_TOKEN is not set` | Secret not added, or job has no access to it (check environment/branch protections) | | Missing iOS / Android credential errors | `gh secret set -f` was not run, or was run against a different repo. Verify with `gh secret list` | | `cap sync` fails in CI but works locally | A native plugin isn’t in `package.json`, or you forgot `bun install` before `cap sync` | | Build succeeds but no app appears in App Store Connect | Wrong team ID, or the app record doesn’t exist yet in App Store Connect. Verify locally with `bunx @capgo/cli@latest build credentials manage` | | Build hangs after “Uploading project” | Project archive is unusually large — check that `node_modules` isn’t being uploaded (it shouldn’t be by default) | | `Provisioning profile doesn't match bundle ID` | The provisioning map points at a different bundle ID than the one Xcode is signing. Re-run `build init` to refresh the profile, then re-export with `build credentials manage` | | Credentials changed locally but CI still fails | Don’t forget to re-export and re-push: `bunx @capgo/cli@latest build credentials manage` → `gh secret set -f .env.capgo.` | | Manager refuses to write the combined file | Shared config keys differ between platforms — the manager warns and asks for confirmation. Either confirm to overwrite-one-wins, or re-export per-platform with `--platform ios` / `--platform android` | | `build last-output` prints an empty URL | The build did not pass `--output-upload`, or it failed before producing an artifact. `outputUrl` will be `null` in the record. Branch on `[ -n "$URL" ]` before using it | | `build last-output` errors with `Unsupported record schemaVersion` | The runner is on an older CLI than the one that wrote the record. Pin both producer and reader to the same explicit version (e.g. `bunx @capgo/cli@7.104.0 
` on both sides) rather than `@latest`, which floats and can drift between jobs | For platform-specific build failures, see the [Troubleshooting guide](/docs/builder/troubleshooting/). ## Next Steps [Section titled “Next Steps”](#next-steps) [Auto OTA or Native ](/docs/builder/ci-ota-or-native/)Branch CI between live update upload and Capgo Build. [Trigger from CI UI ](/docs/builder/ci-ui-trigger/)Run Capgo Build from the Actions tab on demand. [Build Webhooks ](/docs/builder/webhooks/)Start the same workflow from an admin dashboard HTTP call. [Credentials Setup ](/docs/builder/credentials/)Full reference for preparing iOS and Android credentials as base64 secrets. [Configuration Options ](/docs/builder/configuration/)All CLI flags and environment variables for fine-tuning your builds. # iOS Builds > Configure and build iOS apps with Capgo Cloud Build Build and submit iOS apps to TestFlight and the App Store using Capgo’s dedicated Mac infrastructure. ## What you will learn [Section titled “What you will learn”](#what-you-will-learn) * You will learn how to upload your app via Capgo Native build * You will learn how to configure the certificates for Capgo Native Build ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * A Capgo account (a free trial is enough to get started) * Your app already registered in Capgo (run `bunx @capgo/cli@latest app add` if not) * A Mac computer with Xcode installed (it’s possible to setup the build on a linux/windows machine, but it’s not yet documented) * Valid Apple Developer account ($99/year) (You must have admin or owner rights on the Apple Developer account) * Your app must be able to build successfully via Xcode * A Capacitor app * A configured icon for the app. Apps without an icon cannot be uploaded to the App Store. Note I will use the following app for the tutorial: ## Before you start in Apple’s portals [Section titled “Before you start in Apple’s portals”](#before-you-start-in-apples-portals) Before you set up certificates or trigger your first TestFlight upload, make sure the Apple account and team are ready: * Turn on two-factor authentication for the Apple Account used for enrollment * Choose the right membership type: * **Individual / Sole Proprietor**: your legal personal name becomes the seller name on the App Store * **Organization**: requires a legal entity, a D-U-N-S number, a public company website, a work email on the company domain, and a person with authority to bind the organization to Apple’s agreements * Use an account that can access both Apple Developer and App Store Connect for certificates, app records, API keys, and TestFlight * Lock in your final bundle ID early. Changing it later usually means redoing App Store setup * Plan these App Store Connect items before App Review: support URL, privacy policy URL, age rating, screenshots, export compliance, and App Review contact details Note Useful official references: * [Become a member of the Apple Developer Program](https://developer.apple.com/programs/enroll/) * [Submit your apps and games](https://developer.apple.com/app-store/submitting/) * [Platform version information in App Store Connect](https://developer.apple.com/help/app-store-connect/reference/app-information/platform-version-information) ![Start Apple Developer enrollment](/_docs/start-enrollment.C-l07XkV.png) ![Continue Apple enrollment on the web](/_docs/web-enrollment.Bl6dt51u.png) ![Select the correct Apple Developer entity type](/_docs/entity-type.CQ6EfCCV.png) ![App Store Connect after enrollment](/_docs/app-store-connect-home.COt6xb99.png) Caution Apple updates its minimum SDK requirement regularly. As of **April 28, 2026**, iPhone and iPad apps uploaded to App Store Connect must be built with the **iOS & iPadOS 26 SDK or later**. Recommended: automated onboarding You don’t have to do any of this by hand. Capgo’s onboarding creates and configures your iOS signing credentials (distribution certificate + provisioning profile) for you — this is the recommended path: ```bash bunx @capgo/cli@latest build init --platform ios ``` The manual walkthrough below is only for those who prefer to set up credentials themselves, or want to understand exactly what Capgo does under the hood. ## The first manual build [Section titled “The first manual build”](#the-first-manual-build) Before we can start thinking about building the app with Capgo, we should first set it up, and do a first TestFlight build by hand. There are some advantages to doing a manual build first: * You will setup the distribution certificate on your local machine * You will create the App Store record if you haven’t done it yet * You will be able to figure out any issues with the build process linked to your app code Before we can begin, you must have the distribution certificate installed on your local machine. This is quite a bit complex, but I will explain it below. ### Setting up the distribution certificate [Section titled “Setting up the distribution certificate”](#setting-up-the-distribution-certificate) 1. Open Xcode 2. Click on `Xcode` -> `Settings...` Alternatively, you can use the shortcut `Cmd + ,` ![Xcode settings](/native-build-assets/xcode-settings.webp) 3. Go to `Accounts` ![Xcode Accounts tab](/native-build-assets/xcode-apple-accounts.webp) 4. Find the Apple Account that is added to the Apple Developer Account ![Xcode selected apple account](/native-build-assets/xcode-selected-account.webp) 5. Find the team that you will use to deploy the app ![Xcode find team](/native-build-assets/xcode-find-team.webp) 6. Click on the `Manage Certificates...` button ![Xcode manage certificates](/native-build-assets/xcode-manage-certificates.webp) 7. Make sure you can see the distribution certificate in the list ![Xcode distribution certificate](/native-build-assets/xcode-deployment-certificate.webp) 8. If you do not, you need to create a new certificate Note Apple limits the number of distribution certificates you can have to 3. If you have more than 3 certificates, you need to delete one in order to create a new one. I will not cover that in the tutorial. 1. Click on the `+` button and then on `Apple Distribution` ![Xcode add certificate](/native-build-assets/xcode-add-certificate.webp) 2. The certificate will be created automatically. You can see it in the list. Look at the previous step to confirm that you see it. Now that you have the distribution certificate installed, you can begin the build process. ### Manual build to TestFlight [Section titled “Manual build to TestFlight”](#manual-build-to-testflight) 1. Open the app in Xcode Run `bunx cap open ios` to open the app in Xcode. 2. Find and click on the `archive` button In the Xcode toolbar, find and click on the `product` -> `archive` button. ![Xcode toolbar](/native-build-assets/xcode-toolbar.webp) 3. Wait for the build to complete 4. Click on the `Distribute App` button ![Xcode distribute button](/native-build-assets/xcode-distribue-app.webp) 5. Select `TestFlight Internal Only` as the distribution method and click on `Distribute` button ![Xcode TestFlight internal only distribution method](/native-build-assets/xcode-distribue-testflight-1.webp) 6. Configure the app record Fill in the following fields: 1. Name: The name of your app - visible in the App Store 2. SKU - the SKU of your app - this is used to identify your app in the App Store 3. The primary language - the primary language of your app Then, click on the `next` button ![Xcode TestFlight configure app record](/native-build-assets/xcode-configure-app-record-testflight.webp) 7. If the creation of the app record fails, try to close the window and try to archive the app again. 8. Wait for the upload to complete 9. If everything went well, you should see the following screen ![Xcode TestFlight upload complete](/native-build-assets/xcode-upload-complete-testflight.webp) 10. Click on the `Done` button You may instinctively think that all is good now and that you will be able to see your app in TestFlight now, but there are a few more things still to finish: 1. Add yourself to TestFlight 2. Complete export compliance so the build becomes testable 3. Fill in required App Store Connect metadata such as your support URL, privacy policy URL, and age rating 4. Prepare screenshots that match the devices you actually support 5. Add App Review contact details and any test credentials before the production submission Let’s start with the first one: ### Adding yourself to TestFlight [Section titled “Adding yourself to TestFlight”](#adding-yourself-to-testflight) 1. Go to the [App Store Connect](https://appstoreconnect.apple.com/) page ![App Store Connect login page](/native-build-assets/appstore-connect-login.webp) 2. Sign in with your Apple Developer account 3. Select the team that you used when you created the app record. If you are only in one developer account, can skip this step. ![App Store Connect team selection](/native-build-assets/appstore-connect-select-team.webp) 4. Click on the `Apps` button ![App Store Connect apps button](/native-build-assets/appstore-connect-apps-button.webp) 5. Find the app you created in the previous step and click on it ![App Store Connect app selection](/native-build-assets/appstore-connect-select-app.webp) 6. Click on the `TestFlight` button ![App Store Connect testflight button](/native-build-assets/appstore-connect-testflight-button.webp) 7. Click on the `Internal Testers plus` button ![App Store Connect internal testers plus button](/native-build-assets/appstore-connect-testflight-internal-testing-plus.webp) 8. Create a new group I like to name the group “internal”. You can name it whatever you want. ![App Store Connect create new group](/native-build-assets/appstore-connect-testflight-internal-create-group.webp) 9. Click on `Invite testers` button ![App Store Connect invite testers button](/native-build-assets/appstore-connect-testflight-internal-invite-testers.webp) 10. Add yourself to the group Find yourself in the list and select the checkbox next to your name. (You may need to refresh the page to see yourself) Then, click on the `Add` button. ![App Store Connect invite tester checkbox](/native-build-assets/appstore-connect-testflight-internal-invite-tester-checkbox.webp) 11. Verify that you are added to the group Now, you should see yourself in the group. ![App Store Connect verify tester](/native-build-assets/appstore-connect-testflight-internal-verify-tester.webp) Congratulations 🎉 You have added yourself to TestFlight. Now, there is just one more thing you need to do before you can configure Capgo Native Build. ### Setting up the compliance information [Section titled “Setting up the compliance information”](#setting-up-the-compliance-information) You now need to promise Apple that your app doesn’t use any non-standard (like a custom algorithm) encryption. If your app does use any non-standard encryption, I suggest reading the [Apple documentation](https://developer.apple.com/help/app-store-connect/manage-app-information/overview-of-export-compliance) on how to handle this. There are two ways to do this: 1. You can do this by hand every time you build your app. 2. You can configure your plist file to automatically set this value to `false`. Let’s start with the first one: 1. Follow all the steps from the previous section to find the TestFlight section in App Store Connect 2. Click on `Builds -> iOS` ![App Store Connect builds iOS button](/native-build-assets/appstore-connect-builds-ios-button.webp) 3. Find the build with missing compliance information and click on `Manage` ![App Store Connect manage build](/native-build-assets/appstore-connect-manage-build.webp) 4. Select the option that best describes your app For me, this is `none`, but it might be different for you. After, click save ![App Store Connect save compliance information](/native-build-assets/appstore-connect-manage-build-compliance.webp) 5. Your app should now say `ready to test` ![App Store Connect ready to test](/native-build-assets/appstore-connect-ready-to-test.webp) As for the second one, here are the steps: 1. Open the `Info.plist` file 2. Add the following key: ```xml ITSAppUsesNonExemptEncryption ``` 3. Save the file Note [Here](https://developer.apple.com/documentation/security/complying-with-encryption-export-regulations) is the official Apple documentation on how to inform Apple of your compliance with encryption export regulations. ### Installing the TestFlight app and accepting the invitation [Section titled “Installing the TestFlight app and accepting the invitation”](#installing-the-testflight-app-and-accepting-the-invitation) Now, you are **ALMOST** ready to test your app in TestFlight. Before, you need to do the following things: 1. Download the [TestFlight app](https://apps.apple.com/us/app/testflight/id899247664) from the App Store on your iOS/iPadOS device 2. Accept the invitation to test your app I will skip the details of how to install the TestFlight app on your device. If you are not sure how to install an app, Google has some great guides on how to do it. As for accepting the invitation, you will receive an email from Apple with a link to accept the invitation. 1. Open the email from Apple with the link to accept the invitation 2. Click on `View in TestFlight` button ![TestFlight email button](/native-build-assets/testflight-email-button.webp) 3. Click on the `Install` button ![TestFlight install button](/native-build-assets/testflight-install-button.webp) 4. Install the app on your device If you have installed the app previously using Xcode, you may see the following screen. Please click on the `install` button. ![TestFlight install app](/native-build-assets/testflight-install-app.webp) 5. Wait for the app to install 6. Click on the `Open` button and click it [](/native-build-assets/testflight-open-app.mp4) Congratulations 🎉 You have accepted the invitation to test your app in TestFlight. Now, you can configure Capgo Native Build to build and submit your app to TestFlight. ## Configuring Capgo Native Build [Section titled “Configuring Capgo Native Build”](#configuring-capgo-native-build) There are a few things you need to configure in Capgo Native Build to be able to build and submit your app to TestFlight. Here is a list of the things you will pass to the Capgo CLI: | Parameter | Description | | ---------------------------- | ----------------------------------------------------------------------------------------------------- | | `--platform` | The platform to build for (`ios`) | | `--apple-team-id` | Your Apple Developer Team ID (found in [Apple Developer Portal](https://developer.apple.com/account)) | | `--apple-key` | Path to your App Store Connect API Key file (`.p8` file) | | `--apple-key-id` | The Key ID of your App Store Connect API Key | | `--apple-issuer-id` | Your App Store Connect Issuer ID | | `--certificate` | Path to your distribution certificate (`.p12` file) | | `--ios-provisioning-profile` | Provisioning profile mapping (`bundleId=path` or just path for single profile) | Example command: ```bash bunx @capgo/cli@latest build credentials save \ --platform ios \ --apple-team-id YOUR_TEAM_ID \ --apple-key '/path/to/AuthKey_XXXXX.p8' \ --apple-key-id YOUR_KEY_ID \ --apple-issuer-id YOUR_ISSUER_ID \ --certificate '/path/to/certificate.p12' \ --ios-provisioning-profile '/path/to/profile.mobileprovision' ``` ### Team ID [Section titled “Team ID”](#team-id) Let’s start with the team ID. Finding it is quite easy. 1. Go to [Apple Developer Account](https://developer.apple.com/account/) and scroll down 2. Find the `Team ID` ![Team ID location in developer account](/native-build-assets/apple_dev_team_id.png) ### Apple key, Apple key ID and Apple issuer ID [Section titled “Apple key, Apple key ID and Apple issuer ID”](#apple-key-apple-key-id-and-apple-issuer-id) Now, let’s move on to the Apple key. macOS: let Capgo create this key for you On macOS, `capgo build init` can create this App Store Connect API key for you. Choose **“No — create one for me”** and a guided window opens App Store Connect, walks you through each step, and captures the key, Key ID and Issuer ID automatically — no copy-paste. The manual steps below are the alternative (and the path on Windows or Linux). 1. Go to [App Store Connect user and access page](https://appstoreconnect.apple.com/access/users/) Note For me the link sometimes doesn’t work. Reload the page if it doesn’t work for you. 2. Select the correct team in the dropdown 1. Click on your name in the top right corner 2. Click on the team you want to use ![Apple Developer keys team selection](/native-build-assets/apple-developer-select-team.webp) 3. Click on the `Integrations` button ![App Store Connect integrations button](/native-build-assets/appstore-connect-integrations-button.webp) 4. Find the `issuer` Caution This **IS TO BE SAVED** - you will need it later Click on the `copy` button to copy the issuer ![App Store Connect copy issuer](/native-build-assets/appstore-connect-copy-issuer.webp) 5. Click on the plus button ![App Store Connect add key button](/native-build-assets/appstore-connect-add-key-button.webp) 6. Set the name of the key and set the access to `App manager` and click on the `Generate` button ![App Store Connect add key name, set access to app manager and generate button](/native-build-assets/appstore-connect-add-key-name.webp) 7. Save the key ID Caution This **IS TO BE SAVED** - you will need it later ![App Store Connect copy key ID](/native-build-assets/appstore-connect-copy-key-id.webp) 8. Download the key Caution This **IS TO BE SAVED** - you will need it later Danger **NEVER SHARE THE KEY WITH ANYONE - USE IT ONLY IN THE CAPGO CLI** ![App Store Connect download key](/native-build-assets/appstore-connect-download-key.webp) ![App Store Connect download key warning](/native-build-assets/appstore-connect-download-key-warning.webp) Congratulations 🎉 You have created the Apple key, Apple key ID and Apple issuer ID. ### Certificate [Section titled “Certificate”](#certificate) Now, you are ready to export the certificate. As you remember, one of the first steps of this guide was setting up the distribution certificate. However, Apple in their infinite wisdom, decided that the way you export the certificate is quite different from the way you create them 🙃 Let’s get into setting it up: 1. Open Keychain Access 1. Click `Command + Space` to open the search bar 2. Search for `Keychain Access` 3. Click on the `Keychain Access` app [](/native-build-assets/open-keychain-macos.mp4) 2. Select the `login` category and click on the `My Certificates` button ![Keychain Access login category](/native-build-assets/keychain-access-login-category.webp) 3. Find your certificate in the list The certificate should be named `Apple Distribution: [Your Name/Company] (your team ID)` ![Keychain Access find certificate](/native-build-assets/keychain-access-find-certificate.webp) 4. Right-click on the certificate and select `Export` ![Keychain Access export certificate](/native-build-assets/keychain-access-export-certificate.webp) 5. Save the certificate as a `.p12` file Caution This **IS TO BE SAVED** - you will need it later 1. Make sure to select a good name for the certificate file 2. Make sure the file format is set to `Personal Information Exchange (.p12)` 3. Click on the `Save` button ![Keychain Access save certificate dialog](/native-build-assets/keychain-access-save-certificate.webp) 6. When asked for the password, you can either: * Skip the password (recommended for simplicity): Click `OK` without entering a password * Set a password: If you prefer to protect your certificate with a password, you can set one here. Password-protected `.p12` files are fully supported by the Capgo CLI - just provide the password using the `--p12-password` option when running configuration command. ![Keychain Access save certificate password dialog](/native-build-assets/keychain-access-save-certificate-password-dialog.webp) 7. When asked for the “login keychain password”, give the password you use to login to your Mac Give the password you use to login to your Mac. Then, click on the `Allow` button. ![Keychain Access save certificate login keychain password](/native-build-assets/keychain-access-save-certificate-login-keychain-password.webp) Congratulations 🎉 You have exported the certificate. ### Provisioning profile [Section titled “Provisioning profile”](#provisioning-profile) Now, you are ready to export the provisioning profile. I promise, this is the last thing you will need to get from Apple. 1. Go to [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) 2. Select the correct team in the dropdown 1. Click on your name in the top right corner 2. Click on the team you want to use ![Apple Developer keys team selection](/native-build-assets/apple-developer-select-team.webp) 3. Make sure you are on the correct page It should look like this, if it doesn’t click on `profiles` in the sidebar ![Apple Developer profiles page](/native-build-assets/apple-developer-profiles-page.webp) 4. Click on the `+` button ![Apple Developer add profile button](/native-build-assets/apple-developer-add-profile-button.webp) 5. Select the profile type Select `App Store Connect` and click on the `Continue` button ![Apple Developer select profile type](/native-build-assets/apple-developer-select-profile-type.webp) 6. Select the app you want to build Find your app in the dropdown and click on the `Continue` button ![Apple Developer select app](/native-build-assets/apple-developer-select-app.webp) 7. Select the correct distribution certificate Select the certificate you exported in the previous step and click on the `Continue` button ![Apple Developer select distribution certificate](/native-build-assets/apple-developer-select-deployment-certificate.webp) If you are unsure which certificate to select, come back to Keychain Access and find the certificate you exported. Then look at the expiration date. ![Apple Developer select distribution certificate expiration date](/native-build-assets/apple-developer-select-deployment-certificate-expiration-date.webp) 8. Name the profile Give the profile a name and click on the `Generate` button Tip The profile name is automatically extracted by the Capgo CLI — you don’t need to remember it. ![Apple Developer name profile](/native-build-assets/apple-developer-name-profile.webp) 9. Download the profile Click on the `Download` button to download the profile Caution This file **IS TO BE SAVED** - you will need it later ![Apple Developer download profile](/native-build-assets/apple-developer-name-provisioning-profile.webp) Congratulations 🎉 You have now got everything you need to configure Capgo Native Build. Caution Never commit the credentials you just created to your repository. Keep them safe! 🔒 ### Running the configuration command [Section titled “Running the configuration command”](#running-the-configuration-command) You have done it! You have now got everything you need to configure Capgo Native Build. The command you will need to run is: ```bash bunx @capgo/cli@latest build credentials save \ --platform ios \ --apple-team-id UVTJ336J2D \ --apple-key ./capgo-tutorial/AuthKey_66FGQZB566.p8 \ --apple-key-id 66FGQZB566 \ --apple-issuer-id 0cd4db4a-5598-45b8-9d32-75cdf127d005 \ --certificate ./capgo-tutorial/capgo-build-tutorial-certificate.p12 \ --ios-provisioning-profile ./capgo-tutorial/capgo_native_build_tutorial.mobileprovision ``` Replace placeholder values Replace the placeholder values above with your actual credentials gathered in the previous steps: * `--apple-team-id`: Your Apple Team ID * `--apple-key`: Path to your downloaded `.p8` key file * `--apple-key-id`: Your Apple Key ID * `--apple-issuer-id`: Your Apple Issuer ID * `--certificate`: Path to your exported `.p12` certificate * `--ios-provisioning-profile`: Path to your downloaded `.mobileprovision` file (bundle ID auto-inferred for single profiles) If all went well, you will see the following output: ![Capgo CLI credentials save output](/native-build-assets/credentials-save.webp) Apple auth failed? Sync your clock If the App Store Connect API key looks correct but authentication still fails, sync your computer clock and retry. Capgo signs Apple’s JWT with your local system time, and Apple rejects tokens that expire more than 20 minutes in the future. A clock that is only a few seconds out of sync can be enough to fail this step. See the [builder troubleshooting guide](/docs/builder/troubleshooting/#app-store-connect-authentication-failed) for clock sync steps. ### CI/CD setup (GitHub Actions) [Section titled “CI/CD setup (GitHub Actions)”](#cicd-setup-github-actions) If you already completed [Team ID](#team-id), [Apple key, Apple key ID and Apple issuer ID](#apple-key-apple-key-id-and-apple-issuer-id), [Certificate](#certificate), and [Provisioning profile](#provisioning-profile), you already have everything needed for CI/CD. This section only covers how to pass those values as GitHub Actions secrets and environment variables. #### 1) Convert credential files to single-line base64 [Section titled “1) Convert credential files to single-line base64”](#1-convert-credential-files-to-single-line-base64) ```bash # Distribution certificate (.p12) base64 -i ./capgo-tutorial/capgo-build-tutorial-certificate.p12 | tr -d '\n' > certificate_base64.txt # Provisioning profile (.mobileprovision) base64 -i ./capgo-tutorial/capgo_native_build_tutorial.mobileprovision | tr -d '\n' > profile_base64.txt # App Store Connect API key (.p8) base64 -i ./capgo-tutorial/AuthKey_66FGQZB566.p8 | tr -d '\n' > apple_key_base64.txt ``` Tip GitHub secrets should be single-line values. `tr -d '\n'` removes line breaks from base64 output. #### 2) Create repository secrets [Section titled “2) Create repository secrets”](#2-create-repository-secrets) In `GitHub > Repository > Settings > Secrets and variables > Actions`, add: | Secret name | Value | | ---------------------------- | --------------------------------------------------------------------------------------------------------- | | `CAPGO_TOKEN` | Your Capgo API token | | `APP_STORE_CONNECT_TEAM_ID` | Team ID from [Team ID](#team-id) | | `APPLE_KEY_ID` | Key ID from [Apple key, Apple key ID and Apple issuer ID](#apple-key-apple-key-id-and-apple-issuer-id) | | `APPLE_ISSUER_ID` | Issuer ID from [Apple key, Apple key ID and Apple issuer ID](#apple-key-apple-key-id-and-apple-issuer-id) | | `BUILD_CERTIFICATE_BASE64` | Content of `certificate_base64.txt` | | `CAPGO_IOS_PROVISIONING_MAP` | Generated by CLI — copy from `.capgo-credentials` file | | `APPLE_KEY_CONTENT` | Content of `apple_key_base64.txt` | | `P12_PASSWORD` (optional) | Your `.p12` password if set during export | #### 3) Use env vars in your GitHub Actions workflow [Section titled “3) Use env vars in your GitHub Actions workflow”](#3-use-env-vars-in-your-github-actions-workflow) .github/workflows/ios-build.yml ```yaml name: iOS Cloud Build on: workflow_dispatch: push: branches: [main] jobs: ios-build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Request iOS build with Capgo run: bunx @capgo/cli@latest build request --platform ios env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} ``` Tip With this setup, CI sends credentials through environment variables only. You do not need to commit signing files or upload them as workflow artifacts. ### Running the build [Section titled “Running the build”](#running-the-build) Now, you are ready to run your first build. Run the following command to build your app: ```bash bunx @capgo/cli@latest build request --platform ios ``` Congratulations 🎉 At this point, you have successfully built your app and it is ready to be submitted to the App Store. ### Submit to App Store review [Section titled “Submit to App Store review”](#submit-to-app-store-review) The normal App Store build path uploads the build to App Store Connect/TestFlight. If your CI release should also attach the processed TestFlight build to the App Store version and submit it for App Review, pass `--submit-to-store-review` with a release build: ```bash npx @capgo/cli@latest build request com.example.app \ --platform ios \ --build-mode release \ --ios-distribution app_store \ --submit-to-store-review \ --store-release-name "1.2.3" \ --store-release-notes "General improvements" \ --store-release-notes-locale "en-US=General improvements" \ --store-release-notes-locale "nl-NL=Algemene verbeteringen" \ --store-release-notes-locale "fr-FR=Ameliorations generales" \ --no-ios-automatic-release ``` This requires App Store Connect API key credentials (`APPLE_KEY_ID`, `APPLE_ISSUER_ID`, `APPLE_KEY_CONTENT`, and `APP_STORE_CONNECT_TEAM_ID`). App-specific password uploads and `ad_hoc` distribution cannot submit a build for review. `--store-release-name` is the App Store version; if omitted, Capgo reads `MARKETING_VERSION` from the Xcode project. `--store-release-notes` is the fallback App Store What’s New text, and each `--store-release-notes-locale "locale=notes"` entry can override it for a store localization. Use `--ios-automatic-release` to release automatically after Apple approval, or `--no-ios-automatic-release` to wait for a manual release. `--ios-testflight-groups` is still available for external beta distribution, but it is not required for App Store review submission. ## Ad-Hoc Distribution Mode [Section titled “Ad-Hoc Distribution Mode”](#ad-hoc-distribution-mode) By default, Capgo builds iOS apps for App Store distribution (TestFlight + App Store). If you need ad-hoc builds instead (for internal testing or CI artifact collection), you can use the `--ios-distribution` flag. Note Ad-hoc distribution is **not** the same as Enterprise (In-House) distribution. Enterprise distribution requires a separate Apple Developer Enterprise account and uses different provisioning profiles. Capgo currently supports `app_store` and `ad_hoc` modes only. ### When to use ad-hoc mode [Section titled “When to use ad-hoc mode”](#when-to-use-ad-hoc-mode) * You want to distribute IPAs directly to registered devices (no TestFlight) * You don’t have or don’t want to use an App Store Connect API key * You want to collect build artifacts via `--output-upload` without submitting to the App Store ### Requirements [Section titled “Requirements”](#requirements) Ad-hoc builds have **fewer requirements** than App Store builds: | Credential | Required? | | ------------------------------------------------ | --------- | | Distribution certificate (`.p12`) | Yes | | Ad-hoc provisioning profile (`.mobileprovision`) | Yes | | Team ID (`--apple-team-id`) | Yes | | App Store Connect API key (`.p8`) | **No** | | Apple Key ID / Issuer ID | **No** | Note In `ad_hoc` mode, `--apple-key`, `--apple-key-id`, and `--apple-issuer-id` are not supported and are ignored. This is why the two App Store Connect rows above do not show ad-hoc CLI flags; these options apply to `app_store` mode only. Caution Without an App Store Connect API key, build number auto-increment uses a timestamp-based fallback. To suppress the warning, pass `--skip-build-number-bump`. ### Creating an ad-hoc provisioning profile [Section titled “Creating an ad-hoc provisioning profile”](#creating-an-ad-hoc-provisioning-profile) Follow the same steps as [Provisioning profile](#provisioning-profile), but in step 5, select **Ad Hoc** instead of **App Store**: 1. Go to [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) 2. Click the `+` button 3. Select **Ad Hoc** and click Continue 4. Select your app and distribution certificate 5. Select the devices you want to register 6. Name and download the profile ### Saving ad-hoc credentials [Section titled “Saving ad-hoc credentials”](#saving-ad-hoc-credentials) ```bash bunx @capgo/cli@latest build credentials save \ --platform ios \ --ios-distribution ad_hoc \ --apple-team-id YOUR_TEAM_ID \ --certificate './certificate.p12' \ --ios-provisioning-profile './adhoc_profile.mobileprovision' ``` No `--apple-key`, `--apple-key-id`, or `--apple-issuer-id` needed. ### Running an ad-hoc build [Section titled “Running an ad-hoc build”](#running-an-ad-hoc-build) ```bash bunx @capgo/cli@latest build request \ --platform ios \ --ios-distribution ad_hoc ``` To collect the IPA as a build artifact, add `--output-upload`: ```bash bunx @capgo/cli@latest build request \ --platform ios \ --ios-distribution ad_hoc \ --output-upload ``` ### CI/CD with ad-hoc builds [Section titled “CI/CD with ad-hoc builds”](#cicd-with-ad-hoc-builds) For GitHub Actions, you need fewer secrets than App Store builds: .github/workflows/ios-adhoc-build.yml ```yaml name: iOS Ad-Hoc Build on: workflow_dispatch: jobs: ios-adhoc: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: Request iOS ad-hoc build run: bunx @capgo/cli@latest build request --platform ios --ios-distribution ad_hoc --output-upload env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_ADHOC }} CAPGO_IOS_DISTRIBUTION: ad_hoc ``` Tip Notice that `APPLE_KEY_ID`, `APPLE_ISSUER_ID`, and `APPLE_KEY_CONTENT` are not needed for ad-hoc builds. ## Apps with Extensions (Multi-Target Signing) [Section titled “Apps with Extensions (Multi-Target Signing)”](#apps-with-extensions-multi-target-signing) If your app includes extensions (share extensions, widgets, notification service extensions, etc.), each extension target needs its own provisioning profile. Capgo supports this via the repeatable `--ios-provisioning-profile` flag. ### Example: App + Share Extension [Section titled “Example: App + Share Extension”](#example-app--share-extension) ```bash bunx @capgo/cli@latest build credentials save \ --platform ios \ --apple-team-id YOUR_TEAM_ID \ --apple-key '/path/to/AuthKey_XXXXX.p8' \ --apple-key-id YOUR_KEY_ID \ --apple-issuer-id YOUR_ISSUER_ID \ --certificate '/path/to/certificate.p12' \ --ios-provisioning-profile "com.example.app=./app_profile.mobileprovision" \ --ios-provisioning-profile "com.example.app.share-extension=./share_ext_profile.mobileprovision" ``` Each `--ios-provisioning-profile` flag maps a bundle ID to its provisioning profile file. The CLI: 1. Reads each mobileprovision file 2. Auto-extracts the profile name from the embedded plist 3. Base64-encodes the file 4. Stores everything as a single `CAPGO_IOS_PROVISIONING_MAP` credential Tip You need one distribution certificate for all targets — only provisioning profiles differ per target. ### Migration from Single Profile [Section titled “Migration from Single Profile”](#migration-from-single-profile) If you previously used `BUILD_PROVISION_PROFILE_BASE64` (single profile), run: ```bash bunx @capgo/cli@latest build credentials migrate --platform ios ``` This converts your existing single-profile credentials to the new `CAPGO_IOS_PROVISIONING_MAP` format and removes the legacy keys (`BUILD_PROVISION_PROFILE_BASE64`, `APPLE_PROFILE_NAME`). After migration, add extension profiles with the `update` command (additive merge): ```bash bunx @capgo/cli@latest build credentials update \ --platform ios \ --ios-provisioning-profile "com.example.app.share-extension=./share_ext_profile.mobileprovision" ``` Tip Use `update` (not `save`) to add profiles to existing credentials. The `update` command merges new profiles with existing ones. Use `save` only when setting up all credentials from scratch. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### Provisioning profile doesn’t include the XYZ capability. [Section titled “Provisioning profile doesn’t include the XYZ capability.”](#provisioning-profile-doesnt-include-the-xyz-capability) Sometimes, you might see the following error: ```plaintext Provisioning profile "YOUR_PROVISIONING_PROFILE_NAME" doesn't include the XYZ capability. (in target 'App' from project 'App')" ``` This happens because you have enabled a new capability after the provisioning profile was created. The old provisioning profile does not include the new capability yet. To fix this, you need to regenerate the provisioning profile. 1. Open [Apple Developer Portal](https://developer.apple.com/account/) 2. Select the correct team in the dropdown ![Apple Developer keys team selection](/native-build-assets/apple-developer-select-team-2.webp) 3. Click on the `Profiles` button ![Apple Developer profiles button](/native-build-assets/apple-developer-profiles-button.webp) 4. Find the provisioning profile you want to regenerate ![Apple Developer find profile](/native-build-assets/pple-developer-find-profile.webp) 5. Click on the `Edit` button ![Apple Developer edit profile](/native-build-assets/apple-developer-edit-profile.webp) 6. Click on the `Save` button ![Apple Developer save profile](/native-build-assets/apple-developer-save-profile.webp) 7. Click on the `Download` button ![Apple Developer download profile](/native-build-assets/apple-developer-download-profile.webp) 8. [Re-run the Capgo Native Build setup command](/docs/builder/ios/#running-the-configuration-command) with the newly downloaded profile. This should fix the issue. ### Other issues [Section titled “Other issues”](#other-issues) If for whatever reason you are having issues either with Capgo Native Build, configuring the credentials or building the app, please don’t hesitate to reach via our [support](https://support.capgo.app/). ## Keep going from iOS Builds [Section titled “Keep going from iOS Builds”](#keep-going-from-ios-builds) If you are using **iOS Builds** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # Build prescan checks > Full list of Capgo Cloud Build prescan checks and how to skip or warn on specific rules. 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: ```bash npx @capgo/cli@latest build prescan --platform ios ``` There are **80** checks today. Prefer ignoring individual check ids over turning the whole scan off. ## Ignore specific checks [Section titled “Ignore specific checks”](#ignore-specific-checks) ```bash # Skip one check entirely (example: intentional Capacitor server.url / Next.js shell) npx @capgo/cli@latest build request --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 --platform ios \ --prescan-warn ios/capacitor-server-url-shipped # Repeatable or comma-separated npx @capgo/cli@latest build request --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`: ```bash npx @capgo/cli@latest build prescan --platform ios \ --skip ios/capacitor-server-url-shipped \ --warn ios/capacitor-server-cleartext ``` Unknown check ids fail fast with a clear error. Tip Requires `@capgo/cli@latest` with per-check override support. Prefer `--prescan-skip` / `--prescan-warn` so every other check still protects your build. ## Global escapes (use sparingly) [Section titled “Global escapes (use sparingly)”](#global-escapes-use-sparingly) | Flag | Effect | | ----------------------------------------------------------------- | ----------------------------------- | | `--no-prescan` | Skip the entire scan | | `--prescan-ignore-fatal` (or `--ignore-fatal` on `build prescan`) | Run scan, print report, never block | | `--fail-on-warnings` | Treat 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. ## Check catalog [Section titled “Check catalog”](#check-catalog) 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. ### Shared [Section titled “Shared”](#shared) | Id | Platforms | What it checks | Gradual enforce | | ------------------------------ | ------------ | -------------------------------------------------------- | --------------- | | `shared/apikey-permission` | ios, android | API key can request native builds | — | | `shared/app-exists` | ios, android | App id exists and is visible to the API key | — | | `shared/credentials-saved` | ios, android | Required iOS/Android credentials are saved locally | — | | `shared/cap-sync-stale` | ios, android | Web assets built and Capacitor plugins synced | — | | `shared/node-linker-layout` | ios, android | node\_modules layout works with Capacitor native paths | — | | `shared/bundle-id-consistency` | ios, android | Capacitor appId matches native bundle id / applicationId | — | ### iOS [Section titled “iOS”](#ios) | Id | Platforms | What it checks | Gradual enforce | | --------------------------------------------- | --------- | -------------------------------------------------------------------------------- | --------------- | | `ios/p12-opens` | ios | iOS .p12 opens with the provided password | — | | `ios/p12-expiry` | ios | iOS signing certificate is not expired | — | | `ios/profile-expiry` | ios | Provisioning profile is not expired | — | | `ios/profile-bundle-match` | ios | Provisioning profile bundle id matches the app | — | | `ios/profile-type-vs-mode` | ios | Profile type matches app\_store / ad\_hoc mode | — | | `ios/cert-profile-pairing` | ios | Certificate is embedded in the provisioning profile | — | | `ios/targets-covered` | ios | All iOS targets have a provisioning profile | — | | `ios/infoplist-sanity` | ios | Info.plist has required version / identity keys | — | | `ios/asc-key-valid` | ios | App Store Connect API key fields look valid | — | | `ios/asc-key-access` | ios | ASC API key can access the app (remote) | — | | `ios/plist-bundle-id-format` | ios | CFBundleIdentifier format is valid | Yes | | `ios/plist-version-short-format` | ios | CFBundleShortVersionString format is valid | Yes | | `ios/plist-version-build-format` | ios | CFBundleVersion format is valid | Yes | | `ios/plist-encryption-compliance` | ios | ITSAppUsesNonExemptEncryption is declared | Yes | | `ios/plist-ats-arbitrary-loads` | ios | NSAllowsArbitraryLoads is not enabled for production | Yes | | `ios/plist-launch-storyboard` | ios | Launch screen is declared | Yes | | `ios/plist-orientations-multitasking` | ios | Orientation / multitasking settings are consistent | Yes | | `ios/plist-orientations-present` | ios | UISupportedInterfaceOrientations is declared | Yes | | `ios/plist-display-name` | ios | Display name is set | Yes | | `ios/plist-background-modes-sanity` | ios | UIBackgroundModes values look valid | Yes | | `ios/xcode-deployment-target-capacitor` | ios | iOS deployment target meets Capacitor requirements | Yes | | `ios/xcode-signing-team` | ios | Signing team is set | Yes | | `ios/xcode-bundle-id-mismatch-across-configs` | ios | Bundle id is consistent across Xcode configs | Yes | | `ios/xcode-enable-bitcode-leftover` | ios | ENABLE\_BITCODE leftover is removed | Yes | | `ios/xcode-swift-version-sanity` | ios | Swift version setting looks sane | Yes | | `ios/xcode-no-app-target` | ios | Xcode project has an application target | Yes | | `ios/xcode-multiple-app-targets` | ios | Multiple app targets are handled intentionally | Yes | | `ios/entitlements-vs-profile-capability` | ios | Entitlements match profile capabilities | Yes | | `ios/entitlements-aps-environment-vs-mode` | ios | aps-environment matches distribution mode | Yes | | `ios/entitlements-associated-domains-format` | ios | Associated Domains format is valid | Yes | | `ios/entitlements-app-groups-format` | ios | App Groups format is valid | Yes | | `ios/capacitor-server-url-shipped` | ios | server.url is not left as a live-reload / remote shell endpoint for store builds | Yes | | `ios/capacitor-server-cleartext` | ios | server.cleartext is not enabled for production | Yes | | `ios/capacitor-allow-navigation-wildcard` | ios | server.allowNavigation is not a blanket wildcard | Yes | | `ios/pods-not-installed` | ios | CocoaPods Pods / workspace are present when using Pods | Yes | | `ios/pods-lock-missing` | ios | Podfile.lock pins pod versions | Yes | | `ios/pods-capacitor-missing` | ios | Podfile wires Capacitor | Yes | | `ios/spm-package-resolved-missing` | ios | SPM Package.resolved is present | Yes | | `ios/spm-capacitor-dependency-missing` | ios | Package.swift declares Capacitor | Yes | | `ios/appicon-empty-or-placeholder` | ios | AppIcon.appiconset exists and is not empty | Yes | | `ios/appicon-referenced-file-missing` | ios | Contents.json icon files exist on disk | Yes | | `ios/appicon-marketing-missing` | ios | 1024×1024 marketing icon exists | Yes | | `ios/spm-deployment-target-consistency` | ios | SPM deployment target is consistent | Yes | ### Android [Section titled “Android”](#android) | Id | Platforms | What it checks | Gradual enforce | | ---------------------------------------- | --------- | ---------------------------------------------------- | --------------- | | `android/keystore-opens` | android | Android keystore opens with provided passwords | — | | `android/keystore-expiry` | android | Android signing cert is not expired | — | | `android/cordova-vars-present` | android | cordova.variables.gradle is present after cap sync | — | | `android/gradle-props-heuristics` | android | gradle.properties heuristics for common build breaks | — | | `android/play-sa-json` | android | Play service-account JSON is present when configured | — | | `android/flavor-exists` | android | Requested product flavor exists | — | | `android/agp8-package-attr` | android | Manifest package= attribute removed for AGP 8+ | — | | `android/manifest-well-formed` | android | AndroidManifest.xml parses | — | | `android/manifest-tag-typo` | android | Common manifest tag typos | — | | `android/manifest-namespace-uri` | android | xmlns:android namespace URI is correct | — | | `android/manifest-missing-prefix` | android | Android attributes use the android: prefix | — | | `android/manifest-exported-missing` | android | android:exported is set where required | — | | `android/manifest-multiple-uses-sdk` | android | Only one uses-sdk element | — | | `android/manifest-duplicate-component` | android | No duplicate components | — | | `android/manifest-unique-permission` | android | Custom permissions are unique | — | | `android/manifest-hardcoded-debuggable` | android | debuggable=true not shipped | — | | `android/manifest-mock-location` | android | ACCESS\_MOCK\_LOCATION not shipped | — | | `android/manifest-exported-unprotected` | android | Exported components are protected | — | | `android/manifest-query-all-packages` | android | QUERY\_ALL\_PACKAGES justification | — | | `android/manifest-deeplink-valid` | android | Deeplink intent-filters look valid | — | | `android/applicationid-present` | android | applicationId is declared in app/build.gradle | — | | `android/capacitor-build-gradle-applied` | android | capacitor.build.gradle exists when applied | — | | `android/gradle-wrapper-present` | android | Gradle wrapper files are present | — | | `android/flavor-dimensions` | android | Flavor dimensions are declared when flavors exist | — | | `android/google-services-file` | android | google-services.json present when plugin applied | — | | `android/local-properties-committed` | android | local.properties is not committed with secrets | — | | `android/sdk-floors` | android | min/compile/target SDK floors look valid | — | | `android/target-sdk-play` | android | targetSdk meets Play requirements | — | | `android/min-sdk-capacitor` | android | minSdk meets Capacitor requirements | — | | `android/version-fields` | android | versionCode / versionName are present | — | | `android/play-sa-access` | android | Play service account can access the app (remote) | — | ## Example: remote Next.js / server.url shell [Section titled “Example: remote Next.js / server.url shell”](#example-remote-nextjs--serverurl-shell) 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: ```bash npx @capgo/cli@latest build request --platform ios \ --prescan-skip ios/capacitor-server-url-shipped ``` Or keep visibility as a warning: ```bash npx @capgo/cli@latest build request --platform ios \ --prescan-warn ios/capacitor-server-url-shipped ``` ## Related [Section titled “Related”](#related) [Getting Started ](/docs/builder/getting-started/)Create your first Capgo Cloud Build. [Troubleshooting ](/docs/builder/troubleshooting/)Common Cloud Build failures and fixes. [CLI build reference ](/docs/cli/reference/build/)Full build request / prescan command options. # Troubleshooting > Common issues and solutions for Capgo Cloud Build Solutions to common issues when building native apps with Capgo Cloud Build. ## Build Failures [Section titled “Build Failures”](#build-failures) ### ”Upload failed” or “Connection timeout” [Section titled “”Upload failed” or “Connection timeout””](#upload-failed-or-connection-timeout) **Symptoms:** * Build fails during project upload * Timeout errors after 60 seconds **Solutions:** 1. **Check your internet connection** ```bash # Test connection to Capgo curl -I https://api.capgo.app ``` 2. **Reduce project size** * Ensure `node_modules/` is not being uploaded (should be auto-excluded) * Check for large files in your project: ```bash find . -type f -size +10M ``` 3. **Check upload URL expiration** * Upload URLs expire after 1 hour * If you get an expired URL error, re-run the build command Tip Very large projects may hit the build-time limit (see [Known Limitations](#known-limitations)). Contact support for enterprise options. ### ”Build timeout after 10 minutes” [Section titled “”Build timeout after 10 minutes””](#build-timeout-after-10-minutes) **Symptoms:** * Build exceeds maximum allowed time * Status shows `timeout` **Solutions:** 1. **Optimize dependencies** * Remove unused npm packages * Use `npm prune --production` before building 2. **Check for network issues in build** * Some dependencies may download large files during build * Consider pre-caching with a lock file 3. **Review native dependencies** ```bash # iOS - check Podfile for heavy dependencies cat ios/App/Podfile # Android - check build.gradle cat android/app/build.gradle ``` 4. **Contact support** * If your app legitimately needs more time * We can adjust limits for specific use cases ## Authentication Issues [Section titled “Authentication Issues”](#authentication-issues) ### ”API key invalid” or “Unauthorized” [Section titled “”API key invalid” or “Unauthorized””](#api-key-invalid-or-unauthorized) **Symptoms:** * Build fails immediately with authentication error * 401 or 403 errors **Solutions:** 1. **Verify API key is correct** ```bash # Test with a simple command bunx @capgo/cli@latest app list ``` 2. **Check API key permissions** * Key must have `write` or `all` permissions * Check in Capgo dashboard under API Keys 3. **Ensure API key is being read** ```bash # Check environment variable echo $CAPGO_TOKEN # Or check your saved credentials file cat ~/.capgo-credentials/credentials.json # global cat .capgo-credentials.json # local (--local) ``` 4. **Re-authenticate** ```bash bunx @capgo/cli@latest login ``` ### ”App not found” or “No permission for this app” [Section titled “”App not found” or “No permission for this app””](#app-not-found-or-no-permission-for-this-app) **Symptoms:** * Authentication works but app-specific error **Solutions:** 1. **Verify app is registered** ```bash bunx @capgo/cli@latest app list ``` 2. **Check app ID matches** * Verify `capacitor.config.json` appId * Ensure command uses correct app ID 3. **Verify organization access** * Check you’re in the correct organization * API key must have access to the app’s organization ## iOS Build Issues [Section titled “iOS Build Issues”](#ios-build-issues) ### ”Code signing failed” [Section titled “”Code signing failed””](#code-signing-failed) **Symptoms:** * Build fails during code signing phase * Xcode errors about certificates or profiles **Solutions:** 1. **Verify certificate type matches build type** * Development builds need Development certificates * App Store builds need Distribution certificates 2. **Check certificate and profile match** ```bash # Decode and inspect your certificate echo $BUILD_CERTIFICATE_BASE64 | base64 -d > cert.p12 openssl pkcs12 -in cert.p12 -nokeys -passin pass:$P12_PASSWORD | openssl x509 -noout -subject ``` 3. **Ensure provisioning profile is valid** * Check expiration date * Verify it includes your App ID * Confirm it includes the certificate 4. **Regenerate credentials** * Delete old certificate/profile * Create new ones in Apple Developer portal * Re-encode and update environment variables ### ”Provisioning profile doesn’t include signing certificate” [Section titled “”Provisioning profile doesn’t include signing certificate””](#provisioning-profile-doesnt-include-signing-certificate) **Symptoms:** * Xcode can’t find certificate in profile **Solutions:** 1. **Download latest profile from Apple** * Go to Apple Developer → Certificates, IDs & Profiles * Download provisioning profile * Ensure it includes your certificate 2. **Verify certificate is in profile** ```bash # Extract profile echo $BUILD_PROVISION_PROFILE_BASE64 | base64 -d > profile.mobileprovision # View profile contents security cms -D -i profile.mobileprovision ``` 3. **Recreate profile with correct certificate** * In Apple Developer portal, edit profile * Ensure your distribution certificate is selected * Download and re-encode ### ”App Store Connect authentication failed” [Section titled “”App Store Connect authentication failed””](#app-store-connect-authentication-failed) **Symptoms:** * Upload to TestFlight fails * API key errors **Solutions:** 1. **Verify API key credentials** * Check APPLE\_KEY\_ID (should be 10 characters) * Check APPLE\_ISSUER\_ID (should be UUID format) * Verify APPLE\_KEY\_CONTENT is correctly base64-encoded 2. **Sync your computer clock** * App Store Connect authentication uses short-lived JWTs generated from your local system time * Apple rejects tokens that expire more than 20 minutes in the future, so even small clock drift can make an otherwise valid key fail * On Windows, open **Settings > Time & language > Date & time** and click **Sync now** * On macOS, open **System Settings > General > Date & Time** and enable automatic time * On Linux, check `timedatectl status` and enable NTP if needed * After syncing, re-run the Capgo build or credential command See Apple’s [Generating Tokens for API Requests](https://developer.apple.com/documentation/appstoreconnectapi/generating-tokens-for-api-requests) documentation for the App Store Connect token lifetime rule. 3. **Test API key locally** ```bash # Decode key echo $APPLE_KEY_CONTENT | base64 -d > AuthKey.p8 # Test with fastlane (if installed) fastlane pilot list ``` 4. **Check API key permissions** * Key needs “Developer” role or higher * Verify in App Store Connect -> Users and Access -> Keys 5. **Ensure key is not revoked** * Check in App Store Connect * Generate new key if needed ### ”Pod install failed” [Section titled “”Pod install failed””](#pod-install-failed) **Symptoms:** * Build fails during CocoaPods installation * Podfile errors **Solutions:** 1. **Verify Podfile.lock is committed** ```bash git status ios/App/Podfile.lock ``` 2. **Test pod install locally** ```bash cd ios/App pod install ``` 3. **Check for incompatible pods** * Review Podfile for version conflicts * Ensure all pods support your iOS deployment target 4. **Clear pod cache** ```bash cd ios/App rm -rf Pods rm Podfile.lock pod install # Then commit new Podfile.lock ``` ## Android Build Issues [Section titled “Android Build Issues”](#android-build-issues) ### ”Keystore password incorrect” [Section titled “”Keystore password incorrect””](#keystore-password-incorrect) **Symptoms:** * Build fails during signing * Gradle errors about keystore **Solutions:** 1. **Verify keystore password** ```bash # Test keystore locally keytool -list -keystore my-release-key.keystore # Enter password when prompted ``` 2. **Check environment variables** ```bash # Ensure no extra spaces or special characters echo "$KEYSTORE_STORE_PASSWORD" | cat -A echo "$KEYSTORE_KEY_PASSWORD" | cat -A ``` 3. **Verify base64 encoding** ```bash # Decode and test echo $ANDROID_KEYSTORE_FILE | base64 -d > test.keystore keytool -list -keystore test.keystore ``` ### ”Key alias not found” [Section titled “”Key alias not found””](#key-alias-not-found) **Symptoms:** * Signing fails with alias error **Solutions:** 1. **List keystore aliases** ```bash keytool -list -keystore my-release-key.keystore ``` 2. **Verify alias matches exactly** * Alias is case-sensitive * Check for typos in KEYSTORE\_KEY\_ALIAS 3. **Use correct alias from keystore** ```bash # Update environment variable to match export KEYSTORE_KEY_ALIAS="the-exact-alias-name" ``` ### ”Gradle build failed” [Section titled “”Gradle build failed””](#gradle-build-failed) **Symptoms:** * Generic Gradle errors * Compilation or dependency issues **Solutions:** 1. **Test build locally first** ```bash cd android ./gradlew clean ./gradlew assembleRelease ``` 2. **Check for missing dependencies** * Review build.gradle files * Ensure all plugins are listed in dependencies 3. **Verify Gradle version compatibility** ```bash # Check gradle version cat android/gradle/wrapper/gradle-wrapper.properties ``` 4. **Clear Gradle cache** ```bash cd android ./gradlew clean rm -rf .gradle build ``` ### ”Play Store upload failed” [Section titled “”Play Store upload failed””](#play-store-upload-failed) **Symptoms:** * Build succeeds but upload fails * Service account errors **Solutions:** 1. **Verify service account JSON** ```bash # Decode and check format echo $PLAY_CONFIG_JSON | base64 -d | jq . ``` 2. **Check service account permissions** * Go to Play Console → Setup → API Access * Ensure service account has access to your app * Grant “Release to testing tracks” permission 3. **Verify app is set up in Play Console** * App must be created in Play Console first * At least one APK must be uploaded manually initially 4. **Check API is enabled** * Google Play Developer API must be enabled * Check in Google Cloud Console ## General Issues [Section titled “General Issues”](#general-issues) ### ”Job not found” or “Build status unavailable” [Section titled “”Job not found” or “Build status unavailable””](#job-not-found-or-build-status-unavailable) **Symptoms:** * Cannot check build status * Job ID errors **Solutions:** 1. **Wait a moment and retry** * Build jobs may take a few seconds to initialize 2. **Check job ID is correct** * Verify the job ID from the initial build response 3. **Check build hasn’t expired** * Build data is available for 24 hours ### ”Project sync failed” [Section titled “”Project sync failed””](#project-sync-failed) **Symptoms:** * Build fails before compilation starts * Missing files errors **Solutions:** 1. **Run Capacitor sync locally** ```bash bunx cap sync ``` 2. **Ensure all native files are committed** ```bash git status ios/ android/ ``` 3. **Check for gitignored native files** * Review .gitignore * Ensure important config files aren’t ignored ### ”Build succeeded but I don’t see output” [Section titled “”Build succeeded but I don’t see output””](#build-succeeded-but-i-dont-see-output) **Symptoms:** * Build shows success but no download link **Solutions:** 1. **Check build configuration** * Artifact storage may not be configured * Contact support if artifact access is unavailable for your build 2. **For iOS TestFlight submission** * Check App Store Connect * Processing may take 5-30 minutes after upload 3. **For Android Play Store** * Check Play Console → Testing → Internal testing * Processing may take a few minutes ## CI/CD Specific Issues [Section titled “CI/CD Specific Issues”](#cicd-specific-issues) ### GitHub Actions: “Command not found” [Section titled “GitHub Actions: “Command not found””](#github-actions-command-not-found) **Symptoms:** * `bunx @capgo/cli@latest 
` fails in CI with “command not found” **Solutions:** 1. **Set up Bun first** so `bunx` is available: ```yaml - uses: oven-sh/setup-bun@v2 ``` 2. **Then run the CLI** — `bunx` fetches it on demand, no global install needed: ```yaml - run: bunx @capgo/cli@latest build request com.example.app --platform android ``` ### GitHub Actions: “Secrets not found” [Section titled “GitHub Actions: “Secrets not found””](#github-actions-secrets-not-found) **Symptoms:** * Environment variables empty in build **Solutions:** 1. **Verify secrets are set** * Go to repo Settings → Secrets and variables → Actions * Add all required secrets 2. **Use correct syntax** ```yaml env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ``` 3. **Check secret names match** * Names are case-sensitive * No typos in secret references ## Getting More Help [Section titled “Getting More Help”](#getting-more-help) ### Enable Verbose Logging [Section titled “Enable Verbose Logging”](#enable-verbose-logging) ```bash # Add debug flag (when available) bunx @capgo/cli@latest build request com.example.app --verbose ``` ### Collect Build Information [Section titled “Collect Build Information”](#collect-build-information) When contacting support, include: 1. **Build command used** ```bash bunx @capgo/cli@latest build request com.example.app --platform ios ``` 2. **Error message** (full output) 3. **Job ID** (from build output) 4. **Build logs** (copy full terminal output) 5. **Environment info** ```bash node --version npm --version bunx @capgo/cli@latest --version ``` ### Contact Support [Section titled “Contact Support”](#contact-support) * **Discord**: [Join our community](https://discord.com/invite/VnYRvBfgA6) * **Email**: * **Documentation**: [Capgo Docs](/docs/) ### Known Limitations [Section titled “Known Limitations”](#known-limitations) Current limitations: * Maximum build time: 10 minutes * Maximum upload size: \~500MB * iOS builds require 24-hour Mac leases, build on Mac will enqueue to ensure optimal usage * Build artifact download availability depends on build destination and artifact storage configuration These limitations may be adjusted based on feedback. ## Prescan blocked my build [Section titled “Prescan blocked my build”](#prescan-blocked-my-build) Capgo runs a local **prescan** before upload. Fix the reported finding, or ignore only that check id: ```bash npx @capgo/cli@latest build request --platform ios \ --prescan-skip ios/capacitor-server-url-shipped ``` See the full catalog: [Prescan checks](/docs/builder/prescan/). ## Additional Resources [Section titled “Additional Resources”](#additional-resources) * [Getting Started](/docs/builder/getting-started/) - Initial setup guide * [iOS Builds](/docs/builder/ios/) - iOS-specific configuration * [Android Builds](/docs/builder/android/) - Android-specific configuration * [Prescan checks](/docs/builder/prescan/) - Full list of pre-build checks and ignore flags * [CLI Reference](/docs/cli/reference/build/) - Complete command documentation # Trigger Native Builds via Webhook > Expose an HTTP webhook that starts a Capgo Build from your admin dashboard, CMS, or any system that can POST a URL. Capgo Build is normally started from a laptop or CI job. Teams that ship from an **admin dashboard**, CMS, or internal portal often want a single **HTTP webhook**: press a button in their own UI, and a signed native build starts. This guide shows the standard pattern — a thin authenticated HTTP call into your code host, which runs the same Capgo Build workflow you already use. Note Capgo organization webhooks (Dashboard → Organization → Webhooks) notify *your* URLs about Capgo events (bundles, channels, members). This page is the other direction: **your** system calls a URL to **start** a Capgo Build. ## Architecture [Section titled “Architecture”](#architecture) ``` sequenceDiagram participant Admin as Admin dashboard participant Hook as Webhook endpoint participant CI as GitHub / GitLab participant Capgo as Capgo Build Admin->>Hook: POST /native-build (secret) Hook->>CI: repository_dispatch / pipeline trigger CI->>CI: checkout, npm ci, cap sync CI->>Capgo: build request Capgo-->>CI: signed binary / store upload ``` You do **not** need Capgo to expose a public “build webhook.” Your CI already has the signing secrets; the webhook’s only job is to start that CI job safely. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * A Capgo Build workflow that already works from the [CI UI](/docs/builder/ci-ui-trigger/) or on push ([GitHub Actions](/docs/builder/github-actions/)) * Permission to create a fine-grained GitHub token, GitLab trigger token, or equivalent * A shared secret your admin dashboard will send (header or body) ## Option A — GitHub `repository_dispatch` (recommended) [Section titled “Option A — GitHub repository\_dispatch (recommended)”](#option-a--github-repository_dispatch-recommended) GitHub accepts an authenticated API call that starts a workflow listening for `repository_dispatch`. Any dashboard that can `POST` JSON can fire it. ### 1. Workflow that listens for the webhook [Section titled “1. Workflow that listens for the webhook”](#1-workflow-that-listens-for-the-webhook) Validate the payload **before** checkout and before any secret-bearing step. Pass accepted values through job outputs / env vars — never interpolate `client_payload` directly into `run:` scripts ([script injection guidance](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections)). .github/workflows/capgo-build-webhook.yml ```yaml name: Capgo Build (Webhook) on: repository_dispatch: types: [capgo-native-build] jobs: validate: runs-on: ubuntu-latest outputs: platform: ${{ steps.check.outputs.platform }} mode: ${{ steps.check.outputs.mode }} ref: ${{ steps.check.outputs.ref }} platforms_json: ${{ steps.check.outputs.platforms_json }} steps: - id: check env: RAW_PLATFORM: ${{ github.event.client_payload.platform }} RAW_MODE: ${{ github.event.client_payload.mode }} RAW_REF: ${{ github.event.client_payload.ref }} DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} run: | PLATFORM="${RAW_PLATFORM:-android}" MODE="${RAW_MODE:-release}" REF="${RAW_REF:-$DEFAULT_BRANCH}" case "$PLATFORM" in ios|android|both) ;; *) echo "Invalid platform: $PLATFORM" >&2; exit 1;; esac case "$MODE" in debug|release) ;; *) echo "Invalid mode: $MODE" >&2; exit 1;; esac # Allowlist branches / tags / full SHAs only if [[ ! "$REF" =~ ^(main|master|production|release/[A-Za-z0-9._-]+|[0-9a-f]{40})$ ]]; then echo "Ref not allowlisted: $REF" >&2 exit 1 fi if [ "$PLATFORM" = "both" ]; then PLATFORMS_JSON='["ios","android"]' else PLATFORMS_JSON=$(printf '["%s"]' "$PLATFORM") fi { echo "platform=$PLATFORM" echo "mode=$MODE" echo "ref=$REF" echo "platforms_json=$PLATFORMS_JSON" } >> "$GITHUB_OUTPUT" build: needs: validate runs-on: ubuntu-latest environment: ${{ needs.validate.outputs.mode == 'release' && 'production' || 'build-debug' }} strategy: fail-fast: false matrix: platform: ${{ fromJSON(needs.validate.outputs.platforms_json) }} steps: - uses: actions/checkout@v4 with: ref: ${{ needs.validate.outputs.ref }} - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: npm ci - run: npm run build - name: Sync native project env: PLATFORM: ${{ matrix.platform }} run: npx cap sync "$PLATFORM" - name: Capgo Build env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} P12_PASSWORD: ${{ secrets.P12_PASSWORD }} CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }} APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }} ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }} KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }} PLATFORM: ${{ matrix.platform }} MODE: ${{ needs.validate.outputs.mode }} run: | npx @capgo/cli@latest build request com.example.app \ --platform "$PLATFORM" \ --build-mode "$MODE" ``` ### 2. Create a GitHub token [Section titled “2. Create a GitHub token”](#2-create-a-github-token) Create a fine-grained personal access token (or GitHub App installation token) with **Contents: Read and write** on the repository (required for `repository_dispatch`). Store it only in your admin backend — never in the browser. ### 3. Call the webhook from your admin dashboard [Section titled “3. Call the webhook from your admin dashboard”](#3-call-the-webhook-from-your-admin-dashboard) Your backend (not the end-user browser) should send: ```bash curl -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer $GITHUB_TOKEN" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/OWNER/REPO/dispatches \ -d '{ "event_type": "capgo-native-build", "client_payload": { "platform": "both", "mode": "release", "ref": "main", "requested_by": "admin@example.com" } }' ``` | Field | Purpose | | ------------------------- | --------------------------------------------------------- | | `event_type` | Must match `types` in the workflow (`capgo-native-build`) | | `client_payload.platform` | `ios`, `android`, or `both` | | `client_payload.mode` | `debug` or `release` | | `client_payload.ref` | Branch or tag to build (optional) | Wire the same JSON POST to a button in your admin UI (“Build native apps”). The dashboard only needs to reach **your** backend; the backend holds `GITHUB_TOKEN`. Caution Never embed the GitHub token in frontend JavaScript. The admin page should call your server; your server calls GitHub. ## Option B — Tiny proxy webhook (any host) [Section titled “Option B — Tiny proxy webhook (any host)”](#option-b--tiny-proxy-webhook-any-host) If the admin tool can only POST to a URL you control (Zapier, Make, Cloudflare Worker, Express route), put a short proxy in front of GitHub: ```js // Example Cloudflare Worker / Node handler (sketch) export default { async fetch(request, env) { if (request.method !== 'POST') { return new Response('Method not allowed', { status: 405 }) } if (request.headers.get('x-webhook-secret') !== env.WEBHOOK_SECRET) { return new Response('Unauthorized', { status: 401 }) } const body = await request.json().catch(() => ({})) const platform = body.platform || 'both' const mode = body.mode || 'release' const ref = body.ref || 'main' if (!['ios', 'android', 'both'].includes(platform)) { return new Response('Invalid platform', { status: 400 }) } if (!['debug', 'release'].includes(mode)) { return new Response('Invalid mode', { status: 400 }) } if (!/^(main|master|production|release\/[A-Za-z0-9._-]+|[0-9a-f]{40})$/.test(ref)) { return new Response('Ref not allowlisted', { status: 400 }) } const res = await fetch( `https://api.github.com/repos/${env.GITHUB_OWNER}/${env.GITHUB_REPO}/dispatches`, { method: 'POST', headers: { Accept: 'application/vnd.github+json', Authorization: `Bearer ${env.GITHUB_TOKEN}`, 'X-GitHub-Api-Version': '2022-11-28', }, body: JSON.stringify({ event_type: 'capgo-native-build', client_payload: { platform, mode, ref }, }), }, ) return new Response(res.status === 204 ? 'Build queued' : await res.text(), { status: res.status === 204 ? 200 : res.status, }) }, } ``` Then configure the admin product: | Setting | Value | | ------- | ---------------------------------------------- | | URL | `https://your-worker.example.com/native-build` | | Method | `POST` | | Header | `x-webhook-secret: ` | | Body | `{ "platform": "both", "mode": "release" }` | This is the usual shape for connecting a webhook to an on-admin dashboard: the dashboard stores one URL and one secret; Capgo credentials stay in GitHub Actions. ## GitLab Pipeline Trigger [Section titled “GitLab Pipeline Trigger”](#gitlab-pipeline-trigger) GitLab exposes [pipeline trigger tokens](https://docs.gitlab.com/ee/ci/triggers/) that are natural webhook targets. ```yaml # .gitlab-ci.yml fragment capgo_native_webhook: stage: build script: - npm ci && npm run build - npx cap sync "${PLATFORM:-android}" - npx @capgo/cli@latest build request com.example.app --platform "${PLATFORM:-android}" --build-mode "${BUILD_MODE:-release}" rules: - if: '$CI_PIPELINE_SOURCE == "trigger"' ``` Create a trigger token under **Settings → CI/CD → Pipeline trigger tokens**, then from the admin backend: ```bash curl -X POST \ -F token=$GITLAB_TRIGGER_TOKEN \ -F ref=main \ -F "variables[PLATFORM]=android" \ -F "variables[BUILD_MODE]=release" \ https://gitlab.com/api/v4/projects/PROJECT_ID/trigger/pipeline ``` For both platforms, either fire two triggers or expand the job into a parallel matrix the same way as the GitHub example. ## Bitbucket and Azure [Section titled “Bitbucket and Azure”](#bitbucket-and-azure) | Platform | Webhook mechanism | | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Bitbucket** | [Pipeline trigger URL](https://support.atlassian.com/bitbucket-cloud/docs/pipeline-triggers/) or custom pipeline + app password `POST` | | **Azure DevOps** | [Pipeline run REST API](https://learn.microsoft.com/en-us/rest/api/azure/devops/pipelines/runs/run-pipeline) with a PAT; use the manual pipeline from [Trigger from CI UI](/docs/builder/ci-ui-trigger/#azure-devops) | Pattern is identical: admin → your secret check → host API → Capgo Build job. ## Payload Checklist for Admin Tools [Section titled “Payload Checklist for Admin Tools”](#payload-checklist-for-admin-tools) When the dashboard form is built, collect at least: * **Platform** — ios / android / both * **Mode** — debug (QA) or release (store) * **Git ref** — branch or tag to build * **Actor** — email or user id for audit logs (pass through `client_payload`) Optional: after the run, have CI post back to the admin API with the download URL from [`--output-record` / `build last-output`](/docs/builder/github-actions/#read-the-build-output-url-and-qr-code). ## Security [Section titled “Security”](#security) * Authenticate every webhook (`x-webhook-secret`, HMAC signature, or mTLS). * Allowlist `platform`, `mode`, and `ref` in both the proxy and the workflow `validate` job — treat `client_payload` as untrusted input. * Pass accepted values through env vars / job outputs; do not interpolate payload fields into `run:` scripts. * Keep GitHub/GitLab tokens server-side only. * Prefer tokens scoped to a single repository. * Rate-limit the proxy; native builds cost build minutes. * For store-submitting releases, map `release` to a protected GitHub Environment (as in the sample) or require an extra confirmation flag checked in `validate`. ## Related Guides [Section titled “Related Guides”](#related-guides) [Trigger from CI UI ](/docs/builder/ci-ui-trigger/)Same Capgo Build job, started from the Actions / Pipelines tab. [GitHub Actions setup ](/docs/builder/github-actions/)Credential export and secret names used by these workflows. [Auto OTA or Native ](/docs/builder/ci-ota-or-native/)On git push, choose live update vs native automatically. # What Happens When Capgo is Unavailable > Understanding Capgo behavior when service is down, canceled, or when you exceed plan limits # What Happens When Capgo is Unavailable [Section titled “What Happens When Capgo is Unavailable”](#what-happens-when-capgo-is-unavailable) Capgo is designed to be resilient and non-blocking. Your app continues to work even when Capgo services are temporarily unavailable. This document explains what happens in various scenarios. ## When Capgo Service is Down [Section titled “When Capgo Service is Down”](#when-capgo-service-is-down) If Capgo’s servers are temporarily unavailable or experiencing an outage: * **Your app continues to work normally** — Users can still open and use your app * **Updates are not downloaded** — The automatic update check fails silently * **No error is shown to users** — The update process gracefully fails in the background * **Existing updates remain** — Any previously downloaded updates stay on the device * **Updates resume automatically** — Once service is restored, normal update behavior resumes Capgo is designed with a “fail-safe” approach: if update services are unavailable, your app simply ignores the update and continues functioning normally. ## When You Cancel Capgo [Section titled “When You Cancel Capgo”](#when-you-cancel-capgo) After canceling your Capgo subscription: * **Existing updates remain on user devices** — Users who already downloaded updates keep those versions * **No new updates are downloaded** — The app stops checking for and downloading updates * **App functionality is unaffected** — Your app continues to work without any changes * **Historical data is retained** — Your dashboard and analytics data remains accessible for a period * **You can reactivate anytime** — Resubscribing restores full update functionality immediately The update mechanism gracefully degrades — your app becomes “static” but fully functional after cancellation. ## When You Exceed Your Plan Limits [Section titled “When You Exceed Your Plan Limits”](#when-you-exceed-your-plan-limits) If you exceed your plan’s MAU (Monthly Active Users), bandwidth, or storage limits: ### MAU Limits [Section titled “MAU Limits”](#mau-limits) * **New users may not receive updates** — The update check continues but may be throttled * **Existing users are unaffected** — Users who already have updates continue using them * **Analytics may be incomplete** — New user tracking might be paused ### Bandwidth Limits [Section titled “Bandwidth Limits”](#bandwidth-limits) * **Update downloads stop** — Users won’t receive new updates until you add credits or upgrade * **App remains functional** — Existing app version continues to work * **No error to users** — Update failures are silent and non-blocking ### Storage Limits [Section titled “Storage Limits”](#storage-limits) * **New uploads may fail** — You won’t be able to upload new app versions * **Existing versions remain available** — Previously uploaded bundles still work * **You can upgrade or add storage** — Resolving the limit restores full functionality ## Summary Table [Section titled “Summary Table”](#summary-table) | Scenario | App Works | Updates Download | Existing Updates Stay | | --------------------- | --------- | ------------------------------- | --------------------- | | Capgo Down | ✅ Yes | ❌ No | ✅ Yes | | Subscription Canceled | ✅ Yes | ❌ No | ✅ Yes | | MAU Limit Exceeded | ✅ Yes | ⚠ May stop | ✅ Yes | | Bandwidth Limit | ✅ Yes | ❌ No | ✅ Yes | | Storage Limit | ✅ Yes | ⚠ Downloads may be unavailable | ✅ Yes | ## Best Practices [Section titled “Best Practices”](#best-practices) 1. **Always test your app offline** — Ensure core functionality works without updates 2. **Keep a fallback plan** — Have a traditional app store update process as backup 3. **Monitor your limits** — Keep track of usage to avoid unexpected behavior 4. **Test cancellation scenarios** — Verify your app behaves correctly when updates stop ## Need Help? [Section titled “Need Help?”](#need-help) If you have questions about Capgo’s availability policies or need assistance, please [contact support](/docs/getting-help/). ## Keep going from What Happens When Capgo is Unavailable [Section titled “Keep going from What Happens When Capgo is Unavailable”](#keep-going-from-what-happens-when-capgo-is-unavailable) If you are using **What Happens When Capgo is Unavailable** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, and [Update Types](/docs/live-updates/update-types/) for the implementation detail in Update Types. # Overview > This document provides a comprehensive overview of the Capgo CLI, how it can be utilized to enhance your app development process by enabling seamless live updates Use Capgo’s Live Updates feature to update the JavaScript bundles of your app remotely, in real-time. Push JS updates directly to your users without going through the app store review process to instantly fix bugs and ship new features. Always use the latest CLI Always run Capgo CLI with `@latest` (for example `npx @capgo/cli@latest`). The CLI follows its own versioning and does **not** need to match your plugin major or Capacitor major. The latest CLI stays compatible with any supported updater plugin version. See [Capgo versioning](/docs/versioning/). Note Live Updates are limited to JavaScript bundle changes. If you need to update native code, such as adding or removing a plugin or changing native project configuration, you’ll need to submit a new native binary build to the app stores. ## How Live Updates Work [Section titled “How Live Updates Work”](#how-live-updates-work) Capgo’s Live Update system has two key components: 1. The Capgo SDK, which you install in your app. The SDK checks for available updates and downloads them in the background. 2. Channels, which let you target updates to specific groups of users. You can use channels to manage different release tracks, such as `Production`, `Staging`, and `Dev`. When you upload a new JS bundle to Capgo and assign it to a channel, the Capgo SDK in apps configured for that channel will detect the update and download it. The next time the app restarts, the new bundle will be loaded. ## Getting Started [Section titled “Getting Started”](#getting-started) To start using Live Updates, follow these steps: 1. Complete the [Capgo Quickstart](/docs/getting-started/quickstart/) to set up your app in Capgo and install the Capgo SDK. 2. In your app code, call `CapacitorUpdater.notifyAppReady()` after your app has finished initializing. This tells the Capgo SDK that your app is ready to receive updates. 3. Build your JS bundle and upload it to Capgo: ```shell npm run build npx @capgo/cli@latest bundle upload --channel=production ``` 4. Open your app and wait for the update to download. You can check the status with: ```shell npx @capgo/cli@latest app debug ``` 5. Once the update is downloaded, close and reopen your app to load the new bundle. See the [Deploying Live Updates](/docs/getting-started/deploy/) guide for more details. ## The Capgo CLI [Section titled “The Capgo CLI”](#the-capgo-cli) The Capgo CLI is a powerful tool that allows developers to interact with Capgo’s services from their own CI/CD pipelines. With the CLI, you have granular control over when builds are produced and deployed, enabling you to integrate Capgo into your existing enterprise workflows. ### What is the Capgo CLI for? [Section titled “What is the Capgo CLI for?”](#what-is-the-capgo-cli-for) The Capgo CLI is designed for developers and teams who need more control and flexibility in their live update workflows. By using the CLI in your CI/CD pipelines, you can: * Decide exactly when to build and deploy updates, rather than relying on Capgo’s built-in automation * Insert your own processes, such as code signing, QA testing, or manager approvals, between the build and deploy steps * Integrate Capgo into your existing DevOps tooling and workflows ### Authentication [Section titled “Authentication”](#authentication) To use the Capgo CLI, you’ll need to authenticate with your API key. You can generate an API key in your Capgo account settings. To log in and securely store your API key, run: ```shell npx @capgo/cli@latest login [API_KEY] ``` This command will then be saved for future use. You won’t need to provide your API key with each command after logging in. ### Key Differences from Other CLI Tools [Section titled “Key Differences from Other CLI Tools”](#key-differences-from-other-cli-tools) If you’re familiar with other live update CLI tools, there are a few key things to note about Capgo’s CLI: * Capgo uses a single CLI for both development and CI/CD use cases, as Capgo is focused solely on the live update feature set. * The Capgo CLI doesn’t require a separate installation step. It’s bundled with the `@capgo/cli` package and can be run directly using `npx`. * Capgo’s CLI is designed specifically for the live update workflow, so it may not include some features or commands found in more general-purpose CLI tools. ## Next Steps [Section titled “Next Steps”](#next-steps) [ Channels](/docs/live-updates/channels/) [Learn how to use channels to manage different release tracks and target updates to specific users.](/docs/live-updates/channels/) [ Rollbacks](/docs/live-updates/rollbacks/) [Discover how to roll back to a previous JS bundle version if an update causes issues.](/docs/live-updates/rollbacks/) [ Update Behavior](/docs/live-updates/update-behavior/) [Customize how and when updates are downloaded and applied in your app.](/docs/live-updates/update-behavior/) [ Fast Updates](/docs/live-updates/differentials/) [Learn how to use fast updates to speed up the update process.](/docs/live-updates/differentials/) ## Keep going from Overview [Section titled “Keep going from Overview”](#keep-going-from-overview) If you are using **Overview** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # Commands > Capgo CLI documentation, how to use it and what is used for This page is a guided overview. Use the current command reference for exact flags: [app](/docs/cli/reference/app/), [bundle](/docs/cli/reference/bundle/), [channel](/docs/cli/reference/channel/), and [build](/docs/cli/reference/build/). ### Usage [Section titled “Usage”](#usage) All command should be run in your app folder with capacitor project ignited properly. [Capacitor Cross-platform native runtime for web apps ](https://capacitorjs.com/docs/getting-started/) ### **Init** [Section titled “Init”](#init) `npx @capgo/cli@latest init [apikey]` This method is here to onboard you step by step. It will add your app to Capgo. It will add the code to your app to validate the update. Likewise, it will build your app. Furthermore, it will upload your app to Capgo. And it will help you to check if the update works. ### **Login** [Section titled “Login”](#login) `npx @capgo/cli login [apikey]` This method is here to remember the `apikey` for you. Note use `--apikey=********` in any command to override it **Optionally you can give:** `--local` This will store your **apikey** in the local repo and git ignore it. ## **Doctor** [Section titled “Doctor”](#doctor) `npx @capgo/cli doctor` Command to check if you are up-to-date with Capgo packages. This command will also be useful for bug report. ## App [Section titled “App”](#app) ### **Add** [Section titled “Add”](#add) `npx @capgo/cli app add [appId]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). > 💡 All option will be guessed in your config if not provided. Optionally, you can give: * `--icon [/path/to/my/icon]` to have a custom icon display in Capgo web app. * `--name [test]` to have a custom name in the list. * `--apikey [key]` API key to link to your account. * `--retention [retention]` retention period of app bundle in days, 0 by default = infinite. Example of `capacitor.config.json` for appId and AppName, the icon is guess in the resources folder ```json { "appId": "ee.forgr.capacitor_go", "appName": "Capgo", "webDir": "dist" } ``` ### **Set** [Section titled “Set”](#set) `npx @capgo/cli app set [appId]` `[appId]` is your app ID, the format is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--icon [/path/to/my/icon]` to have a custom icon display in Capgo web app. * `--name [test]` to have a custom name in the list. * `--retention [retention]` retention period of app bundle in days, 0 by default = infinite. * `--expose-metadata [true|false]` to expose bundle metadata (link and comment) to the plugin. * `--preview` or `--no-preview` to enable or disable bundle and channel preview QR codes. * `--allow-device-custom-id` or `--no-allow-device-custom-id` to control custom device IDs. * `--block-provider-infra-requests` or `--no-block-provider-infra-requests` to control blocking of known Google and Apple datacenter requests. * `--build-timeout-minutes [5-360]` to set the native build timeout. * `--ios-store-url [url]` or `--android-store-url [url]` to set the store URL. * `--default-upload-channel [channel]` to set the default upload channel. * `--default-download-channel [channel]` to set the default download channel, or `--disable-download-channels` to make all download channels non-public. * `--apikey [key]` API key to link to your account. ### **List** [Section titled “List”](#list) `npx @capgo/cli app list [appId]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey [key]` API key to link to your account. ### **Delete** [Section titled “Delete”](#delete) `npx @capgo/cli app delete [appId]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey [key]` API key to link to your account. * `--bundle` with the version number will only delete this version. ### Debug [Section titled “Debug”](#debug) `npx @capgo/cli app debug [appId]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey [key]` API key to link to your account. * `--device` with the specific device you want to debug ### Setting [Section titled “Setting”](#setting) `npx @capgo/cli app setting [path]` Edit the Capacitor config. `[path]` - path of the setting that you would like to change. For example, to change the `appId`, provide `appId`. If you wish to disable auto update in the `capacitor-updater`, provide `plugins.CapacitorUpdater.autoUpdate` with `--string off`. You MUST provide either `--string` or `--bool`! Options: * `--string ` - sets the setting to a string * `--bool ` - sets the setting to a boolean ## Bundle [Section titled “Bundle”](#bundle) ### Upload [Section titled “Upload”](#upload) `npx @capgo/cli bundle upload [appId]` `[appId]` is your app ID, the format is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey ` API key to link to your account. * `--path ` Path of the folder to upload. * `--channel ` Channel to link to. * `--external ` Link to external URL instead of uploading to Capgo Cloud. * `--iv-session-key ` Set the IV and session key for bundle URL external. * `--s3-endpoint ` URL of S3 endpoint. Does not work with delta uploads or the external option. * `--s3-region ` Region for your S3 bucket. * `--s3-apikey ` API key for your S3 endpoint. * `--s3-apisecret ` API secret for your S3 endpoint. * `--s3-bucket-name ` Name for your AWS S3 bucket. * `--s3-port ` Port for your S3 endpoint. * `--no-s3-ssl` Disable SSL for S3 upload. * `--key ` Custom path for public signing key (v1 system). * `--key-data ` Public signing key (v1 system). * `--key-v2 ` Custom path for private signing key (v2 system). * `--key-data-v2 ` Private signing key (v2 system). * `--bundle-url` Prints bundle URL into stdout. * `--no-key` Ignore signing key and send clear update. * `--no-code-check` Ignore checking if notifyAppReady() is called in source code and index present in root folder. * `--display-iv-session` Show in the console the IV and session key used to encrypt the update. * `--bundle ` Bundle version number of the bundle to upload. * `--auto-bump [level]` Auto-increment from the channel’s linked bundle, else the latest remote app version. Level: `major`, `minor` (default), `patch` (alias `fix`), `metadata`, or `ai` (Workers AI compares local files to the previous Capgo/channel delta manifest, infers the level, and logs a short reason; skips AI and bumps `patch` if no previous Capgo version). Bumps until a free name is found (deleted names stay occupied). Cannot be combined with `--bundle`. * `--min-update-version ` Minimal version required to update to this version. Used only if the disable auto update is set to metadata in channel. * `--auto-min-update-version` Set the min update version based on native packages. * `--ignore-metadata-check` Ignores the metadata (node\_modules) check when uploading. * `--ignore-checksum-check` Ignores the checksum check when uploading. * `--timeout ` Timeout for the upload process in seconds. * `--delta` Uploads Delta (manifest) files alongside the full bundle. * `--delta-only` Uploads only Delta (manifest) updates, skipping the full bundle. * `--no-delta` Disables Delta (manifest) uploads (useful if an instant apply `autoUpdate` mode is enabled but you want a full bundle). * `--tus` Upload the bundle using tus protocol. * `--multipart` Uses multipart protocol to upload data to S3, Deprecated, use TUS instead. * `--encrypted-checksum ` An encrypted checksum (signature). Used only when uploading an external bundle. * `--package-json ` A path to package.json. Useful for monorepos. * `--auto-set-bundle` Set the bundle in capacitor.config.json. * `--node-modules ` A list of path to node\_modules. Useful for monorepos (comma separated ex: ../../node\_modules,./node\_modules) > ⭐ External option helps to unlock 2 cases: corporate with privacy concern, don’t send the code to a third part and app bigger than 200 MB. With this setting, Capgo store only the link to the zip and sends the link to all apps. > 👀 Capgo cloud never looks at what is in the link (for external option), or in the code when stored. > 🔑 You can add a second layer of security by using encryption, then Capgo will not be able to look or modify anything, it becomes “trustless”. Example of `package.json` for version ```json { "version": "1.0.2" } ``` > ⛔ Version should be greater than “0.0.0”. > 💡 Don’t forget to update the version number each time you send one, version number cannot be overridden, or reused after deletion for security reason. ### **List** [Section titled “List”](#list-1) `npx @capgo/cli bundle list [appId]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey [key]` API key to link to your account. ### **Delete** [Section titled “Delete”](#delete-1) `npx @capgo/cli bundle delete [appId]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey [key]` API key to link to your account. * `--bundle` with the version number will only delete this version. ### Cleanup [Section titled “Cleanup”](#cleanup) in a SemVer range for a major version to Cloud `npx @capgo/cli bundle cleanup [appId] --bundle=[majorVersion] --keep=[numberToKeep]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey [key]` API key to link to your account. * `--bundle [majorVersion]` a version you wish to remove previous packages for, it will keep the last one + `numberToKeep`. * `--keep [numberToKeep]` the number of packages you wish to keep (default 4). For example: If you have 10 versions from 10.0.1 to 10.0.11, and you use `npx @capgo/cli cleanup [appId] --bundle=10.0.0` it will remove 10.0.1 to 10.0.6. 10.0.7 until 10.0.11 will be kept. If you have 20 versions in total, and you don’t provide a bundle number like this: `npx @capgo/cli cleanup [appId] --keep=2` It will remove 18 versions, and keep the last 2. > This command will ask for confirmation, it shows a table of what it will be keeping and removing. Note This command will ignore bundles which are currently in use in any channel. ### **Encrypt** [Section titled “Encrypt”](#encrypt) > **Warning**: This command is deprecated and will be removed in the next major release. Please use the new encryption system. `npx @capgo/cli bundle encrypt [path/to/zip]` This command is used when you use external source to store your code or for test purpose. Optionally, you can give: `--key [/path/to/my/private_key]` the path of your private key. `--key-data [privateKey]` the private key data, if you want to use inline. The command will print your `ivSessionKey`y and generate an encrypted zip, to use it with the upload command or decryt command. ### **Encrypt V2** [Section titled “Encrypt V2”](#encrypt-v2) `npx @capgo/cli bundle encrypt [path/to/zip] [checksum]` This command is used when you use external source to store your code or for test purpose. The checksum is the sha256 of the bundle (generated by —key-v2), it is used to verify the integrity of the file after decryption. It will be enncrypted with the private key and sent along with the bundle. In encryption v2 the checksum is upgraded to become a “signature” of the bundle. Optionally, you can give: `--key [/path/to/my/private_key]` the path of your private key. `--key-data [privateKey]` the private key data, if you want to use inline. `--json` to output info as json. The command will print your `ivSessionKey`y and generate an encrypted zip, to use it with the upload command or decryt command. ### **Decrypt** [Section titled “Decrypt”](#decrypt) `npx @capgo/cli bundle decrypt [path/to/zip] [ivSessionKey]` Optionally, you can give: `--key [/path/to/my/private_key]` the path of your private key. `--key-data [privateKey]` the private key data, if you want to use inline. This command is mainly used for test purpose, it will decrypt the zip and print the base64 decrypted session key in the console. ### **Decrypt V2** [Section titled “Decrypt V2”](#decrypt-v2) `npx @capgo/cli bundle decryptV2 [path/to/zip] [ivSessionKey]` Optionally, you can give: `--key [/path/to/my/private_key]` the path of your private key. `--key-data [privateKey]` the private key data, if you want to use inline. This command is mainly used for test purpose, it will decrypt the zip and print the base64 decrypted session key in the console. `--checksum [checksum]` the checksum of the file, it will verify the checksum after decryption. ### **Zip** [Section titled “Zip”](#zip) `npx @capgo/cli bundle zip [appId]` `[appId]` is your app ID, the format is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--path [/path/to/my/bundle]` to upload a specific folder. * `--bundle [1.0.0]` to set the bundle version number of the filename. * `--name [myapp]` to override the filename. * `--json` to output info as json. * `--no-code-check` to ignore the code check and send the bundle anyway. * `--key-v2` to use the new encryption system. This is required as new encryption system use better checksums to verify the integrity of the file. ### **Compatibility** [Section titled “Compatibility”](#compatibility) `npx @capgo/cli bundle compatibility [appId] -c [channelName]` `[appId]` is your app ID, the format is explained [here](https://capacitorjs.com/docs/cli/commands/init/). `[channelName]` the name of the channel to check. Optionally, you can give: * `--apikey [key]` API key to link to your account. * `--text` use text instead of emojis in the table * `--channel [channel]` the channel to check the compatibility with. * `--package-json ` A path to package.json. Useful for monorepos * `--node-modules ` A list of path to node\_modules. Useful for monorepos (comma separated ex: ../../node\_modules,./node\_modules) ## Channel [Section titled “Channel”](#channel) ### **Add** [Section titled “Add”](#add-1) `npx @capgo/cli channel add [channelName] [appId]` `[channelName]` the name of your new channel, such as `production` or `beta`. `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). ### **Delete** [Section titled “Delete”](#delete-2) `npx @capgo/cli channel delete [channelName] [appId]` `[channelName]` the name of the channel you want to delete. `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). ### **List** [Section titled “List”](#list-2) `npx @capgo/cli channel list [appId]` `[appId]` your app ID the format `com.test.app` is explained [here](https://capacitorjs.com/docs/cli/commands/init/). Optionally, you can give: * `--apikey [key]` API key to link to your account. ### **Set** [Section titled “Set”](#set-1) `npx @capgo/cli channel set [channelName] [appId]` `[appId]` is your app ID, the format is explained [here](https://capacitorjs.com/docs/cli/commands/init/). `[channelName]` the name of the channel you want to configure, such as `production` or `beta`. Optionally, you can give: * `--bundle [1.2.3]` your app bundle already sent to the cloud, to link it to a channel. * `--latest` get the bundle version from `package.json:version`, cannot be used with `--bundle`. * `--state [ normal | default ]` set the channel state, can be `normal` or `default`. One channel needs to be `default`. * `--downgrade` allows the channel to send downgrade version to devices. * `--no-downgrade` disallows the channel to send downgrade version to devices. * `--upgrade` allows the channel to send upgrade (major) version to devices. * `--no-upgrade` disallow the channel to send upgrade (major) version to devices. * `--ios` allows the channel to send version to iOS devices. * `--no-ios` disallows the channel to send version to iOS devices. * `--android` allows the channel to send version to android devices. * `--no-android` disallows the channel to send version to android devices. * `--self-assign` allows devices to self assign to this channel. * `--no-self-assign` disallows devices to self assign to this channel. * `--disable-auto-update STRATEGY` Disable auto update strategy for this channel. The possible options are: major, minor, patch, metadata, none. * `--apikey [key]` API key to link to your account. ## Disable updates strategy [Section titled “Disable updates strategy”](#disable-updates-strategy) There are a few ways to handle disabling updates for too old versions.\ Capgo cannot update native code thus an update from a version with the old native code to a version with the updated native code should not be possible. There are a couple of ways to achieve that. First, the `major` strategy. It prevents an update from native baseline `0.0.0` -> target bundle `1.0.0`. The major is the highlighted number (**1**.0.0 and **0**.0.0).\ Second is the `minor` strategy. It prevents an update when the target bundle has a different major or minor than the device native baseline, such as `0.0.0` -> `1.1.0` or `1.1.0` -> `1.2.0`. Third, the `patch` strategy. It was added into capgo as a very strict mode. It’s not recommended to be used unless you fully understand how it works. In order for it to accept an update, the following conditions must be met: * The major is the same between the target bundle and `version_build` * The minor is the same between the target bundle and `version_build` * The patch is the same between the target bundle and `version_build` * Only the version suffix may differ, such as prerelease (`-beta.2`) or build metadata (`+build.2`) Here is an example of which scenarios the update is allowed or denied * 1.0.0-beta.1 -> 1.0.0-beta.2 allowed * 1.0.0+build.1 -> 1.0.0+build.2 allowed * 1.0.0 -> 1.0.1 blocked * 1.0.0 -> 1.1.0 blocked * 1.0.0 -> 2.0.0 blocked The strategy comparison uses the native baseline sent as `version_build`, not the current downloaded bundle sent as `version_name`. Lastly the most complicated strategy. The `metadata` strategy.\ First you need to know that initially after you enable it the updates **WILL** fail as the channel is lacking the required metadata.\ If the channel is lacking metadata you will see a message like this: ![Cannot find metadata](/fail-metadata.webp) If you see something like this you know that you have to go to the current bundle for the failing channel and set the metadata.\ First, figure out what channel is failing. You can do that by looking at the `misconfigured` column ![Misconfigured table](/misconfigured-table.webp) Then go to the failing channel and click on `Bundle number`. This should take you to the bundle page. ![Locate failing channel](/fail-channel-show.webp) Once there fill the `Minimal update version` field. This should be a [semver](/semver_tester/).\ If the value you pass is not a semver you will get an error, but if everything goes correctly you should see something like this: ![Set min version](/set-min-update-version.webp) Now, you likely do not want to set this data manually every time you update. Fortunately, the CLI will prevent you from sending an update without this metadata ![CLI fail no metadata](/cli-fail-no-metadata.webp) To properly upload a bundle when using the `metadata` option you need to pass the `--min-update-version` with the [valid semver](/semver_tester/). Something like this: ![CLI upload with metadata](/cli-upload-with-metadata.webp) The `--min-update-version` is not the ONLY way to do compatibility. There also exists the `--auto-min-update-version`. Here is how it works. First, it takes a look at the version currently uploaded to the channel. It checks compatibility same as `bundle compatibility` command would. Second, if the new version is 100% compatible it reuses the `min_update_version` from the latest version in the channel. If not, then it sets the `min_update_version` to the bundle number of the newly uploaded version. You will always get an information what is the `min_update_version` when using this option. It will look something like this: ![Min update version](/min_update_version_info.webp) If the new version is not compatible it should look something like this ![Min update version not compatible](/min_update_version_not_compatible.webp) ## End-to-End encryption (Trustless) [Section titled “End-to-End encryption (Trustless)”](#end-to-end-encryption-trustless) Capgo supports end-to-end encryption, this means that your bundle(code) is encrypted before sent to the cloud and decrypted on the device. For that, you need to generate an RSA key pair, you can use the following command to generate it. The encryption system is a combination of RSA and AES, the RSA key is used to encrypt the AES key, and the AES key is used to encrypt the file. See below for more information about the encryption system. ![How crypto works](/crypto_explained.webp) Encryption schema ### Create key for your app [Section titled “Create key for your app”](#create-key-for-your-app) `npx @capgo/cli key create` Optionally, you can give: `--force` to overwrite the existing key. This command will create for you a key pair in your app, and will ask you to save the private key in a safe place. It’s recommended to not git commit the private key, and to not share it with anyone. > After your local test, remove the key from the config file and add it on the CI step with `key save` ### Save key in your app config [Section titled “Save key in your app config”](#save-key-in-your-app-config) `npx @capgo/cli key save` Optionally, you can give: `--key [/path/to/my/public_key]` the path of your public key file. `--key-data [publicKey]` the public key data, if you want to use inline. This command is useful if you followed the recommendation and didn’t commit the key in your app config. ## Ci integration [Section titled “Ci integration”](#ci-integration) To automate your work, I recommend you make GitHub action do the job of pushing to our server [GitHub action tutorial](https://capgo.app/blog/automatic-build-and-release-with-github-actions/) ## Our demo app [Section titled “Our demo app”](#our-demo-app) [GitHub - Cap-go/demo-app](https://github.com/Cap-go/demo-app/) Don’t forget to configure CI env variable with your API key ## Keep going from Commands [Section titled “Keep going from Commands”](#keep-going-from-commands) If you are using **Commands** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # CLI From 0.x to 1.x > How to upgrade from 0.x to 1.x, of the updater of Capgo, learn what are the breaking changes and how to handle them There are no significant changes in the CLI. The breaking change is mainly the rename of the argument `--version` to `--bundle` to avoid conflict, and follow the new naming everywhere. ## Keep going from CLI From 0.x to 1.x [Section titled “Keep going from CLI From 0.x to 1.x”](#keep-going-from-cli-from-0x-to-1x) If you are using **CLI From 0.x to 1.x** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # Encryption > How to encrypt your data with encryption v2, secure your app and ensure only you can update your users with your updates This documentation explains how to migrate to the encryption v2 system. Learn more about the encryption v2 system in the [blog post](/blog/introducing-end-to-end-security-to-capacitor-updater-with-code-signing/). ## 1. Create Key Pair [Section titled “1. Create Key Pair”](#1-create-key-pair) ```bash npx @capgo/cli key create ``` Store the private key securely. Never commit it to source control or share it with untrusted parties. This command: * Creates a new key pair in your app * Removes the old key from your Capacitor config * Keeps old key files for backward compatibility ## 2. Update Capacitor Config [Section titled “2. Update Capacitor Config”](#2-update-capacitor-config) When prompted “Do you want to setup encryption with the new channel in order to support old apps and facilitate the migration?”, select yes. This adds a new `defaultChannel` option to your Capacitor config. capacitor.config.ts ```ts import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'Example App', plugins: { CapacitorUpdater: { // ... other options defaultChannel: 'encryption_v2' // New apps will use this channel } } }; export default config; ``` ## 3. Upload Bundle to New Channel [Section titled “3. Upload Bundle to New Channel”](#3-upload-bundle-to-new-channel) ```bash npx @capgo/cli bundle upload --channel encryption_v2 ``` ## 4. Enable Self-Assignment [Section titled “4. Enable Self-Assignment”](#4-enable-self-assignment) Caution Required for the `defaultChannel` option to work ```bash npx @capgo/cli channel set encryption_v2 --self-assign ``` ## 5. Upload to Old Channel [Section titled “5. Upload to Old Channel”](#5-upload-to-old-channel) ```bash npx @capgo/cli bundle upload --channel production ``` Tip Capacitor config is never uploaded to Capgo ## 6. Cleanup (After 3-4 Months) [Section titled “6. Cleanup (After 3-4 Months)”](#6-cleanup-after-3-4-months) Once all users have updated their apps: 1. Remove `defaultChannel` from your Capacitor config 2. Delete the old channel: ```bash npx @capgo/cli channel delete encryption_v2 ``` Note Apps using `encryption_v2` as default will switch to `production` channel after deletion ## Keep going from Encryption [Section titled “Keep going from Encryption”](#keep-going-from-encryption) If you are using **Encryption** to plan security and compliance, connect it with [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, [Capgo Security](/security/) for the product workflow in Capgo Security, and [Capgo Trust Center](/trust/) for the product workflow in Capgo Trust Center. # đŸ‘€ account > đŸ‘€ Manage your Capgo account details and retrieve information for support or collaboration. đŸ‘€ Manage your Capgo account details and retrieve information for support or collaboration. ### []()đŸ”č **Id** [Section titled “ đŸ”č Id”](#--id) ```bash npx @capgo/cli@latest account id ``` đŸȘȘ Retrieve your account ID, safe to share for collaboration or support purposes in Discord or other platforms. **Example:** ```bash npx @capgo/cli@latest account id ``` **Options:** | Param | Type | Description | | ------- | -------- | ------------------------------- | | **-a,** | `string` | API key to link to your account | ## Keep going from account [Section titled “Keep going from account”](#keep-going-from-account) If you are using **account** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # đŸ“± app > đŸ“± Manage your Capgo app settings and configurations in Capgo Cloud. đŸ“± Manage your Capgo app settings and configurations in Capgo Cloud. ### []()➕ **Add** [Section titled “ ➕ Add”](#--add) **Alias:** `a` ```bash npx @capgo/cli@latest app add ``` ➕ Add a new app to Capgo Cloud with a unique app ID in the format com.test.app. All options can be guessed from config if not provided. **Example:** ```bash npx @capgo/cli@latest app add com.example.app --name "My App" --icon ./icon.png ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-n** | `string` | App name for display in Capgo Cloud | | **-i** | `string` | App icon path for display in Capgo Cloud | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ—‘ïž **Delete** [Section titled “ đŸ—‘ïž Delete”](#--delete) ```bash npx @capgo/cli@latest app delete ``` đŸ—‘ïž Delete an app from Capgo Cloud, optionally specifying a version to delete only that bundle. **Example:** ```bash npx @capgo/cli@latest app delete com.example.app ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()📋 **List** [Section titled “ 📋 List”](#--list) **Alias:** `l` ```bash npx @capgo/cli@latest app list ``` 📋 List all apps registered under your account in Capgo Cloud. **Example:** ```bash npx @capgo/cli@latest app list ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()🐞 **Debug** [Section titled “ 🐞 Debug”](#--debug) ```bash npx @capgo/cli@latest app debug ``` 🐞 Listen for live update events in Capgo Cloud to debug your app. Optionally target a specific device for detailed diagnostics. **Example:** ```bash npx @capgo/cli@latest app debug com.example.app --device DEVICE_ID ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **-d** | `string` | The specific device ID to debug | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()⚙ **Setting** [Section titled “ ⚙ Setting”](#--setting) ```bash npx @capgo/cli@latest app setting ``` ⚙ Modify Capacitor configuration programmatically. Specify setting path (e.g., plugins.CapacitorUpdater.defaultChannel) with —string or —bool. **Example:** ```bash npx @capgo/cli@latest app setting plugins.CapacitorUpdater.defaultChannel --string "Production" ``` **Options:** | Param | Type | Description | | ----------- | -------- | ----------------------------------------------------------------------- | | **—bool** | `string` | A value for the setting to modify as a boolean, ex: —bool true | | **—string** | `string` | A value for the setting to modify as a string, ex: —string “Production” | ### []()⚙ **Set** [Section titled “ ⚙ Set”](#--set) **Alias:** `s` ```bash npx @capgo/cli@latest app set ``` ⚙ Update settings for an existing app in Capgo Cloud, such as name, icon, or retention period for bundles. Retention of 0 means infinite storage. **Example:** ```bash npx @capgo/cli@latest app set com.example.app --name "Updated App" --retention 30 ``` **Options:** | Param | Type | Description | | ------------------------------------- | --------- | ------------------------------------------------------------------------------------ | | **-n** | `string` | App name for display in Capgo Cloud | | **-i** | `string` | Local image file path (png, jpg, webp, svg) used as the app icon in Capgo Cloud | | **-a** | `string` | API key to link to your account | | **-r** | `string` | Days to keep old bundles (0 = infinite, default: 0) | | **—expose-metadata** | `string` | Expose bundle metadata (link and comment) to the plugin (true/false, default: false) | | **—preview** | `boolean` | Enable bundle and channel preview QR codes for this app | | **—no-preview** | `boolean` | Disable bundle and channel preview QR codes for this app | | **—allow-device-custom-id** | `boolean` | Allow devices to set a custom device ID for this app | | **—no-allow-device-custom-id** | `boolean` | Disallow custom device IDs for this app | | **—block-provider-infra-requests** | `boolean` | Block provider infrastructure requests for this app | | **—no-block-provider-infra-requests** | `boolean` | Allow provider infrastructure requests for this app | | **—build-timeout-minutes** | `string` | Native build timeout in minutes (5-360, default: 15) | | **—ios-store-url** | `string` | iOS App Store URL for this app | | **—android-store-url** | `string` | Google Play Store URL for this app | | **—default-upload-channel** | `string` | Default upload channel name for this app | | **—default-download-channel** | `string` | Default download channel name for this app (sets channel public=true) | | **—disable-download-channels** | `boolean` | Disable Capgo download channels for this app (sets all channels public=false) | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | # đŸ”č build > đŸ—ïž Manage native iOS/Android builds through Capgo Cloud. đŸ—ïž Manage native iOS/Android builds through Capgo Cloud. ## Build access and output [Section titled “Build access and output”](#build-access-and-output) Native cloud build requests are currently in limited beta and access is restricted. Build credentials are never stored on Capgo servers: they are used only for the build and then deleted. Build outputs can optionally be uploaded with time-limited download links. ### Save credentials first [Section titled “Save credentials first”](#save-credentials-first) ```bash npx @capgo/cli build credentials save --appId YOUR_APP_ID --platform ios npx @capgo/cli build credentials save --appId YOUR_APP_ID --platform android ``` ### Capture an output URL in CI [Section titled “Capture an output URL in CI”](#capture-an-output-url-in-ci) Pass `--output-record` to persist the download URL and QR code, then use `build last-output` to read it: ```bash npx @capgo/cli build request APP_ID --platform android --output-upload --output-record /tmp/build.json npx @capgo/cli build last-output --path /tmp/build.json --field outputUrl ``` ### []()đŸ”č **Needed** [Section titled “ đŸ”č Needed”](#--needed) ```bash npx @capgo/cli@latest build needed ``` 🧭 Print “yes” and exit with code 1 if a native build is required; otherwise print “no” and exit with code 0. Command failures exit with code 2. **Example:** ```bash npx @capgo/cli@latest build needed com.example.app --channel production --verbose ``` **Options:** | Param | Type | Description | | ----------------- | --------- | ----------------------------------------------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **-c** | `string` | Channel to compare against. Defaults to CapacitorUpdater.defaultChannel or the public default channel | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | | **—node-modules** | `string` | Paths to node\_modules directories for monorepos (comma-separated) | | **—verbose** | `boolean` | Enable verbose output with detailed logging | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()🚀 **Init** [Section titled “ 🚀 Init”](#--init) **Alias:** `onboarding` ```bash npx @capgo/cli@latest build init ``` Set up build credentials interactively (iOS: certificates + profiles automated; Android: keystore + Google OAuth provisions GCP service account and Play Console invite) **Options:** | Param | Type | Description | | ----------------- | --------- | --------------------------------------------------------------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **-p** | `string` | Platform to onboard (ios or android). If omitted, auto-detects when only one native folder exists; prompts otherwise. | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—no-analytics** | `boolean` | Disable build onboarding analytics and terminal replay for this run | ### []()đŸ”č **Request** [Section titled “ đŸ”č Request”](#--request) ```bash npx @capgo/cli@latest build request ``` Request a native build from Capgo Cloud. This command will zip your project directory and upload it to Capgo for building. The build will be processed and sent directly to app stores. Credentials are never stored on Capgo servers; they are deleted after the build. Save them before requesting a build: ```bash npx @capgo/cli build credentials save --appId APP_ID --platform ios ``` **Example:** ```bash npx @capgo/cli@latest build request com.example.app --platform ios --path . ``` **Options:** | Param | Type | Description | | -------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **—path** | `string` | Path to the project directory to build (default: current directory) | | **—node-modules** | `string` | Paths to node\_modules directories for monorepos (comma-separated) | | **—platform** | `string` | Target platform: ios or android (required) | | **—build-mode** | `string` | Build mode: debug or release (default: release) | | **—build-certificate-base64** | `string` | iOS: Base64-encoded .p12 certificate | | **—p12-password** | `string` | iOS: Certificate password (optional if cert has no password) | | **—apple-id** | `string` | iOS: Apple ID email for app-specific password uploads (alternative to App Store Connect API key) | | **—apple-app-specific-password** | `string` | iOS: App-specific password (xxxx-xxxx-xxxx-xxxx) for TestFlight uploads | | **—apple-app-id** | `string` | iOS: Numeric App Store Connect app id (required together with —apple-id and —apple-app-specific-password) | | **—apple-key-id** | `string` | iOS: App Store Connect API Key ID | | **—apple-issuer-id** | `string` | iOS: App Store Connect Issuer ID | | **—apple-key-content** | `string` | iOS: Base64-encoded App Store Connect API key (.p8) | | **—app-store-connect-team-id** | `string` | iOS: App Store Connect Team ID | | **—ios-scheme** | `string` | iOS: Xcode scheme to build (default: App) | | **—ios-target** | `string` | iOS: Xcode target for reading build settings (default: same as scheme) | | **—ios-distribution** | `string` | iOS: Distribution mode | | **—ios-provisioning-profile** | `string` | iOS: Provisioning profile path or bundleId=path mapping (repeatable) | | **—android-keystore-file** | `string` | Android: Base64-encoded keystore file | | **—keystore-key-alias** | `string` | Android: Keystore key alias | | **—keystore-key-password** | `string` | Android: Keystore key password | | **—keystore-store-password** | `string` | Android: Keystore store password | | **—play-config-json** | `string` | Android: Base64-encoded Google Play service account JSON | | **—android-flavor** | `string` | Android: Product flavor to build (e.g. production). Required if your project has multiple flavors. | | **—android-track** | `string` | Android: Google Play track for this upload (internal, alpha, beta, production). Default without —submit-to-store-review: internal. With —submit-to-store-review and no track set: production. Precedence: CLI > env > saved credentials | | **—android-release-status** | `string` | Android: Google Play release status (draft, completed, inProgress, halted). Default without —submit-to-store-review: draft. With —submit-to-store-review and no status set: completed. Precedence: CLI > env > saved credentials | | **—in-app-update-priority** | `string` | Android: Google Play in-app update priority for this release (integer 0–5; higher = more urgent). See . Precedence: CLI > env > saved credentials | | **—no-playstore-upload** | `boolean` | Skip Play Store upload for this build (nulls out saved play config). Requires —output-upload. | | **—submit-to-store-review** | `boolean` | After upload, submit the store release for review instead of leaving it as a draft/inactive build. On Android this defaults to the production track with release\_status completed (override with —android-track / PLAY\_STORE\_TRACK and —android-release-status / PLAY\_STORE\_RELEASE\_STATUS). On iOS this submits the processed TestFlight build to App Store review. | | **—store-release-name** | `string` | Store release name/version label. Android sends this as the Google Play version\_name; iOS uses it as the App Store version when creating or reusing the editable version. | | **—store-release-notes** | `string` | Default store release notes. Android uses this as the Play changelog; iOS uses it as the fallback App Store What’s New text. | | **—store-release-notes-locale** | `string` | Localized store release notes (repeatable), for example —store-release-notes-locale en-US=“Bug fixes” —store-release-notes-locale fr-FR=“Corrections”. | | **—ios-testflight-groups** | `string` | iOS: optional comma-separated TestFlight external group names or IDs for external beta distribution. | | **—ios-automatic-release** | `boolean` | iOS: automatically release the App Store version after Apple approval. Default is manual release. | | **—no-ios-automatic-release** | `boolean` | iOS: keep the App Store version waiting for manual release after Apple approval. | | **—output-upload** | `boolean` | Override output upload behavior for this build only (enable). Precedence: CLI > env > saved credentials | | **—no-output-upload** | `boolean` | Override output upload behavior for this build only (disable). Precedence: CLI > env > saved credentials | | **—output-retention** | `string` | Override output link TTL for this build only (1h to 7d). Examples: 1h, 6h, 2d. Precedence: CLI > env > saved credentials | | **—output-record** | `string` | After a successful build, write a JSON record (jobId, status, outputUrl, qrCodeAscii, qrCodePngPath, finishedAt) to a path. A PNG QR code is also written next to that path with the `.qr.png` suffix. Read fields back with `build last-output`. | | **—no-skip-build-number-bump** | `boolean` | Override saved credentials to re-enable automatic build number incrementing for this build only. | | **—skip-marketing-version-bump** | `boolean` | Skip automatic marketing version (CFBundleShortVersionString / versionName) bump when the app is already released. | | **—sync-ios-version** | `boolean` | iOS: sync Xcode MARKETING\_VERSION from package.json before uploading the project. | | **—ai-analytics** | `boolean` | On build failure, send logs to Capgo AI for diagnosis. In interactive terminals this skips the upfront confirmation; in CI this auto-uploads and prints the analysis to stderr. | | **—no-prescan** | `boolean` | Skip the automatic pre-build scan | | **—prescan-ignore-fatal** | `boolean` | Run the pre-build scan but never block the build (report only) | | **—prescan-skip** | `string` | Skip specific prescan check(s) by id (repeatable or comma-separated). Other checks still run. | | **—prescan-warn** | `string` | Downgrade specific prescan check(s) to warning by id (repeatable or comma-separated). Check still runs. | | **—fail-on-warnings** | `boolean` | Treat prescan warnings as fatal | | **—send-logs-to-support** | `boolean` | On a CI/CD build failure, automatically upload the build logs to Capgo support (no email required). Capgo support is notified and will follow up by email. Additive to —ai-analytics. | | **—send-logs** | `boolean` | Deprecated alias for —send-logs-to-support | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | | **—verbose** | `boolean` | Enable verbose output with detailed logging | ### []()đŸ”č **Sync-ios-version** [Section titled “ đŸ”č Sync-ios-version”](#--sync-ios-version) ```bash npx @capgo/cli@latest build sync-ios-version ``` Sync the local iOS Xcode MARKETING\_VERSION from package.json. **Example:** ```bash npx @capgo/cli@latest build sync-ios-version --path . ``` **Options:** | Param | Type | Description | | ---------- | --------- | ---------------------------------------------------------------- | | **—path** | `string` | Path to the project directory (default: current directory) | | **—check** | `boolean` | Check only; exit non-zero when MARKETING\_VERSION is out of sync | ### []()đŸ”č **Prescan** [Section titled “ đŸ”č Prescan”](#--prescan) ```bash npx @capgo/cli@latest build prescan ``` Scan your project and saved credentials for problems that would fail a cloud build — before uploading anything. Checks credentials (expiry, passwords, profile pairing), project state (cap sync, node\_modules layout), and platform config. Runs automatically inside `build request`; this command runs it standalone (e.g. in CI). See [Prescan checks](/docs/builder/prescan/) for the full check catalog and how to `--skip` / `--warn` individual rules. **Options:** | Param | Type | Description | | --------------------- | --------- | ---------------------------------------------------------------------------- | | **—platform** | `string` | Target platform: ios or android (required) | | **—path** | `string` | Path to the project directory (default: current directory) | | **-a** | `string` | API key to link to your account | | **—android-flavor** | `string` | Android: product flavor the build will use | | **—ios-dist** | `string` | iOS: distribution mode to validate against | | **—json** | `boolean` | Output a machine-readable JSON report | | **—fail-on-warnings** | `boolean` | Exit non-zero when warnings are found (CI) | | **—ignore-fatal** | `boolean` | Diagnostic mode: report everything but always exit 0 | | **—skip** | `string` | Skip specific check(s) by id (repeatable or comma-separated) | | **—warn** | `string` | Downgrade specific check(s) to warning by id (repeatable or comma-separated) | | **—verbose** | `boolean` | Enable verbose output with detailed logging | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ”č **Last-output** [Section titled “ đŸ”č Last-output”](#--last-output) ```bash npx @capgo/cli@latest build last-output ``` Read the build output record written by a previous `build request --output-record`. Prints the full JSON by default, a single field with —field, or the ASCII QR code with —qr. Useful in CI to grab the download URL or QR for posting back to a PR or issue. Examples: npx @capgo/cli build last-output —path /tmp/build.json npx @capgo/cli build last-output —path /tmp/build.json —field outputUrl npx @capgo/cli build last-output —path /tmp/build.json —qr **Options:** | Param | Type | Description | | ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------ | | **—path** | `string` | Path to the JSON record written by —output-record (required) | | **—field** | `string` | Print a single field (one of: jobId, appId, platform, buildMode, status, outputUrl, qrCodeAscii, qrCodePngPath, finishedAt, schemaVersion) | | **—qr** | `boolean` | Print the rendered ASCII QR code (shortcut for —field qrCodeAscii) | ### []()đŸ”č **Credentials** [Section titled “ đŸ”č Credentials”](#--credentials) Manage build credentials stored locally on your machine. 🔒 SECURITY: * Credentials saved to \~/.capgo-credentials/credentials.json (global) or .capgo-credentials.json (local) * When building, sent to Capgo but NEVER stored permanently * Deleted from Capgo immediately after build * Build outputs may optionally be uploaded for time-limited download links 📚 DOCUMENTATION: iOS setup: Android setup: #### []()đŸ”č **Apple-key** [Section titled “ đŸ”č Apple-key”](#--apple-key) **Alias:** `asc-key` ```bash npx @capgo/cli@latest build credentials apple-key ``` Create an App Store Connect team API key with a guided macOS helper (macOS only). Opens a native window that walks you through Apple’s App Store Connect UI in an embedded browser, auto-captures the Issuer ID + Key ID, intercepts the one-time .p8, validates it against Apple, and saves it to \~/.appstoreconnect/private\_keys. Progress statistics are forwarded to Capgo analytics (disable with CAPGO\_DISABLE\_TELEMETRY). npx @capgo/cli build credentials apple-key —appId com.example.app **Example:** ```bash Example: ``` **Options:** | Param | Type | Description | | ---------- | --------- | ---------------------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—appId** | `string` | Save the captured key into this app iOS build credentials | | **—local** | `boolean` | Save into the per-project .capgo-credentials.json instead of the global file | | **—json** | `boolean` | Print the captured Key ID / Issuer ID / .p8 path as JSON | #### []()đŸ”č **Save** [Section titled “ đŸ”č Save”](#--save) ```bash npx @capgo/cli@latest build credentials save ``` Save build credentials locally for iOS or Android. Credentials are stored in: * \~/.capgo-credentials/credentials.json (default, global) * .capgo-credentials.json in project root (with —local flag) ⚠ REQUIRED BEFORE BUILDING: You must save credentials before requesting a build. 🔒 These credentials are NEVER stored on Capgo servers permanently. They are deleted immediately after the build completes. 📚 Setup guides: iOS: Android: npx @capgo/cli build credentials save —platform ios\ —certificate ./cert.p12 —p12-password “password”\ —ios-provisioning-profile ./profile.mobileprovision\ —apple-key ./AuthKey.p8 —apple-key-id “KEY123”\ —apple-issuer-id “issuer-uuid” —apple-team-id “team-id” Multi-target Example (app + widget extension): npx @capgo/cli build credentials save —platform ios\ —ios-provisioning-profile ./App.mobileprovision\ —ios-provisioning-profile com.example.widget=./Widget.mobileprovision\ 
 npx @capgo/cli build credentials save —platform android\ —keystore ./release.keystore —keystore-alias “my-key”\ —keystore-key-password “key-pass”\ —play-config ./service-account.json Local storage (per-project): npx @capgo/cli build credentials save —local —platform ios 
 **Example:** ```bash iOS Example: ``` **Options:** | Param | Type | Description | | ----------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | **—appId** | `string` | App ID (e.g., com.example.app) (required) | | **—platform** | `string` | Platform: ios or android (required) | | **—certificate** | `string` | iOS: Path to .p12 certificate file | | **—ios-provisioning-profile** | `string` | iOS: Provisioning profile path or bundleId=path (repeatable) | | **—p12-password** | `string` | iOS: Certificate password (optional if cert has no password) | | **—apple-key** | `string` | iOS: Path to .p8 App Store Connect API key | | **—apple-key-id** | `string` | iOS: App Store Connect API Key ID | | **—apple-issuer-id** | `string` | iOS: App Store Connect Issuer ID | | **—apple-team-id** | `string` | iOS: App Store Connect Team ID | | **—ios-distribution** | `string` | iOS: Distribution mode | | **—apple-id** | `string` | iOS: Apple ID email for app-specific password uploads (alternative to App Store Connect API key) | | **—apple-app-specific-password** | `string` | iOS: App-specific password (xxxx-xxxx-xxxx-xxxx) for TestFlight uploads | | **—apple-app-id** | `string` | iOS: Numeric App Store Connect app id (required together with —apple-id and —apple-app-specific-password) | | **—keystore** | `string` | Android: Path to keystore file (.keystore or .jks) | | **—keystore-alias** | `string` | Android: Keystore key alias | | **—keystore-key-password** | `string` | Android: Keystore key password | | **—keystore-store-password** | `string` | Android: Keystore store password | | **—play-config** | `string` | Android: Path to Play Store service account JSON | | **—android-flavor** | `string` | Android: Product flavor to build (e.g. production). Required if your project has multiple flavors. | | **—in-app-update-priority** | `string` | Android: Google Play in-app update priority for future releases (integer 0–5; higher = more urgent). Omit to leave Play’s existing value untouched. | | **—local** | `boolean` | Save to .capgo-credentials.json in project root instead of global \~/.capgo-credentials/ | | **—output-upload** | `boolean` | Upload build outputs (IPA/APK/AAB) to Capgo storage and print download links | | **—no-output-upload** | `boolean` | Do not upload build outputs (IPA/APK/AAB) to Capgo storage | | **—output-retention** | `string` | Output link TTL: 1h to 7d (default: 1h). Examples: 1h, 6h, 2d | | **—skip-build-number-bump** | `boolean` | Skip automatic build number/version code incrementing on future builds | | **—no-skip-build-number-bump** | `boolean` | Re-enable automatic build number incrementing (default behavior) | | **—skip-marketing-version-bump** | `boolean` | Skip automatic marketing version bump on future builds when the app is already released | | **—no-skip-marketing-version-bump** | `boolean` | Re-enable automatic marketing version bump (default behavior) | #### []()📋 **List** [Section titled “ 📋 List”](#--list) ```bash npx @capgo/cli@latest build credentials list ``` List saved build credentials (passwords masked). Shows what credentials are currently saved (both global and local). Examples: npx @capgo/cli build credentials list # List all apps npx @capgo/cli build credentials list —appId com.example.app # List specific app **Options:** | Param | Type | Description | | ---------- | --------- | -------------------------------------------------------- | | **—appId** | `string` | App ID to list (optional, lists all if omitted) | | **—local** | `boolean` | List credentials from local .capgo-credentials.json only | #### []()đŸ”č **Clear** [Section titled “ đŸ”č Clear”](#--clear) ```bash npx @capgo/cli@latest build credentials clear ``` Clear saved build credentials. Remove credentials from storage. Use —appId and —platform to target specific credentials. Examples: npx @capgo/cli build credentials clear # Clear all apps (global) npx @capgo/cli build credentials clear —local # Clear local credentials npx @capgo/cli build credentials clear —appId com.example.app —platform ios **Options:** | Param | Type | Description | | ------------- | --------- | ----------------------------------------------------------------------------- | | **—appId** | `string` | App ID to clear (optional, clears all apps if omitted) | | **—platform** | `string` | Platform to clear: ios or android (optional, clears all platforms if omitted) | | **—local** | `boolean` | Clear from local .capgo-credentials.json instead of global | #### []()đŸ”č **Update** [Section titled “ đŸ”č Update”](#--update) ```bash npx @capgo/cli@latest build credentials update ``` Update specific credentials without providing all of them again. Update existing credentials by providing only the fields you want to change. Platform is auto-detected from the options you provide. Examples: npx @capgo/cli build credentials update —ios-provisioning-profile ./new-profile.mobileprovision npx @capgo/cli build credentials update —local —keystore ./new-keystore.jks **Options:** | Param | Type | Description | | ----------------------------------- | --------- | --------------------------------------------------------------------------------------------------------- | | **—appId** | `string` | App ID (auto-detected from capacitor.config if omitted) | | **—platform** | `string` | Platform: ios or android (auto-detected from options) | | **—local** | `boolean` | Update local .capgo-credentials.json instead of global | | **—certificate** | `string` | Path to P12 certificate file | | **—ios-provisioning-profile** | `string` | Provisioning profile path or bundleId=path (repeatable, additive by default) | | **—overwrite-ios-provisioning-map** | `boolean` | Replace the entire provisioning map instead of merging (default: merge) | | **—p12-password** | `string` | P12 certificate password | | **—apple-key** | `string` | Path to App Store Connect API key (.p8 file) | | **—apple-key-id** | `string` | App Store Connect API Key ID | | **—apple-issuer-id** | `string` | App Store Connect Issuer ID | | **—apple-team-id** | `string` | App Store Connect Team ID | | **—apple-id** | `string` | iOS: Apple ID email for app-specific password uploads (alternative to App Store Connect API key) | | **—apple-app-specific-password** | `string` | iOS: App-specific password (xxxx-xxxx-xxxx-xxxx) for TestFlight uploads | | **—apple-app-id** | `string` | iOS: Numeric App Store Connect app id (required together with —apple-id and —apple-app-specific-password) | | **—ios-distribution** | `string` | iOS: Distribution mode | | **—keystore** | `string` | Path to keystore file (.keystore or .jks) | | **—keystore-alias** | `string` | Keystore key alias | | **—keystore-key-password** | `string` | Keystore key password | | **—keystore-store-password** | `string` | Keystore store password | | **—play-config** | `string` | Path to Google Play service account JSON | | **—android-flavor** | `string` | Android: Product flavor to build (e.g. production). Required if your project has multiple flavors. | | **—in-app-update-priority** | `string` | Android: Google Play in-app update priority for future releases (integer 0–5; higher = more urgent). | | **—output-upload** | `boolean` | Upload build outputs (IPA/APK/AAB) to Capgo storage and print download links | | **—no-output-upload** | `boolean` | Do not upload build outputs (IPA/APK/AAB) to Capgo storage | | **—output-retention** | `string` | Output link TTL: 1h to 7d. Examples: 1h, 6h, 2d | | **—skip-build-number-bump** | `boolean` | Skip automatic build number/version code incrementing on future builds | | **—no-skip-build-number-bump** | `boolean` | Re-enable automatic build number incrementing (default behavior) | | **—skip-marketing-version-bump** | `boolean` | Skip automatic marketing version bump on future builds when the app is already released | | **—no-skip-marketing-version-bump** | `boolean` | Re-enable automatic marketing version bump (default behavior) | #### []()đŸ”č **Manage** [Section titled “ đŸ”č Manage”](#--manage) ```bash npx @capgo/cli@latest build credentials manage ``` Interactively manage saved build credentials. Browse stored credentials, view what’s configured, export a CI/CD-ready .env file, or delete a platform’s credentials. Reuses the same TUI as `capgo init`. Examples: npx @capgo/cli build credentials manage npx @capgo/cli build credentials manage —appId com.example.app npx @capgo/cli build credentials manage —appId com.example.app —platform ios npx @capgo/cli build credentials manage —local **Options:** | Param | Type | Description | | ------------- | --------- | ------------------------------------------------------------------------- | | **—appId** | `string` | App ID to manage (optional, prompts to pick if omitted) | | **—platform** | `string` | Platform to manage: ios or android (optional, prompts to pick if omitted) | | **—local** | `boolean` | Only browse local .capgo-credentials.json | #### []()đŸ”č **Migrate** [Section titled “ đŸ”č Migrate”](#--migrate) ```bash npx @capgo/cli@latest build credentials migrate ``` Migrate legacy provisioning profile to the new multi-target format. Converts BUILD\_PROVISION\_PROFILE\_BASE64 to CAPGO\_IOS\_PROVISIONING\_MAP. Discovers the main bundle ID from your Xcode project automatically. npx @capgo/cli build credentials migrate —platform ios **Example:** ```bash Example: ``` **Options:** | Param | Type | Description | | ------------- | --------- | ------------------------------------------------------------ | | **—appId** | `string` | App ID (auto-detected from capacitor.config if omitted) | | **—platform** | `string` | Platform (only ios is supported) | | **—local** | `boolean` | Migrate from local .capgo-credentials.json instead of global | # 📩 bundle > 📩 Manage app bundles for deployment in Capgo Cloud, including upload, compatibility checks, and encryption. 📩 Manage app bundles for deployment in Capgo Cloud, including upload, compatibility checks, and encryption. ### []()âŹ†ïž **Upload** [Section titled “ âŹ†ïž Upload”](#--upload) **Alias:** `u` ```bash npx @capgo/cli@latest bundle upload ``` âŹ†ïž Upload a new app bundle to Capgo Cloud for distribution. Version must be > 0.0.0 and unique. Deleted versions cannot be reused for security. External option: Store only a URL link (useful for apps >200MB or privacy requirements). Capgo never inspects external content. Add encryption for trustless security. **Example:** ```bash npx @capgo/cli@latest bundle upload com.example.app --path ./dist --channel production,beta ``` Auto-bump the next free semver from the channel (or latest remote app version) when you do not pass `--bundle`. Useful in CI when `package.json` already matches a version Capgo has: ```bash npx @capgo/cli@latest bundle upload --channel=production --auto-bump npx @capgo/cli@latest bundle upload --auto-bump major npx @capgo/cli@latest bundle upload --auto-bump minor # default when the flag has no value npx @capgo/cli@latest bundle upload --auto-bump patch # alias: fix npx @capgo/cli@latest bundle upload --auto-bump metadata npx @capgo/cli@latest bundle upload --channel=production --auto-bump ai ``` With `--auto-bump ai`, Capgo Cloudflare Workers AI compares local bundle files to the previous Capgo/channel delta manifest, infers `major` | `minor` | `patch` | `metadata`, and prints a short reason in the CLI log. If no previous Capgo version exists, AI is skipped and the bump defaults to **patch**. **Options:** | Param | Type | Description | | ----------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **-p** | `string` | Path of the folder to upload, if not provided it will use the webDir set in capacitor.config | | **-c** | `string` | Channel to link to. Use commas for multiple channels, for example production,beta | | **—rollout** | `string` | Set the uploaded bundle as this channel’s rollout target at a percentage from 0 to 100 | | **—rollout-percentage-bps** | `string` | Set the uploaded bundle rollout percentage in basis points from 0 to 10000 | | **—rollout-cache-ttl-seconds** | `string` | Cloudflare rollout decision cache TTL in seconds | | **-e** | `string` | Link to external URL instead of upload to Capgo Cloud | | **—iv-session-key** | `string` | Set the IV and session key for bundle URL external | | **—s3-region** | `string` | Region for your S3 bucket | | **—s3-apikey** | `string` | API key for your S3 endpoint | | **—s3-apisecret** | `string` | API secret for your S3 endpoint | | **—s3-endpoint** | `string` | URL of S3 endpoint | | **—s3-bucket-name** | `string` | Name for your AWS S3 bucket | | **—s3-port** | `string` | Port for your S3 endpoint | | **—no-s3-ssl** | `boolean` | Disable SSL for S3 upload | | **—key-v2** | `string` | Custom path for private signing key (v2 system) | | **—key-data-v2** | `string` | Private signing key (v2 system) | | **—bundle-url** | `boolean` | Prints bundle URL into stdout | | **—no-key** | `boolean` | Ignore signing key and send clear update | | **—no-code-check** | `boolean` | Ignore checking if notifyAppReady() is called in source code and index present in root folder | | **—display-iv-session** | `boolean` | Show in the console the IV and session key used to encrypt the update | | **-b** | `string` | Bundle version number of the bundle to upload | | **—auto-bump** | `string` | Auto-increment from the channel’s linked bundle, else the latest remote app version. Level: major, minor (default), patch (alias fix), metadata, or ai (Workers AI infers level from local vs previous delta manifest; falls back to patch with no previous Capgo version). Bumps until a free name is found (deleted names stay occupied). Cannot be combined with —bundle (-b) | | **—link** | `string` | Link to external resource (e.g. GitHub release) | | **—comment** | `string` | Comment about this version, could be a release note, a commit hash, a commit message, etc. | | **—min-update-version** | `string` | Minimal version required to update to this version. Used only if the disable auto update is set to metadata in channel | | **—auto-min-update-version** | `boolean` | Set the min update version based on native packages | | **—ignore-metadata-check** | `boolean` | Ignores the metadata (node\_modules) check when uploading | | **—fail-on-incompatible** | `boolean` | Fail the upload (exit non-zero) instead of uploading when the bundle is incompatible with the channel’s current native packages. In an interactive terminal you can still choose a native build; declining fails. Cannot be combined with —ignore-metadata-check. | | **—ignore-checksum-check** | `boolean` | Ignores the checksum check when uploading | | **—force-crc32-checksum** | `boolean` | Force CRC32 checksum for upload (override auto-detection) | | **—timeout** | `string` | Timeout for the upload process in seconds | | **—multipart** | `boolean` | \[DEPRECATED] Use —tus instead. Uses multipart protocol for S3 uploads | | **—zip** | `boolean` | Upload the bundle using zip to Capgo cloud (legacy) | | **—tus** | `boolean` | Upload the bundle using TUS to Capgo cloud | | **—tus-chunk-size** | `string` | Chunk size in bytes for TUS resumable uploads (default: auto) | | **—partial** | `boolean` | \[DEPRECATED] Use —delta instead. Upload incremental updates | | **—partial-only** | `boolean` | \[DEPRECATED] Use —delta-only instead. Upload only incremental updates, skip full bundle | | **—delta** | `boolean` | Upload delta updates (only changed files) for instant, super-fast updates instead of big zip downloads | | **—delta-only** | `boolean` | Upload only delta updates without full bundle for maximum speed (useful for large apps) | | **—no-delta** | `boolean` | Disable delta updates even if instant updates are enabled | | **—encrypted-checksum** | `string` | An encrypted checksum (signature). Used only when uploading an external bundle. | | **—auto-set-bundle** | `boolean` | Set the bundle in capacitor.config.json | | **—dry-upload** | `boolean` | Dry upload the bundle process: add the row in database without uploading files or updating channels (Used by Capgo for internal testing) | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | | **—node-modules** | `string` | Paths to node\_modules directories for monorepos (comma-separated) | | **—encrypt-partial** | `boolean` | Encrypt delta update files (auto-enabled for updater > 6.14.4) | | **—delete-linked-bundle-on-upload** | `boolean` | Locates the currently linked bundle in the channel you are trying to upload to, and deletes it | | **—no-brotli-patterns** | `string` | Files to exclude from Brotli compression (comma-separated globs, e.g., “*.jpg,*.png”) | | **—disable-brotli** | `boolean` | Completely disable brotli compression even if updater version supports it | | **—version-exists-ok** | `boolean` | Exit successfully if bundle version already exists, useful for CI/CD workflows with monorepos | | **—self-assign** | `boolean` | Allow devices to auto-join this channel (updates channel setting) | | **—qr-preview** | `boolean` | Print a terminal QR code for this bundle preview after upload | | **—send-update-notification** | `boolean` | Send a native update-check notification to devices after updating linked channel bundles | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | | **—verbose** | `boolean` | Enable verbose output with detailed logging | ### []()đŸ§Ș **Compatibility** [Section titled “ đŸ§Ș Compatibility”](#--compatibility) ```bash npx @capgo/cli@latest bundle compatibility ``` đŸ§Ș Check compatibility of a bundle with a specific channel in Capgo Cloud to ensure updates are safe. **Example:** ```bash npx @capgo/cli@latest bundle compatibility com.example.app --channel production ``` **Options:** | Param | Type | Description | | ----------------- | --------- | ------------------------------------------------------------------ | | **-a** | `string` | API key to link to your account | | **-c** | `string` | Channel to check the compatibility with | | **—text** | `boolean` | Output text instead of emojis | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | | **—node-modules** | `string` | Paths to node\_modules directories for monorepos (comma-separated) | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ”č **ReleaseType** [Section titled “ đŸ”č ReleaseType”](#--releasetype) ```bash npx @capgo/cli@latest bundle releaseType ``` 🧭 Print “native” or “OTA” based on compatibility with a channel’s latest metadata. **Example:** ```bash npx @capgo/cli@latest bundle releaseType com.example.app --channel production ``` **Options:** | Param | Type | Description | | ----------------- | -------- | ------------------------------------------------------------------ | | **-a** | `string` | API key to link to your account | | **-c** | `string` | Channel to compare against | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | | **—node-modules** | `string` | Paths to node\_modules directories for monorepos (comma-separated) | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ—‘ïž **Delete** [Section titled “ đŸ—‘ïž Delete”](#--delete) **Alias:** `d` ```bash npx @capgo/cli@latest bundle delete ``` đŸ—‘ïž Delete a specific bundle from Capgo Cloud, optionally targeting a single version. **Example:** ```bash npx @capgo/cli@latest bundle delete BUNDLE_ID com.example.app ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()📋 **List** [Section titled “ 📋 List”](#--list) **Alias:** `l` ```bash npx @capgo/cli@latest bundle list ``` 📋 List all bundles uploaded for an app in Capgo Cloud. **Example:** ```bash npx @capgo/cli@latest bundle list com.example.app ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ§č **Cleanup** [Section titled “ đŸ§č Cleanup”](#--cleanup) **Alias:** `c` ```bash npx @capgo/cli@latest bundle cleanup ``` đŸ§č Delete old bundles in Capgo Cloud, keeping specified number of recent versions. Bundles linked to channels are preserved unless —ignore-channel is used. **Example:** ```bash npx @capgo/cli@latest bundle cleanup com.example.app --bundle=1.0 --keep=3 ``` **Options:** | Param | Type | Description | | ------------------- | --------- | ------------------------------------------------------------------------- | | **-b** | `string` | Bundle version number of the app to delete | | **-a** | `string` | API key to link to your account | | **-k** | `string` | Number of versions to keep | | **-f** | `boolean` | Force removal | | **—ignore-channel** | `boolean` | Delete bundles even if linked to channels (WARNING: deletes channels too) | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()🔒 **Encrypt** [Section titled “ 🔒 Encrypt”](#--encrypt) ```bash npx @capgo/cli@latest bundle encrypt ``` 🔒 Encrypt a zip bundle for secure external storage. Returns ivSessionKey for upload/decryption. Get checksum using ‘bundle zip —json’. **Example:** ```bash npx @capgo/cli@latest bundle encrypt ./myapp.zip CHECKSUM ``` **Options:** | Param | Type | Description | | ----------------- | --------- | ----------------------------------------------------------- | | **—key** | `string` | Custom path for private signing key | | **—key-data** | `string` | Private signing key | | **-j** | `boolean` | Output in JSON | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | ### []()🔓 **Decrypt** [Section titled “ 🔓 Decrypt”](#--decrypt) ```bash npx @capgo/cli@latest bundle decrypt ``` 🔓 Decrypt an encrypted bundle (mainly for testing). Prints base64 session key for verification. **Example:** ```bash npx @capgo/cli@latest bundle decrypt ./myapp_encrypted.zip CHECKSUM ``` **Options:** | Param | Type | Description | | ----------------- | -------- | ------------------------------------------------------------- | | **—key** | `string` | Custom path for private signing key | | **—key-data** | `string` | Private signing key | | **—checksum** | `string` | Checksum of the bundle, to verify the integrity of the bundle | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | ### []()đŸ”č **Zip** [Section titled “ đŸ”č Zip”](#--zip) ```bash npx @capgo/cli@latest bundle zip ``` đŸ—œïž Create a zip file of your app bundle. Returns checksum for use with encryption. Use —json for machine-readable output. **Example:** ```bash npx @capgo/cli@latest bundle zip com.example.app --path ./dist ``` **Options:** | Param | Type | Description | | ------------------ | --------- | --------------------------------------------------------------------------------------------- | | **-p** | `string` | Path of the folder to upload, if not provided it will use the webDir set in capacitor.config | | **-b** | `string` | Bundle version number to name the zip file | | **-n** | `string` | Name of the zip file | | **-j** | `boolean` | Output in JSON | | **—no-code-check** | `boolean` | Ignore checking if notifyAppReady() is called in source code and index present in root folder | | **—key-v2** | `boolean` | Use encryption v2 | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | # 📱 channel > 📱 Manage distribution channels for app updates in Capgo Cloud, controlling how updates are delivered to devices. 📱 Manage distribution channels for app updates in Capgo Cloud, controlling how updates are delivered to devices. ### []()➕ **Add** [Section titled “ ➕ Add”](#--add) **Alias:** `a` ```bash npx @capgo/cli@latest channel add ``` ➕ Create a new channel for app distribution in Capgo Cloud to manage update delivery. **Example:** ```bash npx @capgo/cli@latest channel add production com.example.app --default ``` **Options:** | Param | Type | Description | | ---------------- | --------- | ---------------------------------------------------------------- | | **-d** | `boolean` | Set the channel as default | | **—self-assign** | `boolean` | Allow device to self-assign to this channel | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ—‘ïž **Delete** [Section titled “ đŸ—‘ïž Delete”](#--delete) **Alias:** `d` ```bash npx @capgo/cli@latest channel delete ``` đŸ—‘ïž Delete a channel from Capgo Cloud, optionally removing associated bundles to free up resources. **Example:** ```bash npx @capgo/cli@latest channel delete production com.example.app ``` **Options:** | Param | Type | Description | | ------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—delete-bundle** | `boolean` | Delete the bundle associated with the channel. An App Preview key can atomically delete only its own preview channel and linked, unshared bundle. | | **—success-if-not-found** | `boolean` | Success if the channel is not found | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | Caution Use an organization- and app-bound **App Preview** API key with `--delete-bundle` only for a non-public PR preview channel. The command uses a narrow atomic cleanup route: it succeeds only for the channel and linked, unshared bundle that key created. The key cannot use it on an existing default/main channel, another preview key’s channel, or another key’s bundle, and it still does not receive general `bundle.delete`. See [API Keys](/docs/webapp/api-keys/#use-an-app-preview-key-for-preview-workflows) for setup. ### []()📋 **List** [Section titled “ 📋 List”](#--list) **Alias:** `l` ```bash npx @capgo/cli@latest channel list ``` 📋 List all channels configured for an app in Capgo Cloud to review distribution settings. **Example:** ```bash npx @capgo/cli@latest channel list com.example.app ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()📩 **CurrentBundle** [Section titled “ 📩 CurrentBundle”](#--currentbundle) ```bash npx @capgo/cli@latest channel currentBundle ``` 📩 Get the current bundle linked to a specific channel in Capgo Cloud for update tracking. **Example:** ```bash npx @capgo/cli@latest channel currentBundle production com.example.app ``` **Options:** | Param | Type | Description | | -------------- | --------- | ---------------------------------------------------------------- | | **-c** | `string` | Channel to get the current bundle from | | **-a** | `string` | API key to link to your account | | **—quiet** | `boolean` | Only print the bundle version | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()⚙ **Set** [Section titled “ ⚙ Set”](#--set) **Alias:** `s` ```bash npx @capgo/cli@latest channel set ``` ⚙ Configure settings for a channel, such as linking a bundle, setting update strategies (major, minor, metadata, patch, none), or device targeting (iOS, Android, dev, prod, emulator, device). One channel must be default. **Example:** ```bash npx @capgo/cli@latest channel set production com.example.app --bundle 1.0.0 --state default ``` **Options:** | Param | Type | Description | | -------------------------------- | --------- | ------------------------------------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **-b** | `string` | Bundle version number of the file to set | | **-s** | `string` | Set the state of the channel, default or normal | | **—latest-remote** | `boolean` | Get the latest bundle uploaded in capgo cloud and set it to the channel | | **—latest** | `boolean` | Get the latest version key in the package.json to set it to the channel | | **—downgrade** | `boolean` | Allow to downgrade to version under native one | | **—no-downgrade** | `boolean` | Disable downgrade to version under native one | | **—ios** | `boolean` | Allow sending update to iOS devices | | **—no-ios** | `boolean` | Disable sending update to iOS devices | | **—android** | `boolean` | Allow sending update to Android devices | | **—no-android** | `boolean` | Disable sending update to Android devices | | **—self-assign** | `boolean` | Allow device to self-assign to this channel | | **—no-self-assign** | `boolean` | Disable devices to self-assign to this channel | | **—disable-auto-update** | `string` | Block updates by type: major, minor, metadata, patch, or none (allows all) | | **—rollout-bundle** | `string` | Bundle version to release gradually on this channel | | **—rollout-percentage** | `string` | Rollout percentage from 0 to 100 | | **—rollout-percentage-bps** | `string` | Rollout percentage in basis points from 0 to 10000 | | **—rollout-enable** | `boolean` | Enable the configured rollout | | **—rollout-disable** | `boolean` | Disable the configured rollout | | **—rollout-pause** | `boolean` | Pause rollout exposure without rolling back selected devices | | **—rollout-resume** | `boolean` | Resume a paused rollout | | **—rollout-rollback** | `boolean` | Clear rollout state and return devices to stable | | **—rollout-promote** | `boolean` | Promote rollout target to stable and clear rollout state | | **—rollout-cache-ttl-seconds** | `string` | Cloudflare rollout decision cache TTL in seconds | | **—auto-pause-enabled** | `boolean` | Enable rollout auto-pause policy | | **—auto-pause-disabled** | `boolean` | Disable rollout auto-pause policy | | **—auto-pause-window-minutes** | `string` | Stats window for rollout auto-pause | | **—auto-pause-failure-rate-bps** | `string` | Failure-rate threshold in basis points | | **—auto-pause-confidence** | `string` | Confidence level between 0 and 1 | | **—auto-pause-min-attempts** | `string` | Minimum install plus fail attempts before auto-pause can trigger | | **—auto-pause-min-failures** | `string` | Minimum failures before auto-pause can trigger | | **—auto-pause-action** | `string` | Auto-pause action: pause, rollback, or notify | | **—auto-pause-cooldown-minutes** | `string` | Cooldown before auto-pause can trigger again | | **—dev** | `boolean` | Allow sending update to development devices | | **—no-dev** | `boolean` | Disable sending update to development devices | | **—prod** | `boolean` | Allow sending update to production devices | | **—no-prod** | `boolean` | Disable sending update to production devices | | **—emulator** | `boolean` | Allow sending update to emulator devices | | **—no-emulator** | `boolean` | Disable sending update to emulator devices | | **—device** | `boolean` | Allow sending update to physical devices | | **—no-device** | `boolean` | Disable sending update to physical devices | | **—qr-preview** | `boolean` | Print a terminal QR code for this channel preview after updating it | | **—send-update-notification** | `boolean` | Send a native update-check notification to devices after updating the linked channel bundle | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | | **—ignore-metadata-check** | `boolean` | Ignore checking node\_modules compatibility if present in the bundle | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | # đŸ‘šâ€âš•ïž doctor > đŸ‘šâ€âš•ïž Check if your Capgo app installation is up-to-date and gather information useful for bug reports. đŸ‘šâ€âš•ïž Check if your Capgo app installation is up-to-date and gather information useful for bug reports. ```bash npx @capgo/cli@latest doctor ``` This command helps diagnose issues with your setup. **Example:** ```bash npx @capgo/cli@latest doctor ``` ## []()Options [Section titled “ Options”](#-options) | Param | Type | Description | | ----------------- | -------- | ----------------------------------------------------------- | | **—package-json** | `string` | Paths to package.json files for monorepos (comma-separated) | ## Keep going from doctor [Section titled “Keep going from doctor”](#keep-going-from-doctor) If you are using **doctor** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # đŸ”č get-qr > 🔳 Print a terminal QR code for a bundle or channel preview. 🔳 Print a terminal QR code for a bundle or channel preview. ```bash npx @capgo/cli@latest get-qr ``` Preview must be enabled for the app. Examples: npx @capgo/cli\@latest get-qr com.example.app —bundle 1.2.3 npx @capgo/cli\@latest get-qr com.example.app —bundle 123 npx @capgo/cli\@latest get-qr com.example.app —channel production npx @capgo/cli\@latest get-qr com.example.app production —type channel ## []()Options (Get-qr) [Section titled “ Options (Get-qr)”](#-options-get-qr) | Param | Type | Description | | ---------------- | --------- | ----------------------------------------------------------------------------------- | | **-a** | `string` | API key to link to your account | | **—bundle** | `string` | Bundle name or id to preview | | **—channel** | `string` | Channel name or id to preview | | **—type** | `string` | Type for positional target | | **—png** | `string` | Write the preview QR code as a PNG image to the given file path | | **—url** | `boolean` | Print preview URLs only (web and deep link), without a terminal QR code | | **—web-url** | `boolean` | Encode the web preview URL in the QR code and PNG instead of the capgo:// deep link | | **—preview-env** | `string` | Preview web URL environment | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | # 🚀 init > 🚀 Initialize a new app in Capgo Cloud with step-by-step guidance. 🚀 Initialize a new app in Capgo Cloud with step-by-step guidance. **Alias:** `i` ```bash npx @capgo/cli@latest init ``` This includes adding code for updates, building, uploading your app, and verifying update functionality. Capgo bundles are web assets and can be fetched by anyone who knows the URL. Use encryption for banking, regulated, or other high-security apps. **Example:** ```bash npx @capgo/cli@latest init YOUR_API_KEY com.example.app ``` ## []()Options [Section titled “ Options”](#-options) | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-n,** | `string` | App name for display in Capgo Cloud | | **-i,** | `string` | App icon path for display in Capgo Cloud | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ## Keep going from init [Section titled “Keep going from init”](#keep-going-from-init) If you are using **init** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # 🔐 key > 🔐 Manage encryption keys for secure bundle distribution in Capgo Cloud, supporting end-to-end encryption with RSA and AES combination. 🔐 Manage encryption keys for secure bundle distribution in Capgo Cloud, supporting end-to-end encryption with RSA and AES combination. ### []()đŸ”č **Save** [Section titled “ đŸ”č Save”](#--save) ```bash npx @capgo/cli@latest key save ``` đŸ’Ÿ Save the public key in the Capacitor config, useful for CI environments. Recommended not to commit the key for security. **Example:** ```bash npx @capgo/cli@latest key save --key ./path/to/key.pub ``` **Options:** | Param | Type | Description | | ------------- | -------- | ------------------------------------ | | **-f,** | `string` | Force generate a new one | | **—key** | `string` | Key path to save in Capacitor config | | **—key-data** | `string` | Key data to save in Capacitor config | ### []()🔹 **Create** [Section titled “ 🔹 Create”](#--create) ```bash npx @capgo/cli@latest key create ``` 🔹 Create RSA key pair for end-to-end encryption. Creates .capgo\_key\_v2 (private) and .capgo\_key\_v2.pub (public) in project root. Public key is saved to capacitor.config for mobile app decryption. NEVER commit the private key - store it securely! **Example:** ```bash npx @capgo/cli@latest key create ``` **Options:** | Param | Type | Description | | ------- | -------- | ------------------------ | | **-f,** | `string` | Force generate a new one | ### []()đŸ—‘ïž **Delete\_old** [Section titled “ đŸ—‘ïž Delete\_old”](#--delete_old) ```bash npx @capgo/cli@latest key delete_old ``` đŸ§č Delete the old encryption key from the Capacitor config to ensure only the current key is used. **Example:** ```bash npx @capgo/cli@latest key delete_old ``` ## Keep going from key [Section titled “Keep going from key”](#keep-going-from-key) If you are using **key** to plan security and compliance, connect it with [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, [Capgo Security](/security/) for the product workflow in Capgo Security, and [Capgo Trust Center](/trust/) for the product workflow in Capgo Trust Center. # 🔑 login > 🔑 Save your Capgo API key to your machine or local folder for easier access to Capgo Cloud services. 🔑 Save your Capgo API key to your machine or local folder for easier access to Capgo Cloud services. **Alias:** `l` ```bash npx @capgo/cli@latest login ``` Use —apikey=\*\*\*\*\*\*\*\* in any command to override it. **Example:** ```bash npx @capgo/cli@latest login YOUR_API_KEY ``` ## []()Options [Section titled “ Options”](#-options) | Param | Type | Description | | -------------- | --------- | ---------------------------------------------------------------- | | **—local** | `boolean` | Only save in local folder, git ignored for security. | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ## Keep going from login [Section titled “Keep going from login”](#keep-going-from-login) If you are using **login** to plan security and compliance, connect it with [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, [Capgo Security](/security/) for the product workflow in Capgo Security, and [Capgo Trust Center](/trust/) for the product workflow in Capgo Trust Center. # đŸ”č mcp > đŸ€– Start the Capgo MCP (Model Context Protocol) server for AI agent integration. đŸ€– Start the Capgo MCP (Model Context Protocol) server for AI agent integration. ```bash npx @capgo/cli@latest mcp ``` This command starts an MCP server that exposes Capgo functionality as tools for AI agents. The server communicates via stdio and is designed for non-interactive, programmatic use. Available tools include: * `capgo_list_apps`, `capgo_add_app`, `capgo_update_app`, `capgo_delete_app` * `capgo_upload_bundle`, `capgo_list_bundles`, `capgo_delete_bundle`, `capgo_cleanup_bundles` * `capgo_list_channels`, `capgo_add_channel`, `capgo_update_channel`, `capgo_delete_channel` * `capgo_get_current_bundle`, `capgo_check_compatibility` * `capgo_list_organizations`, `capgo_add_organization` * `capgo_star_repository`, `capgo_star_all_repositories` * `capgo_get_account_id`, `capgo_doctor`, `capgo_get_stats` * `capgo_request_build`, `capgo_generate_encryption_keys` ## Example configuration [Section titled “Example configuration”](#example-configuration) Add the following configuration to `claude_desktop_config.json`: ```json { "mcpServers": { "capgo": { "command": "npx", "args": ["@capgo/cli", "mcp"] } } } ``` **Example:** ```bash npx @capgo/cli mcp ``` # đŸ”č notifications > 🔔 Set up Capgo native notifications in your Capacitor app. 🔔 Set up Capgo native notifications in your Capacitor app. ### []()⚙ **Setup** [Section titled “ ⚙ Setup”](#--setup) ```bash npx @capgo/cli@latest notifications setup ``` Install the Capgo notifications plugin, add Capacitor config, create a helper file, and run Capacitor sync. Before sending production notifications, configure Android and iOS push credentials in the Capgo app Notifications tab. **Example:** ```bash npx @capgo/cli@latest notifications setup com.example.app ``` **Options:** | Param | Type | Description | | --------------- | --------- | ----------------------------------------------------------- | | **—server-url** | `string` | Capgo API server URL | | **—file** | `string` | Helper file to create (default: src/capgo-notifications.ts) | | **—force** | `boolean` | Overwrite the helper file if it already exists | | **—no-install** | `boolean` | Skip installing the notifications package | | **—no-sync** | `boolean` | Skip Capacitor sync | # đŸ”č organisation > [DEPRECATED] Use "organization" instead. This command will be removed in a future version. \[DEPRECATED] Use “organization” instead. This command will be removed in a future version. ### []()📋 **List** [Section titled “ 📋 List”](#--list) **Alias:** `l` ```bash npx @capgo/cli@latest organisation list ``` \[DEPRECATED] Use “organization list” instead. **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()➕ **Add** [Section titled “ ➕ Add”](#--add) **Alias:** `a` ```bash npx @capgo/cli@latest organisation add ``` \[DEPRECATED] Use “organization add” instead. **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-n,** | `string` | Organization name | | **-e,** | `string` | Management email for the organization | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()⚙ **Set** [Section titled “ ⚙ Set”](#--set) **Alias:** `s` ```bash npx @capgo/cli@latest organisation set ``` \[DEPRECATED] Use “organization set” instead. **Options:** | Param | Type | Description | | --------------------------------- | --------- | -------------------------------------------------------------------------- | | **-n,** | `string` | Organization name | | **-e,** | `string` | Management email for the organization | | **—enforce-2fa** | `boolean` | Enable 2FA enforcement for all organization members | | **—no-enforce-2fa** | `boolean` | Disable 2FA enforcement for organization | | **—password-policy** | `boolean` | Enable password policy enforcement for organization | | **—no-password-policy** | `boolean` | Disable password policy enforcement | | **—min-length** | `string` | Minimum password length (6-128, default: 10) | | **—require-uppercase** | `boolean` | Require uppercase letter in password | | **—no-require-uppercase** | `boolean` | Do not require uppercase letter | | **—require-number** | `boolean` | Require number in password | | **—no-require-number** | `boolean` | Do not require number | | **—require-special** | `boolean` | Require special character in password | | **—no-require-special** | `boolean` | Do not require special character | | **—require-apikey-expiration** | `boolean` | Require all API keys to have an expiration date | | **—no-require-apikey-expiration** | `boolean` | Do not require API key expiration | | **—max-apikey-expiration-days** | `string` | Maximum days before API key expiration (1-365, null for no limit) | | **—enforce-hashed-api-keys** | `boolean` | Enforce hashed/secure API keys (key value stored as hash, shown only once) | | **—no-enforce-hashed-api-keys** | `boolean` | Allow plain-text API keys | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ—‘ïž **Delete** [Section titled “ đŸ—‘ïž Delete”](#--delete) **Alias:** `d` ```bash npx @capgo/cli@latest organisation delete ``` \[DEPRECATED] Use “organization delete” instead. **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ## Keep going from organisation [Section titled “Keep going from organisation”](#keep-going-from-organisation) If you are using **organisation** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # đŸ”č organization > 🏱 Manage your organizations in Capgo Cloud for team collaboration and app management. 🏱 Manage your organizations in Capgo Cloud for team collaboration and app management. ### []()📋 **List** [Section titled “ 📋 List”](#--list) **Alias:** `l` ```bash npx @capgo/cli@latest organization list ``` 📋 List all organizations you have access to in Capgo Cloud. **Example:** ```bash npx @capgo/cli@latest organization list ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()➕ **Add** [Section titled “ ➕ Add”](#--add) **Alias:** `a` ```bash npx @capgo/cli@latest organization add ``` ➕ Create a new organization in Capgo Cloud for team collaboration. **Example:** ```bash npx @capgo/cli@latest organization add --name "My Company" --email admin@mycompany.com ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-n,** | `string` | Organization name | | **-e,** | `string` | Management email for the organization | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ”č **Members** [Section titled “ đŸ”č Members”](#--members) **Alias:** `m` ```bash npx @capgo/cli@latest organization members ``` đŸ‘„ List organization members and their 2FA status. Shows all members of an organization with their roles and whether they have 2FA enabled. Useful before enabling 2FA enforcement to see which members will be affected. > â„č Viewing 2FA status requires super\_admin rights in the organization. **Example:** ```bash npx @capgo/cli@latest organization members ORG_ID ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()⚙ **Set** [Section titled “ ⚙ Set”](#--set) **Alias:** `s` ```bash npx @capgo/cli@latest organization set ``` ⚙ Update organization settings including name, email, security policies, and enforcement options. Security settings require super\_admin role. **Example:** ```bash npx @capgo/cli@latest organization set ORG_ID --name "New Name" ``` **Options:** | Param | Type | Description | | --------------------------------- | --------- | -------------------------------------------------------------------------- | | **-n,** | `string` | Organization name | | **-e,** | `string` | Management email for the organization | | **—enforce-2fa** | `boolean` | Enable 2FA enforcement for all organization members | | **—no-enforce-2fa** | `boolean` | Disable 2FA enforcement for organization | | **—password-policy** | `boolean` | Enable password policy enforcement for organization | | **—no-password-policy** | `boolean` | Disable password policy enforcement | | **—min-length** | `string` | Minimum password length (6-128, default: 10) | | **—require-uppercase** | `boolean` | Require uppercase letter in password | | **—no-require-uppercase** | `boolean` | Do not require uppercase letter | | **—require-number** | `boolean` | Require number in password | | **—no-require-number** | `boolean` | Do not require number | | **—require-special** | `boolean` | Require special character in password | | **—no-require-special** | `boolean` | Do not require special character | | **—require-apikey-expiration** | `boolean` | Require all API keys to have an expiration date | | **—no-require-apikey-expiration** | `boolean` | Do not require API key expiration | | **—max-apikey-expiration-days** | `string` | Maximum days before API key expiration (1-365, null for no limit) | | **—enforce-hashed-api-keys** | `boolean` | Enforce hashed/secure API keys (key value stored as hash, shown only once) | | **—no-enforce-hashed-api-keys** | `boolean` | Allow plain-text API keys | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ### []()đŸ—‘ïž **Delete** [Section titled “ đŸ—‘ïž Delete”](#--delete) **Alias:** `d` ```bash npx @capgo/cli@latest organization delete ``` đŸ—‘ïž Delete an organization from Capgo Cloud. This action cannot be undone. Only organization owners can delete organizations. **Example:** ```bash npx @capgo/cli@latest organization delete ORG_ID ``` **Options:** | Param | Type | Description | | -------------- | -------- | ---------------------------------------------------------------- | | **-a,** | `string` | API key to link to your account | | **—supa-host** | `string` | Custom Supabase host URL (for self-hosting or Capgo development) | | **—supa-anon** | `string` | Custom Supabase anon key (for self-hosting) | ## Keep going from organization [Section titled “Keep going from organization”](#keep-going-from-organization) If you are using **organization** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # đŸ”č probe > 🔎 Probe the Capgo updates endpoint to check if an update is available for your app. 🔎 Probe the Capgo updates endpoint to check if an update is available for your app. ```bash npx @capgo/cli@latest probe ``` Sends a single request to the updates endpoint using your project’s capacitor config and reports whether an update would be delivered, or explains why not. **Example:** ```bash npx @capgo/cli@latest probe --platform ios ``` ## []()Options [Section titled “ Options”](#-options) | Param | Type | Description | | ------------- | -------- | --------------------------------- | | **—platform** | `string` | Platform to probe: ios or android | ## Keep going from probe [Section titled “Keep going from probe”](#keep-going-from-probe) If you are using **probe** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # đŸ“± run > đŸ“± Run Capacitor apps on devices from the CLI. đŸ“± Run Capacitor apps on devices from the CLI. ### []()đŸ”č **Device** [Section titled “ đŸ”č Device”](#--device) ```bash npx @capgo/cli@latest run device ``` đŸ“± Run your Capacitor app on a connected device or simulator. If you omit the platform in an interactive terminal, the command asks whether to start on iOS or Android. The command lists available devices and simulators, lets you reload the list, and runs with your selection. For iOS, this asks whether to use a physical iPhone/iPad or simulator before showing devices. Use —no-launch to print the resolved command without starting the app. **Example:** ```bash npx @capgo/cli@latest run device ios --no-launch ``` **Options:** | Param | Type | Description | | -------------- | --------- | ---------------------------------------------------------- | | **—no-launch** | `boolean` | Resolve and print the run command without starting the app | # đŸ”č star > ⭐ Star a Capgo GitHub repository to support the project. ⭐ Star a Capgo GitHub repository to support the project. ```bash npx @capgo/cli@latest star ``` If you do not pass a repository name, this defaults to capacitor-updater in the Cap-go org. ## Keep going from star [Section titled “Keep going from star”](#keep-going-from-star) If you are using **star** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # đŸ”č star-all > ⭐ Star all Capgo GitHub repositories with a small random delay between each request. ⭐ Star all Capgo GitHub repositories with a small random delay between each request. ```bash npx @capgo/cli@latest star-all ``` If you do not pass repositories, this defaults to all Cap-go repositories whose name starts with `capacitor-`. ## []()Options [Section titled “ Options”](#-options) | Param | Type | Description | | -------------------- | -------- | ---------------------------------------------------------------- | | **—min-delay-ms** | `string` | Minimum delay in ms between each star action (default: 20) | | **—max-delay-ms** | `string` | Maximum delay in ms between each star action (default: 180) | | **—max-concurrency** | `string` | Maximum number of star requests running in parallel (default: 4) | ## Keep going from star-all [Section titled “Keep going from star-all”](#keep-going-from-star-all) If you are using **star-all** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # Adding or Updating Plugins > Complete guide for contributors and agents on how to add new plugins or update existing plugins in the Capgo documentation. This guide explains how to add new Capacitor plugins to the Capgo website or update existing plugin documentation. This is useful for contributors, maintainers, and AI agents helping to maintain the documentation. ## Overview [Section titled “Overview”](#overview) When adding a new plugin to the Capgo ecosystem, you need to update several files and locations across the website to ensure the plugin appears correctly in all relevant places: 1. **Plugin List Configuration** - Add plugin metadata to the master list 2. **Plugin Index Page** - Add plugin to the categorized plugin listing page 3. **Sidebar Navigation** - Add plugin to the documentation sidebar 4. **Plugin Documentation** - Create overview and getting-started pages 5. **Plugin Tutorial** - Create a comprehensive tutorial ## File Locations [Section titled “File Locations”](#file-locations) ### Key Files to Update [Section titled “Key Files to Update”](#key-files-to-update) | File | Purpose | | ----------------------------------------------- | --------------------------------- | | `/src/config/plugins.ts` | Master plugin list with metadata | | `/src/content/docs/docs/plugins/index.mdx` | Plugin index page with categories | | `/astro.config.mjs` | Sidebar navigation configuration | | `/src/content/docs/docs/plugins/[plugin-name]/` | Plugin documentation directory | | `/src/content/plugins-tutorials/en/` | English tutorial files | ## Step-by-Step Guide [Section titled “Step-by-Step Guide”](#step-by-step-guide) 1. ### Add Plugin to Master List [Section titled “Add Plugin to Master List”](#add-plugin-to-master-list) Open `/src/config/plugins.ts` and add your plugin to the `actions` array: ```typescript // First, import an appropriate Heroicon import YourIconName from 'astro-heroicons/mini/IconName.astro' // Then add to the actions array { name: '@capgo/your-plugin-name', author: 'github.com/Cap-go', description: 'Brief description of what the plugin does', href: 'https://github.com/Cap-go/your-plugin-name/', title: 'Display Name', icon: YourIconName, } ``` **Available Icons**: Check `/node_modules/astro-heroicons/mini/` for available icons. 2. ### Add Plugin to Index Page [Section titled “Add Plugin to Index Page”](#add-plugin-to-index-page) Open `/src/content/docs/docs/plugins/index.mdx` and add your plugin under the appropriate category: ```mdx ``` **Categories**: * ⭐ Featured Plugins * đŸ“± Device & System Plugins * đŸŽ„ Media & Camera Plugins * đŸ› ïž Utility Plugins * đŸ€– AI & Advanced Media * 📍 Location & Background Services * 📞 Communication & Analytics * 🔐 Security & System * 📊 Android-Specific Features * đŸ“„ Download & Navigation 3. ### Add to Sidebar Navigation [Section titled “Add to Sidebar Navigation”](#add-to-sidebar-navigation) Open `/astro.config.mjs` and add your plugin to the sidebar configuration (around line 540): ```javascript { label: 'Your Plugin Name', items: [ { label: 'Overview', link: '/docs/plugins/your-plugin-name/' }, { label: 'Getting started', link: '/docs/plugins/your-plugin-name/getting-started' }, ], collapsed: true, } ``` Plugins are listed alphabetically in the sidebar. 4. ### Create Plugin Documentation Directory [Section titled “Create Plugin Documentation Directory”](#create-plugin-documentation-directory) Create a new directory for your plugin documentation: ```bash mkdir -p /src/content/docs/docs/plugins/your-plugin-name/ ``` 5. ### Create Plugin Overview Page [Section titled “Create Plugin Overview Page”](#create-plugin-overview-page) Create `/src/content/docs/docs/plugins/your-plugin-name/index.mdx`: ```mdx --- title: "@capgo/your-plugin-name" description: Brief description of the plugin's purpose tableOfContents: false next: false prev: false sidebar: order: 1 label: "Introduction" hero: tagline: Detailed tagline explaining what the plugin does image: file: ~public/your-plugin-icon.svg actions: - text: Get started link: /docs/plugins/your-plugin-name/getting-started/ icon: right-arrow variant: primary - text: Github link: https://github.com/Cap-go/your-plugin-name/ icon: external variant: minimal --- import { Card, CardGrid } from '@astrojs/starlight/components'; Description of first key feature Description of second key feature Works on both iOS and Android đŸ“± Check the [Documentation](/docs/plugins/your-plugin-name/getting-started/) to master the plugin. ``` 6. ### Create Getting Started Guide [Section titled “Create Getting Started Guide”](#create-getting-started-guide) Create `/src/content/docs/docs/plugins/your-plugin-name/getting-started.mdx`: ```mdx --- title: Getting Started description: Learn how to install and use the plugin in your Capacitor app. sidebar: order: 2 --- import { Steps } from '@astrojs/starlight/components'; import { PackageManagers } from 'starlight-package-managers' 1. **Install the package** 2. **Sync with native projects** ## Configuration ### iOS Configuration [iOS-specific setup instructions] ### Android Configuration [Android-specific setup instructions] ## Usage [Basic usage examples] ## API Reference [Detailed API documentation] ## Complete Example [Full working example] ## Best Practices [Recommended practices and tips] ## Platform Notes [Platform-specific notes and limitations] ``` 7. ### Create Tutorial File [Section titled “Create Tutorial File”](#create-tutorial-file) Create `/src/content/plugins-tutorials/en/your-plugin-name.md`: ```markdown --- locale: en --- # Using @capgo/your-plugin-name Package The `@capgo/your-plugin-name` package [brief description]. In this tutorial, we will guide you through the installation, configuration, and usage of this package in your Ionic Capacitor app. ## Installation [Installation steps] ## Configuration [Configuration steps for iOS and Android] ## API Usage [Detailed API usage examples] ## Complete Example [Full working example] ## Best Practices [Tips and best practices] ## Troubleshooting [Common issues and solutions] ## Conclusion [Summary and links to additional resources] ``` ## Plugin Documentation Structure [Section titled “Plugin Documentation Structure”](#plugin-documentation-structure) ### Required Files [Section titled “Required Files”](#required-files) ```plaintext src/content/docs/docs/plugins/your-plugin-name/ ├── index.mdx # Overview page with hero and feature cards └── getting-started.mdx # Installation and usage guide src/content/plugins-tutorials/en/ └── your-plugin-name.md # Comprehensive tutorial ``` ### Optional Files [Section titled “Optional Files”](#optional-files) For complex plugins, you may add additional documentation pages: ```plaintext src/content/docs/docs/plugins/your-plugin-name/ ├── index.mdx ├── getting-started.mdx ├── api-reference.mdx # Detailed API documentation ├── examples.mdx # Additional examples ├── troubleshooting.mdx # Troubleshooting guide └── migrations.mdx # Migration guides ``` ## Content Guidelines [Section titled “Content Guidelines”](#content-guidelines) ### Writing Plugin Descriptions [Section titled “Writing Plugin Descriptions”](#writing-plugin-descriptions) * **Be Concise**: Keep descriptions under 100 characters * **Be Specific**: Explain what the plugin does, not what it is * **Use Action Words**: Start with verbs like “Control”, “Integrate”, “Enable” **Good Examples**: * “Control device flashlight and torch with simple on/off toggle” * “Integrate Crisp live chat and customer support into your app” * “Enable secure authentication using Face ID and Touch ID” **Bad Examples**: * “A plugin for flash” * “This is a Crisp plugin” * “Biometric plugin” ### Writing Documentation [Section titled “Writing Documentation”](#writing-documentation) 1. **Start with Installation**: Always begin with clear installation steps 2. **Provide Configuration**: Include platform-specific setup requirements 3. **Show Usage Examples**: Provide working code examples 4. **Include API Reference**: Document all methods and parameters 5. **Add Complete Examples**: Show real-world usage patterns 6. **List Best Practices**: Share tips for optimal usage 7. **Document Platform Differences**: Clarify iOS vs Android behavior 8. **Add Troubleshooting**: Address common issues ### Code Examples [Section titled “Code Examples”](#code-examples) * Use TypeScript for all code examples * Include imports at the top * Add comments explaining key steps * Show error handling * Demonstrate both basic and advanced usage ## Checklist [Section titled “Checklist”](#checklist) Use this checklist when adding a new plugin: * [ ] Added plugin to `/src/config/plugins.ts` * [ ] Selected appropriate icon from Heroicons * [ ] Added plugin to `/src/content/docs/docs/plugins/index.mdx` under correct category * [ ] Added sidebar entry in `/astro.config.mjs` * [ ] Created plugin documentation directory * [ ] Created `index.mdx` overview page * [ ] Created `getting-started.mdx` guide * [ ] Created tutorial in `/src/content/plugins-tutorials/en/` * [ ] Included installation instructions * [ ] Documented iOS configuration * [ ] Documented Android configuration * [ ] Provided usage examples * [ ] Added API reference * [ ] Included complete working example * [ ] Listed best practices * [ ] Added platform-specific notes * [ ] Tested all links work correctly ## Icon Reference [Section titled “Icon Reference”](#icon-reference) Common icons used for plugins (from `astro-heroicons/mini/`): | Icon | Use Case | | ------------------------ | ----------------------------------- | | `BoltIcon` | Flash, power, energy | | `CameraIcon` | Camera, photo, video | | `ChatBubbleLeftIcon` | Chat, messaging, communication | | `FingerPrintIcon` | Biometric, security, authentication | | `MapPinIcon` | Location, geolocation, maps | | `SpeakerWaveIcon` | Audio, sound, music | | `VideoCameraIcon` | Video, recording, streaming | | `CreditCardIcon` | Payments, purchases | | `PlayCircleIcon` | Media players, video players | | `SignalIcon` | Connectivity, network, beacon | | `RadioIcon` | Beacon, broadcast, wireless | | `ChatBubbleOvalLeftIcon` | Social media, WeChat | ## Updating Existing Plugins [Section titled “Updating Existing Plugins”](#updating-existing-plugins) When updating an existing plugin: 1. **Update version numbers** in documentation 2. **Add migration guides** if breaking changes exist 3. **Update API reference** with new methods 4. **Add new examples** for new features 5. **Update platform requirements** if changed 6. **Revise best practices** based on new features 7. **Keep tutorial current** with latest API ## Language Paths [Section titled “Language Paths”](#language-paths) Write and review plugin docs in English. Localized paths are generated by the site metadata and translated at the edge by the translation Worker. ## Testing Your Changes [Section titled “Testing Your Changes”](#testing-your-changes) After adding or updating plugin documentation: 1. **Build the site locally**: ```bash bun run build ``` 2. **Check for errors**: * Verify all links work * Ensure images load correctly * Confirm code examples are valid * Test navigation works 3. **Preview the site**: ```bash bun run dev ``` 4. **Verify your plugin appears**: * Check plugin listing page * Verify sidebar navigation * Test all documentation pages * Confirm tutorial page works ## Common Pitfalls [Section titled “Common Pitfalls”](#common-pitfalls) Caution **Avoid these common mistakes:** 1. **Forgetting to sync**: Always run `bunx cap sync` in examples 2. **Inconsistent naming**: Use the same plugin name everywhere 3. **Missing platform config**: Document both iOS and Android setup 4. **Broken links**: Use relative links and verify they work 5. **No error handling**: Always show try-catch in examples 6. **Missing imports**: Include all necessary imports in examples 7. **Unclear descriptions**: Be specific about what the plugin does ## Getting Help [Section titled “Getting Help”](#getting-help) If you need help adding or updating plugin documentation: * **Discord**: Join our [Discord community](https://discord.capgo.app) * **GitHub**: Open an issue on the [website repository](https://github.com/Cap-go/website) * **Email**: Contact the team at ## Examples [Section titled “Examples”](#examples) For reference, check these well-documented plugins: * **Updater**: `/src/content/docs/docs/plugins/updater/` (complex plugin with multiple pages) * **Flash**: `/src/content/docs/docs/plugins/flash/` (simple plugin, good starter example) * **Social Login**: `/src/content/docs/docs/plugins/social-login/` (plugin with sub-pages) ## Summary [Section titled “Summary”](#summary) Adding a plugin to the Capgo documentation involves: 1. Adding metadata to the master configuration 2. Adding the plugin to the categorized index page 3. Configuring sidebar navigation 4. Creating comprehensive documentation pages 5. Writing a detailed tutorial 6. Testing all changes locally By following this guide, you ensure that plugins are consistently documented and easily discoverable by users. ## Keep going from Adding or Updating Plugins [Section titled “Keep going from Adding or Updating Plugins”](#keep-going-from-adding-or-updating-plugins) If you are using **Adding or Updating Plugins** to plan native plugin work, connect it with [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, and [Capacitor Plugins: What You Need to Know](/blog/capacitor-plugins-what-you-need-to-know/) for the practical context in Capacitor Plugins: What You Need to Know. # FAQ > Frequently asked questions about Capgo, how to solve the most common issue in Capgo or with the Updater, what is OTA and how to manage them If you have questions not answered here, please ask! Both filing an issue or asking on [Discord](https://discord.capgo.app) work. ### What is “code push”?[](https://capgo.app/docs/#what-is-code-push "Direct link to What is \"code push\"?") [Section titled “What is “code push”?”](#what-is-code-push) Code push, also referred to as “over-the-air updates” (OTA) is a cloud service enabling Capacitor developers to deploy updates to their apps in production. Capgo currently works on Android, iOS, and Electron. “Code Push” is a reference to the name of a deploy feature used by the React Native community from [Microsoft](https://appcenter.ms/) and [Expo](https://expo.dev/), neither of which support Capacitor. ### Do Capgo CLI majors need to match my plugin or Capacitor version? [Section titled “Do Capgo CLI majors need to match my plugin or Capacitor version?”](#do-capgo-cli-majors-need-to-match-my-plugin-or-capacitor-version) No. Always use the latest Capgo CLI (`npx @capgo/cli@latest`). The CLI and Capgo Console follow their own versioning and stay compatible with any supported updater plugin major. Capgo plugins follow Capacitor majors; see [Capgo versioning](/docs/versioning/) for LTS tags such as `@lts-v7`. ### What is the difference between a bundle and a release?[](https://capgo.app/docs/faq/#what-is-the-difference-between-a-bundle-and-a-release "Direct link to What is the difference between a bundle and a release?") [Section titled “What is the difference between a bundle and a release?”](#what-is-the-difference-between-a-bundle-and-a-release) We use the term “release” to mean preparing a binary for the app stores. In order to later generate a bundle Capgo needs to know the exact binary that was shipped to the app stores. We use the term “bundle” to mean a patch that can be applied to a release to update it to new code. The `npx @capgo/cli@latest bundle upload` command is used to generate a bundle from your new local code which is then shipped to your users. ### Are there Delta update file-path limitations?[](https://capgo.app/docs/faq/#are-there-delta-update-file-path-limitations "Direct link to Are there Delta update file-path limitations?") [Section titled “Are there Delta update file-path limitations?”](#are-there-delta-update-file-path-limitations) Yes: * **Zero-byte files:** The CLI logs `Ignoring empty file...` and excludes empty files from the Delta manifest. It does not fail the upload, so an empty file can change the resulting bundle without stopping your deployment. Do not include zero-byte files in Delta bundle paths. * **Paths with spaces:** Delta uploads fail early with a clear error when a bundle path contains a space. Rename files or directories to remove spaces before uploading a Delta update. See [Delta updates](/docs/live-updates/differentials/) for setup details. ### What is the roadmap?[](https://capgo.app/docs/faq/#what-is-the-roadmap "Direct link to What is the roadmap?") [Section titled “What is the roadmap?”](#what-is-the-roadmap) Our project boards are also public and found at: [https://github.com/orgs/Cap-go/projects](https://github.com/orgs/Cap-go/projects/) Our team also operates in the public, so you can see what we’re working on at any time. We’re happy to answer any questions you have about our roadmap or priorities via Github issues or [Discord](https://discord.capgo.app). ### Can I use Capgo with my team?[](https://capgo.app/docs/faq/#can-i-use-capgo-with-my-team "Direct link to Can I use Capgo with my team?") [Section titled “Can I use Capgo with my team?”](#can-i-use-capgo-with-my-team) Yes! All plans support unlimited developers. We only limit app metrics (MAU, storage and bandwidth) to each organization. See [Teams](https://capgo.app/pricing/) for more information. ### Does Capgo store my source code?[](https://capgo.app/docs/faq/#does-capgo-store-my-source-code "Direct link to Does Capgo store my source code?") [Section titled “Does Capgo store my source code?”](#does-capgo-store-my-source-code) No. Capgo servers never see your source code. When you run `npx @capgo/cli@latest bundle upload`, Capgo stores a zip file of the minified/compiled code - the same code that a browser would receive, not your source code. For additional security, you have two options: * **End-to-End Encryption**: Encrypt your bundle before uploading to protect it in storage and transit and to prevent third parties from generating valid encrypted updates without your private key. This does not make shipped web assets impossible to reverse engineer because the public key is present in the distributed app. * **External URL Upload**: Store the bundle on your own server and only provide Capgo with the download link with the option `--external ` See also our privacy policy: [https://capgo.app/privacy](https://capgo.app/privacy/) ### Are bundle files private data?[](https://capgo.app/docs/faq/#are-bundle-files-private-data "Direct link to Are bundle files private data?") [Section titled “Are bundle files private data?”](#are-bundle-files-private-data) No. Bundle files are public web assets intended to be downloaded by your app users. Anyone who knows the bundle URL can fetch those files, and Capgo informs users of this during setup and in the documentation. Access to bundle files is not considered a data breach. Do not put secrets, credentials, personal data, or regulated data in your app bundle. If you need stronger confidentiality for high-security use cases, use end-to-end encryption, but still treat shipped app code and assets as public from a security-reporting perspective. ### Can I use Capgo from my CI system?[](https://capgo.app/docs/faq/#can-i-use-capgo-from-my-ci-system "Direct link to Can I use Capgo from my CI system?") [Section titled “Can I use Capgo from my CI system?”](#can-i-use-capgo-from-my-ci-system) Yes. Capgo is intended to be used from CI systems. We’ve published a guide for [Android and Github Actions](https://capgo.app/blog/automatic-capacitor-android-build-github-action/) and [iOS](https://capgo.app/blog/automatic-capacitor-ios-build-github-action/), and for [GitLab](https://capgo.app/blog/setup-ci-and-cd-in-gitlab/). Other CI systems should be similar. Please don’t hesitate to reach out over GitHub issues or Discord if you encounter any issues. ### How does this relate to Firebase Remote Config or Launch Darkly?[](https://capgo.app/docs/faq/#how-does-this-relate-to-firebase-remote-config-or-launch-darkly "Direct link to How does this relate to Firebase Remote Config or Launch Darkly?") [Section titled “How does this relate to Firebase Remote Config or Launch Darkly?”](#how-does-this-relate-to-firebase-remote-config-or-launch-darkly) Code push allows adding new code / replacing code on the device. Firebase Remote Config and Launch Darkly are both configuration systems. They allow you to change the configuration of your app without having to ship a new version. They are not intended to replace code. ### How big of a dependency footprint does this add?[](https://capgo.app/docs/faq/#how-big-of-a-dependency-footprint-does-this-add "Direct link to How big of a dependency footprint does this add?") [Section titled “How big of a dependency footprint does this add?”](#how-big-of-a-dependency-footprint-does-this-add) I haven’t measured recently, but I expect the code push library to add less than one megabyte to Capacitor apps. We know of ways we can make this smaller when that becomes a priority. If size is a blocker for you, please let us know! ### Does Capgo work on the iOS 18.4 Simulator?[](https://capgo.app/docs/faq/#does-capgo-work-on-the-ios-18-4-simulator "Direct link to Does Capgo work on the iOS 18.4 Simulator?") [Section titled “Does Capgo work on the iOS 18.4 Simulator?”](#does-capgo-work-on-the-ios-184-simulator) No. Due to an upstream issue affecting the iOS 18.4 Simulator, Capgo does not run reliably there. Please test on a real device or use a different iOS simulator version. See details in the React Native issue: [facebook/react-native#50510](https://github.com/facebook/react-native/issues/50510) ### Does code push work with large applications?[](https://capgo.app/docs/faq/#does-code-push-work-with-large-applications "Direct link to Does code push work with large applications?") [Section titled “Does code push work with large applications?”](#does-code-push-work-with-large-applications) Yes. There is no limit on the size of the application that can be updated with code push. As noted [below](https://capgo.app/docs/faq/#what-types-of-changes-does-capgo-code-push-support), Capgo can change any JS code in your application regardless of size. To note: A bigger size make it harder for users to download updates. We recommend keeping your app as small as possible. ### What can I use Capgo code push for?[](https://capgo.app/docs/faq/#what-can-i-use-capgo-code-push-for "Direct link to What can I use Capgo code push for?") [Section titled “What can I use Capgo code push for?”](#what-can-i-use-capgo-code-push-for) We’ve seen a variety of uses, including: * Emergency fixes to production apps. * Shipping bug fixes to users on older versions of your app. * Shipping constantly (e.g. every hour). Note that most app stores prohibit shipping code that changes the behavior of the app in a significant way. Please see [below](https://capgo.app/docs/faq/#how-does-this-relate-to-the-appplay-store-review-process-or-policies) for more information. ### What counts as a “MAU” for Capgo?[](https://capgo.app/docs/faq/#what-counts-as-a-mau-for-capgo "Direct link to What counts as a \"MAU\" for Capgo?") [Section titled “What counts as a “MAU” for Capgo?”](#what-counts-as-a-mau-for-capgo) A MAU is a Monthly Active Device. A distinct device that contacts Capgo during a rolling 30-day period counts as one MAU for that native app ID. The same physical device used with two distinct native app IDs counts once for each app ID; it is not deduplicated across them. If your flavours differ only in their web layer or update routing, use one native app ID with [channels](/docs/live-updates/channels/). That keeps the flavours under one Capgo app and makes releases simpler. Use separate native app IDs when a flavour needs a distinct bundle ID, signing identity, entitlement set, or store listing. On iOS, **v7.25.0+** keeps the random, app-scoped device ID through normal reinstalls using Keychain. On Android, use **v7.50.1+** (or **v5.50.1+** and **v6.50.1+** on those release lines); the ID is restored only when Android Backup/Restore retains the app preferences. Disabling backup, excluding those preferences, or clearing app data generates a new device ID. Updating the app does not create a new device ID. For test and development builds, turn off development-build and emulator delivery on production channels. That controls delivery, not MAU: a device can still count when it contacts Capgo. To keep it out of production usage, disable live updates and do not call production Capgo endpoints. See [Test Native Builds Without Live Updates](/docs/live-updates/testing-native-builds-without-live-updates/) for the exact settings. ### What can’t we use Capgo code push for?[](https://capgo.app/docs/faq/#what-cant-we-use-capgo-code-push-for "Direct link to What can't we use Capgo code push for?") [Section titled “What can’t we use Capgo code push for?”](#what-cant-we-use-capgo-code-push-for) Capgo cannot change native code such as Java, Kotlin, Objective-C, Swift, native plugins, or native configuration. Those changes require a new native app release. For store-review scope, see [App Store and Google Play policies](#how-does-this-relate-to-the-appplay-store-review-process-or-policies). ### Can I update capacitor.config.ts changes via Capgo?[](https://capgo.app/docs/faq/#can-i-update-capacitorconfigts-changes-via-capgo "Direct link to Can I update capacitor.config.ts changes via Capgo?") [Section titled “Can I update capacitor.config.ts changes via Capgo?”](#can-i-update-capacitorconfigts-changes-via-capgo) No. Short rule: Capgo can send the generated web build folder, including HTML, CSS, JavaScript, assets, and pure-JavaScript package changes bundled into that output. Changes to `capacitor.config.ts`, native plugin configuration, native package installs or upgrades, and anything that must update the iOS or Android project through `npx cap sync` or `npx cap copy` require a native app release. The Capacitor configuration file is read at native build time and compiled into the native app binary. If you need to change your Capacitor configuration, you must: 1. Update `capacitor.config.ts` locally 2. Rebuild your native app (`npx cap sync` followed by a native build) 3. Submit the new binary to the app stores ### Does Capgo submit to the stores for me?[](https://capgo.app/docs/faq/#does-capgo-submit-to-the-stores-for-me "Direct link to Does Capgo submit to the stores for me?") [Section titled “Does Capgo submit to the stores for me?”](#does-capgo-submit-to-the-stores-for-me) Capgo Build can compile and sign a prepared native iOS or Android project and, when configured, submit the signed result to App Store Connect or Google Play. You can keep your existing CI for private dependencies, web builds, Capacitor sync, and custom native preparation; Capgo receives the prepared native project for the native build step. See [Capgo Build](/docs/builder/) and the [build configuration reference](/docs/builder/configuration/) for the workflow and store-submission options. ### What does Capgo store on disk and where?[](https://capgo.app/docs/faq/#what-does-capgo-store-on-disk-and-where "Direct link to What does Capgo store on disk and where?") [Section titled “What does Capgo store on disk and where?”](#what-does-capgo-store-on-disk-and-where) The Capgo updater (included in your application when you build your app) caches the latest downloaded bundle in the only directory that capacitor allow to load code. On Android, this is located in `/data/user/0/com.example.app/code_cache/capgo_updater` although the base of that path is provided by the Android system and can change dynamically at runtime. On iOS devices, data is stored under `Library/Application Support/capgo`. The Capgo command line tools (e.g. `npx @capgo/cli@latest bundle upload`) are installed on disk in npm caches, your logins are stored in your home directory in `~/.capgo`. ### How does this relate to Capacitor Hot Reload?[](https://capgo.app/docs/faq/#how-does-this-relate-to-capacitor-hot-reload "Direct link to How does this relate to Capacitor Hot Reload?") [Section titled “How does this relate to Capacitor Hot Reload?”](#how-does-this-relate-to-capacitor-hot-reload) Capacitor’s Hot reload is a development-time-only feature. Code push is for production. Hot reload is a feature of Capacitor that allows you to change code on the device during development. It requires building the Capacitor app with a proxy to connect to your local machine. Code push is a feature that allows you to change code on the device in production. We will use a variety of different techniques to make this possible depending on the platform. ### What types of changes does Capgo code push support?[](https://capgo.app/docs/faq/#what-types-of-changes-does-capgo-code-push-support "Direct link to What types of changes does Capgo code push support?") [Section titled “What types of changes does Capgo code push support?”](#what-types-of-changes-does-capgo-code-push-support) Capgo can change any JS code in your application. This includes app code and generated code. You can also update dependencies in `package.json` as long as they don’t require native code changes. We do not have plans to support changing native code (e.g. Java/Kotlin on Android or Objective-C/Swift on iOS), and the tool will warn you if it detects that you have changed native code as it will not be included in the bundle. ### Does this support Web?[](https://capgo.app/docs/faq/#does-this-support-web "Direct link to Does this support Web?") [Section titled “Does this support Web?”](#does-this-support-web) Code push isn’t needed for web as the web already works this way. When a user opens a web app it downloads the latest version from the server if needed. If you have a use case for code push with web, we’d love to know! ### Will this work on iOS, Android, Mac, Windows, Linux, etc?[](https://capgo.app/docs/faq/#will-this-work-on-ios-android-mac-windows-linux-etc "Direct link to Will this work on iOS, Android, Mac, Windows, Linux, etc?") [Section titled “Will this work on iOS, Android, Mac, Windows, Linux, etc?”](#will-this-work-on-ios-android-mac-windows-linux-etc) Yes. So far we’ve focused on Android, iOS, and Electron support, and code push is production-ready on all three. ### What OS versions does Capgo support?[](https://capgo.app/docs/faq/#what-os-versions-does-capgo-support "Direct link to What OS versions does Capgo support?") [Section titled “What OS versions does Capgo support?”](#what-os-versions-does-capgo-support) Capgo supports the same versions of Android that Capacitor supports. Capacitor currently supports Android API level 22+ and iOS 13.0+: [https://capacitorjs.com/docs/main/reference/support-policy](https://capacitorjs.com/docs/main/reference/support-policy/) ### What versions of Capacitor does Capgo support?[](https://capgo.app/docs/faq/#what-versions-of-capacitor-does-capgo-support "Direct link to What versions of Capacitor does Capgo support?") [Section titled “What versions of Capacitor does Capgo support?”](#what-versions-of-capacitor-does-capgo-support) Capgo currently supports only recent stable releases of Capacitor. We could support older versions of Capacitor as well, we just haven’t built out the infrastructure necessary to maintain such over time. We intend to support more versions of Capacitor in the future, including any version for our enterprise customers. [https://github.com/Cap-go/capgo/issues/1100](https://github.com/Cap-go/capgo/issues/1100/) Capgo tracks Capacitor stable and generally updates within a few hours of any stable release. Our system for doing these updates is automated takes a few minutes to run. We then do an extra manual verification step before publishing to our servers. ### How does this relate to the App/Play Store review process or policies?[](https://capgo.app/docs/faq/#how-does-this-relate-to-the-appplay-store-review-process-or-policies "Direct link to How does this relate to the App/Play Store review process or policies?") [Section titled “How does this relate to the App/Play Store review process or policies?”](#how-does-this-relate-to-the-appplay-store-review-process-or-policies) Capgo delivers changes only to the Capacitor web layer: the HTML, CSS, JavaScript, and assets already running in the app’s WebView. It does not change the native binary, native plugins, permissions, entitlements, signing, or store metadata. Use a native store release for every native change and for material changes that could affect the app’s reviewed purpose or functionality. Keep live updates within the app experience you submitted and disclosed to users. ### Does Capgo guarantee App Store or Google Play approval?[](https://capgo.app/docs/faq/#does-capgo-guarantee-app-store-or-google-play-approval "Direct link to Does Capgo guarantee App Store or Google Play approval?") [Section titled “Does Capgo guarantee App Store or Google Play approval?”](#does-capgo-guarantee-app-store-or-google-play-approval) No. Apple and Google review each app and release on its own facts, and Capgo cannot guarantee an individual approval or review outcome. Your team remains responsible for the app’s content, disclosures, update scope, and compliance with the current store policies. For review and release planning, read the official policies directly: [Apple App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/) and [Google Play Device and Network Abuse policy](https://support.google.com/googleplay/android-developer/answer/16559646). ### Can I use Capgo in my country?[](https://capgo.app/docs/faq/#can-i-use-capgo-in-my-country "Direct link to Can I use Capgo in my country?") [Section titled “Can I use Capgo in my country?”](#can-i-use-capgo-in-my-country) We have not attempted to restrict access to Capgo from any country. We recognize that some countries have restrictions on what urls can be accessed from within the country. Capgo currently uses Cloudflare Cloud for hosting, including R2 Storage and Cloudflare workers. The following URLs are used by Capgo: * [https://api.capgo.app](https://api.capgo.app/) — used by the `npx @capgo/cli` command line tools to interact with the Capgo servers as well as the Capgo updater on users’ devices to check for updates. * [https://\*.r2.cloudflarestorage.com](https://*.r2.cloudflarestorage.com/) — used by the `npx @capgo/cli` command line tool to upload and download bundle If all of those URLs are accessible from your country, then Capgo should work. If your region requires blocking access to any of those URLs, please let us know and we can work with you to find a solution. Proxy servers are one option. ### Can I self-host Capgo?[](https://capgo.app/docs/faq/#can-i-self-host-capgo "Direct link to Can I self-host Capgo?") [Section titled “Can I self-host Capgo?”](#can-i-self-host-capgo) Yes. Enterprise supports licensed self-hosted Capgo deployments when you need to run the updater backend in your own infrastructure. See [Self-Hosted Updater](/docs/plugins/updater/self-hosted/getting-started/) for the deployment model and endpoints. ### Does code push require the internet to work?[](https://capgo.app/docs/faq/#does-code-push-require-the-internet-to-work "Direct link to Does code push require the internet to work?") [Section titled “Does code push require the internet to work?”](#does-code-push-require-the-internet-to-work) Yes. One could imagine running a server to distribute the updates separately from the general internet, but some form of network connectivity is required to transport updates to the devices. ### How is Capgo affected by lack of network connectivity?[](https://capgo.app/docs/faq/#how-is-capgo-affected-by-lack-of-network-connectivity "Direct link to How is Capgo affected by lack of network connectivity?") [Section titled “How is Capgo affected by lack of network connectivity?”](#how-is-capgo-affected-by-lack-of-network-connectivity) Capgo updater (included in your application when you build your app with Capgo) is designed to be resilient to network connectivity issues. In the default update behavior, when the application launches it alerts the Capgo updater, which spawns a separate thread to make a network request to Capgo’s servers and ask for an update. We intentionally use a separate thread to avoid affecting blocking anything else the application might be doing. If the network request fails or times out, the updater will simply try to check again next time the application launches. Capgo command line tools (e.g. `npx @capgo/cli@latest bundle upload`) require network connectivity to function. If you are using Capgo to distribute your app, you should ensure that your CI system has network connectivity. ### What happens if a user doesn’t update for a long time and misses an update?[](https://capgo.app/docs/faq/#what-happens-if-a-user-doesnt-update-for-a-long-time-and-misses-an-update "Direct link to What happens if a user doesn't update for a long time and misses an update?") [Section titled “What happens if a user doesn’t update for a long time and misses an update?”](#what-happens-if-a-user-doesnt-update-for-a-long-time-and-misses-an-update) Our implementation always sends an update specifically tailored for the device that is requesting it updating the requestor always to the latest version available. Thus if a user doesn’t update for a while they will “miss” intermediate updates. The update server could be changed to support responding with either the next incremental version or the latest version depending on your application’s needs. Please let us know if alternative update behaviors are important to you. ### How does Capgo relate to Capacitor?[](https://capgo.app/docs/faq/#how-does-capgo-relate-to-capacitor "Direct link to How does Capgo relate to Capacitor?") [Section titled “How does Capgo relate to Capacitor?”](#how-does-capgo-relate-to-capacitor) Capgo is a plugin for Capacitor that adds code push. Capgo is not a replacement for Capacitor. You can continue to use the Capacitor tooling you already know and love. We track the latest stable release of Capacitor and update our code push plugin to work with it. ### When do updates happen?[](https://capgo.app/docs/faq/#when-do-updates-happen "Direct link to When do updates happen?") [Section titled “When do updates happen?”](#when-do-updates-happen) By default, the Capgo updater checks for updates on app startup. It runs on a background thread and does not block the UI thread. Any updates will be installed while the user is using the app and will be applied the next time the app is restarted. It is also possible to run the Capgo updater manually using the `@capgo/capacitor-updater` package, through which it is possible to trigger updates at any time, including via a push notification. The Capgo updater is designed such that when the network is not available, or the server is down or otherwise unreachable, the app will continue to run as normal. Should you ever choose to delete an update from our servers, all your clients will continue to run as normal. We have added the ability to rollback patches. The simplest thing is to simply attach a previous bundle to your channel to undo. ### Do I need to keep my app\_id secret?[](https://capgo.app/docs/faq/#do-i-need-to-keep-my-app_id-secret "Direct link to Do I need to keep my app_id secret?") [Section titled “Do I need to keep my app\_id secret?”](#do-i-need-to-keep-my-app_id-secret) No. The `app_id` is included in your app and is safe to be public. You can check it into version control (even publicly) and not worry about someone else accessing it. Someone who has your `app_id` can fetch the latest version of your app from Capgo servers, but they cannot push updates to your app or access any other aspect of your Capgo account. ### What information is sent to Capgo servers?[](https://capgo.app/docs/faq/#what-information-is-sent-to-capgo-servers "Direct link to What information is sent to Capgo servers?") [Section titled “What information is sent to Capgo servers?”](#what-information-is-sent-to-capgo-servers) The complete data inventory, endpoint behavior, and privacy controls are documented in [Compliance](/docs/live-updates/compliance/). Set `statsUrl: ''` to disable explicit updater statistics reports. You can also send `statsUrl` to a proxy or endpoint you control; see [handling statistics in self-hosted infrastructure](/docs/plugins/updater/self-hosted/handling-stats/). Update checks still need an app-scoped device identifier so Capgo can select the correct update and measure monthly active devices. The [sub-processor list](https://capgo.app/subprocessors/) is our up-to-date public source of truth for providers, processing locations, transfer mechanisms, and change history. ### Can I use Capgo for HIPAA-sensitive apps?[](https://capgo.app/docs/faq/#can-i-use-capgo-for-hipaa-sensitive-apps "Direct link to Can I use Capgo for HIPAA-sensitive apps?") [Section titled “Can I use Capgo for HIPAA-sensitive apps?”](#can-i-use-capgo-for-hipaa-sensitive-apps) Yes, but your compliance owner needs to choose the right deployment model. Capgo Cloud is not currently presented as a HIPAA-compliant hosted statistics processor. By default, the updater data is device-scoped and not tied to a known app user, and many teams use that model successfully. For stricter reviews, you can geo-localize plugin traffic, disable statistics by setting `statsUrl` to an empty string, self-host only the statistics endpoint, or use licensed self-hosting. Do not call `CapacitorUpdater.setCustomId(...)` with an email, user ID, patient ID, employee ID, or any value that maps updater telemetry back to a person. See [HIPAA Compliance](/docs/live-updates/hipaa-compliance/) for the full technical setup and the observability tradeoffs when statistics are disabled. ### Can I keep Capgo live update data in Europe?[](https://capgo.app/docs/faq/#can-i-keep-capgo-live-update-data-in-europe "Direct link to Can I keep Capgo live update data in Europe?") [Section titled “Can I keep Capgo live update data in Europe?”](#can-i-keep-capgo-live-update-data-in-europe) Yes. Apps that need EU data residency for Capgo Cloud plugin traffic can set the updater endpoints to the EU host: * `updateUrl`: `https://plugin.eu.capgo.app/updates` * `statsUrl`: `https://plugin.eu.capgo.app/stats` * `channelUrl`: `https://plugin.eu.capgo.app/channel_self` Use all three EU URLs together so update checks, statistics, and channel self-assignment use the same regional data path. Because these values live in `capacitor.config.ts`, production mobile apps need a native release before existing installs use the new endpoints. See [Data Location](/docs/live-updates/data-location/) for exact Capacitor and Electron examples. ### What platforms does Capgo support?[](https://capgo.app/docs/faq/#what-platforms-does-capgo-support "Direct link to What platforms does Capgo support?") [Section titled “What platforms does Capgo support?”](#what-platforms-does-capgo-support) Currently, Capgo supports Android, iOS, and Electron. All are production-ready. Use of Capgo for iOS, Android, or Electron can be independent decisions. You can set your channel strategy for Android and an ipa built to the App Store, or Electron channels, as needed. Capgo can (relatively easily) be made to support desktop or embedded targets. If those are important to you, please let us know. ### How does Capgo interact with Play Testing Tracks or Apple TestFlight?[](https://capgo.app/docs/faq/#how-does-capgo-interact-with-play-testing-tracks-or-apple-testflight "Direct link to How does Capgo interact with Play Testing Tracks or Apple TestFlight?") [Section titled “How does Capgo interact with Play Testing Tracks or Apple TestFlight?”](#how-does-capgo-interact-with-play-testing-tracks-or-apple-testflight) Each of the app stores have separate mechanisms for distributing apps to limited groups of users (e.g. “internal testing”, “closed beta”, etc.). These are all mechanisms for segmenting your users into groups and distributing specific versions of your apps to each. Unfortunately, these not all of these mechanisms allow 3rd parties to detect when apps are installed in any specific Test Track or via TestFlight. Thus, we do not have reliable visibility into composition of these groups, and cannot reliably gate access to Capgo patches based on these groups. [https://stackoverflow.com/questions/53291007/can-an-android-application-identify-the-test-track-within-google-play](https://stackoverflow.com/questions/53291007/can-an-android-application-identify-the-test-track-within-google-play/) [https://stackoverflow.com/questions/26081543/how-to-tell-at-runtime-whether-an-ios-app-is-running-through-a-testflight-beta-i](https://stackoverflow.com/questions/26081543/how-to-tell-at-runtime-whether-an-ios-app-is-running-through-a-testflight-beta-i/) If you’d like to segment availability of Capgo bundle, there are 4 potential options: 1. Use separate channel for each group. This is the most straightforward approach, but requires you to manage multiple channels. You may already have a dev channels and prod channels with different availability. You can thus update your dev channels, verify it and then separately update your prod channels. We recommend using branches / tags in your version control to help keep track of the sources associated with each release. 2. Track your own set of opt-in users, disable automatic updates, and trigger updates only for certain users via the `@capgo/capacitor-updater` package. This works today, but requires you to manage your own opt-in list. 3. Capgo allow creare its own opt-in mechanism on a per-device basis (similar to Test Tracks or TestFlight, just platform agnostic). This allow your QA team to opt-in to bundle before they’re promoted to the general public. 4. Use [progressive rollouts](/docs/live-updates/progressive-rollouts/) to deliver a candidate bundle to a random, sticky subset of a channel. Set a rollout from 0–100%, or use `--rollout-percentage-bps` for 0.01% increments; configure cache duration from 60 seconds to 365 days and optional auto-pause policy. This does not select a named device group. ## Billing[](https://capgo.app/docs/faq/#billing "Direct link to Billing") [Section titled “Billing”](#billing) ### How do I upgrade or downgrade my plan?[](https://capgo.app/docs/faq/#how-do-i-upgrade-or-downgrade-my-plan "Direct link to How do I upgrade or downgrade my plan?") [Section titled “How do I upgrade or downgrade my plan?”](#how-do-i-upgrade-or-downgrade-my-plan) You can upgrade or downgrade your plan at any time in your dashboard: [https://console.capgo.app/settings/organization/plans](https://console.capgo.app/settings/organization/plans/) ### When does my billing period reset?[](https://capgo.app/docs/faq/#when-does-my-billing-period-reset "Direct link to When does my billing period reset?") [Section titled “When does my billing period reset?”](#when-does-my-billing-period-reset) Billing periods are reset automatically every month on the month you first subscribed to Capgo. For example, if you subscribed on the 15th of the month, your billing period will reset on the 15th of every month. ### How do I cancel my subscription?[](https://capgo.app/docs/faq/#how-do-i-cancel-my-subscription "Direct link to How do I cancel my subscription?") [Section titled “How do I cancel my subscription?”](#how-do-i-cancel-my-subscription) You can cancel your subscription at any time in your dashboard: [https://console.capgo.app/settings/organization/plans](https://console.capgo.app/settings/organization/plans/) ### Can I pay for a year in advance?[](https://capgo.app/docs/faq/#can-i-pay-for-a-year-in-advance "Direct link to Can I pay for a year in advance?") [Section titled “Can I pay for a year in advance?”](#can-i-pay-for-a-year-in-advance) Yes. You can choose annual billing in your [organization plan settings](https://console.capgo.app/settings/organization/plans/). ### What counts toward storage, and can we change retention?[](https://capgo.app/docs/faq/#what-counts-toward-storage-and-can-we-change-retention "Direct link to What counts toward storage, and can we change retention?") [Section titled “What counts toward storage, and can we change retention?”](#what-counts-toward-storage-and-can-we-change-retention) Storage includes retained historical bundles and their Delta assets across your channels. You control unused-bundle retention for each app in App Settings. Bundles linked to an active channel or rollout stay protected so they remain available for delivery and rollback. ### Does regional replication multiply storage or bandwidth?[](https://capgo.app/docs/faq/#does-regional-replication-multiply-storage-or-bandwidth "Direct link to Does regional replication multiply storage or bandwidth?") [Section titled “Does regional replication multiply storage or bandwidth?”](#does-regional-replication-multiply-storage-or-bandwidth) No. A bundle is counted once for storage, regardless of the regions serving it. Capgo bandwidth is based on device downloads that are not served from the edge cache; cache-served deliveries do not count against Capgo bandwidth usage. ### What does the Enterprise SLA include?[](https://capgo.app/docs/faq/#what-does-the-enterprise-sla-include "Direct link to What does the Enterprise SLA include?") [Section titled “What does the Enterprise SLA include?”](#what-does-the-enterprise-sla-include) Enterprise includes a 99.9% monthly availability commitment for the production platform. If that commitment is missed, the service-credit schedule is 10% to 30% based on monthly availability. Initial support-response targets are P1: one hour, 24/7/365; P2: two business hours; P3: one business day; and P4: two business days. Read the [Enterprise SLA](https://capgo.app/sla/) for the complete terms. ### Stats and analytics[](https://capgo.app/docs/faq/#stats-and-analytics "Direct link to Stats and analytics") [Section titled “Stats and analytics”](#stats-and-analytics) The stats in your dashboard are updated every midnight UTC. The stats are calculated from distinct [MAUs](/docs/faq/#what-counts-as-a-mau-for-capgo) active during the rolling 30-day period. ## How device ID is generated[](https://capgo.app/docs/faq/#how-device-id-is-generated "Direct link to How device ID is generated") [Section titled “How device ID is generated”](#how-device-id-is-generated) The device ID is generated on the device on first run, and is used to de-duplicate per-device installs and allow us to charge based on users installed to (e.g. monthly active users), rather than total patches or total patch installs. MAU is a better solution than number of installs to price Capgo, as it is more accurate and reflects the actual cost of Capgo per device. **Device-ID persistence:** * **iOS**: From v7.25.0+, the device ID is stored in Keychain and persists through normal reinstalls. * **Android**: Use v7.50.1+ (or v5.50.1+/v6.50.1+ on those release lines). The device ID is restored only when Android Backup/Restore keeps the app preferences. * **Electron**: The device ID is stored in secure storage. * **Android caveat**: Disabling backup, excluding the relevant preferences, or clearing app data generates a new device ID. Android v7.25.0 through v7.50.0 can generate a new device ID after a reinstall even when backup is enabled. The device ID is app-scoped and supports live-update delivery and MAU de-duplication; it is not an advertising or cross-app tracking identifier. Device IDs are listed after the app checks in with Capgo through the updater or stats endpoints. A device does not need to install a patch before it can appear in the device list. ## Why my device number is different than my MAU?[](https://capgo.app/docs/faq/#why-my-device-number-is-different-than-my-mau "Direct link to Why my device number is different than my MAU?") [Section titled “Why my device number is different than my MAU?”](#why-my-device-number-is-different-than-my-mau) The device list and MAU are based on different signals. The device list shows the latest known metadata for each device, such as the device ID, platform, plugin version, OS version, native version, channel, installed bundle, and request country when available. The request country is the latest valid two-letter code received from a Cloudflare-handled request for that device, not GPS or app-provided location. Requests without a valid country do not clear the last valid value. Capgo updates this metadata when the app checks in, but repeated check-ins that report the same metadata may not change the row or its last update time. MAU counts distinct active devices during the billing window. That activity can increase even when the device metadata stays the same, so the device count and MAU can be different. ## How to have different update by platform?[](https://capgo.app/docs/faq/#how-to-have-different-update-by-platform "Direct link to How to have different update by platform?") [Section titled “How to have different update by platform?”](#how-to-have-different-update-by-platform) You can create a channel for each platform. and disable platform specific updates in each channel. On ios channel disable android updates and on android channel disable ios updates. Then upload a bundle to each channel to have different update for each platform. If you need to have the same update for both platform, you can link one bundle to multiple channels. No need to duplicate the bundle. ## Keep going from FAQ [Section titled “Keep going from FAQ”](#keep-going-from-faq) If you are using **FAQ** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, and [Update Types](/docs/live-updates/update-types/) for the implementation detail in Update Types. # Tech support for Capgo > How to get tech support for Capgo and our updater, please follow this guide to get help when the doc and our articles are not enough ## Support by discord [Section titled “Support by discord”](#support-by-discord) Capgo has an official [discord server](https://discord.capgo.app). Getting tech support there is likely one of the fastest ways to get a response. Here is a crash course: Step 1 - go to the `questions` channel ![Ask on discord](/discord-questions.webp) Step 2 - create your thread ![Create a question on discord](/discord-newquestion.webp) Step 3 - Describe your problem and select the relevant tags ![Create a post on discord](/discord-new-post.webp) Step 4 - Share your secure account id (optional) This will allow the capgo staff to take a look at your account. Sharing this id is safe, as it was designed to be shared publicly. To share this, please go to [capgo’s settings](https://console.capgo.app/dashboard/settings/account/). There please click on `copy account id`. ![Share your id without leaking your info](/share-secure-id.webp) This will copy the secure account id to the clipboard. Please include that in your discord post. ## Support by email [Section titled “Support by email”](#support-by-email) This is the slowest way to get support. Please use the discord server first. If you need to contact us by email, please send an email to . ## Keep going from Tech support for Capgo [Section titled “Keep going from Tech support for Capgo”](#keep-going-from-tech-support-for-capgo) If you are using **Tech support for Capgo** to plan migration and enterprise operations, connect it with [Capgo Enterprise](/enterprise/) for the product workflow in Capgo Enterprise, [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives, [Capgo Alternatives](/alternatives/) for the product workflow in Capgo Alternatives, [Capgo Consulting](/consulting/) for the product workflow in Capgo Consulting, and [Capgo Premium Support](/premium-support/) for the product workflow in Capgo Premium Support. # Add an App > Add an app to your Capgo account, and install the plugin in your app ## Requirements [Section titled “Requirements”](#requirements) Before getting started with Capgo, make sure you have: * A Capacitor app installed and configured. [Learn how to set up Capacitor](https://capacitorjs.com/docs/getting-started/) * Node.js 20 or later installed * One of the following development environments: * **macOS** with Xcode (for iOS development) and/or Android Studio (for Android development) * **Linux** with Android Studio (for Android development) * **Windows** with Android Studio (for Android development) Note Using Cordova instead of Capacitor? Create the Capgo app the same way, then install [`@capgo/cordova-updater`](/docs/plugins/cordova-updater/getting-started/) in your Cordova project instead of the Capacitor plugin. ## Introduction to Capgo [Section titled “Introduction to Capgo”](#introduction-to-capgo) [Capgo in 15 min](https://www.youtube-nocookie.com/embed/NzXXKoyhTIo) ## Live updates are 3 step away [Section titled “Live updates are 3 step away”](#live-updates-are-3-step-away) ### Guided setup [Section titled “Guided setup”](#guided-setup) 1. Create your account at [https://capgo.app/register](https://capgo.app/register/). ![signup screenshot](/signup.webp "signup screenshot") 2. Use the Init commands to get started ```bash npx @capgo/cli@latest init [APIKEY] ``` You will be presented with a series of questions. Provide the necessary answers to complete the automated setup. 3. Deploy a live update Tip By following these steps, you’ll be up and running in no time. If you need any further assistance during the process, our support team is [here to help](https://support.capgo.app). Happy onboarding! [Detailed Onboarding Guide ](/docs/getting-started/onboarding/)See the complete step-by-step guide for the CLI onboarding process [Deploy a live update ](/docs/getting-started/deploy/)Learn how to deploy a live update to your app ### Manual setup [Section titled “Manual setup”](#manual-setup) In case the init command doesn’t work for you, you can manually add an app. 1. Connect the CLI to your account: ```bash npx @capgo/cli@latest login [APIKEY] ``` 2. Add the app to your account with this command: ```bash npx @capgo/cli@latest app add [APP_NAME] ``` 3. Install the plugin in your app: ```bash npm i @capgo/capacitor-updater ``` 4. Configure the plugin in your `capacitor.config` ```json { "plugins": { CapacitorUpdater: { "appId": "Your appID", "autoUpdate": "atBackground", "version": "1.0.0" } } } ``` [See all available options](/docs/plugins/updater/settings/). This information will be inferred if not provided. 5. Call the init method as early as possible in your app: ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater'; CapacitorUpdater.notifyAppReady(); ``` 6. Deploy a live update Installing for older Capacitor versions The command above (step 3) installs the latest version (v8.x) for Capacitor 8. For older Capacitor versions, use the appropriate npm tag: ```bash # Capacitor 7 npm i @capgo/capacitor-updater@lts-v7 # Capacitor 6 npm i @capgo/capacitor-updater@lts-v6 # Capacitor 5 npm i @capgo/capacitor-updater@lts-v5 # Capacitor 4 npm i @capgo/capacitor-updater@lts-v4 ``` Each plugin major version matches the Capacitor major version (v8 → Capacitor 8, v7 → Capacitor 7, v6 → Capacitor 6, v5 → Capacitor 5, v4 → Capacitor 4). When the latest line is `8.3.4`, the matching LTS line is `7.3.4` with the same features and bug fixes. The updater receives monthly mirrored LTS backports for `v7`/`v6`/`v5`; `lts-v4` remains available for Capacitor 4 outside that cadence. Other Capgo plugins are backported on demand. The Capgo CLI major does **not** need to match the plugin or Capacitor major — always use `npx @capgo/cli@latest`. See [Capgo versioning](/docs/versioning/) for the full policy. ## Keep going from Add an App [Section titled “Keep going from Add an App”](#keep-going-from-add-an-app) If you are using **Add an App** to plan native plugin work, connect it with [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives, and [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds. # One time setup checklist > What to configure once after onboarding so Capgo runs smoothly: store release, channels, delta upload, CI, and team access. You finished [onboarding](/docs/getting-started/onboarding/). Now configure Capgo **once**. After that, daily work is only **upload → test → deploy**. Ship a new store build first Installing the Capgo plugin in your project is not enough. **OTA updates only work on devices running a native app that already includes the plugin.** After you add Capgo and call `CapacitorUpdater.notifyAppReady()`: 1. Run `npx cap sync` 2. Build a new iOS / Android binary 3. Submit to the App Store, Play Store, TestFlight, or your internal distribution Users on an older store build **without** the plugin will never receive live updates. Uploading bundles to Capgo only affects devices on a Capgo-enabled binary. See also [troubleshooting](/docs/getting-started/troubleshooting/). **Rule:** channels are release lanes (`development`, `production`), not tickets, features, or developer names. *** ## One time setup checklist [Section titled “One time setup checklist”](#one-time-setup-checklist) 1. **Create channels**: pick the smallest set that fits (see below). 2. **Set default upload channel** in [app settings](/docs/webapp/main-app-page/): * Solo app → `production` * Team → `development` 3. **Production channel:** public on, device self-set off, block updates under native on, auto-update guard on `major`. 4. **Test channel** (`development` / `staging`): public off, device self-set on for QA. 5. **Upload from CI** with `--delta` (checksum and native dependencies are automatic): ```bash npx @capgo/cli@latest bundle upload \ --channel development \ --bundle "1.8.0-${BUILD_NUMBER}" \ --comment "commit ${GIT_SHA:0:7} run ${CI_RUN_ID}" \ --delta ``` The `--bundle` value **must** be valid [semantic versioning](/docs/live-updates/channels/#bundle-versioning-and-channels). Validate it in the [SemVer tester](/semver_tester/) before you upload. 6. **Deploy to production** only after testing, from the [dashboard](/docs/webapp/channels/) or CLI. 7. **Team & security:** invite once, least permissions, [2FA](/docs/webapp/mfa/) for the org, one API key in CI. Leave encryption, `min_update_version`, metadata, and preview **off** unless you have a clear reason. *** ## Pick your size [Section titled “Pick your size”](#pick-your-size) **Simple**: 1 app, 1 channel: `production` **Team**: `development` + `production`. Upload to dev, deploy to prod. **Native versions**: add channels only when needed, e.g. `production-9.0` + `test-9.0`. Keep store users on the main production channel. **Many apps**: same simple model per app (usually one `production` each). Do not create extra channels just because the org is big. **Release train** (optional): `staging` → `rc` → `production`. Same template on every app that needs it. Caution Do not use channels named after tickets, people, or CI variables like `${inputs_capgo_channel}`. *** ## Bundle name vs comment [Section titled “Bundle name vs comment”](#bundle-name-vs-comment) Bundle names are **required** to follow [semantic versioning](/docs/live-updates/channels/#bundle-versioning-and-channels). Capgo uses semver for compatibility checks, channel auto-update rules, and rollbacks. Validate every name in the [SemVer tester](/semver_tester/) before upload. * **Name** = semver from CI, e.g. `1.8.0`, `1.8.0-beta.1`, or `1.8.0-20260629.42` * **Comment** = free text for humans → `commit abc1234 run 28059070270` Use semver **pre-release** labels (the part after `-`) when you ship many builds under the same `MAJOR.MINOR.PATCH`. For example, keep `1.8.0` and add the date or build counter in the pre-release: `1.8.0-20260629.1`, `1.8.0-beta.2`. Do not invent custom formats like `fix-login-bug` or `2.5.2026062306`. They are not valid semver and uploads will fail or behave unpredictably. Put release notes in `--comment`, not in the bundle name. See also [version targeting](/docs/live-updates/version-targeting/) and [bundle versioning](/docs/live-updates/channels/#bundle-versioning-and-channels). *** ## Delta upload [Section titled “Delta upload”](#delta-upload) `--delta` uploads a **manifest** so devices download only changed files instead of the full bundle every time. Checksum is always computed automatically. You do not pass a checksum flag. ### Default: `--delta` (manifest + zip backup) [Section titled “Default: --delta (manifest + zip backup)”](#default---delta-manifest--zip-backup) ```bash npx @capgo/cli@latest bundle upload \ --channel development \ --bundle "1.8.0-${BUILD_NUMBER}" \ --delta ``` This is the recommended default for most apps. Capgo stores the manifest **and** keeps the full zip as a backup. Good when storage cost is not your main concern. ### Storage saving: `--delta-only` [Section titled “Storage saving: --delta-only”](#storage-saving---delta-only) ```bash npx @capgo/cli@latest bundle upload \ --channel development \ --bundle "1.8.0-${BUILD_NUMBER}" \ --comment "commit ${GIT_SHA:0:7} run ${CI_RUN_ID}" \ --delta-only ``` Use `--delta-only` when you want to **reduce Capgo storage**. Only the delta/manifest files are stored, not the full zip. Choose this for large apps or high upload volume where storage adds up. Trade-off: without the zip backup on the server, you rely fully on the manifest path. Skip `--delta-only` unless you actually need the storage savings. No extra plugin config is required on the device. The updater reads the manifest and fetches changed files only. Tip See [Delta updates](/docs/live-updates/differentials/) for troubleshooting and `directUpdate` behavior. *** ## Daily workflow [Section titled “Daily workflow”](#daily-workflow) ```plaintext Upload to development (--delta) → test → deploy to production → don't touch channel settings again ``` *** ## Common mistakes [Section titled “Common mistakes”](#common-mistakes) | Mistake | Fix | | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | Expecting OTA before a new store release | Rebuild and ship the native app after adding the plugin | | Uploading a bundle but not deploying to a channel | Assign the bundle to a channel (e.g. `production`) | | Channel per feature, ticket, or developer | Use permanent release lanes only | | Dynamic CI channel names | Fixed names: `development`, `production` | | Too many channels for a simple app | Start with 1-2 channels | | Device self-set on production | Off for production, on for test channels | | Skipping `--delta` | Add `--delta` to uploads; use `--delta-only` only when you need to save storage | | Non-semver bundle names | Follow [semantic versioning](/docs/live-updates/channels/#bundle-versioning-and-channels) and validate in the [SemVer tester](/semver_tester/) | | Changing versioning scheme over time | Keep semver; use pre-release labels for extra builds (`1.8.0-20260629.1`) | | Metadata / preview enabled without reason | Leave off by default | *** ## Learn more [Section titled “Learn more”](#learn-more) [Channels ](/docs/live-updates/channels/)Defaults, precedence, and routing. [Delta updates ](/docs/live-updates/differentials/)Why and how to use --delta. [CI/CD ](/docs/getting-started/cicd-integration/)Automate upload and deploy. [Bundles ](/docs/webapp/bundles/)Checksum, dependencies, and metadata. # CI/CD Integration > Integrating Capgo into your CI/CD pipeline allows you to fully automate the process of building and deploying updates to your app. By leveraging the Capgo CLI and semantic-release, you can ensure consistent, reliable deployments and enable rapid iteration. Integrating Capgo into your CI/CD pipeline allows you to fully automate the process of building and deploying updates to your app. By leveraging the Capgo CLI and semantic-release, you can ensure consistent, reliable deployments and enable rapid iteration. ## Benefits of CI/CD Integration [Section titled “Benefits of CI/CD Integration”](#benefits-of-cicd-integration) * **Automation**: No more manual steps or room for human error. Your entire build, test, and deployment process can be automated from end to end. * **Consistency**: Every deployment follows the same set of steps, ensuring a predictable and repeatable process. This is especially valuable when you have multiple team members contributing code. * **Faster iterations**: With automated deployments, you can ship updates more frequently and with confidence. No more waiting for manual QA or release approvals. ## Capgo CLI [Section titled “Capgo CLI”](#capgo-cli) The Capgo CLI is the key to integrating Capgo into your CI/CD workflow. It provides commands for pushing new bundle versions, managing channels, and more. The most important command for CI/CD integration is `bundle upload`: ```shell npx @capgo/cli@latest bundle upload --channel Production --apikey YOUR_API_KEY ``` If you use encryption you should provide it from one of these ways: **Using a private key file path:** ```shell npx @capgo/cli@latest bundle upload --channel Production --apikey YOUR_API_KEY --key-v2 PRIVATE_KEY_PATH ``` **Using the private key content directly (recommended for CI/CD):** ```shell npx @capgo/cli@latest bundle upload --channel Production --apikey YOUR_API_KEY --key-data-v2 PRIVATE_KEY_CONTENT ``` **Using environment variables (best practice for CI/CD):** ```shell npx @capgo/cli@latest bundle upload --channel Production --apikey YOUR_API_KEY --key-data-v2 "$CAPGO_PRIVATE_KEY" ``` ### Setting up Environment Variables for Encryption [Section titled “Setting up Environment Variables for Encryption”](#setting-up-environment-variables-for-encryption) For CI/CD environments, it’s recommended to store your private key as an environment variable rather than a file. Here’s how to set it up: 1. **Get your private key content:** ```shell cat .capgo_key_v2 | pbcopy ``` This copies the key content to your clipboard. 2. **Add it to your CI/CD environment:** * **GitHub Actions**: Add `CAPGO_PRIVATE_KEY` to your repository secrets * **GitLab CI**: Add it as a masked variable in your project settings * **CircleCI**: Add it as an environment variable in your project settings * **Jenkins**: Add it as a secret text credential 3. **Use it in your pipeline:** ```yaml - run: npx @capgo/cli@latest bundle upload --channel=production --apikey=${{ secrets.CAPGO_API_KEY }} --key-data-v2 "${{ secrets.CAPGO_PRIVATE_KEY }}" ``` **Note**: The `--key-data-v2` flag allows you to pass the private key content directly as a string, making it perfect for environment variables in CI/CD pipelines where you don’t want to create temporary files. This command uploads the current web build to the specified channel. You’ll typically run this as the last step in your CI/CD pipeline, after your web build has completed successfully. ## Setting up Capgo in your CI/CD Pipeline [Section titled “Setting up Capgo in your CI/CD Pipeline”](#setting-up-capgo-in-your-cicd-pipeline) While the exact steps will vary depending on your CI/CD tool of choice, the general process for integrating Capgo looks like this: 1. **Generate an API key**: Log in to the Capgo dashboard and create a new API key. This key will be used to authenticate the CLI in your CI/CD environment. Keep it secret and never commit it to your repository! 2. **Configure the `bundle upload` command**: Add a step to your CI/CD configuration that runs the `bundle upload` command with the appropriate arguments: upload.yml ```yaml - run: npx @capgo/cli@latest bundle upload --channel=production --apikey=${{ secrets.CAPGO_API_KEY }} ``` \n Replace `Production` with the channel you want to deploy to, `${{ secrets.CAPGO_API_KEY }}` with the environment variable holding your API key, and add `--key-data-v2 "${{ secrets.CAPGO_PRIVATE_KEY }}"` if using encryption. 3. **Add the `upload` step after your web build**: Ensure that the `upload` step comes after your web build has completed successfully. This ensures you’re always deploying your latest code.\n Here’s an example configuration for GitHub Actions:\n upload.yml ```yaml name: Deploy to Capgo on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '24' - run: npm ci - run: npm run build - run: npm install -g @capgo/cli - run: npx @capgo/cli@latest bundle upload --channel=production --apikey=${{ secrets.CAPGO_API_KEY }} --key-data-v2 "${{ secrets.CAPGO_PRIVATE_KEY }}" ``` ## Version Management with Semantic-release [Section titled “Version Management with Semantic-release”](#version-management-with-semantic-release) The recommended way to handle versioning with Capgo is to set the version in your `capacitor.config.ts` file by importing it from `package.json`: ```ts import pkg from './package.json' const config: CapacitorConfig = { // ... other config plugins: { CapacitorUpdater: { version: pkg.version, } } } ``` This approach allows you to: 1. Use semantic-release (or any other tool) to update the `package.json` version 2. Build your app with the updated version automatically included 3. Upload the bundle with the correct version Your CI/CD workflow would look like this: ```yaml - run: npm ci - run: npx semantic-release # Updates package.json version - run: npm run build # Builds with new version from capacitor.config - run: npx @capgo/cli@latest bundle upload --channel=production --apikey=${{ secrets.CAPGO_API_KEY }} ``` Here’s a sample `.releaserc` configuration file for semantic-release: ```json { "branches": [ "main", { "name": "beta", "prerelease": true } ], "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", "@semantic-release/changelog", [ "@semantic-release/git", { "assets": ["CHANGELOG.md", "package.json"], "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" } ] ] } ``` This configuration does the following: 1. Analyzes commit messages to determine the next version number, following the Conventional Commits spec. 2. Generates release notes based on the commits since the last release. 3. Updates the `CHANGELOG.md` file with the new release notes. 4. Updates the `package.json` version, which will be picked up by your capacitor.config. 5. Commits the updated `CHANGELOG.md`, `package.json`, and any other changed files back to the repository. Make sure to run semantic-release before building your app so that the updated version from `package.json` is included in your build through the capacitor.config. ### Auto-bump when the local version is already on Capgo [Section titled “Auto-bump when the local version is already on Capgo”](#auto-bump-when-the-local-version-is-already-on-capgo) Bundle names must be unique (deleted versions still occupy their name). If CI keeps uploading the same `package.json` version, the upload fails. Prefer bumping `package.json` (for example with semantic-release). When that is not practical, let the CLI pick the next free semver from the channel’s linked bundle, or else the latest remote app version: ```bash npx @capgo/cli@latest bundle upload --channel=production --auto-bump npx @capgo/cli@latest bundle upload --auto-bump major npx @capgo/cli@latest bundle upload --auto-bump minor # default when the flag has no value npx @capgo/cli@latest bundle upload --auto-bump patch # alias: fix npx @capgo/cli@latest bundle upload --auto-bump metadata npx @capgo/cli@latest bundle upload --channel=production --auto-bump ai ``` `--auto-bump ai` uses Capgo Cloudflare Workers AI to compare local bundle files against the previous Capgo/channel delta manifest, pick `major` | `minor` | `patch` | `metadata`, and print a short reason. With no previous Capgo version, AI is skipped and the bump is **patch**. Do not combine `--auto-bump` with `--bundle` / `-b`. See the [`bundle upload` reference](/docs/cli/reference/bundle/#bundle-upload) for the full option list. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) If you encounter issues with your Capgo CI/CD integration, here are a few things to check: * **API key**: Ensure your API key is valid and has the necessary permissions. If using an environment variable, double check that it’s set correctly. * **CLI version**: Make sure you’re using the latest version of the Capgo CLI. Older versions may have compatibility issues or lack certain features. * **Build artifacts**: Confirm that your web build is generating the expected output files. The Capgo CLI needs a valid web build to create a bundle. * **Network connectivity**: Check that your CI/CD environment has network access to the Capgo servers. Firewall or proxy issues can sometimes interfere with the `upload` command. If you’re still having trouble, reach out to Capgo support for assistance. They can help troubleshoot any issues with your specific setup. ## Conclusion [Section titled “Conclusion”](#conclusion) Integrating Capgo into your CI/CD pipeline with proper version management can greatly streamline your development workflow. By automating your deployments and versioning through the capacitor.config approach, you can ship updates faster and with more confidence. The recommended approach of setting the version in your `capacitor.config.ts` file and using semantic-release to update `package.json` provides a robust and reliable deployment process that allows you to focus on building great features rather than worrying about manual release steps. For more details on the Capgo CLI commands and options, check out the [CLI reference](/docs/cli/). And for a deeper dive into semantic-release configuration, see the [semantic-release docs](https://github.com/semantic-release/semantic-release). Happy deploying! ## Keep going from CI/CD Integration [Section titled “Keep going from CI/CD Integration”](#keep-going-from-cicd-integration) If you are using **CI/CD Integration** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration, and [GitLab CI/CD Integration](/docs/live-updates/integrations/gitlab-ci/) for the implementation detail in GitLab CI/CD Integration. # Deploy a Live Update > Learn how to deploy a live update to your app using Capgo's Live Updates feature, enabling real-time UI and logic updates without app store resubmission. Use Capgo’s Live Updates feature to update the UI and business logic of your app remotely, in real-time. Push JS bundle updates directly to your users without going through the app store to instantly fix bugs and ship new features. Tip Capgo uploads the generated web build folder. HTML, CSS, JavaScript, assets, and pure-JavaScript package changes can go OTA once they are bundled there. Changes to `capacitor.config.ts`, native plugin configuration, native packages, or iOS/Android project files require a native app release. This guide assumes you’ve completed the [Capgo Quickstart](/docs/getting-started/quickstart/) and have already: 1. Installed the `@capgo/capacitor-updater` SDK in your Capacitor app 2. Configured your app ID and update channel in `capacitor.config.ts` 3. Added in your code the `CapacitorUpdater.notifyAppReady()` method If you haven’t done those steps yet, please go back and complete the quickstart first. [Add an app ](/docs/getting-started/add-an-app/)Add an app to your Capgo account, and install the plugin in your app ## Uploading a Bundle [Section titled “Uploading a Bundle”](#uploading-a-bundle) With the Capgo SDK installed and configured, you’re ready to upload your first live update bundle: 1. Build your web assets: ```shell npm run build ``` 2. Upload the bundle to Capgo: * Console ```shell npx @capgo/cli@latest bundle upload --channel=production ``` * Github Actions .github/workflows/build\_and\_deploy.yml ```yml name: Build source code and send to Capgo concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: push: branches: - main jobs: deploy_to_capgo: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '24' - name: Install dependencies run: npm install - name: Build run: npm run build - name: Deploy to Capgo run: npx @capgo/cli@latest bundle upload -a ${{ secrets.CAPGO_TOKEN }} --channel ${{ env.CHANNEL }} env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ``` * Gitlab .gitlab-ci.yml ```yml stages: - build build: stage: build image: node:18 cache: - key: files: - package-lock.json paths: - .node_modules/ script: - npm install - npm run build - npx @capgo/cli@latest bundle upload -a $CAPGO_TOKEN --channel $CAPGO_CHANNEL artifacts: paths: - node_modules/ - dist/ only: - master ``` This will upload a new bundle version to the channel specified in the command. ### Troubleshooting Uploads [Section titled “Troubleshooting Uploads”](#troubleshooting-uploads) If your upload fails, double check: * Your app ID in `capacitor.config.ts` matches your app in the Capgo dashboard * You’re running the upload command from the root of your Capacitor project * Your web assets are built and up to date If you’re still having trouble, go to the [Troubleshooting](/docs/getting-started/troubleshooting/) section. ## Receiving an Update on a Device [Section titled “Receiving an Update on a Device”](#receiving-an-update-on-a-device) Once your bundle is uploaded, you can test the live update on a device: 1. Sync your app to the device: ```shell npx cap sync ios ``` 2. Open another terminal and run the following command to check the update status: ```shell npx @capgo/cli@latest app debug ``` 3. Run your app locally: ```shell npx cap run ios ``` Or open the iOS/Android project in Xcode/Android Studio and do a native run. 4. Keep the app open for about 30 seconds to allow the update to download in the background. 5. The logs will take a few seconds to update and show the update status. 6. Close and reopen the app. You should see your live update applied! Refer back to the [Capgo Quickstart](/docs/getting-started/quickstart/#receiving-a-live-update-on-a-device) for more details on testing live updates. ## Next Steps [Section titled “Next Steps”](#next-steps) Congrats on deploying your first live update with Capgo! 🎉 To learn more, review the rest of the [Capgo Live Updates documentation](/docs/live-updates/). Some key topics to check out next: * [Targeting Updates with Channels](/docs/live-updates/channels/) * [Customizing Update Behavior](/docs/live-updates/update-behavior/) * [Live Update Rollbacks](/docs/live-updates/rollbacks/) ## Keep going from Deploy a Live Update [Section titled “Keep going from Deploy a Live Update”](#keep-going-from-deploy-a-live-update) If you are using **Deploy a Live Update** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # CLI Onboarding Guide > Complete step-by-step guide to onboard your app with Capgo using the interactive CLI ## Quick Overview [Section titled “Quick Overview”](#quick-overview) The Capgo CLI provides an interactive onboarding that sets up live updates for your Capacitor app. You’ll: 1. ✅ Register your app in Capgo 2. 🔌 Install and configure the updater plugin 3. 🚀 Deploy your first live update 4. đŸ“± Test the update on your device **Estimated time:** 10-20 minutes (varies based on your internet speed and build time) Tip The onboarding is fully resumable - exit anytime and continue later from where you left off. ## Starting the Onboarding [Section titled “Starting the Onboarding”](#starting-the-onboarding) Run the onboarding command with your API key: ```bash npx @capgo/cli@latest init [APIKEY] ``` You’ll see the welcome message: ```plaintext Capgo onboarding đŸ›« ``` ## What Happens During Onboarding [Section titled “What Happens During Onboarding”](#what-happens-during-onboarding) The CLI will guide you through 13 interactive steps: **Setup Phase (Steps 1-6):** * Check your development environment (Xcode/Android Studio) * Add your app to Capgo and create a production channel * Install the `@capgo/capacitor-updater` plugin * Inject the required code into your app * Optionally enable end-to-end encryption * Choose a platform for testing (iOS or Android) **Testing Phase (Steps 7-12):** * Build your app and run it on a device/simulator * Make a visible code change (automatic or manual) * Upload the updated bundle to Capgo * See the live update appear on your device in real-time **Completion (Step 13):** * Your app is ready for live updates! 🎉 ## The 13-Step Onboarding Process [Section titled “The 13-Step Onboarding Process”](#the-13-step-onboarding-process) ### Step 1: Check Prerequisites [Section titled “Step 1: Check Prerequisites”](#step-1-check-prerequisites) The CLI checks your development environment to ensure you have the necessary tools installed. **What’s checked:** * **Xcode** (macOS only) - for iOS development * **Android SDK** - for Android development **Possible outcomes:** ✅ **Both environments found:** ```plaintext ✅ Xcode detected - iOS development ready ✅ Android SDK detected - Android development ready ``` ⚠ **No environment found:** ```plaintext ⚠ Xcode not found ⚠ Android SDK not found ❌ No development environment detected đŸ“± To develop mobile apps with Capacitor, you need: ‱ For iOS: Xcode (macOS only) - https://developer.apple.com/xcode/ ‱ For Android: Android Studio - https://developer.android.com/studio ``` **Questions you may be asked:** Caution If no development environment is detected, you’ll be asked if you want to continue. It’s recommended to install at least one platform before proceeding. ### Step 2: Add Your App [Section titled “Step 2: Add Your App”](#step-2-add-your-app) The CLI will log you into Capgo and add your app to your account. ```plaintext (spinner) Running: npm @capgo/cli@latest login *** Login Done ✅ ❓ Add {appId} in Capgo? ``` **If your app ID is already taken:** The CLI will suggest alternatives: ```plaintext ❌ App ID "com.example.app" is already taken 💡 Here are some suggestions: 1. com.example.app2 2. com.example.app3 3. com.example.app.new 4. com.example.app.app ❓ What would you like to do? ``` You can choose a suggestion or enter a custom app ID. Note App IDs must follow reverse domain notation (e.g., `com.example.myapp`) ### Step 3: Create Production Channel [Section titled “Step 3: Create Production Channel”](#step-3-create-production-channel) Channels allow you to manage different update streams for your app. ```plaintext ❓ Create default channel production for {appId} in Capgo? ``` Tip **Don’t worry!** This is just for local testing during onboarding. Creating a “production” channel doesn’t mean your updates will go live to customers immediately. You have full control over when updates are deployed. Select **Yes** unless you have specific channel requirements. **If you select Yes:** ```plaintext (spinner) Running: npm @capgo/cli@latest channel add production {appId} --default Channel add Done ✅ (or "Channel already added ✅") ``` A production channel will be created and set as default. This is the recommended option for most users. **If you select No:** ```plaintext If you change your mind, run it for yourself with: "npm @capgo/cli@latest channel add production {appId} --default" ``` You’ll need to create and configure channels manually later. Alternatively, you can: * Set the channel in your `capacitor.config.ts` file * Use the JavaScript `setChannel()` method to dynamically set the channel * Configure channels later from the Capgo web console ### Step 4: Install Updater Plugin [Section titled “Step 4: Install Updater Plugin”](#step-4-install-updater-plugin) The CLI will install the `@capgo/capacitor-updater` plugin compatible with your Capacitor version. ```plaintext ❓ Automatic Install "@capgo/capacitor-updater" dependency in {appId}? ``` **Version compatibility:** * **Capacitor 5**: Installs `@capgo/capacitor-updater` v5 * **Capacitor 6**: Installs `@capgo/capacitor-updater` v6 * **Capacitor 7**: Installs `@capgo/capacitor-updater` v7 * **Capacitor 8+**: Installs latest version Caution Capgo only supports Capacitor v5 and above. If you’re using an older version, you’ll need to upgrade first. **Instant updates option:** After installation, you’ll be asked: ```plaintext ❓ Do you want to set instant updates in {appId}? Read more: https://capgo.app/docs/live-updates/update-behavior/#applying-updates-immediately ``` Tip **What are instant updates?** With instant updates enabled, your app applies updates immediately when backgrounded and reopened. This works seamlessly because Capgo can distribute updates worldwide in under 300ms. Without it (standard mode), updates download in the background and apply on the next app restart. Instant updates are great for faster iteration during development and critical bug fixes in production. **If you select Yes:** * Updates will be configured to apply immediately when the app is backgrounded and reopened * `autoUpdate: 'always'` and `autoSplashscreen: true` will be added to your config * Your `capacitor.config.ts` will be updated automatically * **Delta updates** will be automatically enabled - this sends only the files that changed between updates instead of the full bundle, making updates much faster **If you select No:** * Updates will use standard behavior (download in background, apply on next restart) * You can always enable instant updates later by modifying your `capacitor.config.ts` ### Step 5: Add Integration Code [Section titled “Step 5: Add Integration Code”](#step-5-add-integration-code) The CLI will automatically inject the required code into your main application file. ```plaintext ❓ Automatic Add "CapacitorUpdater.notifyAppReady()" code and import in {appId}? ``` **What gets added:** ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater' CapacitorUpdater.notifyAppReady() ``` **Project type detection:** * **Nuxt.js**: Creates `plugins/capacitorUpdater.client.ts` * **Other frameworks**: Adds to your main entry file Tip **If auto-injection fails**, you can add the code manually to your main application file: **For Nuxt.js:** Create `plugins/capacitorUpdater.client.ts`: ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater' export default defineNuxtPlugin(() => { CapacitorUpdater.notifyAppReady() }) ``` **For other frameworks:** Add to your main entry file (e.g., `main.ts`, `index.js`, `App.tsx`): ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater' CapacitorUpdater.notifyAppReady() ``` Place this code after your imports and before your app initialization. For more details, see the [Add an App guide](/docs/getting-started/add-an-app/). ### Step 6: Setup Encryption (Optional) [Section titled “Step 6: Setup Encryption (Optional)”](#step-6-setup-encryption-optional) End-to-end encryption adds an extra security layer for your updates. ```plaintext 🔐 End-to-end encryption ✅ Use this for: Banking, healthcare, or apps with legal encryption requirements ⚠ Note: Makes debugging harder - skip if you don't need it ❓ Enable end-to-end encryption for {appId} updates? ``` Note Encryption is only available for Capacitor v6 and above. If you enable encryption, the CLI will: 1. Generate encryption keys 2. Offer to sync your Capacitor configuration ### Step 7: Select Platform [Section titled “Step 7: Select Platform”](#step-7-select-platform) Choose which platform to test with during onboarding. ```plaintext đŸ“± Platform selection for onboarding This is just for testing during onboarding - your app will work on all platforms ❓ Which platform do you want to test with during this onboarding? Options: - iOS - Android ``` Tip This only affects the onboarding process. Your final app will support all platforms. ### Step 8: Build Your Project [Section titled “Step 8: Build Your Project”](#step-8-build-your-project) The CLI will build your app and sync it with Capacitor. ```plaintext ❓ Automatic build {appId} with "npm run build"? ``` **What happens:** 1. Detects your project type 2. Runs your build script 3. Executes `npx cap sync {platform}` **If build script is missing:** You’ll be asked if you want to skip the build or add a build script to your `package.json`. ### Step 9: Run on Device [Section titled “Step 9: Run on Device”](#step-9-run-on-device) Test the initial version of your app on a device or simulator. ```plaintext ❓ Run {appId} on {PLATFORM} device now to test the initial version? ``` If you select **Yes**: ```plaintext (spinner) Running: npx cap run {platform} (device picker appears) App started ✅ đŸ“± Your app should now be running on your {platform} device with Capgo integrated 🔄 This is your baseline version - we'll create an update next ``` ### Step 10: Make a Test Change [Section titled “Step 10: Make a Test Change”](#step-10-make-a-test-change) Now it’s time to test Capgo’s update system by making a visible change. ```plaintext 🎯 Now let's test Capgo by making a visible change and deploying an update! ❓ How would you like to test the update? Options: - Auto: Let Capgo CLI make a visible change for you - Manual: I'll make changes myself ``` **Auto mode:** The CLI will automatically modify your files to add a visible test banner or change. **Manual mode:** You make your own changes (e.g., change text, colors, or add elements). **Version handling:** ```plaintext ❓ How do you want to handle the version for this update? Options: - Auto: Bump patch version ({currentVersion} → {nextVersion}) - Manual: I'll provide the version number ``` **Build with changes:** ```plaintext ❓ Build {appId} with changes before uploading? ``` Tip If you need to build manually in another terminal, select “No” and build yourself, then continue. ### Step 11: Upload Bundle [Section titled “Step 11: Upload Bundle”](#step-11-upload-bundle) Upload your updated app bundle to Capgo. ```plaintext ❓ Upload the updated {appId} bundle (v{version}) to Capgo? ``` The CLI runs: ```bash npx @capgo/cli@latest bundle upload ``` Tip **Delta updates with instant updates:** If you enabled instant updates in Step 4, the CLI will automatically ask if you want to enable delta updates. Delta updates send only the files that changed between versions instead of the entire bundle. Since usually only a few files change between updates, this makes downloads much faster. Select **Yes** for the best experience with instant updates. **Delta updates prompt (if an instant apply mode is enabled):** ```plaintext 💡 Instant updates are enabled in your config Delta updates send only changed files instead of the full bundle ❓ Enable delta updates for this upload? (Recommended with instant updates) ``` Caution For monorepos, you may need to provide additional paths to your `package.json` and `node_modules`. **Success:** ```plaintext ✅ Update v{version} uploaded successfully! 🎉 Your updated bundle is now available on Capgo ``` ### Step 12: Test Update on Device [Section titled “Step 12: Test Update on Device”](#step-12-test-update-on-device) Time to see the update in action! ```plaintext đŸ§Ș Time to test the Capgo update system! đŸ“± Go to your device where the app is running ``` **For instant updates:** ```plaintext 🔄 IMPORTANT: Background your app (swipe up/press home button) and then reopen it ⏱ The update should be downloaded and applied automatically ``` **For standard updates:** ```plaintext đŸ“± With standard updates, you will need to: 1. Background the app (swipe up/press home button) to start download 2. Wait a few seconds for download to complete 3. Background and foreground again to see the update ``` **Monitor logs:** ```plaintext ❓ Monitor Capgo logs to verify the update worked? ``` If you select **Yes**, you’ll see live logs from your device showing the update process. ### Step 13: Completion [Section titled “Step 13: Completion”](#step-13-completion) ```plaintext Welcome onboard ✈! ``` Congratulations! You’ve successfully set up Capgo live updates for your app. ## What You’ve Accomplished [Section titled “What You’ve Accomplished”](#what-youve-accomplished) After completing the onboarding, you have: ✅ App Registered Your app is registered in Capgo with a production channel ✅ Plugin Installed The Capacitor Updater plugin is installed and configured ✅ Code Integrated Integration code is added to your app ✅ Update Tested You’ve successfully deployed and received a live update ## Daily Workflow [Section titled “Daily Workflow”](#daily-workflow) For subsequent updates, use: ```bash npm run build npx @capgo/cli@latest bundle upload --channel=production ``` For more deployment options, see [Deploy a Live Update](/docs/getting-started/deploy/). ## Resuming Onboarding [Section titled “Resuming Onboarding”](#resuming-onboarding) If you exit the onboarding process, you can resume anytime: ```bash npx @capgo/cli@latest init [APIKEY] ``` You’ll see: ```plaintext You have already got to the step {stepNumber}/13 in the previous session ❓ Would you like to continue from where you left off? ``` Tip Progress is saved locally, so you can safely exit and resume the onboarding process. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### No Development Environment [Section titled “No Development Environment”](#no-development-environment) **Problem:** Neither Xcode nor Android SDK is detected. **Solution:** * **For iOS**: Install [Xcode](https://developer.apple.com/xcode/) (macOS only) * **For Android**: Install [Android Studio](https://developer.android.com/studio) ### App ID Already Taken [Section titled “App ID Already Taken”](#app-id-already-taken) **Problem:** Your app ID is already registered. **Solution:** Choose one of the suggested alternatives or enter a custom app ID in reverse domain notation. ### Build Script Missing [Section titled “Build Script Missing”](#build-script-missing) **Problem:** No build script found in `package.json`. **Solution:** Add a build script to your `package.json`: ```json { "scripts": { "build": "your-build-command" } } ``` ### Auto-Injection Failed [Section titled “Auto-Injection Failed”](#auto-injection-failed) **Problem:** CLI cannot automatically inject the integration code. **Solution:** Add the code manually to your main file: ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater' CapacitorUpdater.notifyAppReady() ``` ### Capacitor Version Too Old [Section titled “Capacitor Version Too Old”](#capacitor-version-too-old) **Problem:** Your Capacitor version is below v5. **Solution:** Upgrade Capacitor to v5 or higher: * [Upgrading to Capacitor 5](https://capacitorjs.com/docs/updating/5-0) * [Upgrading to Capacitor 6](https://capacitorjs.com/docs/updating/6-0) * [Upgrading to Capacitor 7](https://capacitorjs.com/docs/updating/7-0) ## Next Steps [Section titled “Next Steps”](#next-steps) Now that you’ve completed onboarding, explore these topics: [ One time setup checklist](/docs/getting-started/after-onboarding-setup-checklist/) [Configure channels, CI, and delta upload once for long-term stability](/docs/getting-started/after-onboarding-setup-checklist/) [ Deploy Updates](/docs/getting-started/deploy/) [Learn how to deploy updates from the Capgo dashboard](/docs/getting-started/deploy/) [ Update Types](/docs/live-updates/update-types/) [Reference of all OTA update types: apply timing, delay conditions, version blocking, and delivery](/docs/live-updates/update-types/) [ CI/CD Integration](/docs/getting-started/cicd-integration/) [Automate your update deployments with CI/CD](/docs/getting-started/cicd-integration/) [ Channels](/docs/live-updates/channels/) [Manage multiple update streams with channels](/docs/live-updates/channels/) [ Encryption](/docs/live-updates/encryption/) [Secure your updates with end-to-end encryption](/docs/live-updates/encryption/) [ Update Behavior](/docs/live-updates/update-behavior/) [Customize when and how updates are applied (direct, delta, etc.)](/docs/live-updates/update-behavior/) ## Getting Help [Section titled “Getting Help”](#getting-help) If you encounter issues during onboarding: * Check the [Troubleshooting Guide](/docs/getting-started/troubleshooting/) * Join the [Discord Community](https://discord.capgo.app) * Review the [FAQ](/docs/faq/) * Contact [Support](/docs/getting-help/) ## Keep going from CLI Onboarding Guide [Section titled “Keep going from CLI Onboarding Guide”](#keep-going-from-cli-onboarding-guide) If you are using **CLI Onboarding Guide** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # Overview > Get started with Capgo by learning the key concepts and steps to integrate and deploy live updates to your app. The quickstart tutorial will walk you through the key concepts of Capgo! Concepts that will be explored include: 1. Adding an app to your Capgo account 2. Integrating Capgo with your CI/CD 3. Triggering bundle upload on Capgo by pushing commits 4. Configuring and customizing the Capgo bundle publishing 5. Setting up your app to enable live updates via Capgo 6. Deploying live updates to your app from Capgo Simply follow the guide step-by-step, or navigate directly to the documentation for the component that interests you. [ Start the Tutorial](/docs/getting-started/add-an-app/) [Follow the quickstart tutorial and get up and running with Capgo in no time!](/docs/getting-started/add-an-app/) [ CLI Onboarding Guide](/docs/getting-started/onboarding/) [Complete step-by-step guide for the interactive CLI onboarding process.](/docs/getting-started/onboarding/) [ Ship updates](/docs/getting-started/deploy/) [Ship updates to your app from the Capgo dashboard.](/docs/getting-started/deploy/) [ Automate updates](/docs/getting-started/cicd-integration/) [Integrate Capgo with your CI/CD and trigger bundle uploads on Capgo by pushing commits.](/docs/getting-started/cicd-integration/) [ Trouble Shooting](/docs/getting-started/troubleshooting/) [Common issues and how to solve them.](/docs/getting-started/troubleshooting/) [ Wrap Up](/docs/getting-started/wrapping-up/) [Wrap up the tutorial and get a quick overview of what you’ve learned.](/docs/getting-started/wrapping-up/) Tip The Over-the-Air (OTA) update feature is applicable only for modifications made to HTML, CSS, and JavaScript files. If you make any changes to the native code, such as updates to Capacitor plugins, it is mandatory to resubmit the application to the app store for approval. Bundle Confidentiality Treat every bundle uploaded to Capgo as a public web asset unless you enable Capgo encryption. Private channels control which devices are eligible to receive an update, but they do not make the uploaded bundle confidential. Encryption protects the delivery path and prevents third parties from producing valid encrypted updates, but shipped web assets can still be reverse engineered from the app with enough effort because the public key is distributed in the binary. See [Live Update encryption](/docs/live-updates/encryption/). ## Join Discord Community [Section titled “Join Discord Community”](#join-discord-community) [Join the Capgo Discord Server!](https://discord.capgo.app) ## Maintenance [Section titled “Maintenance”](#maintenance) | Plugin version | Capacitor compatibility | Maintained | | ------------------ | ----------------------- | -------------------------------------------------------- | | v7.\*.\* (≄7.25.0) | v7.\*.\* | ✅ Fully supported | | v6.\*.\* (≄6.25.0) | v6.\*.\* | ✅ Fully supported | | v5.\*.\* (≄5.10.0) | v5.\*.\* | ✅ Fully supported | | v5.\*.\* (<5.10.0) | v5.\*.\* | ⚠ Deprecated | | v4.\*.\* | v4.\*.\* | ❌ No longer supported | | v3.\*.\* | v3.\*.\* | ❌ No longer supported | | >= 8 | v4.\*.\* | ⚠ Deprecated due to versioning issues in our CI process | ## Store Guideline Compliance [Section titled “Store Guideline Compliance”](#store-guideline-compliance) Android Google Play and iOS App Store have corresponding guidelines that have rules you should be aware of before integrating the Capacitor-updater solution within your application. ### Google play [Section titled “Google play”](#google-play) Third paragraph of [Device and Network Abuse](https://support.google.com/googleplay/android-developer/answer/9888379/?hl=en) topic describe that updating source code by any method other than Google Play’s update mechanism is restricted. But this restriction does not apply to updating javascript bundles. > This restriction does not apply to code that runs in a virtual machine and has limited access to Android APIs (such as JavaScript in a webview or browser). That fully allows Capacitor-updater as it updates just the JS bundles and won’t update native code. ### App Store [Section titled “App Store”](#app-store) Paragraph **3.3.2**, since back in 2015’s [Apple Developer Program License Agreement](https://developer.apple.com/programs/ios/information/) fully allows performing over-the-air updates of JavaScript and assets - and in its latest version (20170605) [downloadable here](https://developer.apple.com/terms/) this ruling is even broader: > Interpreted code may be downloaded to an Application but only so long as such code: (a) does not change the primary purpose of the Application by providing features or functionality that are inconsistent with the intended and advertised purpose of the Application as submitted to the App Store, (b) does not create a store or storefront for other code or applications, and (c) does not bypass signing, sandbox, or other security features of the OS. Capacitor Updater allows you to follow these rules in full compliance so long as the update you push does not significantly deviate your product from its original App Store approved intent. To further remain in compliance with Apple’s guidelines we suggest that App Store-distributed apps do not enable the `Force update` scenario, since in the [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/) state that: > Apps must not force users to rate the app, review the app, download other apps, or other similar actions in order to access functionality, content, or use of the app. This is not a problem for the default behavior of background update, since it won’t force the user to apply the new version until next time they close the app, but at least you should be aware of that role if you decide to show it. ## Open source [Section titled “Open source”](#open-source) The plugin is under the LGPL-3.0 License and the back-end is AGPL-3.0 License. > 💡 LGPL-3.0 means if someone modifies the code of the plugin, it’s mandatory to publish it, in open-source with the same licensing. If you use the code without modification, that doesn’t concern you. See the issue below for more details check the link 👇 [Licensing? ](https://github.com/Cap-go/capacitor-updater/issues/7) [Try GPTS Capgo to Get help instead of reading the docs ](https://chat.openai.com/g/g-3dMwHbF2w-capgo-doc-gpt) > You can include it in your app without worrying ## Final Notes [Section titled “Final Notes”](#final-notes) If you self-host and find this tool useful, please consider supporting my work by becoming a [GitHub sponsor](https://github.com/sponsors/riderx/). I made a bet to open-source all the code I built here instead of paywalling it. By opening it up instead of fighting and hiding, I believe we can make the world a better place. To make this possible, it’s necessary for all of us to do our part, including you đŸ„č. If Capgo cloud doesn’t meet your needs, you can back a bootstrapped Maker [here](https://github.com/sponsors/riderx/) on your own terms. ## Simple Maths [Section titled “Simple Maths”](#simple-maths) The price of the basic plan: $14\*12 = $168 a year. While average dev/hour = $60. That means that 3 hours wasted of dev time on self-host allows you to pay for a whole year, if you spent more than 3 hours you’re losing money ^^ ## Keep going from Overview [Section titled “Keep going from Overview”](#keep-going-from-overview) If you are using **Overview** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # Troubleshooting > Resolve common issues encountered while using Capgo with detailed troubleshooting steps and advanced options for upload and debugging. Here are some common issues you might encounter while using Capgo and how to resolve them. 🚀 Need Expert Help? Stuck with a complex issue? Our expert team is here to help! Get personalized support, code reviews, and custom solutions tailored to your specific needs. [Get Professional Support](/consulting/) ### Upload failures [Section titled “Upload failures”](#upload-failures) If your bundle upload fails, double check: * Your app ID in `capacitor.config.ts` matches your app in the Capgo dashboard * You’re running the upload command from the root of your Capacitor project * Your web assets are built and up to date #### Advanced upload options [Section titled “Advanced upload options”](#advanced-upload-options) The Capgo CLI provides some additional flags to help with common upload issues: * `--tus`: Uses the [tus resumable upload protocol](https://tus.io/) for more reliable uploads of large bundles or on poor network connections. If your bundle is over 10MB or you’re on a spotty connection, consider using `--tus`: ```shell npx @capgo/cli@latest bundle upload --tus ``` * `--package-json` and `--node-modules`: Tells Capgo where to find your root `package.json` and `node_modules` if your app uses a non-standard structure like a monorepo or npm workspace. Pass the path to the root `package.json` and the `--node_modules` path: ```shell npx @capgo/cli@latest bundle upload --package-json=path/to/package.json --node_modules=path/to/node_modules ``` Capgo needs this information to correctly bundle your app’s dependencies. You can combine these flags with other options like `--channel` as needed. See the [Capgo CLI docs](/docs/cli/) for full details on the available upload options. If you’re still having trouble with uploads, reach out to [Capgo support](https://support.capgo.app) for further assistance. ### Debugging Updates [Section titled “Debugging Updates”](#debugging-updates) If you’re encountering issues with live updates, the Capgo debug command is a helpful tool for troubleshooting. To use it: 1. Run the following command in your project directory: ```shell npx @capgo/cli@latest app debug ``` 2. Launch your app on a device or emulator and perform the action that should trigger an update (e.g. reopening the app after uploading a new bundle). 3. Watch the output of the debug command. It will log information about the update process, including: * When the app checks for an update * If an update is found and what version it is * Download and installation progress for the update * Any errors that occur during the update process 4. Use the debug logs to identify where the issue is occurring. For example: * If no update is found, double check that your bundle was uploaded successfully and the app is configured to use the correct channel. * If the update downloads but doesn’t install, make sure you’ve called `CapacitorUpdater.notifyAppReady()` and that the app was fully closed and reopened. * If you see an error message, look up that specific error in the Capgo docs or reach out to support for help. The debug command is especially useful for identifying issues with the update download and installation process. If the logs show the expected update version was found but not ultimately applied, focus your troubleshooting on the steps after the download. ### Debugging with Native Logs [Section titled “Debugging with Native Logs”](#debugging-with-native-logs) In addition to the Capgo debug command, the native logs on Android, iOS, and Electron can provide valuable troubleshooting information, especially for issues on the native side of the update process. #### Android Logs [Section titled “Android Logs”](#android-logs) To access the Android logs: 1. Connect your device or start your emulator 2. Open Android Studio and select “View > Tool Windows > Logcat” 3. In the Logcat window, filter the logs to just your app’s process by selecting it from the dropdown at the top 4. Look for any lines that include `Capgo` to find the SDK logs Alternatively, you can use the `adb logcat` command and grep for `Capgo` to filter the logs. The Capgo SDK will log key events during the update process, such as: * When an update check is initiated * If an update is found and what version it is * When the update download starts and completes * When the update installation is triggered * Any errors that occur during the native update steps Common Android-specific issues you might see in the logs include: * Network connectivity problems preventing the update download * File permissions errors when saving or reading the update bundle * Out of storage space for the update bundle * Failure to restart the app after the update is installed #### iOS Logs [Section titled “iOS Logs”](#ios-logs) To access the iOS logs: 1. Connect your device or start your simulator 2. Open Xcode and go to “Window > Devices and Simulators” 3. Select your device and click on “Open Console” 4. In the console output, look for any lines that include `Capgo` to find the SDK logs You can also use the `log stream` command in the terminal and grep for `Capgo` to filter the logs. Similar to Android, the Capgo SDK will log key iOS-side events: * Update check initiation and result * Download start, progress, and completion * Installation trigger and result * Any errors during the native update process iOS-specific issues you might identify in the logs include: * SSL certificate problems when downloading the update * App transport security blocking the update download * Insufficient storage space for the update bundle * Failure to properly extract or apply the update bundle #### Electron Logs [Section titled “Electron Logs”](#electron-logs) For Electron apps, check both the main process and renderer process output: 1. Run the Electron app from your terminal using your normal launch command (for example `bun run electron:dev` or `bun run electron:serve`) and watch the terminal output for startup, update checks, and network errors. 2. Open DevTools in the renderer window (View → Toggle Developer Tools) and inspect console logs and failed network requests while reproducing the update flow. 3. For packaged apps, check OS log tools for crashes or startup failures: * **macOS**: open `Console.app` and filter on your app name * **Windows**: open **Event Viewer** → **Windows Logs** → **Application** * **Linux**: use your desktop log viewer or `journalctl` for your app process When debugging updates, compare messages from both main-process and renderer-process logs to separate Electron bootstrap issues from Capgo update lifecycle issues. Across platforms, the native logs provide a lower-level view into the update process, with more details on the native implementation. They are especially useful for identifying issues that occur outside of the Capgo JavaScript layer. When troubleshooting a tricky live update problem, it’s a good idea to capture both the Capgo debug logs and the native logs for a comprehensive picture of what’s happening. The two logs together will give you the best chance of identifying and resolving the issue. ### Updates not applying [Section titled “Updates not applying”](#updates-not-applying) If you’ve uploaded a bundle but aren’t seeing the changes on your device: * Make sure you’ve called `CapacitorUpdater.notifyAppReady()` in your app code as shown in the [quickstart](/docs/getting-started/quickstart/) * Check that your device is connected to the internet and the Capgo debug logs show the update was downloaded * Try fully closing and reopening the app, as updates are only applied on a fresh launch * Look for any errors in the native logs that might indicate a problem applying the update Refer to the [deploying live updates](/docs/getting-started/deploy/) guide for more details on the update process. If you’re still stuck, use the `npx @capgo/cli@latest app debug` command and native logs to get more visibility into what’s happening. ### Common update failure codes [Section titled “Common update failure codes”](#common-update-failure-codes) If your logs show backend errors such as `disable_auto_update_to_major`, `semver_error`, or `cannot_update_via_private_channel`, use the dedicated guide: * [Common Update Problems](/docs/plugins/updater/commonproblems/) It explains what each common code means, why it happens, and how to fix it. ## SDK Installation [Section titled “SDK Installation”](#sdk-installation) If you’re having trouble installing the Capgo SDK, make sure: * Your app is using a supported version of Capacitor (4.0 or newer) * You’ve followed the [quickstart](/docs/getting-started/quickstart/) steps in order, including syncing your app after installing the SDK ## CI/CD Integration [Section titled “CI/CD Integration”](#cicd-integration) For issues with triggering Capgo uploads from your CI/CD pipeline: * Double check your Capgo authentication token is set up correctly * Make sure you’re running the upload command after your web assets are built * Check that the upload command is using the correct channel name for your target environment See the [CI/CD integration](/docs/getting-started/cicd-integration/) docs for more troubleshooting tips. You can also use the `npx @capgo/cli@latest app debug` command to confirm if your CI/CD-triggered updates are being received by the app. ## Keep going from Troubleshooting [Section titled “Keep going from Troubleshooting”](#keep-going-from-troubleshooting) If you are using **Troubleshooting** to plan storage and file handling, connect it with [@capgo/capacitor-data-storage-sqlite](/docs/plugins/data-storage-sqlite/) for the implementation detail in @capgo/capacitor-data-storage-sqlite, [Using @capgo/capacitor-data-storage-sqlite](/plugins/capacitor-data-storage-sqlite/) for the native capability in Using @capgo/capacitor-data-storage-sqlite, [@capgo/capacitor-file](/docs/plugins/file/) for the implementation detail in @capgo/capacitor-file, [Using @capgo/capacitor-file](/plugins/capacitor-file/) for the native capability in Using @capgo/capacitor-file, and [@capgo/capacitor-uploader](/docs/plugins/uploader/) for the implementation detail in @capgo/capacitor-uploader. # Wrapping up > Wrap up your Capgo journey with a concise overview of key concepts and next steps, ensuring a solid foundation for future exploration and mastery. Now that you have completed the quickstart guide, you should have a basic understanding of the key concepts of Capgo! The key concepts you have learned in this guide are: 1. Adding an app to your Capgo account 2. Integrating Capgo with your CI/CD pipeline 3. Triggering bundle uploads to Capgo on new commits 4. Configuring your app to enable live updates with the Capgo SDK 5. Deploying live updates to your app from the Capgo dashboard But there’s still more to learn about Capgo! Continue exploring the docs or check out some of these key topics: [ One time setup checklist](/docs/getting-started/after-onboarding-setup-checklist/) [One-time channel, CI, and delta upload setup for production.](/docs/getting-started/after-onboarding-setup-checklist/) [ CI/CD Integration](/docs/getting-started/cicd-integration/) [Already have a CI/CD pipeline? Learn how to incorporate Capgo into your existing workflow.](/docs/getting-started/cicd-integration/) [ Live Updates](/docs/live-updates/) [Dive deeper into Capgo’s live update features and best practices.](/docs/live-updates/) [ FAQ](/docs/faq/) [Find answers to common questions about Capgo.](/docs/faq/) [ Troubleshooting](/docs/getting-started/troubleshooting/) [Get help with common issues that can come up while using Capgo.](/docs/getting-started/troubleshooting/) ## Keep going from Wrapping up [Section titled “Keep going from Wrapping up”](#keep-going-from-wrapping-up) If you are using **Wrapping up** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, and [Update Types](/docs/live-updates/update-types/) for the implementation detail in Update Types. # How to > A comprehensive guide to Capgo, offering detailed tutorials, insightful tips, and advanced techniques to enhance your effective usage of the platform [Capgo versioning policy ](/docs/versioning/)How plugins, CLI, and Console are versioned, including LTS tags [How version works in Capgo ](https://capgo.app/blog/how-version-work-in-capgo/)capgo.app [How to release major version in Capgo ](https://capgo.app/blog/how-to-release-major-version-in-capgo/)capgo.app [How to send specific update to one user or a group ](https://capgo.app/blog/how-to-send-specific-version-to-users/)capgo.app ## CI / CD [Section titled “CI / CD”](#ci--cd) [Automatic build and release with GitHub Actions ](https://capgo.app/blog/automatic-build-and-release-with-github-actions/)capgo.app [Manage development and production build with GitHub Actions ](https://capgo.app/blog/automatic-build-and-release-with-github-actions/)capgo.app ## Contributing [Section titled “Contributing”](#contributing) [Contributing to Capgo open source ](https://github.com/Cap-go/capgo/blob/main/CONTRIBUTING.md)github.com ## Keep going from How to [Section titled “Keep going from How to”](#keep-going-from-how-to) If you are using **How to** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, and [Update Types](/docs/live-updates/update-types/) for the implementation detail in Update Types. # Overview > Discover how Capgo's Live Updates enable seamless JavaScript bundle updates, allowing you to push changes directly to users without app store delays. Use Capgo’s Live Updates feature to update the JavaScript bundles of your app remotely, in real-time. Push JS updates directly to your users on iOS, Android, and Electron without going through store-level review cycles to fix bugs and ship new features faster. Note Live Updates are limited to JavaScript bundle changes. If you need to update native code, such as adding or removing a plugin or changing native project configuration, you’ll need to submit a new binary build through the usual platform distribution process. Public Asset Model Unencrypted bundles uploaded to Capgo should be treated as public delivery assets. Channels determine which devices are offered an update, but channel privacy does not make the underlying bundle confidential. Encryption adds protection in storage and transit and stops third parties from producing valid encrypted updates, but it does not make shipped web assets impossible to inspect because the app contains the public key needed for decryption. See [end-to-end encryption](/docs/live-updates/encryption/) for the exact threat model. ## How Live Updates Work [Section titled “How Live Updates Work”](#how-live-updates-work) Capgo’s Live Update system has two key components: 1. The Capgo SDK, which you install in your app. The SDK checks for available updates and downloads them in the background. 2. Channels, which let you target updates to specific groups of users. You can use channels to manage different release tracks, such as `Production`, `Staging`, and `Dev`. When you upload a new JS bundle to Capgo and assign it to a channel, the Capgo SDK in apps configured for that channel will detect the update and download it. The next time the app restarts, the new bundle will be loaded. ## Why Capgo Logs Matter (marketing view) [Section titled “Why Capgo Logs Matter (marketing view)”](#why-capgo-logs-matter-marketing-view) * **Instant x-ray of every rollout**: Per-device timelines show checks, downloads, installs, policy blocks, and rollbacks, so you know exactly what happened—no guesswork or “it works on my phone” debates. * **Faster incident response**: Alert-like codes (e.g., rate limits, checksum fails, notifyAppReady misses) surface before users start flooding support, letting you ship a fix or rollback in minutes. * **Channel policy proof**: Logs verify that guardrails (block majors, disable emulators/dev builds, platform limits) are actively protecting production. * **Revenue & reputation protection**: See when updates stall on poor networks or hit plan limits, so you can intervene before conversions, sessions, or reviews drop. * **Single source of truth**: Product, QA, and Support share the same cloud log stream—no digging through Xcode/Android Studio or DM’ing engineers for native logs. ## Getting Started [Section titled “Getting Started”](#getting-started) To start using Live Updates, follow these steps: 1. Complete the [Capgo Quickstart](/docs/getting-started/quickstart/) to set up your app in Capgo and install the Capgo SDK. 2. In your app code, call `CapacitorUpdater.notifyAppReady()` after your app has finished initializing. This tells the Capgo SDK that your app is ready to receive updates. 3. Build your JS bundle and upload it to Capgo: ```shell npm run build npx @capgo/cli@latest bundle upload --channel=production ``` 4. Open your app and wait for the update to download. You can check the status with: ```shell npx @capgo/cli@latest app debug ``` 5. Once the update is downloaded, close and reopen your app to load the new bundle. See the [Deploying Live Updates](/docs/getting-started/deploy/) guide for more details. ## Next Steps [Section titled “Next Steps”](#next-steps) [ Update Types](/docs/live-updates/update-types/) [Reference of all OTA update types: apply timing, delay conditions, version blocking, and delivery.](/docs/live-updates/update-types/) [ Channels](/docs/live-updates/channels/) [Learn how to use channels to manage different release tracks and target updates to specific users.](/docs/live-updates/channels/) [ Progressive rollouts](/docs/live-updates/progressive-rollouts/) [Deliver a candidate bundle to a sticky cohort, monitor it, then promote or roll it back.](/docs/live-updates/progressive-rollouts/) [ Rollbacks](/docs/live-updates/rollbacks/) [Discover how to roll back to a previous JS bundle version if an update causes issues.](/docs/live-updates/rollbacks/) [ Update Behavior](/docs/live-updates/update-behavior/) [Customize how and when updates are downloaded and applied in your app.](/docs/live-updates/update-behavior/) [ Native + OTA Workflow](/docs/live-updates/native-ota-channel-workflow/) [Dev/production channels with `--fail-on-incompatible`, and how to upload when native code changes on purpose.](/docs/live-updates/native-ota-channel-workflow/) [ Test Native Builds](/docs/live-updates/testing-native-builds-without-live-updates/) [Verify a native binary without a downloaded live update masking its bundled web assets.](/docs/live-updates/testing-native-builds-without-live-updates/) [ Fast Updates](/docs/live-updates/differentials/) [Learn how to use fast updates to speed up the update process.](/docs/live-updates/differentials/) ## Keep going from Overview [Section titled “Keep going from Overview”](#keep-going-from-overview) If you are using **Overview** to plan store approval and distribution, connect it with [@capgo/capacitor-in-app-review](/docs/plugins/in-app-review/) for the implementation detail in @capgo/capacitor-in-app-review, [Using @capgo/capacitor-in-app-review](/plugins/capacitor-in-app-review/) for the native capability in Using @capgo/capacitor-in-app-review, [@capgo/capacitor-native-market](/docs/plugins/native-market/) for the implementation detail in @capgo/capacitor-native-market, [Using @capgo/capacitor-native-market](/plugins/capacitor-native-market/) for the native capability in Using @capgo/capacitor-native-market, and [Capacitor OTA Updates: App Store Approval Guide](/blog/capacitor-ota-updates-app-store-approval-guide/) for the practical context in Capacitor OTA Updates: App Store Approval Guide. # Breaking Changes > How to handle breaking changes with versioned channels This documentation explains how to handle breaking changes in your app using versioned channels. This approach allows you to maintain different versions of your app while ensuring users receive compatible updates. ## Example Scenario [Section titled “Example Scenario”](#example-scenario) Let’s say you have: * App version 1.2.3 (old version) - uses production channel * App version 2.0.0 (new version with breaking changes) - uses v2 channel * Live update 1.2.4 (compatible with 1.2.3) * Live update 2.0.1 (compatible with 2.0.0) ## Strategy: Always Use defaultChannel for Major Versions [Section titled “Strategy: Always Use defaultChannel for Major Versions”](#strategy-always-use-defaultchannel-for-major-versions) **Recommended approach:** Set a `defaultChannel` for every major version. This ensures you can always push updates to specific user groups without relying on dynamic channel assignment. ```ts // Version 1.x releases defaultChannel: 'v1' // Version 2.x releases defaultChannel: 'v2' // Version 3.x releases (future) defaultChannel: 'v3' ``` Tip **Benefits of this approach:** * **Always have control** over which users receive updates * **No dynamic channel switching** needed in your app code * **Clear separation** between different app versions * **Flexibility** to push updates to any specific version group ## 1. Create Channel for New Version [Section titled “1. Create Channel for New Version”](#1-create-channel-for-new-version) ```bash # Create channel for version 2.x npx @capgo/cli channel create v2 ``` ## 2. Update Capacitor Config for Version 2.0.0 [Section titled “2. Update Capacitor Config for Version 2.0.0”](#2-update-capacitor-config-for-version-200) Update your Capacitor config before building version 2.0.0 for the app store: capacitor.config.ts ```ts import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'Example App', plugins: { CapacitorUpdater: { // ... other options defaultChannel: 'v2' // All 2.0.0 users will use v2 channel } } }; export default config; ``` Note **For version 1.x:** If you didn’t set a `defaultChannel` initially, version 1.x users are on the `production` channel. For future major versions, always set a specific channel like `v3`, `v4`, etc. ## 3. Manage Separate Code Branches [Section titled “3. Manage Separate Code Branches”](#3-manage-separate-code-branches) Create separate git branches to maintain compatibility between app versions: ```bash # Create and maintain a branch for version 1.x updates git checkout -b v1-maintenance git push origin v1-maintenance # Your main branch continues with version 2.x development git checkout main ``` **Critical:** Never push JavaScript bundles to older apps that expect native code/APIs they don’t have. Always build updates from the appropriate branch: * **v1-maintenance branch**: For updates to 1.x apps (production channel) * **main branch**: For updates to 2.x apps (v2 channel) ## 4. Upload Bundles to Respective Channels [Section titled “4. Upload Bundles to Respective Channels”](#4-upload-bundles-to-respective-channels) ```bash # For 1.x updates: Build from v1-maintenance branch git checkout v1-maintenance # Make your 1.x compatible changes here npx @capgo/cli bundle upload --channel production # For 2.x updates: Build from main branch git checkout main # Make your 2.x changes here npx @capgo/cli bundle upload --channel v2 ``` ## 5. Enable Self-Assignment [Section titled “5. Enable Self-Assignment”](#5-enable-self-assignment) ```bash # Allow apps to self-assign to v2 channel npx @capgo/cli channel set v2 --self-assign ``` ## 6. Deploy to App Store [Section titled “6. Deploy to App Store”](#6-deploy-to-app-store) Build and deploy version 2.0.0 to the app store. All users who download this version (whether new users or existing users upgrading) will automatically use the v2 channel because it’s configured in the app bundle. Note **No code changes needed!** Since `defaultChannel: 'v2'` is bundled with the app store version, all users downloading version 2.0.0 will automatically use the correct channel. ## Scaling to Future Versions [Section titled “Scaling to Future Versions”](#scaling-to-future-versions) When you release version 3.0.0 with more breaking changes: ```bash # Create channel for version 3.x npx @capgo/cli channel create v3 ``` ```ts // capacitor.config.ts for version 3.0.0 const config: CapacitorConfig = { // ... plugins: { CapacitorUpdater: { defaultChannel: 'v3' // Version 3.x users } } }; ``` Now you can push updates to any version: * `production` channel → Version 1.x users * `v2` channel → Version 2.x users * `v3` channel → Version 3.x users ## 7. Cleanup (After Migration) [Section titled “7. Cleanup (After Migration)”](#7-cleanup-after-migration) Once all users have migrated to version 2.x (count 3-4 months): 1. Remove `defaultChannel` from your Capacitor config 2. Delete the v2 channel: ```bash npx @capgo/cli channel delete v2 ``` 3. Delete the v1-maintenance branch: ```bash git branch -d v1-maintenance git push origin --delete v1-maintenance ``` Tip This approach ensures users only receive updates compatible with their app version Always test updates thoroughly in each channel before deployment Note You can safely delete the v2 channel in Capgo even if some users still have the channel override. They will automatically receive updates from the production channel instead. ## Maintaining Version 1.x Updates [Section titled “Maintaining Version 1.x Updates”](#maintaining-version-1x-updates) To send updates compatible with version 1.x: 1. Switch to the v1-maintenance branch: ```bash git checkout v1-maintenance ``` 2. Make your changes and commit: ```bash # Make 1.x compatible changes git add . git commit -m "Fix for v1.x" git push origin v1-maintenance ``` 3. Build and upload to production channel: ```bash npx @capgo/cli bundle upload --channel production ``` Tip Keep your v1-maintenance branch up to date with bug fixes that are compatible with version 1.x, but never merge breaking changes from main ## Keep going from Breaking Changes [Section titled “Keep going from Breaking Changes”](#keep-going-from-breaking-changes) If you are using **Breaking Changes** to plan channel routing and staged rollout, connect it with [Channels](/docs/live-updates/channels/) for the implementation detail in Channels, [Channels](/docs/public-api/channels/) for the implementation detail in Channels, [Channels](/docs/webapp/channels/) for the implementation detail in Channels, [Beta Testing Solution](/solutions/beta-testing/) for the product workflow in Beta Testing Solution, and [Version Targeting Solution](/solutions/version-targeting/) for the product workflow in Version Targeting Solution. # Channels > Learn how to manage and configure Live Update channels in Capgo, enabling seamless app updates by directing specific JS bundle builds to devices configured for those channels. A Live Update channel points to a specific JS bundle build of your app that will be shared with any devices configured to listen to that channel for updates. When you [install the Capgo Live Updates SDK](/docs/getting-started/quickstart/) in your app, any native binary configured to that channel will check for available updates whenever the app is launched. You can change the build a channel points to at any time and can also roll back to previous builds if needed. Channels Do Not Provide Confidentiality Channels control update eligibility, not bundle secrecy. Even if a channel is private or self-assignment is disabled, any unencrypted bundle uploaded to Capgo should still be treated as a public asset delivered to clients. Encryption protects the delivery path and authenticity of updates, but shipped bundles can still be reverse engineered from the distributed app with enough effort because the public key is part of the client. See [Live Update encryption](/docs/live-updates/encryption/) for details. ## How a device picks a channel (precedence) [Section titled “How a device picks a channel (precedence)”](#how-a-device-picks-a-channel-precedence) When a device checks for an update, Capgo decides which channel to use in this strict order (highest priority first): 1. **Forced device mapping (Dashboard)** – Manually pin a specific device ID to a channel. Use for urgent debugging or controlled testing with a single real user. This always wins. 2. **Cloud override (per‑device) via Dashboard or API** – Created when you change the device’s channel in the dashboard or via API. Use for QA users switching between feature / PR channels or to reproduce a user issue. Reinstalling the binary does not clear it; deleting the device entry does. 3. **Plugin `setChannel()` local channel** – Created when the app calls `setChannel()` and the backend validates that the target channel allows self-assignment. The selected channel is stored locally on that device, takes effect instantly, and is not shown in the Device Override UI. Instant Channel Switching with setChannel() **Starting from plugin version 5.34.0, 6.34.0, 7.34.0, or 8.0.0** (depending on your major version), `setChannel()` works differently: it contacts the backend to **validate** that the channel is allowed (checking if self-assignment is enabled for that channel), then stores the channel **locally on the device** as `defaultChannel`. This means the new channel takes effect **instantly** for the next update check—no waiting for replication. Previously, `setChannel()` saved the channel override to the backend database (like Dashboard or API changes), and devices had to wait for data replication (up to 2 minutes) before the new channel was recognized. The new behavior only reads from the backend (for validation) and stores locally, making channel switches instant. Because `setChannel()` is local-only, it does **not** create a Device Override entry in the Capgo dashboard. The Device Override UI only shows overrides created from the dashboard or the Public API. **Note:** Even if a channel becomes disallowed after being set locally, the backend will still validate the channel during update checks, so security is maintained. **Important:** When channel changes are made via the Dashboard or API, there is still a replication lag of up to 2 minutes before all edge servers reflect the change. For instant channel switching, use `setChannel()` from your app code—it validates with the backend, then sets the channel locally for immediate effect. 4. **Capacitor config `defaultChannel` (test build default)** – If present in `capacitor.config.*` and no force/override/local channel exists, the app starts on this channel (e.g. `beta`, `qa`, `pr-123`). Intended for TestFlight / internal builds so testers land on a pre‑release channel automatically. Production builds typically leave this unset. 5. **Cloud Default Channel (primary path \~99% of users)** – If you mark a default channel in the dashboard, all normal end‑users (no force, no Dashboard/API override, no plugin local channel, no config defaultChannel) attach here. Change it to roll out or roll back instantly—no new binary. If you have platform-specific defaults (for example, one iOS-only, one Android-only, one Electron-only), each device lands on the default matching its platform. Leaving the cloud default unset is allowed; in that case the device must match on steps 1–4 to receive updates. Best practice: * Treat 1–4 as exception / testing layers; when you set a cloud default, real users should flow into it. If you choose not to set one, be deliberate about how users attach (typically via `defaultChannel` in config or per-device overrides). * Only configure `defaultChannel` in binaries you explicitly ship to testers. Leaving it unset keeps production logic centralized in the dashboard. * Use `setChannel()` sparingly in production—mainly for QA or targeted diagnostics. If a channel is disabled for the platform (iOS/Android/Electron toggles) when it would otherwise be chosen, the selection process skips it and continues down the list. > Summary: Force > Dashboard/API Override > Plugin `setChannel()` local channel > Config `defaultChannel` > Cloud Default. ## Default Channel Behavior [Section titled “Default Channel Behavior”](#default-channel-behavior) Setting a cloud default is optional, but it usually serves as the catch-all path for new devices. Without one, only devices that match on forced mappings, overrides, or a `defaultChannel` in the Capacitor config will receive updates. When you do choose to mark defaults, keep these patterns in mind: * **Single default (most common)** – If a channel has iOS, Android, and Electron enabled, it becomes the lone default; any device without overrides will attach here. * **Platform-specific defaults** – If you split channels by platform (for example, `ios-production` with only iOS enabled, `android-production` with only Android enabled, and `electron-production` with only Electron enabled), mark each one as the default for its platform. iOS devices go to the iOS default, Android devices go to the Android default, and Electron apps go to the Electron default. Remember that the cloud default and `defaultChannel` in `capacitor.config.*` both occupy the same decision layer. If you set a cloud default, you don’t need to duplicate the value in your Capacitor config—leave `defaultChannel` empty for production builds. Reserve `defaultChannel` for binaries you intentionally ship to testers or QA when you want them to start on a non-production channel even if the cloud default is different. You can change defaults at any time in the dashboard. When you swap a default, new devices obey the new routing immediately and existing devices follow the normal precedence rules the next time they check in. ## Setting up a Channel [Section titled “Setting up a Channel”](#setting-up-a-channel) During onboarding you create the first channel (most teams name it “Production”), but nothing is locked—you can rename or delete any channel at any time. To add additional channels later: 1. Go to the “Channels” section of the Capgo dashboard 2. Click the “New Channel” button 3. Enter a name for the channel and click “Create” Channel names can be anything you’d like. A common strategy is to match channels to your development stages, such as: * `Development` - for testing live updates on local devices or emulators * `QA` - for your QA team to verify updates before wider release * `Staging` - for final testing in a production-like environment * `Production` - for the version of your app that end users receive from the app stores ## Configuring the Channel in Your App [Section titled “Configuring the Channel in Your App”](#configuring-the-channel-in-your-app) With your channels created, you need to configure your app to listen to the appropriate channel. In this example, we’ll use the `Development` channel. Open your `capacitor.config.ts` (or `capacitor.config.json`) file. Under the `plugins` section, optionally set `defaultChannel` for **test builds** (internal / QA). For production builds, prefer omitting it so devices use the Cloud Default unless explicitly overridden. ```ts import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { plugins: { CapacitorUpdater: { // For a QA/TestFlight build – testers start on the Development channel automatically. defaultChannel: 'Development', // Production builds usually omit this so users attach to the Cloud Default channel. }, }, }; ``` Next, build your web app and run `npx cap sync` to copy the updated config file to your iOS, Android, and Electron projects. If you skip this sync step, your native projects will continue to use whichever channel they were previously configured for. Caution Channel selection order: Force > Dashboard/API device override > Plugin `setChannel()` local channel > Config `defaultChannel` > Cloud Default. Use `defaultChannel` only in test/internal builds; leave it out for production so users follow the Cloud Default (when set) instead of duplicating the routing in native config. You can still force (pin) a device or apply an override later—those immediately supersede the config value. > Channel names are case sensitive. ## Channel Options and Strategies [Section titled “Channel Options and Strategies”](#channel-options-and-strategies) Channels have several options that control who can receive updates and how updates are delivered. The most important ones are below. You can configure these from the web app, the CLI, or the Public API. * Default channel: Optionally mark the channel or platform-specific channels that new devices attach to. See “Default Channel Behavior” for routing scenarios. * Platform filters: Enable or disable delivery to `iOS`, `Android`, or `Electron` devices per channel. * Disable auto downgrade under native: Prevents sending an update when the device’s native app version is newer than the channel’s bundle (for example, device on 1.2.3 while channel has 1.2.2). * Allow development builds: Permit updates to development builds (useful for testing). * Allow emulator devices: Permit updates to emulators/simulators (useful for testing). * Allow device self‑assignment: Lets the app switch to this channel at runtime using `setChannel`. If disabled, `setChannel` will fail for this channel. ### Progressive rollouts [Section titled “Progressive rollouts”](#progressive-rollouts) A channel can keep a stable bundle while gradually exposing a separate rollout target to a sticky device cohort. You can pause, resume, promote, roll back, and configure an automatic failure response without switching the channel for everyone. See [Progressive rollouts](/docs/live-updates/progressive-rollouts/) for the delivery model, dashboard workflow, API fields, and CLI commands. ### Disable Auto Update strategies [Section titled “Disable Auto Update strategies”](#disable-auto-update-strategies) Use this to restrict which kinds of updates the channel will automatically deliver. Options: * major: Blocks a target bundle whose major version is higher than the device native baseline (`version_build`). Example: `1.2.3 -> 2.0.0` is blocked; `1.2.3 -> 1.9.0` is allowed. * minor: Blocks a target bundle whose major or minor version differs from `version_build`. Example: `1.2.3 -> 1.3.0` is blocked; `1.2.3 -> 1.2.4` is allowed. * patch: Strictest mode. Blocks any change to major, minor, or patch number. Only suffix changes are allowed while `MAJOR.MINOR.PATCH` stays identical. Examples: `1.0.0-beta.1 -> 1.0.0-beta.2` is allowed, `1.0.0+build.1 -> 1.0.0+build.2` is allowed, `1.0.0 -> 1.0.1` is blocked. * metadata: Require a minimum update version metadata on each bundle. Configure via CLI using `--min-update-version` or `--auto-min-update-version`. If missing, the channel is marked misconfigured and updates will be rejected until set. * none: Allow all updates according to [semver compatibility](/semver_tester/). These strategies compare the channel’s target bundle against the native baseline sent as `version_build`, not the current downloaded bundle sent as `version_name`. Learn more details and examples in Disable updates strategy at /docs/cli/commands/#disable-updates-strategy. Example (CLI): ```bash # Block major updates on the Production channel npx @capgo/cli@latest channel set production com.example.app \ --disable-auto-update major # Allow devices to self-assign to the Beta channel npx @capgo/cli@latest channel set beta com.example.app --self-assign ``` ### Using setChannel() from Your App [Section titled “Using setChannel() from Your App”](#using-setchannel-from-your-app) The `setChannel()` method allows your app to programmatically switch channels at runtime. This is particularly useful for: * QA/debug menus where testers can switch between channels * Beta program opt-in flows * Feature flag implementations * A/B testing scenarios ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater'; // Switch to the beta channel await CapacitorUpdater.setChannel({ channel: 'beta' }); // Optionally trigger an immediate update check after switching await CapacitorUpdater.setChannel({ channel: 'beta', triggerAutoUpdate: true }); ``` How setChannel() Works (v5.34.0+ / v6.34.0+ / v7.34.0+ / v8.0.0+) When `setChannel()` is called: 1. **Backend validation (read-only)**: A request is sent to the Capgo backend to validate the channel is allowed (checking self-assignment permissions) 2. **Local storage update**: If validation passes, the channel is saved to the device’s local storage as `defaultChannel` 3. **Instant effect**: The next update check uses the new channel immediately (no waiting for replication) **Why this matters:** In older versions, `setChannel()` saved the channel override to the backend database (same as Dashboard or API changes). Devices had to wait for backend replication (up to 2 minutes) before the channel change took effect. Now, `setChannel()` only reads from the backend (for validation) and stores locally, making channel switches instant. **Dashboard visibility:** A channel set with the plugin does not make the device appear as a Device Override in the Capgo UI. Only channel assignments created from the dashboard or the Public API are listed there. Use the dashboard or API when you need an admin-visible override. **Security note:** Even if a channel’s permissions change after being set locally (e.g., self-assignment is disabled), the backend will still validate the channel during update checks, ensuring security is maintained. **Comparison of channel change methods:** | Method | Effect Time | Persisted Where | Shown in Device Override UI | Use Case | | -------------------------- | ----------- | ------------------- | --------------------------- | -------------------------------------------- | | `setChannel()` from plugin | **Instant** | Device only (local) | No | User-initiated channel switching in-app | | Dashboard device override | Up to 2 min | Backend database | Yes | Admin-initiated changes for specific devices | | API channel assignment | Up to 2 min | Backend database | Yes | Automated backend integrations | For the best user experience when building channel-switching UIs, always use the plugin’s `setChannel()` method. Minimum versions for local-only channel switching: **5.34.0**, **6.34.0**, **7.34.0**, or **8.0.0** (depending on your major version). Each minor version number corresponds to the same feature set across all major versions (e.g., X.34.0 includes the same features whether X is 5, 6, 7, or 8). See [plugin installation](/docs/getting-started/add-an-app/) for version tags. ## Assigning a Bundle to a Channel [Section titled “Assigning a Bundle to a Channel”](#assigning-a-bundle-to-a-channel) To deploy a live update, you need to upload a new JS bundle build and assign it to a channel. You can do this in one step with the Capgo CLI: ```shell npx @capgo/cli@latest bundle upload --channel=Development ``` This will upload your built web assets and set the new bundle as the active build for the `Development` channel. Any apps configured to listen to that channel will receive the update the next time they check for one. You can also assign builds to channels from the “Bundles” section of the Capgo dashboard. Click the menu icon next to a build and select “Assign to Channel” to choose the channel for that build. ## Bundle Versioning and Channels [Section titled “Bundle Versioning and Channels”](#bundle-versioning-and-channels) It’s important to note that bundles in Capgo are global to your app, not specific to individual channels. The same bundle can be assigned to multiple channels. When versioning your bundles, we recommend using [semantic versioning with Capgo’s Semver Tester](/semver_tester/) and pre-release identifiers for channel-specific builds. For example, a beta release might be versioned as `1.2.3-beta.1`. In CI, if the local version was already uploaded, use `npx @capgo/cli@latest bundle upload --auto-bump` (optionally `major`, `minor`, `patch`/`fix`, `metadata`, or `ai`) so the CLI bumps from the channel’s linked bundle until a free name is found. With `ai`, Workers AI infers the level from the local vs previous delta manifest (falls back to `patch` with no previous Capgo version). You cannot combine it with `--bundle`. See [CI/CD Integration](/docs/getting-started/cicd-integration/#auto-bump-when-the-local-version-is-already-on-capgo) and the [CLI reference](/docs/cli/reference/bundle/#bundle-upload). This approach has several benefits: * It clearly communicates the relationship between builds. `1.2.3-beta.1` is obviously a pre-release of `1.2.3`. * It allows for reusing version numbers across channels, reducing confusion. * It enables clear rollback paths. If you need to roll back from `1.2.3`, you know `1.2.2` is the previous stable release. Here’s an example of how you might align your bundle versions with a typical channel setup: * `Development` channel: `1.2.3-dev.1`, `1.2.3-dev.2`, etc. * `QA` channel: `1.2.3-qa.1`, `1.2.3-qa.2`, etc. * `Staging` channel: `1.2.3-rc.1`, `1.2.3-rc.2`, etc. * `Production` channel: `1.2.3`, `1.2.4`, etc. Using [semver with pre-release identifiers](/semver_tester/) is a recommended approach, but not strictly required. The key is to find a versioning scheme that clearly communicates the relationships between your builds and aligns with your team’s development process. ## Rolling Back a Live Update [Section titled “Rolling Back a Live Update”](#rolling-back-a-live-update) If you deploy a live update that introduces a bug or otherwise needs to be reverted, you can easily roll back to a previous build. From the “Channels” section of the dashboard: 1. Click the name of the channel you want to roll back 2. Find the build you want to revert to and click the crown icon ![Rollback build](/select_bundle.webp) 3. Confirm the action The selected build will immediately become the active build for that channel again. Apps will receive the rolled back version the next time they check for an update. ## Automating Deployments [Section titled “Automating Deployments”](#automating-deployments) For more advanced workflows, you can automate your live update deployments as part of your CI/CD pipeline. By integrating Capgo into your build process, you can automatically upload new bundles and assign them to channels whenever you push to certain branches or create new releases. Check out the [CI/CD Integration](/docs/getting-started/cicd-integration/) docs to learn more about automating Capgo live updates. ### Least-privilege PR previews [Section titled “Least-privilege PR previews”](#least-privilege-pr-previews) Use an **App Preview** API key when CI needs one temporary channel per pull request but must not manage existing main/default channels. The key remains bound to the owning organization and selected app; it simply has no organization-wide role. Each non-public preview channel it creates receives its own automatic, channel-scoped lifecycle permission. 1. Have an organization administrator create a secure API key limited to the preview app and select **App Preview**. See [API Keys](/docs/webapp/api-keys/#use-an-app-preview-key-for-preview-workflows). 2. Use a unique, non-public channel such as `pr-123`. Do not pass `--default`, `--self-assign`, rollout options, or `--delete-linked-bundle-on-upload`. 3. Upload and promote the PR bundle in one command, then delete the owned channel and bundle when the PR closes: ```bash APP_ID="com.example.app" PREVIEW_CHANNEL="pr-123" BUNDLE_VERSION="1.2.3-pr.123" npx @capgo/cli@latest bundle upload "$APP_ID" \ --apikey "$CAPGO_PREVIEW_KEY" \ --path ./dist \ --channel "$PREVIEW_CHANNEL" \ --bundle "$BUNDLE_VERSION" npx @capgo/cli@latest channel delete "$PREVIEW_CHANNEL" "$APP_ID" \ --apikey "$CAPGO_PREVIEW_KEY" \ --delete-bundle \ --success-if-not-found ``` `bundle upload --channel` creates a missing channel, uploads the bundle, and promotes it in one flow. Cleanup is atomic and ownership-checked: the key can delete only a channel it created and its linked, unshared bundle. It cannot change, promote, or delete an existing main/default channel, another preview key’s channel, or another key’s bundle. If reviewers need a QR code or preview URL, an administrator must enable previews once for the app: ```bash npx @capgo/cli@latest app set "$APP_ID" --preview npx @capgo/cli@latest get-qr "$APP_ID" --channel "$PREVIEW_CHANNEL" --apikey "$CAPGO_PREVIEW_KEY" --url ``` An App Preview key cannot enable previews itself because it has no app-settings permission. In GitHub Actions, run secret-bearing preview jobs on `pull_request`, not `pull_request_target`, and restrict them to same-repository PRs with `github.event.pull_request.head.repo.full_name == github.repository`. ## Deploying to a Device [Section titled “Deploying to a Device”](#deploying-to-a-device) Now that you understand channels, you’re ready to start deploying live updates to real devices. The basic process is: 1. Install the Capgo SDK in your app 2. Configure the app to listen to your desired channel 3. Upload a build and assign it to that channel 4. Launch the app and wait for the update! For a more detailed walkthrough, see the [Deploying Live Updates](/docs/getting-started/deploy/) guide. Happy updating! ## Advanced Channel Usage: User Segmentation [Section titled “Advanced Channel Usage: User Segmentation”](#advanced-channel-usage-user-segmentation) Channels can be used for more than just development stages. They’re a powerful tool for user segmentation, enabling features like: * Feature flags for different user tiers * A/B testing * Gradual feature rollouts * Beta testing programs Learn how to implement these advanced use cases in our guide: [How to Segment Users by Plan and Channels for Feature Flags and A/B Testing](/blog/how-to-segment-users-by-plan-and-channels/). ## Keep going from Channels [Section titled “Keep going from Channels”](#keep-going-from-channels) If you are using **Channels** to plan channel routing and staged rollout, connect it with [Channels](/docs/public-api/channels/) for the implementation detail in Channels, [Channels](/docs/webapp/channels/) for the implementation detail in Channels, [Beta Testing Solution](/solutions/beta-testing/) for the product workflow in Beta Testing Solution, [Version Targeting Solution](/solutions/version-targeting/) for the product workflow in Version Targeting Solution, and [Capgo Environment Best Practices: Staging with One Mobile App ID](/blog/staging-environments-with-capgo-channels/) for the practical context in Capgo Environment Best Practices: Staging with One Mobile App ID. # Using Capgo in China > Learn how to configure Capgo Live Updates to work in China by using regional OST URLs for optimal performance and reliability. If you’re deploying your app to users in China, you’ll need to configure Capgo to use regional OST (Object Storage Technology) URLs to ensure reliable and fast updates. ## Why Use China-Specific URLs? [Section titled “Why Use China-Specific URLs?”](#why-use-china-specific-urls) Due to network infrastructure and regulations in China (the Great Firewall), direct connections to international servers can be slow or unreliable. Capgo provides dedicated OST URLs with data located in Hong Kong to minimize latency and ensure your users receive updates as quickly and reliably as possible. ## Configuration [Section titled “Configuration”](#configuration) To configure Capgo for China, you need to set three specific URLs in your Capacitor configuration file. These URLs point to Capgo’s Hong Kong-based infrastructure. 1. Open your `capacitor.config.ts` file 2. Add the following configuration to the `CapacitorUpdater` plugin section: ```typescript import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', updateUrl: 'https://updater.capgo.com.cn/updates', statsUrl: 'https://updater.capgo.com.cn/stats', channelUrl: 'https://updater.capgo.com.cn/channel_self', }, }, }; export default config; ``` 3. Rebuild your app to apply the changes: ```shell npm run build npx cap sync ``` ## Configuration Details [Section titled “Configuration Details”](#configuration-details) Here’s what each URL does: * **updateUrl**: `https://updater.capgo.com.cn/updates` - Used to check for and download available updates for your app * **statsUrl**: `https://updater.capgo.com.cn/stats` - Used to report analytics and usage statistics back to Capgo * **channelUrl**: `https://updater.capgo.com.cn/channel_self` - Used to retrieve channel configuration and determine which updates to apply Tip All three URLs must be configured together to ensure full functionality of the Capgo updater in China. ## Recommended Settings for China [Section titled “Recommended Settings for China”](#recommended-settings-for-china) Due to network performance limitations caused by the Great Firewall of China, we have specific recommendations for apps deployed in mainland China: ### Increase API Response Timeout [Section titled “Increase API Response Timeout”](#increase-api-response-timeout) The Capgo updater plugin aborts API calls when `responseTimeout` is exceeded (value is in **seconds**). Edge infrastructure in front of Capgo also treats about **3 seconds** as a failure budget for some paths. In mainland China, cross-border latency is often higher. Keep a higher `responseTimeout` so the plugin has enough room to finish update checks and downloads through `updater.capgo.com.cn` instead of failing early: ```typescript const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', // Seconds. Raise above the default (20) for China network conditions. responseTimeout: 60, updateUrl: 'https://updater.capgo.com.cn/updates', statsUrl: 'https://updater.capgo.com.cn/stats', channelUrl: 'https://updater.capgo.com.cn/channel_self', }, }, }; ``` Tip Prefer `responseTimeout: 60` (or higher) for China deployments. A low timeout does not make updates faster — it only causes the plugin to give up while the request may still succeed on Capgo’s side. ### Use Background Updates [Section titled “Use Background Updates”](#use-background-updates) We **strongly recommend using `autoUpdate: 'atBackground'`** for apps in China. Network connectivity in China is less performant than in other regions, and instant apply modes can lead to a poor user experience if downloads are interrupted or slow. Instead, use the default update behavior where updates download in the background and apply when the app backgrounds or restarts. This provides a more reliable experience for your users. ```typescript const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', // Recommended for China updateUrl: 'https://updater.capgo.com.cn/updates', statsUrl: 'https://updater.capgo.com.cn/stats', channelUrl: 'https://updater.capgo.com.cn/channel_self', }, }, }; ``` Caution While our Hong Kong-based infrastructure helps minimize latency and improve reliability, network performance to mainland China can still be affected by the Great Firewall. Using background updates helps ensure updates complete successfully without disrupting the user experience. ## Complete Configuration Example [Section titled “Complete Configuration Example”](#complete-configuration-example) Here’s a complete example with recommended settings for apps deployed in China: ```typescript import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'My App', webDir: 'dist', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', // Recommended for better reliability in China responseTimeout: 60, // Seconds — give China network more room updateUrl: 'https://updater.capgo.com.cn/updates', statsUrl: 'https://updater.capgo.com.cn/stats', channelUrl: 'https://updater.capgo.com.cn/channel_self', }, }, }; export default config; ``` ## Testing Your Configuration [Section titled “Testing Your Configuration”](#testing-your-configuration) After configuring the China-specific URLs, you can verify that updates are working correctly: 1. Upload a new bundle to Capgo: ```shell npx @capgo/cli@latest bundle upload --channel=production ``` 2. Install your app on a test device in China 3. Monitor the update process: ```shell npx @capgo/cli@latest app debug ``` 4. Check that updates are being downloaded from the China OST URLs Note The update behavior and timing remain the same as with standard Capgo configuration. See the [Update Behavior](/docs/live-updates/update-behavior/) documentation for details on how and when updates are applied. ## Multi-Region Deployment [Section titled “Multi-Region Deployment”](#multi-region-deployment) If your app serves users both inside and outside China, you can use the Chinese domain configuration for all users worldwide. The `updater.capgo.com.cn` domain is resolved globally thanks to Alibaba DNS infrastructure, making it accessible both inside China and everywhere else in the world. ### Using Chinese Domains Globally [Section titled “Using Chinese Domains Globally”](#using-chinese-domains-globally) The Chinese domain URLs work seamlessly for multi-region apps: ```typescript const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', // Recommended for China users updateUrl: 'https://updater.capgo.com.cn/updates', statsUrl: 'https://updater.capgo.com.cn/stats', channelUrl: 'https://updater.capgo.com.cn/channel_self', }, }, }; ``` This single configuration will work for: * Users in mainland China (using Hong Kong-based infrastructure) * Users outside China (accessing the same infrastructure via Alibaba DNS) **Performance Considerations:** While the `.cn` domain is resolved globally through Alibaba DNS and works everywhere, it’s slightly less performant for users outside China compared to the standard domain (`api.capgo.app`), which is resolved directly by Cloudflare where our backend is hosted. However, DNS resolution is fast, so the performance difference is minimal and won’t significantly impact the user experience. Tip Using the `.cn` domain for all users simplifies your deployment and ensures consistent update behavior across all regions. You don’t need separate builds or environment-based configurations. The small performance trade-off outside China is typically worth the simplified deployment. ### Alternative: Region-Specific Configurations [Section titled “Alternative: Region-Specific Configurations”](#alternative-region-specific-configurations) If you prefer to optimize differently for each region, you can also consider: * Building separate app variants with different configurations * Using environment-based configuration to dynamically set the URLs * Creating different release channels for different regions If you need assistance with multi-region deployment strategies, please contact us at or join our [Discord community](https://discord.capgo.app) for help. ## Monitoring China Infrastructure [Section titled “Monitoring China Infrastructure”](#monitoring-china-infrastructure) You can monitor the health and status of Capgo’s China-specific endpoints at [status.capgo.com.cn](https://status.capgo.com.cn/). Use this page to check for incidents, latency, and uptime of the China OST URLs before troubleshooting your app. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) If you experience issues with updates in China: 1. **Verify your configuration** - Double-check that all three URLs are correctly set in your `capacitor.config.ts` 2. **Raise `responseTimeout`** - Use at least `60` seconds in China so the plugin does not abort while the update request is still in flight 3. **Check network connectivity** - Ensure your device can reach the `updater.capgo.com.cn` domain 4. **Check the China status page** - Review [status.capgo.com.cn](https://status.capgo.com.cn/) for any ongoing incidents or degraded performance 5. **Review logs** - Use `npx @capgo/cli@latest app debug` to check for error messages 6. **Test updates** - Try uploading a new bundle and monitoring the download process 7. **Contact support** - If issues persist, reach out to us at or join our [Discord community](https://discord.capgo.app) for assistance Caution Make sure to use the `.cn` domain (`updater.capgo.com.cn`) and not the standard international domain when configuring for China. ## Next Steps [Section titled “Next Steps”](#next-steps) * Learn about [Update Behavior](/docs/live-updates/update-behavior/) to customize when updates are applied * Explore [Channels](/docs/live-updates/channels/) to manage different release tracks * Review [Encryption](/docs/live-updates/encryption/) to secure your updates ## Keep going from Using Capgo in China [Section titled “Keep going from Using Capgo in China”](#keep-going-from-using-capgo-in-china) If you are using **Using Capgo in China** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, and [Update Types](/docs/live-updates/update-types/) for the implementation detail in Update Types. # Native Compatibility > Why Capgo live updates can't change native code, how Capgo detects native-incompatible bundles, and how to ship native changes safely. A Capgo live update replaces your app’s **JavaScript bundle** instantly, but it can’t change the **native** part of your app — the Capacitor/Cordova plugins, native dependencies, and native project configuration that are compiled into the installed binary. When a new bundle expects native code that the installed binary doesn’t have, the bundle is **native-incompatible**: Capgo can still deliver it, but it may crash or misbehave on devices that are still running the older native build. This page explains how Capgo detects native compatibility, what an incompatible update means for your users, and how to ship native changes safely. Note Live updates are limited to JavaScript bundle changes. If you need to update native code — adding or removing a plugin, upgrading Capacitor, or changing native project configuration — you’ll need to submit a new binary build through the usual app-store distribution process. ## TLDR: OTA or native? [Section titled “TLDR: OTA or native?”](#tldr-ota-or-native) Capgo can send files from your generated web build folder. If the change only affects HTML, CSS, JavaScript, assets, or pure-JavaScript packages bundled into that output, ship it as a live update. Use a native app release when a change updates `capacitor.config.ts`, plugin configuration stored in Capacitor config, native plugins or dependencies, Capacitor itself, or iOS/Android project files. A practical check: if the change must update the native project through `npx cap sync` or `npx cap copy` before installed devices can use it, treat it as native. | Change | Ship with Capgo OTA? | Why | | -------------------------------------------------------------------- | -------------------- | ------------------------------------------------------------------ | | HTML, CSS, app JavaScript, images, fonts, and other web build assets | Yes | They are loaded from the web bundle at runtime. | | Pure-JavaScript package changes bundled into your web output | Yes | The generated JavaScript is part of the web bundle. | | `capacitor.config.ts` changes | No | Capacitor config is read into the native app at build time. | | Adding, removing, or upgrading Capacitor/Cordova plugins | No | The installed native binary must contain the matching native code. | | iOS or Android project file changes | No | Existing users need a new binary from the stores. | ## Client plugins by stack [Section titled “Client plugins by stack”](#client-plugins-by-stack) Capgo ships dedicated updater clients for each hybrid runtime: | Plugin | Use when | | ------------------------------------------------------------ | --------------------------------- | | [`@capgo/capacitor-updater`](/docs/plugins/updater/) | Capacitor iOS/Android apps | | [`@capgo/cordova-updater`](/docs/plugins/cordova-updater/) | Cordova iOS 7+ / Android 13+ apps | | [`@capgo/electron-updater`](/docs/plugins/electron-updater/) | Electron desktop apps | Native compatibility checks apply regardless of client plugin — they compare the bundle’s recorded native dependencies against the installed binary. ## Why native compatibility matters [Section titled “Why native compatibility matters”](#why-native-compatibility-matters) Every Capacitor app ships in two layers: * The **native binary** users install from the App Store / Play Store. It contains Capacitor, your native plugins, and native configuration. * The **JavaScript bundle** (your web app) that Capgo can update over the air. A live update swaps only the JavaScript layer. If that new JavaScript calls a native plugin or API that isn’t compiled into the installed binary, the call fails at runtime — which can crash the app or silently break a feature. Put simply: Capgo cannot update native code, so a device running the old native build can’t safely run a bundle that was built against new native code. ## How Capgo detects compatibility [Section titled “How Capgo detects compatibility”](#how-capgo-detects-compatibility) When you upload a bundle — or run the check manually — Capgo compares the **native packages** in your local project (your Capacitor/Cordova plugins and their versions) against the native packages recorded for the bundle **currently live on the channel**: * If they match, the change is JavaScript-only and **safe to ship over the air**. * If a plugin was added, removed, or changed version, the bundle is **native-incompatible** — those changes only take effect once users install a new native binary. ### Check from the CLI [Section titled “Check from the CLI”](#check-from-the-cli) ```bash bunx @capgo/cli@latest bundle compatibility com.example.app --channel production ``` The CLI prints a table of each native package with its local version, the version live on the channel, and a status: ```text Package Local Remote Status @capacitor/core 6.1.2 6.1.2 ✅ @capacitor/share 6.0.0 6.0.0 ✅ @capacitor/camera 6.1.0 — ❌ not in the live bundle ``` Tip Add `--text` to swap the emojis for `OK`/`FAIL` (handy in CI logs), and `--package-json` / `--node-modules` to point at the right paths in a monorepo. ### Get a machine-readable verdict (CI) [Section titled “Get a machine-readable verdict (CI)”](#get-a-machine-readable-verdict-ci) For pipelines, `bundle releaseType` collapses the check into a single word: ```bash bunx @capgo/cli@latest bundle releaseType com.example.app --channel production # → OTA safe to ship as a live update # → native needs a new app-store build ``` Gate your release pipeline on this: ship a live update when it prints `OTA`, and trigger a native build when it prints `native`. ## What an incompatible update means for your users [Section titled “What an incompatible update means for your users”](#what-an-incompatible-update-means-for-your-users) Caution By default, detecting incompatibility does **not** block the upload — if you upload a native-incompatible bundle and set it as a channel’s active build, Capgo **will deliver it** to devices on that channel. (You can turn this into a hard gate with `--fail-on-incompatible` — see [Prevent incompatible deliveries](#prevent-incompatible-deliveries) below.) On devices still running the **older native binary**, the missing native code can cause crashes or broken features — even though the update downloaded and applied “successfully.” This is why a live update can be live and delivered yet still break the app for existing users, and why Capgo can warn you when an incompatible bundle goes live. Capgo’s [automatic rollback](/docs/live-updates/rollbacks/#automatic-rollback-protection) can catch a JavaScript error thrown before `notifyAppReady()` runs, but it isn’t a substitute for shipping compatible native code — a mismatch that crashes later, or crashes natively, can slip past it. ## How to ship native changes safely [Section titled “How to ship native changes safely”](#how-to-ship-native-changes-safely) ### Publish a new native build (the real fix) [Section titled “Publish a new native build (the real fix)”](#publish-a-new-native-build-the-real-fix) When a bundle needs new native code, build and submit a new binary to the App Store / Play Store (or rebuild with Capgo Cloud Build). Once users update the binary, the bundle’s native dependencies line up and the live update runs correctly. ### Roll back if an incompatible bundle is already live [Section titled “Roll back if an incompatible bundle is already live”](#roll-back-if-an-incompatible-bundle-is-already-live) If an incompatible bundle is already active on a channel, revert the channel to the last compatible build to stop serving it until the native build is out. See [Rollbacks](/docs/live-updates/rollbacks/). ### Prevent incompatible deliveries [Section titled “Prevent incompatible deliveries”](#prevent-incompatible-deliveries) Two complementary guards, both of which actually inspect your native packages: **Fail the upload in CI — `--fail-on-incompatible`** Add the flag to your `bundle upload` step. If the bundle’s native packages don’t match the channel’s currently-live version, the upload **fails with a non-zero exit and nothing is shipped** — so your pipeline stops you from silently publishing an OTA update that can’t take effect until users install a native build: ```bash bunx @capgo/cli@latest bundle upload --channel production --fail-on-incompatible ``` Compatible uploads — and cases where the check can’t run (a new channel, or no remote metadata) — pass through unchanged. In an interactive terminal it offers the Capgo Builder native-build flow instead; declining fails. (Can’t be combined with `--ignore-metadata-check`.) Tip When you **intentionally** need a bundle that differs from the channel’s live native packages (new plugin, Capacitor upgrade, and so on), omit `--fail-on-incompatible` for that baseline upload. Keep the flag on everyday OTA CI. Full channel workflow: [Native + OTA Channel Workflow](/docs/live-updates/native-ota-channel-workflow/). **Gate delivery by native version — `metadata` + `--auto-min-update-version`** When you *do* ship the native build and the bundle together, put the channel on the `metadata` strategy and upload with `--auto-min-update-version`. Capgo runs the compatibility check on every upload and, when a bundle needs new native code, raises the update floor so devices that haven’t installed the matching native build don’t receive it: ```bash # one-time: switch the channel to the metadata strategy bunx @capgo/cli@latest channel set production com.example.app --disable-auto-update metadata # from then on, Capgo sets the floor automatically on every upload bunx @capgo/cli@latest bundle upload --channel production --auto-min-update-version ``` Caution Version-number rules like `--disable-auto-update major` are **not** a substitute — they only block version jumps and never inspect native code, so a native change shipped in a minor or patch release still goes out. Use `--fail-on-incompatible` or `--auto-min-update-version`, which check your native packages. See [Version Targeting](/docs/live-updates/version-targeting/) for the full set of targeting options. ## Related [Section titled “Related”](#related) [ Native + OTA Workflow](/docs/live-updates/native-ota-channel-workflow/) [Dev/production channels, when to keep `--fail-on-incompatible`, and how to ship an intentional native baseline.](/docs/live-updates/native-ota-channel-workflow/) [ Auto OTA or Native](/docs/builder/ci-ota-or-native/) [Wire `bundle releaseType` into GitHub Actions or GitLab so CI picks live update vs Capgo Build.](/docs/builder/ci-ota-or-native/) [ Version Targeting](/docs/live-updates/version-targeting/) [Deliver only compatible bundles using channels, semver rules, and the metadata strategy.](/docs/live-updates/version-targeting/) [ Rollbacks](/docs/live-updates/rollbacks/) [Revert a channel to the last compatible build if an incompatible bundle went live.](/docs/live-updates/rollbacks/) [ Update Types](/docs/live-updates/update-types/) [How apply timing, delay conditions, and version blocking work together.](/docs/live-updates/update-types/) [ CLI: bundle](/docs/cli/reference/bundle/) [Reference for the bundle compatibility, releaseType, and upload options.](/docs/cli/reference/bundle/) ## Keep going from Native Compatibility [Section titled “Keep going from Native Compatibility”](#keep-going-from-native-compatibility) If you are using **Native Compatibility** to keep live updates safe, connect it with [Version Targeting](/docs/live-updates/version-targeting/) to route bundles by native version, [Rollbacks](/docs/live-updates/rollbacks/) to recover when an incompatible bundle ships, [Update Types](/docs/live-updates/update-types/) to understand channel version blocking, and the [Capgo CLI bundle reference](/docs/cli/reference/bundle/) for the compatibility and releaseType commands. # Compliance > Learn about Capgo's privacy practices, data collection, security compliance, and how we protect your users' information during live updates. Capgo is designed with privacy, security, and compliance in mind. This document explains what data is collected, how it’s used, and what measures are in place to protect your users’ privacy and ensure regulatory compliance when using Capgo’s live update service. ## Data Collection Overview [Section titled “Data Collection Overview”](#data-collection-overview) Capgo collects minimal data necessary to provide the live update service effectively. The data collection is focused on operational requirements rather than user tracking or analytics. ### What Data is Collected [Section titled “What Data is Collected”](#what-data-is-collected) Capgo collects only the data that is necessary to provide the live updates feature. When your app checks for updates or downloads new bundles, the following information is collected: * **App ID**: A unique identifier for your app that is used to associate the app with the correct account * **App Version Code**: The version code of the app that is used to determine which updates are compatible with the app * **App Version Name**: The version name of the app that is used for display purposes * **Platform**: The platform (iOS, Android, Electron) of the app that is used to determine which updates are compatible with the app * **Device ID**: A randomly generated, app-scoped device identifier used for live-update operation, update eligibility, de-duplication of monthly active devices, support, abuse prevention, and operational reliability. It is not an advertising ID, is not derived from hardware identifiers, and is not used to track users across apps, websites, or Capgo customers. On iOS, **v7.25.0+** keeps the ID through normal reinstalls using Keychain. On Android, use **v7.50.1+** (or **v5.50.1+** and **v6.50.1+** on those release lines); the ID is restored only when Android Backup/Restore retains the app preferences. Disabling backup, excluding those preferences, or clearing app data generates a new device ID. * **Bundle ID**: The unique identifier for the bundle that is currently installed on the device * **Channel Name**: The name of the channel that is selected to receive updates * **OS Version**: The version of the operating system that is used to determine which updates are compatible with the device * **Plugin Version**: The version of the @capgo/capacitor-updater plugin that is used to deliver updates to the device * **Request Country**: When available, the latest valid two-letter ISO 3166-1 code received from a Cloudflare-handled request for the device. It is not GPS or a location value supplied by your app. **Additional Technical Data:** * Update check timestamps * Download success/failure status * Bundle installation status * Rollback events and reasons * IP address (for geolocation and CDN optimization) Note You can verify the data that is collected by inspecting the source code of the @capgo/capacitor-updater plugin, which is open-source and available on [GitHub](https://github.com/Cap-go/capacitor-updater). Capgo does not collect direct personal identifiers such as names, email addresses, or phone numbers. We treat the app-scoped device identifier as pseudonymous personal data where GDPR applies; it is not an advertising ID, is not derived from hardware identifiers, and is not used to track users across apps, websites, or Capgo customers. ### Endpoint Storage Detail [Section titled “Endpoint Storage Detail”](#endpoint-storage-detail) The updater can use up to three configured endpoints for update checks, channel self-assignment, and statistics: * `updateUrl` (`/updates`) checks which bundle the device should receive. This endpoint is required for Capgo Cloud live updates. * `channelUrl` (`/channel_self`) reads and updates a device channel assignment. * `statsUrl` (`/stats`) sends explicit update lifecycle, health, and failure events. Set `statsUrl` to an empty string to disable these extra stats reports, or point it to a self-hosted endpoint or proxy you control. A proxy keeps statistics out of Capgo only when it terminates the payload instead of forwarding it. See the [self-hosted statistics endpoint contract](/docs/plugins/updater/self-hosted/handling-stats/). Disabling `statsUrl` changes only the explicit statistics path. `/updates` and `/channel_self` still need a stable, app-scoped `device_id` so Capgo can decide which update and channel apply and count monthly active devices for billing. When `statsUrl` is enabled, Capgo can store: | Record | Stored fields | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Billing MAU | `device_id`, `app_id`, `org_id`, `timestamp` | | Device inventory | `device_id`, `app_id`, `updated_at`, `platform`, `plugin_version`, `os_version`, `version_build`, `version_name`, `is_prod`, `is_emulator`, `default_channel`, `key_id`, optional `custom_id`, optional request country code | | Stats event | `device_id`, `app_id`, `action`, `version_name`, `created_at` | When `statsUrl` is disabled but `updateUrl` remains enabled, Capgo can still store: | Record | Stored fields | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Billing MAU | `device_id`, `app_id`, `org_id`, `timestamp` | | Device inventory | `device_id`, `app_id`, `updated_at`, `platform`, `plugin_version`, `os_version`, `version_build`, `version_name`, `is_prod`, `is_emulator`, `default_channel`, `key_id`, optional `custom_id`, optional request country code | | Update-decision event | `device_id`, `app_id`, `action`, `version_name`, `created_at`; actions can include `get`, `noNew`, `missingBundle`, `cannotGetBundle`, platform/version blocking actions, and plan or channel errors | For native-version billing and charts, runtime telemetry can also include `platform` and `version_build` with MAU usage when the deployed billing store supports those fields. Newer stats telemetry can also include optional stats `metadata` when the app sends it. Caution For HIPAA-minimum deployments, do not send `custom_id`, disable `allow_device_custom_id` for the app, and do not send stats `metadata`. If you disable `statsUrl`, remember that `/updates` still stores the billing and update-decision data listed above. The absolute minimum needed to bill MAU is a stable anonymous `device_id`, `app_id`, `org_id`, and a timestamp. ### What Data is NOT Collected [Section titled “What Data is NOT Collected”](#what-data-is-not-collected) Capgo explicitly does not collect: * Personal user information or credentials * App usage analytics or user behavior data * Content from your app or user-generated data * Location data beyond general geographic region * Advertising IDs, hardware-derived identifiers, or identifiers used to track users across apps, websites, or Capgo customers * Biometric or sensitive personal data ## Data Usage and Purpose [Section titled “Data Usage and Purpose”](#data-usage-and-purpose) The data collected by Capgo is used exclusively for: ### Service Operation [Section titled “Service Operation”](#service-operation) * Determining which updates are available for specific app versions * Optimizing content delivery through geographic CDN selection * Ensuring compatibility between updates and device capabilities * Managing update rollouts and channel assignments ### Service Improvement [Section titled “Service Improvement”](#service-improvement) * Monitoring update success rates and identifying issues * Optimizing download performance and reliability * Improving the overall update delivery system * Debugging and troubleshooting update failures ### Security and Integrity [Section titled “Security and Integrity”](#security-and-integrity) * Preventing abuse and ensuring service availability * Validating update authenticity and integrity * Protecting against malicious or corrupted updates * Maintaining service security and stability ## Data Storage and Retention [Section titled “Data Storage and Retention”](#data-storage-and-retention) ### Storage Location [Section titled “Storage Location”](#storage-location) * Update bundles and metadata are stored on secure cloud infrastructure * Data is distributed across multiple geographic regions for performance * Apps that need EU data residency can set `updateUrl` to `https://plugin.eu.capgo.app/updates`, `statsUrl` to `https://plugin.eu.capgo.app/stats`, and `channelUrl` to `https://plugin.eu.capgo.app/channel_self`. See [Data Location](/docs/live-updates/data-location/) for the exact configuration. * All data transmission is encrypted using industry-standard protocols (HTTPS/TLS) ### Data Retention [Section titled “Data Retention”](#data-retention) * Operational records are retained for service operation, security, billing, and support. * Bundle retention is configurable for each app in App Settings. Bundles that are linked to an active channel or rollout remain protected; unused bundles become eligible for removal under the app’s selected retention rule. * Retained historical bundles and Delta assets contribute to storage usage. Regional replication does not multiply storage consumption. * Personal data, if any, is deleted according to applicable data protection laws. ### Data Security [Section titled “Data Security”](#data-security) * All data is encrypted in transit and at rest * Access to data is restricted to authorized personnel only * Regular security audits and monitoring are performed * Industry-standard security practices are followed * **SOC 2 Certification**: Capgo is currently SOC 2 Type II certified, ensuring the highest standards of security, availability, and confidentiality. View our compliance status at [trust.capgo.app](https://trust.capgo.app) * **ISO 27001**: Capgo is ISO 27001 certified. View our compliance status at [trust.capgo.app](https://trust.capgo.app) * **Continuous Code Auditing**: Every commit is automatically audited by [SonarCloud](https://sonarcloud.io/summary/overall?id=Cap-go_capacitor-updater\&branch=main) for the [plugin](https://sonarcloud.io/summary/overall?id=Cap-go_capgo\&branch=main) and [backend](https://sonarcloud.io/summary/overall?id=Cap-go_capgo\&branch=main), ensuring code quality, security vulnerabilities detection, and maintainability * **Vulnerability Scanning**: Additional security scanning is performed by [Snyk](https://snyk.io/test/github/Cap-go/capgo) to detect and remediate security vulnerabilities in dependencies * **Infrastructure Security**: Our hosting infrastructure is continuously monitored and verified through [hosting security checks](https://hosting-checker.net/websites/api.capgo.app) * **AI-Powered Code Review**: Every pull request is reviewed by CodeRabbit AI to catch potential issues, security concerns, and maintain code quality standards ## Privacy Controls [Section titled “Privacy Controls”](#privacy-controls) ### For App Developers [Section titled “For App Developers”](#for-app-developers) As a Capgo user, you have control over: * **Channel Management**: Control which updates are distributed to which users * **Data Minimization**: Configure what device information is shared * **Geographic Controls**: Manage where your updates are distributed * **Retention Settings**: Control how long update data is retained ### For End Users [Section titled “For End Users”](#for-end-users) Your app users benefit from: * **Minimal Data Collection**: Only essential data for update delivery is collected * **No Tracking**: No cross-app or persistent user tracking * **Transparency**: This privacy policy explains exactly what data is collected * **Security**: All data transmission is encrypted and secure ## Compliance and Legal [Section titled “Compliance and Legal”](#compliance-and-legal) ### Data Protection Regulations [Section titled “Data Protection Regulations”](#data-protection-regulations) Capgo is designed to support compliance with major data protection regulations, including: * **GDPR** (General Data Protection Regulation) * **CCPA** (California Consumer Privacy Act) * **COPPA** (Children’s Online Privacy Protection Act) * Other applicable regional privacy laws ### Current compliance documents [Section titled “Current compliance documents”](#current-compliance-documents) * The [sub-processor list](https://capgo.app/subprocessors/) is Capgo’s current public source of truth. It is kept up to date and lists each provider’s purpose, processing location, transfer mechanism, and change history. * The [Data Processing Agreement](https://capgo.app/dpa/) is available for review. ### App Store and Play Store considerations [Section titled “App Store and Play Store considerations”](#app-store-and-play-store-considerations) Capgo updates only the Capacitor web layer: JavaScript, HTML, CSS, and static assets. It does not change your native binary, native plugins, permissions, entitlements, or store metadata. Each app is reviewed on its own merits, so Capgo cannot guarantee an individual App Store or Play Store approval. Use live updates only for web-layer changes that remain within the store rules and your submitted app’s scope. Ship a normal native release for native capabilities or material functionality changes. Review [Apple’s App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/) (including guideline 2.5.2) and [Google Play’s Device and Network Abuse policy](https://support.google.com/googleplay/android-developer/answer/16559646) for your app before release. ### Your Responsibilities [Section titled “Your Responsibilities”](#your-responsibilities) As an app developer using Capgo, you should: * Include appropriate privacy disclosures in your app’s privacy policy * Inform users about the use of live update services when required * Confirm that each planned update complies with applicable laws and store rules * Implement appropriate consent mechanisms if required Tip **Review your disclosures**: Capgo provides privacy controls and a documented data inventory, but you remain responsible for your app’s privacy declarations and regional compliance requirements. ## Privacy by Design [Section titled “Privacy by Design”](#privacy-by-design) Capgo follows privacy-by-design principles: ### Data Minimization [Section titled “Data Minimization”](#data-minimization) * Only collect data that is absolutely necessary for service operation * Avoid collecting personal or sensitive information * Use aggregated and anonymized data where possible ### Purpose Limitation [Section titled “Purpose Limitation”](#purpose-limitation) * Use collected data only for the stated purposes * Do not repurpose data for unrelated activities * Maintain clear boundaries on data usage ### Transparency [Section titled “Transparency”](#transparency) * Provide clear information about data collection and usage * Make privacy practices easily accessible and understandable * Regularly update privacy documentation ## Contact and Questions [Section titled “Contact and Questions”](#contact-and-questions) If you have questions about Capgo’s privacy practices or need to report a privacy concern: * Review our full Privacy Policy at [capgo.app/privacy](https://capgo.app/privacy/) * View our security and compliance status at [capgo.app/trust](https://capgo.app/trust/) * Contact our privacy team through the support channels * Report any privacy-related issues through our security contact Tip Remember to update your own app’s privacy policy to reflect the use of Capgo’s live update service and any data collection that may occur as part of the update process. ## Best Practices for Privacy [Section titled “Best Practices for Privacy”](#best-practices-for-privacy) When implementing Capgo in your app: 1. **Be Transparent**: Inform users about the live update functionality 2. **Minimize Data**: Only enable data collection features you actually need 3. **Secure Implementation**: Follow security best practices in your integration 4. **Regular Reviews**: Periodically review your privacy practices and update policies 5. **User Control**: Consider providing users with options to control update behavior By following these practices and understanding Capgo’s privacy approach, you can provide your users with a secure, privacy-respecting live update experience. ## Keep going from Compliance [Section titled “Keep going from Compliance”](#keep-going-from-compliance) If you are using **Compliance** to plan security and compliance, connect it with [HIPAA Compliance](/docs/live-updates/hipaa-compliance/) for regulated telemetry controls, [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, [Capgo Security](/security/) for the product workflow in Capgo Security, [Capgo Trust Center](/trust/) for the product workflow in Capgo Trust Center, and [Organization Security](/docs/webapp/organization-security/) for the implementation detail in Organization Security. # Custom Storage > Learn how to use custom storage solutions with Capgo Live Updates, including external URLs, S3 integration, and bundle encryption for secure deployments. Capgo supports custom storage solutions for your app bundles, allowing you to host your updates on your own infrastructure or third-party storage services. This is particularly useful for organizations with specific security requirements, compliance needs, or existing storage infrastructure. ## Overview [Section titled “Overview”](#overview) Custom storage in Capgo works by uploading your bundle to an external location and providing Capgo with the URL to access it. The Capgo SDK will then download updates directly from your custom storage location instead of Capgo’s default cloud storage. Tip Custom storage is ideal for: * Organizations with strict data residency requirements * Teams with existing CDN or storage infrastructure * Applications requiring additional security layers * Cost optimization for large bundle sizes ## External URL Upload [Section titled “External URL Upload”](#external-url-upload) The simplest way to use custom storage is by uploading your bundle to any publicly accessible URL and providing that URL to Capgo. ### Basic External URL Upload [Section titled “Basic External URL Upload”](#basic-external-url-upload) ```shell npx @capgo/cli@latest bundle upload --external https://your-domain.com/bundles/v1.2.3.zip ``` This command tells Capgo to reference the bundle at the specified URL instead of uploading it to Capgo’s cloud storage. ### With Encryption [Section titled “With Encryption”](#with-encryption) For secure external storage, you can encrypt your bundle and provide the decryption keys: ```shell npx @capgo/cli@latest bundle upload --external https://your-domain.com/bundles/v1.2.3.zip --iv-session-key YOUR_IV_SESSION_KEY ``` ## S3 Integration [Section titled “S3 Integration”](#s3-integration) Capgo provides built-in support for Amazon S3 and S3-compatible storage services. The CLI can automatically upload your bundle to S3 and configure Capgo to use the S3 URL. ### S3 Upload Options [Section titled “S3 Upload Options”](#s3-upload-options) ```shell npx @capgo/cli@latest bundle upload \ --s3-region us-east-1 \ --s3-apikey YOUR_ACCESS_KEY \ --s3-apisecret YOUR_SECRET_KEY \ --s3-bucket-name your-bucket-name ``` ### Complete S3 Configuration [Section titled “Complete S3 Configuration”](#complete-s3-configuration) For S3-compatible services or custom endpoints: ```shell npx @capgo/cli@latest bundle upload \ --s3-region us-east-1 \ --s3-apikey YOUR_ACCESS_KEY \ --s3-apisecret YOUR_SECRET_KEY \ --s3-endpoint https://s3.your-provider.com \ --s3-bucket-name your-bucket-name \ --s3-port 443 \ --no-s3-ssl # Only if your endpoint doesn't support SSL ``` ### S3 Configuration Parameters [Section titled “S3 Configuration Parameters”](#s3-configuration-parameters) | Parameter | Description | Required | | ------------------ | ----------------------------- | -------- | | `--s3-region` | AWS region for your S3 bucket | Yes | | `--s3-apikey` | S3 access key ID | Yes | | `--s3-apisecret` | S3 secret access key | Yes | | `--s3-bucket-name` | Name of your S3 bucket | Yes | | `--s3-endpoint` | Custom S3 endpoint URL | No | | `--s3-port` | Port for S3 endpoint | No | | `--no-s3-ssl` | Disable SSL for S3 upload | No | ## Bundle Preparation and Encryption [Section titled “Bundle Preparation and Encryption”](#bundle-preparation-and-encryption) When using custom storage, especially with encryption, you need to prepare your bundles properly. This involves creating a zip file and optionally encrypting it. ### Step 1: Create a Zip Bundle [Section titled “Step 1: Create a Zip Bundle”](#step-1-create-a-zip-bundle) First, create a zip file of your app bundle: ```shell npx @capgo/cli@latest bundle zip com.example.app --path ./dist ``` The zip command will return the checksum of the zip file. You can use this checksum to encrypt the zip file if needed. Use the `--json` option to get structured output including the checksum. #### Zip Command Options [Section titled “Zip Command Options”](#zip-command-options) ```shell npx @capgo/cli@latest bundle zip [appId] \ --path ./dist \ --bundle 1.2.3 \ --name myapp-v1.2.3 \ --json \ --no-code-check \ --key-v2 \ --package-json ../../package.json,./package.json ``` | Option | Description | | ----------------- | -------------------------------------------------------------------- | | `--path` | Path to the folder to zip (defaults to webDir from capacitor.config) | | `--bundle` | Bundle version number to name the zip file | | `--name` | Custom name for the zip file | | `--json` | Output results in JSON format (includes checksum) | | `--no-code-check` | Skip checking for notifyAppReady() call and index file | | `--key-v2` | Use encryption v2 | | `--package-json` | Paths to package.json files for monorepos (comma separated) | ### Step 2: Encrypt the Bundle (Optional) [Section titled “Step 2: Encrypt the Bundle (Optional)”](#step-2-encrypt-the-bundle-optional) For enhanced security, encrypt your zip bundle before uploading: ```shell # Using default local key npx @capgo/cli@latest bundle encrypt ./myapp.zip CHECKSUM # Using custom key file npx @capgo/cli@latest bundle encrypt ./myapp.zip CHECKSUM --key ./path/to/.capgo_key_v2 # Using key data directly npx @capgo/cli@latest bundle encrypt ./myapp.zip CHECKSUM --key-data "PRIVATE_KEY_CONTENT" ``` The `CHECKSUM` parameter is required and should be the checksum of your zip file. You can get the checksum from the zip command output (use `--json` option for structured output). By default, the encrypt command will use your local private signing key. You can specify a custom key using the `--key` or `--key-data` options. The encrypt command will return the `ivSessionKey` needed for upload or decryption. #### Encryption Command Options [Section titled “Encryption Command Options”](#encryption-command-options) | Option | Description | | ------------ | ------------------------------------------------------------------------- | | `zipPath` | Path to the zip file to encrypt (required) | | `checksum` | Checksum of the zip file (required) - get it from zip command | | `--key` | Custom path for private signing key (optional, uses local key by default) | | `--key-data` | Private signing key data directly (optional) | | `--json` | Output results in JSON format | Caution The encrypt command will output an `ivSessionKey` that you’ll need to provide when uploading with the `--iv-session-key` option. ## Complete Workflow Examples [Section titled “Complete Workflow Examples”](#complete-workflow-examples) ### Example 1: External URL with Encryption [Section titled “Example 1: External URL with Encryption”](#example-1-external-url-with-encryption) 1. **Build your app:** ```shell npm run build ``` 2. **Create a zip bundle:** ```shell npx @capgo/cli@latest bundle zip com.example.app --path ./dist --bundle 1.2.3 ``` Note the checksum returned by this command. 3. **Encrypt the bundle:** ```shell npx @capgo/cli@latest bundle encrypt ./com.example.app-1.2.3.zip CHECKSUM_FROM_STEP_2 ``` Note the `ivSessionKey` from the output. 4. **Upload to your storage:** Upload the encrypted zip file to your hosting service. 5. **Register with Capgo:** ```shell npx @capgo/cli@latest bundle upload \ --external https://your-cdn.com/bundles/com.example.app-1.2.3.zip \ --iv-session-key IV_SESSION_KEY_FROM_STEP_3 ``` ### Example 2: Direct S3 Upload [Section titled “Example 2: Direct S3 Upload”](#example-2-direct-s3-upload) 1. **Build your app:** ```shell npm run build ``` 2. **Upload directly to S3:** ```shell npx @capgo/cli@latest bundle upload \ --s3-region us-west-2 \ --s3-apikey YOUR_ACCESS_KEY \ --s3-apisecret YOUR_SECRET_KEY \ --s3-bucket-name your-app-bundles \ --channel Production ``` ### Example 3: S3 with Encryption [Section titled “Example 3: S3 with Encryption”](#example-3-s3-with-encryption) 1. **Build and zip:** ```shell npm run build npx @capgo/cli@latest bundle zip com.example.app --path ./dist --key-v2 ``` 2. **Encrypt the bundle:** ```shell npx @capgo/cli@latest bundle encrypt ./com.example.app.zip CHECKSUM ``` 3. **Upload to S3 with encryption:** ```shell npx @capgo/cli@latest bundle upload \ --s3-region us-west-2 \ --s3-apikey YOUR_ACCESS_KEY \ --s3-apisecret YOUR_SECRET_KEY \ --s3-bucket-name your-app-bundles \ --iv-session-key IV_SESSION_KEY_FROM_STEP_2 \ --channel Production ``` ## Security Considerations [Section titled “Security Considerations”](#security-considerations) When using custom storage, consider these security best practices: ### Access Control [Section titled “Access Control”](#access-control) * Ensure your storage URLs are accessible to your app users but not publicly discoverable * Use signed URLs or token-based authentication when possible * Implement proper CORS headers for web-based apps ### Encryption [Section titled “Encryption”](#encryption) * Always encrypt sensitive bundles using the Capgo encryption tools * Store encryption keys securely and rotate them regularly * Use HTTPS for all bundle URLs (required for mobile and Electron apps) ### Monitoring [Section titled “Monitoring”](#monitoring) * Monitor access logs to detect unusual download patterns * Set up alerts for failed bundle downloads * Regularly audit your storage permissions ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### Common Issues [Section titled “Common Issues”](#common-issues) **Bundle not downloading:** * Verify the URL is publicly accessible and uses HTTPS (required for mobile and Electron apps) * Check CORS headers for web apps * Ensure the bundle format is correct **Encryption errors:** * Verify the `ivSessionKey` matches the encrypted bundle * Check that the bundle was encrypted with the correct key * Ensure encryption v2 is used for new bundles **S3 upload failures:** * Verify your S3 credentials and permissions * Check bucket policies and CORS configuration * Ensure the specified region is correct ### Debug Commands [Section titled “Debug Commands”](#debug-commands) Check bundle status: ```shell npx @capgo/cli@latest app debug ``` Verify bundle integrity: ```shell npx @capgo/cli@latest bundle list ``` ## Next Steps [Section titled “Next Steps”](#next-steps) * Learn about [Channels](/docs/live-updates/channels/) to manage different deployment environments * Explore [Update Behavior](/docs/live-updates/update-behavior/) to customize how updates are applied * Set up [CI/CD Integration](/docs/getting-started/cicd-integration/) to automate your custom storage workflow ## Keep going from Custom Storage [Section titled “Keep going from Custom Storage”](#keep-going-from-custom-storage) If you are using **Custom Storage** to plan security and compliance, connect it with [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, [Capgo Security](/security/) for the product workflow in Capgo Security, and [Capgo Trust Center](/trust/) for the product workflow in Capgo Trust Center. # Data Location > Configure Capgo Cloud and the updater plugin to keep live update data in Europe. Capgo Cloud can keep the live update data generated by the updater plugin in Europe. For apps with EU data residency requirements, configure the plugin to use the EU Capgo Cloud host for update checks, statistics, and channel self-assignment. ## What the EU host controls [Section titled “What the EU host controls”](#what-the-eu-host-controls) The updater plugin talks to Capgo Cloud through three endpoints: * `updateUrl` checks which update is available and downloads the assigned bundle. * `statsUrl` sends update delivery, install, failure, and rollback statistics. * `channelUrl` reads and updates the device channel assignment through `channel_self`. Set these complete endpoint URLs to geo-block this plugin data path to Europe: * `updateUrl`: `https://plugin.eu.capgo.app/updates` * `statsUrl`: `https://plugin.eu.capgo.app/stats` * `channelUrl`: `https://plugin.eu.capgo.app/channel_self` When the update, stats, and `channel_self` requests use the EU URLs, Capgo Cloud stores the related live update data in Europe. Caution Use the EU URLs for all three endpoints together. Mixing `plugin.capgo.app` and `plugin.eu.capgo.app` can route part of the plugin data path outside Europe. ## Capacitor updater configuration [Section titled “Capacitor updater configuration”](#capacitor-updater-configuration) Set the URLs in `capacitor.config.ts`: ```typescript import type { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'My App', webDir: 'dist', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', updateUrl: 'https://plugin.eu.capgo.app/updates', statsUrl: 'https://plugin.eu.capgo.app/stats', channelUrl: 'https://plugin.eu.capgo.app/channel_self', }, }, }; export default config; ``` Note For iOS and Android production apps, changes to `capacitor.config.ts` are applied through the native binary. Sync the native projects and release a new app version so existing installs start using the EU endpoints. ## Electron updater configuration [Section titled “Electron updater configuration”](#electron-updater-configuration) The Electron updater uses the same Capgo Cloud endpoint names: ```typescript import { ElectronUpdater } from '@capgo/electron-updater'; const updater = new ElectronUpdater({ appId: 'com.example.app', updateUrl: 'https://plugin.eu.capgo.app/updates', statsUrl: 'https://plugin.eu.capgo.app/stats', channelUrl: 'https://plugin.eu.capgo.app/channel_self', }); ``` ## Migration notes [Section titled “Migration notes”](#migration-notes) * The EU host applies to future plugin requests after users install a build with the new configuration. * It does not rewrite historical plugin requests that were already sent to the default global host. * Keep using your normal Capgo Cloud workflow for channels, bundles, rollbacks, and monitoring. ## Keep going from Data Location [Section titled “Keep going from Data Location”](#keep-going-from-data-location) If you are using **Data Location** to plan security and compliance, connect it with [HIPAA Compliance](/docs/live-updates/hipaa-compliance/) for regulated telemetry controls, [Compliance](/docs/live-updates/compliance/) for privacy and retention details, [Encryption](/docs/live-updates/encryption/) for bundle protection, [Channels](/docs/live-updates/channels/) for rollout targeting, and [Settings](/docs/plugins/updater/settings/) for the updater plugin configuration reference. # Delta updates > Learn how Capgo's Delta (manifest) updates optimize data transfer by only sending changed files, enhancing performance on slower networks. Capgo’s Live Update system can deliver updates faster and more efficiently by only sending the changed files, rather than the entire JS bundle. This is especially beneficial for users on slower or metered network connections, as it minimizes the amount of data that needs to be downloaded. A second benefit is when the app have large assets who change rarely, like images or videos, compare to zipped JS files it will be downloaded only once. ## How Delta (Manifest) Updates Work [Section titled “How Delta (Manifest) Updates Work”](#how-delta-manifest-updates-work) Delta (manifest) updates in Capgo are handled by the Capgo plugin installed in your app. When you upload a new version of your app using the `--delta` flag, Capgo does the following: 1. Each file in your build is uploaded individually 2. Checksums are generated for each file 3. A new json manifest is created, listing all files and their checksums 4. This manifest is uploaded to the Capgo database When a device running your app checks for an update, the Capgo plugin receives the new manifest from the server. It compares this manifest to the one it currently has, identifying which files have changed based on the checksums and file paths. The plugin then downloads only the changed files, rather than the entire JS bundle. It reconstructs the new version of the app by combining these downloaded files with the unchanged files it already has. Manifest In case of Delta (manifest) updates, the device stores all downloaded files in a common cache. Capgo never cleans it, but the OS can at any time. ## Enabling Delta (Manifest) Updates [Section titled “Enabling Delta (Manifest) Updates”](#enabling-delta-manifest-updates) To enable Delta (manifest) updates for your Capgo app, simply use the `--delta` flag when uploading a new version: ```shell npx @capgo/cli@latest bundle upload --delta ``` If `autoUpdate` is set to an instant apply mode (`"atInstall"`, `"onLaunch"`, or `"always"`) in your `capacitor.config`, the CLI detects it. In non-interactive environments it sends Delta (manifest) updates automatically, and in interactive environments it prompts you to confirm before uploading. Legacy `directUpdate` config is still detected. Use `--no-delta` to force a full bundle upload. ## Delta update limitations [Section titled “Delta update limitations”](#delta-update-limitations) * **Empty files:** The CLI logs `Ignoring empty file...` and excludes zero-byte files from the Delta manifest. It does not fail the upload, so adding an empty file can change the resulting bundle without stopping your deployment. Do not include zero-byte files in Delta bundle paths. * **Spaces in paths:** Delta uploads fail before uploading files when a bundle path contains a space. Rename the file or directory to remove spaces before uploading a Delta update. ## Enforcing Delta (Manifest) Updates [Section titled “Enforcing Delta (Manifest) Updates”](#enforcing-delta-manifest-updates) If you want to ensure that all uploads are Delta (manifest) updates and prevent any accidental full bundle uploads, you can use the `--delta-only` flag: ```shell npx @capgo/cli@latest bundle upload --delta-only ``` When `--delta-only` is used, Capgo will only upload individual files and generate a manifest. Any device that does not support Delta (manifest) updates will not be able to download the update. You might want to use `--delta-only` if: * You always want to use Delta (manifest) updates and never want to allow full bundle uploads * You’re setting up a CI/CD pipeline and want to ensure all automated uploads are Delta (manifest) * Your app is large and bandwidth is constrained, so you need to minimize upload/download sizes If you need to do a full bundle upload while `--delta-only` is set, simply run the upload command without `--delta-only`. This will override the setting for that single upload, allowing you to push a complete bundle when needed. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) If Delta (manifest) updates don’t seem to be working (i.e. devices are always downloading the full JS bundle even for small changes), double check that: * You’re using the `--delta` flag every time you upload a new version * If using `--delta-only`, make sure you haven’t accidentally omitted the `--delta` flag * Your device is running the latest version of the Capgo plugin * Your device has a stable network connection and can reach the Capgo servers You can also use the Capgo webapp to check the details of your last upload: 1. Go to the [webapp](https://app.capgo.io) 2. Click on your app 3. Click on the bundles number of the stats bar. 4. Select the last bundle 5. Check the `Partial` field ![bundle type](/bundle_type.webp) If you continue to have trouble, please reach out to Capgo support for further assistance. They can check the server logs to confirm that your Delta (manifest) uploads are being processed correctly and that devices are receiving the updated manifests. That’s it! The `--delta` flag tells Capgo to perform the individual file uploads and manifest generation needed for Delta (manifest) updates. Note that you need to use `--delta` every time you upload a new version that you want to be delivered as a Delta (manifest) update. If you omit the flag, Capgo will upload the entire JS bundle as a single file, and devices will download the whole bundle even if only a small part has changed. ## Keep going from Delta updates [Section titled “Keep going from Delta updates”](#keep-going-from-delta-updates) If you are using **Delta updates** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, and [Update Types](/docs/live-updates/update-types/) for the implementation detail in Update Types. # Encryption > Learn how Capgo's end-to-end encryption and signature validation protect app bundle contents during transmission and storage. Capgo provides robust end-to-end encryption for your app bundles, ensuring that your JavaScript code and assets are protected during transmission and storage. This encryption system is designed to give you complete control over your app’s security while maintaining the convenience of live updates. ## Overview [Section titled “Overview”](#overview) Capgo’s encryption system uses industry-standard cryptographic methods to protect your bundles from unauthorized access. When encryption is enabled, your bundles are encrypted before leaving your development environment and remain encrypted until they’re decrypted by your app on the user’s device. **What Encryption Actually Protects**: Unlike OTA systems that only sign updates, Capgo encrypts the uploaded bundle before storage and delivery. This protects the bundle contents from casual access in storage or transit and ensures only someone with your private key can produce a valid encrypted update. It does **not** make shipped web assets impossible to reverse engineer: the public key used by the client to decrypt updates is distributed in the app, so a determined attacker can still extract it and inspect bundle contents with enough effort. When You Need Encryption If you upload a bundle without encryption, treat it as a public asset. Private channels limit which devices receive an update, but they do not make the uploaded bundle confidential. Encryption is useful when you want better protection in storage and transit and when you want only holders of the private key to be able to publish valid encrypted updates. It does not guarantee that shipped JavaScript, HTML, or CSS can never be inspected. Threat Model Capgo encryption protects against bundle disclosure by Capgo, storage providers, CDNs, or anyone who only sees the encrypted delivery artifact. It also prevents third parties from generating valid encrypted updates without your private key. Because the public key is embedded in the distributed app so the client can decrypt updates, someone who has your app binary and enough motivation can still recover the key material needed to inspect the bundle. Tip Encryption is particularly important for: * Apps handling sensitive data or business logic * Enterprise applications with compliance requirements * Apps deployed in regulated industries * Organizations with strict security policies ## How Encryption Works [Section titled “How Encryption Works”](#how-encryption-works) Capgo uses a hybrid encryption approach that combines RSA and AES encryption for optimal security and performance: ![Capgo Encryption Flow](/encryption_flow.webp) ### 1. Key Generation [Section titled “1. Key Generation”](#1-key-generation) * **Private Key**: Generated and stored securely in your development environment (used for encryption) * **Public Key**: Derived from your private key and stored in your app’s Capacitor config (used for decryption) * **Session Keys**: Random AES keys generated for each bundle upload ### 2. Encryption Process [Section titled “2. Encryption Process”](#2-encryption-process) 1. A random AES session key is generated for each bundle upload 2. Your bundle is encrypted using the AES session key 3. The bundle checksum is calculated 4. Both the AES session key and checksum are encrypted together using your RSA private key (creating the “signature”) 5. The encrypted bundle and encrypted signature are stored The checksum is encrypted alongside the AES key to prevent tampering. Since only your RSA private key can create this signature, and only the corresponding public key can decrypt it, this ensures that both the AES session key and the expected checksum are authentic and haven’t been modified by an attacker. ### 3. Decryption Process [Section titled “3. Decryption Process”](#3-decryption-process) 1. Your app downloads the encrypted bundle and encrypted signature 2. The Capgo SDK uses your RSA public key (stored in the app) to decrypt the signature 3. This reveals the AES session key and the original checksum 4. The AES session key is used to decrypt the bundle 5. A checksum of the decrypted bundle is calculated and compared with the original checksum for integrity verification This process ensures that even if an attacker intercepts the encrypted bundle, they cannot modify the AES session key or provide a fake checksum, because they would need your private key to create a valid signature that the public key can decrypt. Tip RSA cannot encrypt large amounts of data efficiently, so AES is used for the actual bundle encryption while RSA secures the AES key and provides integrity verification through checksum signing. ## Capgo vs Other Platforms [Section titled “Capgo vs Other Platforms”](#capgo-vs-other-platforms) | Feature | Capgo | Other OTA Platforms | | ------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------- | | **Bundle Content** | Encrypted in storage/transit; still inspectable by a determined reverse engineer with the app binary | Publicly readable | | **Security Method** | True end-to-end encryption | Code signing only | | **Privacy Level** | Strong delivery/storage protection; not anti-reverse-engineering | Platform can access your code | | **Protection** | Content + integrity + authenticity | Integrity + authenticity only | **Why This Matters:** * **Code signing** only verifies that updates haven’t been tampered with and come from the right source * **Capgo encryption** protects the bundle while it is stored and delivered and makes forged encrypted updates much harder because the attacker would need your private key * **Reverse engineering is still possible** after the app ships, because the client contains the public key needed to decrypt and load the update ## Encryption Methods [Section titled “Encryption Methods”](#encryption-methods) Capgo uses Encryption V2 as the standard encryption method: ### Encryption V2 (Current Standard) [Section titled “Encryption V2 (Current Standard)”](#encryption-v2-current-standard) * Uses RSA-4096 for enhanced security * AES-256-GCM for authenticated encryption * Provides integrity verification * Better performance and security ### Encryption V1 (Deprecated) [Section titled “Encryption V1 (Deprecated)”](#encryption-v1-deprecated) * Uses RSA-2048 for key encryption * AES-256-CBC for bundle encryption * **No longer available in the current CLI** * Legacy apps using V1 must migrate to V2 Danger Encryption V1 is no longer supported in the current Capgo CLI. If you’re using V1 encryption, you must migrate to V2. See the [migration guide](/docs/cli/migrations/encryption/) for detailed instructions. ## Setting Up Encryption [Section titled “Setting Up Encryption”](#setting-up-encryption) ### Step 1: Generate Encryption Keys [Section titled “Step 1: Generate Encryption Keys”](#step-1-generate-encryption-keys) First, generate your encryption keys using the Capgo CLI: ```shell # Generate new encryption keys (creates files in current directory) npx @capgo/cli@latest key create ``` This creates: * `.capgo_key_v2`: Your private key (keep this secure!) * `.capgo_key_v2.pub`: Your public key (used by your app) These files are created in the current directory where you run the command. Caution **Important Storage Notes:** * **Private Key (`.capgo_key_v2`)**: Never commit this to version control. This file should be kept secure and used only for encryption during bundle uploads. * **Public Key (`.capgo_key_v2.pub`)**: This is safe to commit to version control as it’s a backup of your public key. * **File Location**: Keys are created in the current directory where you run the `key create` command. * **Public Key in Config**: You must run `key save` to store the public key in your Capacitor config for the mobile app to use. For production use, store the private key securely (environment variables, key management services) and remove it from your local project after setup. ### Step 2: Save Your Public Key to Capacitor Config (Required) [Section titled “Step 2: Save Your Public Key to Capacitor Config (Required)”](#step-2-save-your-public-key-to-capacitor-config-required) You **must** save your public key to the Capacitor config so your mobile app can decrypt bundles: ```shell # Save public key from file to Capacitor config (required) npx @capgo/cli@latest key save --key ./.capgo_key_v2.pub # Or save public key data directly npx @capgo/cli@latest key save --key-data "$CAPGO_PUBLIC_KEY" ``` ### Step 3: Sync Capacitor Platform (Required) [Section titled “Step 3: Sync Capacitor Platform (Required)”](#step-3-sync-capacitor-platform-required) After saving the public key, you **must** sync the Capacitor platform to copy the updated config to the native layer: ```shell # Sync the platform to copy config to native npx cap sync ``` Caution **Required Steps**: 1. The `key save` command stores the public key in your Capacitor config 2. `npx cap sync` copies this config to the native layer where the mobile app can access it 3. Without both steps, your app won’t be able to decrypt encrypted updates ## Encrypting Bundles [Section titled “Encrypting Bundles”](#encrypting-bundles) ### Method 1: Encrypt During Upload [Section titled “Method 1: Encrypt During Upload”](#method-1-encrypt-during-upload) The simplest way is to encrypt during the upload process: ```shell # Upload with automatic encryption npx @capgo/cli@latest bundle upload --key-v2 # For external storage, you must encrypt first (see Manual Encryption Workflow below) ``` ### Method 2: Manual Encryption Workflow [Section titled “Method 2: Manual Encryption Workflow”](#method-2-manual-encryption-workflow) For more control, you can manually encrypt bundles: 1. **Create a zip bundle:** ```shell npx @capgo/cli@latest bundle zip com.example.app --path ./dist --key-v2 ``` 2. **Encrypt the bundle:** ```shell npx @capgo/cli@latest bundle encrypt ./com.example.app.zip CHECKSUM_FROM_STEP_1 ``` 3. **Upload to your storage (e.g., S3) and register with Capgo:** ```shell # First upload the encrypted bundle to your storage (e.g., AWS S3) aws s3 cp ./encrypted-bundle.zip s3://your-bucket/encrypted-bundle.zip # Then register with Capgo using the external URL npx @capgo/cli@latest bundle upload --external https://your-storage.com/encrypted-bundle.zip --iv-session-key IV_SESSION_KEY_FROM_STEP_2 ``` ## Key Management [Section titled “Key Management”](#key-management) ### Storing Keys Securely [Section titled “Storing Keys Securely”](#storing-keys-securely) **Private Key Options:** 1. **File-based (local development):** ```shell # Key stored as .capgo_key_v2 file in project root npx @capgo/cli@latest bundle upload --key-v2 ``` 2. **Environment variable (CI/CD):** ```shell # Store in environment variable for CI export CAPGO_PRIVATE_KEY="$(cat .capgo_key_v2)" npx @capgo/cli@latest bundle upload --key-data-v2 "$CAPGO_PRIVATE_KEY" ``` **Public Key Setup (Required):** ```shell # Must save public key to Capacitor config for mobile app npx @capgo/cli@latest key save --key ./.capgo_key_v2.pub ``` **Production Environment:** * Store private keys in secure key management services (AWS KMS, Azure Key Vault, etc.) * Use CI/CD secret management for private keys * Never commit private keys to version control **Key Usage:** * **Private Key**: Used by CLI for encryption during bundle upload (keep secure) * **Public Key**: Stored in app configuration for decryption on device (safe to commit) ### Rotate after a private-key compromise [Section titled “Rotate after a private-key compromise”](#rotate-after-a-private-key-compromise) Rotate the key pair when the private key is suspected or confirmed compromised. A routine calendar rotation is not required. This is a native-key migration, not an OTA-only change. 1. **Generate a replacement key pair:** ```shell npx @capgo/cli@latest key create ``` 2. **Save the replacement public key to your Capacitor config:** ```shell npx @capgo/cli@latest key save --key ./.capgo_key_v2.pub ``` 3. **Sync and ship a native release:** Run `npx cap sync`, then distribute a new native app version containing the replacement public key. 4. **Target the new native version:** Devices still running the old native binary cannot decrypt updates encrypted with the replacement key. Use [Version Targeting](/docs/live-updates/version-targeting/) to restrict replacement-key bundles to the new native version while the rest of the fleet updates through the store or MDM. 5. **Switch your upload secret:** As soon as that native release is live, replace the private key in CI and upload only bundles targeted to native versions that contain the replacement public key. Caution If the private key is compromised, stop using it immediately. Existing installs with the old public key need a native store or MDM update before they can receive bundles encrypted with the replacement key. ## Security Best Practices [Section titled “Security Best Practices”](#security-best-practices) ### Key Security [Section titled “Key Security”](#key-security) * **Never share private keys** between environments or team members * **Use different keys** for different environments (dev, staging, production) * **Rotate after a compromise**: replace the key pair when the private key is suspected or confirmed compromised; a routine calendar rotation is not required * **Store keys securely** using proper key management systems ### Bundle Security [Section titled “Bundle Security”](#bundle-security) * **Always verify** bundle integrity after decryption * **Monitor** for unusual download patterns or failures * **Use HTTPS** for all bundle URLs (required for mobile apps) * **Implement** proper error handling for decryption failures ### Access Control [Section titled “Access Control”](#access-control) * **Limit access** to encryption keys to authorized personnel only * **Use role-based access** for key management operations * **Audit** key usage and access regularly * **Implement** proper backup and recovery procedures ## Troubleshooting Encryption [Section titled “Troubleshooting Encryption”](#troubleshooting-encryption) ### Common Issues [Section titled “Common Issues”](#common-issues) **Decryption failures:** * Verify the private key matches the public key used for encryption * Check that the `ivSessionKey` is correct * Ensure you’re using Encryption V2 (V1 is no longer supported) **Key-related errors:** * Confirm the private key format is correct (PEM format) * Verify the key hasn’t been corrupted during storage/transfer * Check that the key has proper permissions in your app configuration **Performance issues:** * Large bundles may take longer to encrypt/decrypt * Consider using Delta (manifest) updates to reduce bundle sizes * Monitor device performance during decryption ### Debug Commands [Section titled “Debug Commands”](#debug-commands) Check encryption status: ```shell npx @capgo/cli@latest app debug ``` Test encryption/decryption workflow: ```shell # Test the complete workflow: zip → encrypt → decrypt → unzip npx @capgo/cli@latest bundle zip com.example.app --key-v2 npx @capgo/cli@latest bundle encrypt ./com.example.app.zip CHECKSUM --json npx @capgo/cli@latest bundle decrypt ./encrypted-bundle.zip IV_SESSION_KEY ``` ## Compliance and Standards [Section titled “Compliance and Standards”](#compliance-and-standards) Capgo’s encryption implementation follows industry standards: * **AES-256**: FIPS 140-2 approved encryption algorithm * **RSA-4096**: Strong asymmetric encryption for key protection * **GCM Mode**: Provides both confidentiality and authenticity * **Secure Random**: Cryptographically secure random number generation This makes Capgo suitable for applications requiring compliance with: * GDPR (General Data Protection Regulation) * HIPAA (Health Insurance Portability and Accountability Act) * SOC 2 (Service Organization Control 2) * ISO 27001 (Information Security Management) ## Performance Considerations [Section titled “Performance Considerations”](#performance-considerations) ### Encryption Overhead [Section titled “Encryption Overhead”](#encryption-overhead) * **Bundle size**: Encrypted bundles are slightly larger (\~1-2% overhead) * **Processing time**: Encryption/decryption adds minimal latency * **Memory usage**: Temporary increase during encryption/decryption operations ### Optimization Tips [Section titled “Optimization Tips”](#optimization-tips) * Use Delta (manifest) updates to minimize encrypted data transfer * Optimize your bundle size by converting images to WebP format * Minimize JavaScript and CSS files before bundling * Remove unused dependencies and code * Monitor device performance on older/slower devices ## Next Steps [Section titled “Next Steps”](#next-steps) * Learn about [Custom Storage](/docs/live-updates/custom-storage/) to use encryption with your own infrastructure * Explore [Channels](/docs/live-updates/channels/) to manage encrypted bundles across environments * Set up [CI/CD Integration](/docs/getting-started/cicd-integration/) to automate encrypted deployments ## Keep going from Encryption [Section titled “Keep going from Encryption”](#keep-going-from-encryption) If you are using **Encryption** to plan security and compliance, connect it with [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, [Capgo Security](/security/) for the product workflow in Capgo Security, [Capgo Trust Center](/trust/) for the product workflow in Capgo Trust Center, and [Organization Security](/docs/webapp/organization-security/) for the implementation detail in Organization Security. # Features > Complete reference of all Capgo Live Update capabilities, from core update system to advanced deployment controls, analytics, and team collaboration features. This page provides a comprehensive overview of all features available in Capgo Live Updates. Each feature includes a brief description and links to detailed documentation. ## Core Update System [Section titled “Core Update System”](#core-update-system) ### Over-the-Air (OTA) Updates [Section titled “Over-the-Air (OTA) Updates”](#over-the-air-ota-updates) Deploy JavaScript, HTML, CSS, and asset updates directly to users without app store approval. Updates are downloaded in the background and applied on next app restart. **Key capabilities:** * Background downloads * Automatic installation * No user interruption * Cross-platform support (iOS, Android, Electron) [Learn more about update behavior →](/docs/live-updates/update-behavior/) *** ### Delta Updates (Differential Updates) [Section titled “Delta Updates (Differential Updates)”](#delta-updates-differential-updates) Only download files that have changed between versions, reducing bandwidth usage by up to 95% and speeding up update delivery. **Key capabilities:** * Automatic file-level diffing * Checksum-based verification * Manifest comparison * Intelligent fallback to full updates when needed [Learn more about delta updates →](/docs/live-updates/differentials/) *** ### Automatic Rollback [Section titled “Automatic Rollback”](#automatic-rollback) If an update fails to load or causes crashes, the system automatically reverts to the last known working version. **Key capabilities:** * Crash detection * Timeout detection * Automatic reversion * No user intervention required [Learn more about rollbacks →](/docs/live-updates/rollbacks/) *** ### Checksum Validation & Fallback [Section titled “Checksum Validation & Fallback”](#checksum-validation--fallback) Verifies bundle integrity via checksums and automatically falls back to the last known working version if corruption is detected. **Key capabilities:** * Checksum validation on download * Corruption detection * Automatic fallback to last working bundle * Manual recovery tools available *** ### Breaking Update Detection [Section titled “Breaking Update Detection”](#breaking-update-detection) Prevents incompatible updates from being applied to devices running older native code versions. **Key capabilities:** * Native version compatibility checking * Plugin dependency validation * Automatic blocking of incompatible updates * Clear error messaging [Learn more about version targeting →](/docs/live-updates/version-targeting/) *** ## Deployment Control [Section titled “Deployment Control”](#deployment-control) ### Channel System [Section titled “Channel System”](#channel-system) Organize and manage updates across different environments and user segments with flexible channel configurations. **Key capabilities:** * Unlimited custom channels (production, staging, beta, etc.) * Per-channel bundle assignments * Channel-specific targeting rules * Device self-assignment * Channel override per device [Learn more about channels →](/docs/live-updates/channels/) *** ### Device Targeting [Section titled “Device Targeting”](#device-targeting) Target specific devices, versions, or user segments for phased rollouts and controlled deployments. **Key capabilities:** * Version-based targeting * Device-specific overrides * Platform filtering (iOS, Android, Electron) * Custom metadata filtering * Emulator/dev build blocking *** ### Channel Policies [Section titled “Channel Policies”](#channel-policies) Configure rules and restrictions for how updates are delivered on each channel. **Key capabilities:** * Disable auto-updates * Block major version updates * Disable updates on emulators * Disable updates in development builds * Platform-specific policies (iOS-only, Android-only, Electron-only) [Learn more about channel policies →](/docs/live-updates/channels/#channel-policies) *** ## Developer Tools [Section titled “Developer Tools”](#developer-tools) ### Bundle Preview [Section titled “Bundle Preview”](#bundle-preview) Preview bundles in a live web environment before deploying to devices, accessible from the web dashboard. **Location:** Web Dashboard → App → Bundle → Preview tab *** ### Live Debugging [Section titled “Live Debugging”](#live-debugging) Real-time monitoring of update events for specific devices via CLI, showing check, download, install, and error events. **Usage:** ```bash npx @capgo/cli app debug [appId] ``` **Shows:** * Update checks * Download progress * Installation status * Error messages * Policy blocks *** ### Bundle Manifest Viewer [Section titled “Bundle Manifest Viewer”](#bundle-manifest-viewer) Inspect the complete manifest of any bundle including file list, checksums, and metadata. **Location:** Web Dashboard → App → Bundle → Manifest tab **Shows:** * File list with checksums * Bundle metadata * Native version compatibility * Plugin dependencies *** ### Native Plugin Dependencies [Section titled “Native Plugin Dependencies”](#native-plugin-dependencies) View all native Capacitor plugins included in each bundle to track dependency changes across versions. **Location:** Web Dashboard → App → Bundle → Dependencies tab **Shows:** * Plugin names and versions * Dependency additions/removals * Compatibility warnings *** ### CLI Integration [Section titled “CLI Integration”](#cli-integration) Comprehensive command-line interface for automated deployments and CI/CD integration. **Key commands:** * `bundle upload` - Upload new bundles * `bundle list` - List all bundles * `bundle delete` - Delete bundles * `bundle cleanup` - Clean up old bundles * `channel set` - Configure channels * `app debug` - Live debugging [View full CLI reference →](/docs/cli/commands/) *** ### Bundle Encryption [Section titled “Bundle Encryption”](#bundle-encryption) End-to-end encryption for bundles with AES-256 encryption, protecting your code in transit and at rest. **Key capabilities:** * RSA key pair generation * AES-256 bundle encryption * Code signature verification * Encryption key management [Learn more about encryption →](/docs/live-updates/encryption/) *** ### Bundle Cleanup & Retention [Section titled “Bundle Cleanup & Retention”](#bundle-cleanup--retention) Automatically clean up old bundles based on retention policies to manage storage usage. **Key capabilities:** * Configurable retention count * Automatic cleanup via CLI * Scheduled cleanup jobs * Storage usage tracking **Usage:** ```bash npx @capgo/cli bundle cleanup --keep=10 ``` *** ## Analytics & Monitoring [Section titled “Analytics & Monitoring”](#analytics--monitoring) ### Update Statistics [Section titled “Update Statistics”](#update-statistics) Track update adoption rates, success rates, and deployment progress across your user base. **Metrics available:** * Download success rate * Installation success rate * Error rates by type * Update adoption over time * Version distribution **Location:** Web Dashboard → App → Statistics *** ### Device Logs [Section titled “Device Logs”](#device-logs) Per-device event logs showing complete update lifecycle from check to installation. **Event types:** * Update checks * Download start/complete/fail * Install start/complete/fail * Rollback events * Policy blocks **Location:** * Web Dashboard → App → Device → Logs * Web Dashboard → App → Logs (all devices) [Learn more about logs →](/docs/webapp/logs/) *** ### Bundle Usage Analytics [Section titled “Bundle Usage Analytics”](#bundle-usage-analytics) Detailed analytics on which bundles are active, download counts, and storage usage. **Metrics:** * Active installations per bundle * Download counts * Storage usage per bundle * Bandwidth usage *** ### Channel Statistics [Section titled “Channel Statistics”](#channel-statistics) Track performance and adoption metrics per channel. **Metrics:** * Devices per channel * Update success rates per channel * Deployment history * Error rates by channel **Location:** Web Dashboard → App → Channel → Statistics *** ### Deployment History [Section titled “Deployment History”](#deployment-history) Complete audit trail of all bundle deployments, channel assignments, and configuration changes. **Tracked events:** * Bundle uploads * Channel assignments * Policy changes * Device overrides **Location:** Web Dashboard → App → Channel → History *** ## Security & Compliance [Section titled “Security & Compliance”](#security--compliance) ### End-to-End Encryption [Section titled “End-to-End Encryption”](#end-to-end-encryption) Encrypt bundles at rest and in transit with industry-standard AES-256 encryption. [Learn more about encryption →](/docs/live-updates/encryption/) *** ### Code Signing [Section titled “Code Signing”](#code-signing) Verify bundle integrity with cryptographic signatures to prevent tampering. *** ### SOC 2 Type II Compliance [Section titled “SOC 2 Type II Compliance”](#soc-2-type-ii-compliance) Infrastructure and processes certified to SOC 2 Type II standards for enterprise security. *** ### App Store Compliance [Section titled “App Store Compliance”](#app-store-compliance) Fully compliant with Apple App Store and Google Play Store policies for OTA updates. [Learn more about compliance →](/docs/live-updates/compliance/) *** ### 2FA Enforcement (Organization-level) [Section titled “2FA Enforcement (Organization-level)”](#2fa-enforcement-organization-level) Require two-factor authentication for all organization members to access the dashboard and API. **Location:** Web Dashboard → Organization → Security [Learn more about 2FA →](/docs/webapp/2fa-enforcement/) *** ### Encrypted Bundles Enforcement [Section titled “Encrypted Bundles Enforcement”](#encrypted-bundles-enforcement) Require all bundles to be encrypted at the organization level. **Location:** Web Dashboard → Organization → Security *** ## Team Collaboration [Section titled “Team Collaboration”](#team-collaboration) ### Role-Based Access Control (RBAC) [Section titled “Role-Based Access Control (RBAC)”](#role-based-access-control-rbac) Granular permissions for organization and app-level access control. **Organization roles:** * `org_super_admin` - Full organization control * `org_admin` - Organization administration (no billing/deletion) * `org_billing_admin` - Billing-only access * `org_member` - Read-only organization access **App roles:** * `app_admin` - Full control of one app * `app_developer` - Upload bundles, manage devices * `app_uploader` - Upload bundles only * `app_reader` - Read-only access **Location:** * Web Dashboard → Organization → Members * Web Dashboard → App → Access [Learn more about RBAC →](/docs/webapp/organization-system/#roles-overview) *** ### Audit Logs [Section titled “Audit Logs”](#audit-logs) Complete audit trail of all organization and app activities for compliance and security. **Logged events:** * User actions (login, logout, permission changes) * Bundle operations (upload, delete, assign) * Channel operations (create, update, delete) * Organization changes (settings, members) **Location:** Web Dashboard → Organization → Audit Logs *** ### Webhooks [Section titled “Webhooks”](#webhooks) Receive real-time notifications about events in your apps via HTTP webhooks. **Supported events:** * `apps` - App created/updated/deleted * `app_versions` - Bundle uploaded/deleted * `channels` - Channel created/updated/deleted * `org_users` - Member added/removed * `orgs` - Organization updated **Features:** * Custom webhook URLs * Event filtering * Delivery logs * Retry mechanism * Test functionality **Location:** Web Dashboard → Organization → Webhooks *** ### Multi-User Collaboration [Section titled “Multi-User Collaboration”](#multi-user-collaboration) Invite team members to your organization with specific roles and permissions. **Features:** * Email invitations * Role assignment * Member management * Access revocation **Location:** Web Dashboard → Organization → Members *** ### API Key Management [Section titled “API Key Management”](#api-key-management) Create, manage, and revoke API keys with optional expiration dates and hashed storage. **Key capabilities:** * Per-app or per-organization keys * Optional expiration dates * Hashed storage (irreversible) * Key rotation support **Location:** Web Dashboard → API Keys [Learn more about API keys →](/docs/public-api/#authentication) *** ### Password Policies [Section titled “Password Policies”](#password-policies) Organization-level password requirements to enforce security standards. **Configurable policies:** * Minimum length * Require uppercase * Require numbers * Require special characters **Location:** Web Dashboard → Organization → Security *** ## Platform Support [Section titled “Platform Support”](#platform-support) ### Multi-Platform Support [Section titled “Multi-Platform Support”](#multi-platform-support) Support for iOS, Android, and Electron apps with a single SDK. **Supported platforms:** * iOS (Capacitor 5, 6, 7, 8) * Android (Capacitor 5, 6, 7, 8) * Electron (NEW in 2025) *** ### Long-Term Support [Section titled “Long-Term Support”](#long-term-support) Continued support for older Capacitor versions to maintain compatibility with legacy apps. **Currently supported:** * Capacitor 8 (latest) * Capacitor 7 * Capacitor 6 * Capacitor 5 *** ### Custom Storage Backends [Section titled “Custom Storage Backends”](#custom-storage-backends) Use your own storage infrastructure (S3, R2, etc.) instead of Capgo’s default storage. [Learn more about custom storage →](/docs/live-updates/custom-storage/) *** ### China Configuration [Section titled “China Configuration”](#china-configuration) Special configuration for apps distributed in mainland China to comply with local regulations. [Learn more about China configuration →](/docs/live-updates/china-configuration/) *** ## Advanced Features [Section titled “Advanced Features”](#advanced-features) ### Custom Update Behavior [Section titled “Custom Update Behavior”](#custom-update-behavior) Configure when and how updates are checked and applied via the SDK. **Configurable options:** * Check interval (`periodCheckDelay` - minimum 600 seconds) * Auto-update policy (`autoUpdate` - off, atBackground, atInstall, onLaunch, always, onlyDownload) * Network requirements (Android only - via WorkManager) [Learn more about update behavior →](/docs/live-updates/update-behavior/) *** ### Update Types [Section titled “Update Types”](#update-types) Different update types for different use cases, from instant updates to user-controlled installations. **Available types:** * Background updates (default) * Immediate updates * User-prompted updates * Conditional updates [Learn more about update types →](/docs/live-updates/update-types/) *** ### Credit System [Section titled “Credit System”](#credit-system) Usage-based billing with credits for bandwidth, storage, and other resources. **Features:** * Credit usage tracking * Usage alerts * Top-up via Stripe * Credit ledger **Location:** Web Dashboard → Organization → Credits *** ## Getting Started [Section titled “Getting Started”](#getting-started) Ready to start using these features? Follow our [Quickstart Guide](/docs/getting-started/quickstart/) to set up your first app with Capgo Live Updates. ## Need Help? [Section titled “Need Help?”](#need-help) * [Join our Discord](https://discord.capgo.app) for community support * [Check the FAQ](/docs/faq/) for common questions * [Browse API documentation](/docs/public-api/) for API integration * [Contact support](https://capgo.app/consulting/) for enterprise assistance ## Keep going from Features [Section titled “Keep going from Features”](#keep-going-from-features) If you are using **Features** to plan monitoring and analytics, connect it with [Statistics](/docs/public-api/statistics/) for the implementation detail in Statistics, [Logs](/docs/webapp/logs/) for the implementation detail in Logs, [@capgo/capacitor-appinsights](/docs/plugins/appinsights/) for the implementation detail in @capgo/capacitor-appinsights, [Using @capgo/capacitor-appinsights](/plugins/capacitor-appinsights/) for the native capability in Using @capgo/capacitor-appinsights, and [@capgo/capacitor-firebase-analytics](/docs/plugins/firebase-analytics/) for the implementation detail in @capgo/capacitor-firebase-analytics. # HIPAA Compliance > Configure Capgo live updates for HIPAA-sensitive reviews with data residency, statistics controls, and self-hosted deployment options. This page explains the technical options teams use when a HIPAA review does not allow live update statistics to be sent to Capgo Cloud. Capgo Cloud is not currently presented as a HIPAA-compliant hosted statistics processor. Many HIPAA-sensitive apps still use Capgo because the updater data is minimal, device-scoped, and not tied to a known app user by default. If your company policy, reviewer, or customer contract requires stricter control, you can geo-localize the plugin traffic, disable the statistics endpoint, self-host only the statistics endpoint, or move to a licensed self-hosted setup. Note This page is implementation guidance, not legal advice. Your compliance owner decides whether Capgo Cloud, a reduced telemetry configuration, or self-hosting fits your HIPAA review. ## What Capgo receives by default [Section titled “What Capgo receives by default”](#what-capgo-receives-by-default) The updater plugin sends operational data needed to deliver and observe live updates. The statistics payload can include these fields: * `app_id` - your Capacitor app identifier * `device_id` - a random, app-scoped device identifier generated by the updater plugin * `platform` - `ios`, `android`, or `electron` * `version_name` - the installed web bundle version * `version_build` - the native app version name * `version_code` - the native build number * `version_os` - the operating system version * `plugin_version` - the installed `@capgo/capacitor-updater` version * `action` - the update lifecycle event, such as install, download, failure, rollback, or app-ready events * `is_emulator` and `is_prod` - environment flags when available * `custom_id` - only if your app explicitly sets it with `CapacitorUpdater.setCustomId(...)` * IP address - used at transport level for regional routing, abuse prevention, and CDN optimization By default, this data is anonymous to the app user. Capgo does not receive names, emails, account IDs, medical record numbers, credentials, user content, app analytics events, or behavioral analytics from the updater. The only stable identifier is the random, app-scoped `device_id`, which is not an advertising ID and is not tied to a known user unless you set `custom_id` yourself. If your HIPAA review requires no hosted update statistics at all, set `statsUrl` to an empty string. That fully disables updater statistics reporting to Capgo Cloud while update checks can still use `updateUrl` and `channelUrl` if you leave them enabled. ## Do not set a custom ID [Section titled “Do not set a custom ID”](#do-not-set-a-custom-id) For HIPAA-sensitive deployments, do not call `CapacitorUpdater.setCustomId(...)`. The custom ID is included in updater statistics when it is configured. If you set it to an email address, user ID, patient ID, employee ID, account ID, or any other value that maps back to a person, you have tied the updater telemetry to personal data in your own app context. If your review requires hosted Capgo telemetry to stay device-scoped, leave `custom_id` unset. ## Option 1: Geo-localize Capgo Cloud plugin traffic [Section titled “Option 1: Geo-localize Capgo Cloud plugin traffic”](#option-1-geo-localize-capgo-cloud-plugin-traffic) If your review allows Capgo Cloud but requires EU data residency for plugin data, configure all three updater endpoints to the EU host: capacitor.config.ts ```typescript import type { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'My App', webDir: 'dist', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', updateUrl: 'https://plugin.eu.capgo.app/updates', statsUrl: 'https://plugin.eu.capgo.app/stats', channelUrl: 'https://plugin.eu.capgo.app/channel_self', }, }, }; export default config; ``` Use the EU URLs together. Mixing `plugin.capgo.app` and `plugin.eu.capgo.app` can route part of the plugin data path outside the EU host. This keeps Capgo’s hosted update monitoring, statistics, alerts, and troubleshooting data available while placing the plugin data path in Europe. [Data Location ](/docs/live-updates/data-location/) ## Option 2: Disable the statistics endpoint [Section titled “Option 2: Disable the statistics endpoint”](#option-2-disable-the-statistics-endpoint) If your review does not allow statistics to be sent to Capgo Cloud, set `statsUrl` to an empty string: capacitor.config.ts ```typescript import type { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'My App', webDir: 'dist', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', statsUrl: '', }, }, }; export default config; ``` This disables statistics reporting from the updater plugin. Update checks and downloads can still use Capgo Cloud if you keep the default `updateUrl` and `channelUrl`. After changing `capacitor.config.ts`, sync the native projects and ship a new store build. Existing installs will keep using their previous native config until they receive that new binary. ## What you lose when statistics are disabled [Section titled “What you lose when statistics are disabled”](#what-you-lose-when-statistics-are-disabled) Disabling `statsUrl` removes the hosted signal Capgo uses to explain what happened inside your app after an update was offered or downloaded. You lose: * Dashboard visibility into successful installs, failed installs, download failures, rollbacks, and app-ready events * Failure alerts that depend on hosted statistics * The ability to quickly tell which app versions, OS versions, platforms, or plugin versions are affected by an update issue * Device-level troubleshooting trails in Capgo Cloud * Aggregate update adoption and app usage statistics in the Capgo dashboard * Better support context from the Capgo team, because the hosted service no longer receives the events that explain the device-side update path Automatic update delivery can still work, but you are operating with reduced observability. Plan your own monitoring before disabling statistics in production. ## Option 3: Self-host the statistics endpoint [Section titled “Option 3: Self-host the statistics endpoint”](#option-3-self-host-the-statistics-endpoint) If your review allows update checks through Capgo Cloud but requires statistics to remain inside your infrastructure, point `statsUrl` to your own endpoint: capacitor.config.ts ```typescript import type { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'My App', webDir: 'dist', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', statsUrl: 'https://updates.example.com/capgo/stats', }, }, }; export default config; ``` Your endpoint should accept the updater statistics payload and return: ```json { "status": "ok" } ``` Use this path when you want to keep internal alerting, audit logs, and incident analysis without sending device update statistics to Capgo Cloud. [Statistics API Endpoint ](/docs/plugins/updater/self-hosted/handling-stats/) ## Option 4: Licensed self-hosting [Section titled “Option 4: Licensed self-hosting”](#option-4-licensed-self-hosting) If Capgo Cloud, EU data residency, disabled statistics, or a self-hosted statistics endpoint still does not satisfy your HIPAA review, Capgo can help you move to a licensed self-hosted deployment. This is the strictest option because your organization controls the updater backend, statistics endpoint, logs, retention, infrastructure, and network boundary. It also means you must own more of the operational work that Capgo Cloud normally handles for you. [Self-hosted updater ](/docs/plugins/updater/self-hosted/getting-started/) ## Practical review checklist [Section titled “Practical review checklist”](#practical-review-checklist) Before a HIPAA review, decide: * Whether hosted Capgo Cloud is allowed for update checks * Whether hosted Capgo Cloud is allowed for statistics * Which region the plugin traffic must use * Whether `custom_id` is disabled in your app * Who monitors update failures if hosted statistics are disabled * Whether your team needs a licensed self-hosted deployment Capgo works with companies going through HIPAA compliance review, including companies in the U.S. that use Capgo in HIPAA-compliant programs. Contact Capgo if your reviewer needs a deployment model, data flow, or licensing path that is stricter than the hosted defaults. ## Keep going from HIPAA Compliance [Section titled “Keep going from HIPAA Compliance”](#keep-going-from-hipaa-compliance) If you are using **HIPAA Compliance** to plan a regulated live update rollout, connect it with [Compliance](/docs/live-updates/compliance/) for privacy and data collection details, [Data Location](/docs/live-updates/data-location/) for EU endpoint configuration, [Statistics API Endpoint](/docs/plugins/updater/self-hosted/handling-stats/) for self-hosted telemetry, and [Self-hosted updater](/docs/plugins/updater/self-hosted/getting-started/) for licensed deployment planning. # CI/CD Integrations > Integrate Capgo Live Updates with your favorite CI/CD platform for automated deployment workflows. Automate your Capgo Live Updates deployment process by integrating with popular CI/CD platforms. These integrations allow you to automatically deploy app updates whenever you push code changes, test feature branches, and manage multiple deployment environments. ## Available Integrations [Section titled “Available Integrations”](#available-integrations) Choose your CI/CD platform to get started with automated deployments: [Azure DevOps ](/docs/live-updates/integrations/azure-devops/)Integrate with Azure DevOps Pipelines for automated builds, testing, and deployment workflows. [GitLab CI/CD ](/docs/live-updates/integrations/gitlab-ci/)Set up GitLab CI/CD pipelines to automatically deploy your app updates with comprehensive environment management. [GitHub Actions ](/docs/live-updates/integrations/github-actions/)Use GitHub Actions for powerful automation with multi-channel deployments and environment protection. [Bitbucket Pipelines ](/docs/live-updates/integrations/bitbucket-pipeline/)Deploy with Bitbucket Pipelines using simple or advanced configurations for multiple environments. ## What You’ll Get [Section titled “What You’ll Get”](#what-youll-get) All integration guides include: * **Simple Setup**: Basic configuration to get started quickly * **Advanced Workflows**: Multi-environment deployments with staging and production * **Feature Branch Testing**: Automatic deployment of feature branches to test channels * **Security Best Practices**: Secure secret management and environment protection * **Monitoring**: Notifications and logging for deployment status Tip **New to CI/CD?** Start with the simple configuration for your platform, then gradually add more advanced features like multi-channel deployments and automated testing as your needs grow. ## Common Features [Section titled “Common Features”](#common-features) Each integration supports: * **Automated Builds**: Trigger deployments on code changes * **Multi-Channel Support**: Deploy to different channels (development, staging, production) * **Pull Request/Merge Request Testing**: Test changes in isolated environments * **Encryption Support**: Secure deployments with Capgo’s encryption feature * **Environment Protection**: Manual approvals and restricted access for production * **Notifications**: Slack, email, and other notification integrations ## Prerequisites [Section titled “Prerequisites”](#prerequisites) Before setting up any integration, ensure you have: * A Capgo account with an app configured * Your app’s source code in a Git repository * A Capgo API token from [console.capgo.app/apikeys](https://console.capgo.app/apikeys) * Node.js and npm/yarn configured in your project ## Related Documentation [Section titled “Related Documentation”](#related-documentation) * [Channels](/docs/live-updates/channels/) - Learn how to manage different deployment environments * [Encryption](/docs/live-updates/encryption/) - Secure your deployments with end-to-end encryption * [Update Behavior](/docs/live-updates/update-behavior/) - Customize how updates are applied to your apps Choose your CI/CD platform above to start automating your Capgo deployments! ## Keep going from CI/CD Integrations [Section titled “Keep going from CI/CD Integrations”](#keep-going-from-cicd-integrations) If you are using **CI/CD Integrations** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # Azure DevOps Integration > Learn how to integrate Capgo Live Updates with Azure DevOps Pipelines for automated deployment of your app updates. Integrate Capgo Live Updates with Azure DevOps Pipelines to automatically deploy your app updates whenever you push code changes. This guide covers setting up automated builds, testing, and deployment workflows. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) Before setting up Azure DevOps integration, ensure you have: * An Azure DevOps organization and project * A Capgo account with an app configured * Your app’s source code in an Azure Repos Git repository * Node.js and npm/yarn configured in your project ## Setting Up Azure DevOps Pipeline [Section titled “Setting Up Azure DevOps Pipeline”](#setting-up-azure-devops-pipeline) ### Step 1: Create Pipeline Variables [Section titled “Step 1: Create Pipeline Variables”](#step-1-create-pipeline-variables) First, set up the necessary variables in your Azure DevOps project: 1. Navigate to your Azure DevOps project 2. Go to **Pipelines** → **Library** → **Variable groups** 3. Create a new variable group named `Capgo-Variables` 4. Add the following variables: | Variable Name | Value | Secure | | ------------- | -------------------- | ------ | | `CAPGO_TOKEN` | Your Capgo API token | ✅ Yes | Tip Get your Capgo API token from [console.capgo.app/apikeys](https://console.capgo.app/apikeys). Your app ID is already configured in your `capacitor.config.ts` file. ## Simple [Section titled “Simple”](#simple) Basic configuration that deploys to production on every push to the main branch: ```yaml # Simple Azure DevOps Pipeline for Capgo Live Updates trigger: branches: include: - main variables: - group: Capgo-Variables jobs: - job: BuildAndDeploy displayName: 'Build and Deploy to Capgo' pool: vmImage: 'ubuntu-latest' steps: - task: NodeTool@0 displayName: 'Setup Node.js' inputs: versionSpec: '22.x' - script: | npm ci npm run test npm run build displayName: 'Install, test and build' - script: | npm install -g @capgo/cli npx @capgo/cli bundle upload --apikey $(CAPGO_TOKEN) --channel production displayName: 'Deploy to Capgo' ``` ## Advanced [Section titled “Advanced”](#advanced) ### Feature Branch Deployments [Section titled “Feature Branch Deployments”](#feature-branch-deployments) Deploy feature branches to test channels for review and testing: ```yaml # Feature branch deployment trigger: branches: include: - feature/* variables: - group: Capgo-Variables jobs: - job: DeployFeature displayName: 'Deploy Feature Branch' pool: vmImage: 'ubuntu-latest' condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/feature/') steps: - task: NodeTool@0 inputs: versionSpec: '22.x' - script: | npm ci npm run test npm run build displayName: 'Install, test and build' - script: | BRANCH_NAME=$(echo "$(Build.SourceBranchName)" | sed 's/[^a-zA-Z0-9-]/-/g') CHANNEL_NAME="feature-$BRANCH_NAME" npm install -g @capgo/cli npx @capgo/cli channel create $CHANNEL_NAME --apikey $(CAPGO_TOKEN) || true npx @capgo/cli bundle upload --apikey $(CAPGO_TOKEN) --channel $CHANNEL_NAME displayName: 'Deploy to Feature Channel' ``` Tip **Testing with Channels**: After deploying to a feature channel, you can test the update in your app by configuring it to use that specific channel. Learn more about [configuring channels in your app](/docs/live-updates/channels/#configuring-the-channel-in-your-app). ### Using Encryption [Section titled “Using Encryption”](#using-encryption) If you’re using [Capgo’s encryption feature](/docs/live-updates/encryption/), you’ll need to store your private key securely in your CI/CD environment. After [setting up encryption keys](/docs/live-updates/encryption/#setting-up-encryption) locally, add your private key to Azure DevOps variables: ```shell # Display your private key content (copy this output) cat .capgo_key_v2 ``` Add this content as `CAPGO_PRIVATE_KEY` in your Azure DevOps variable group (mark as secret), then use it in pipelines: ```yaml # Deploy with encryption - script: | npm install -g @capgo/cli npx @capgo/cli bundle upload --apikey $(CAPGO_TOKEN) --key-data-v2 "$(CAPGO_PRIVATE_KEY)" --channel production displayName: 'Deploy to Capgo with Encryption' ``` Caution **Security Best Practices:** * Never commit the `.capgo_key_v2` file to version control * Store the private key only in secure CI/CD secret management * Use different keys for different environments ### Multi-Channel Configuration [Section titled “Multi-Channel Configuration”](#multi-channel-configuration) For comprehensive information about setting up and managing multiple deployment channels, see the [Channels documentation](/docs/live-updates/channels/). Complete configuration with multiple environments and pull request deployments: ```yaml # Advanced Azure DevOps Pipeline with Multiple Channels trigger: branches: include: - main - develop pr: branches: include: - main - develop variables: - group: Capgo-Variables stages: # Build stage - stage: Build jobs: - job: BuildApp pool: vmImage: 'ubuntu-latest' steps: - task: NodeTool@0 inputs: versionSpec: '22.x' - script: | npm ci npm run test npm run build displayName: 'Install, test and build' - task: PublishBuildArtifacts@1 inputs: pathToPublish: 'dist' artifactName: 'app-build' # Deploy to development - stage: DeployDev condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')) jobs: - deployment: DeployDevelopment environment: development pool: vmImage: 'ubuntu-latest' strategy: runOnce: deploy: steps: - task: NodeTool@0 inputs: versionSpec: '22.x' - task: DownloadBuildArtifacts@0 inputs: artifactName: 'app-build' downloadPath: '$(Pipeline.Workspace)' - script: | npm install -g @capgo/cli npx @capgo/cli bundle upload --apikey $(CAPGO_TOKEN) --channel development --path $(Pipeline.Workspace)/app-build displayName: 'Deploy to Development' # Deploy PR to test channel - stage: DeployPR condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest')) jobs: - job: DeployPRChannel pool: vmImage: 'ubuntu-latest' steps: - task: NodeTool@0 inputs: versionSpec: '22.x' - task: DownloadBuildArtifacts@0 inputs: artifactName: 'app-build' downloadPath: '$(Pipeline.Workspace)' - script: | CHANNEL_NAME="pr-$(System.PullRequest.PullRequestNumber)" npm install -g @capgo/cli npx @capgo/cli channel create $CHANNEL_NAME --apikey $(CAPGO_TOKEN) || true npx @capgo/cli bundle upload --apikey $(CAPGO_TOKEN) --channel $CHANNEL_NAME --path $(Pipeline.Workspace)/app-build displayName: 'Deploy to PR Channel' # Deploy to production - stage: DeployProd condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main')) jobs: - deployment: DeployProduction environment: production pool: vmImage: 'ubuntu-latest' strategy: runOnce: deploy: steps: - task: NodeTool@0 inputs: versionSpec: '22.x' - task: DownloadBuildArtifacts@0 inputs: artifactName: 'app-build' downloadPath: '$(Pipeline.Workspace)' - script: | npm install -g @capgo/cli npx @capgo/cli bundle upload --apikey $(CAPGO_TOKEN) --channel production --path $(Pipeline.Workspace)/app-build displayName: 'Deploy to Production' ``` ### Multi-Environment Deployment [Section titled “Multi-Environment Deployment”](#multi-environment-deployment) For complex scenarios with multiple environments: ```yaml # Extended pipeline with multiple environments parameters: - name: deployEnvironment displayName: 'Deploy Environment' type: string default: 'staging' values: - staging - production variables: - group: Capgo-Variables - name: channelName ${{ if eq(parameters.deployEnvironment, 'production') }}: value: 'production' ${{ else }}: value: 'staging' stages: # Build stage - stage: Build jobs: - job: BuildApp pool: vmImage: 'ubuntu-latest' steps: - task: NodeTool@0 inputs: versionSpec: '22.x' - script: | npm ci npm run test npm run build displayName: 'Install, test and build' - task: PublishBuildArtifacts@1 inputs: pathToPublish: 'dist' artifactName: 'app-build' - stage: DeployStaging displayName: 'Deploy to Staging' dependsOn: Build condition: and(succeeded(), eq('${{ parameters.deployEnvironment }}', 'staging')) jobs: - deployment: DeployStaging displayName: 'Deploy to Staging Channel' pool: vmImage: 'ubuntu-latest' environment: 'staging' strategy: runOnce: deploy: steps: - template: deploy-steps.yml parameters: channel: 'staging' - stage: DeployProduction displayName: 'Deploy to Production' dependsOn: Build condition: and(succeeded(), eq('${{ parameters.deployEnvironment }}', 'production')) jobs: - deployment: DeployProduction displayName: 'Deploy to Production Channel' pool: vmImage: 'ubuntu-latest' environment: 'production' strategy: runOnce: deploy: steps: - template: deploy-steps.yml parameters: channel: 'production' ``` ### Deployment Template (deploy-steps.yml) [Section titled “Deployment Template (deploy-steps.yml)”](#deployment-template-deploy-stepsyml) Create a reusable template file `deploy-steps.yml`: deploy-steps.yml ```yaml parameters: - name: channel type: string steps: - task: NodeTool@0 displayName: 'Install Node.js' inputs: versionSpec: '22.x' - task: DownloadBuildArtifacts@0 displayName: 'Download build artifacts' inputs: artifactName: 'app-build' downloadPath: '$(System.ArtifactsDirectory)' - script: | npm install -g @capgo/cli displayName: 'Install Capgo CLI' - script: | npx @capgo/cli bundle upload \ --apikey $(CAPGO_TOKEN) \ --channel ${{ parameters.channel }} \ --path $(System.ArtifactsDirectory)/app-build displayName: 'Upload to Capgo (${{ parameters.channel }})' ``` ### Branch-Based Deployment Strategy [Section titled “Branch-Based Deployment Strategy”](#branch-based-deployment-strategy) Configure different deployment strategies based on Git branches: ```yaml trigger: branches: include: - main - develop - feature/* variables: - group: Capgo-Variables - name: targetChannel ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: value: 'production' ${{ elseif eq(variables['Build.SourceBranch'], 'refs/heads/develop') }}: value: 'staging' ${{ else }}: value: 'development' stages: - stage: Build jobs: - job: BuildApp pool: vmImage: 'ubuntu-latest' steps: - task: NodeTool@0 inputs: versionSpec: '22.x' - script: | npm ci npm run test npm run build displayName: 'Install, test and build' - task: PublishBuildArtifacts@1 inputs: pathToPublish: 'dist' artifactName: 'app-build' - stage: Deploy displayName: 'Deploy to $(targetChannel)' dependsOn: Build condition: succeeded() jobs: - deployment: DeployJob displayName: 'Deploy to $(targetChannel) Channel' pool: vmImage: 'ubuntu-latest' environment: '$(targetChannel)' strategy: runOnce: deploy: steps: - template: deploy-steps.yml parameters: channel: '$(targetChannel)' ``` ## Security Best Practices [Section titled “Security Best Practices”](#security-best-practices) ### Secure Variable Management [Section titled “Secure Variable Management”](#secure-variable-management) 1. **Use Variable Groups**: Store sensitive data in Azure DevOps variable groups 2. **Mark as Secret**: Always mark API tokens and keys as secret variables 3. **Scope Access**: Limit variable group access to specific pipelines and users 4. **Rotate Keys**: Regularly rotate your Capgo API tokens ## Monitoring and Notifications [Section titled “Monitoring and Notifications”](#monitoring-and-notifications) ### Teams Integration [Section titled “Teams Integration”](#teams-integration) Add Microsoft Teams notifications to your pipeline: ```yaml - task: ms-teams-deploy-card@1.4.1 displayName: 'Notify Teams on Success' condition: succeeded() inputs: webhookUri: '$(TEAMS_WEBHOOK_URL)' title: 'Capgo Deployment Successful' text: 'App deployed to $(targetChannel) channel' themeColor: '00FF00' - task: ms-teams-deploy-card@1.4.1 displayName: 'Notify Teams on Failure' condition: failed() inputs: webhookUri: '$(TEAMS_WEBHOOK_URL)' title: 'Capgo Deployment Failed' text: 'Deployment to $(targetChannel) failed' themeColor: 'FF0000' ``` ### Email Notifications [Section titled “Email Notifications”](#email-notifications) Configure email notifications for deployment status: ```yaml - task: EmailReport@1 displayName: 'Send Email Report' condition: always() inputs: sendMailConditionConfig: 'Always' subject: 'Capgo Deployment Report - $(Build.BuildNumber)' to: 'team@yourcompany.com' body: | Deployment Status: $(Agent.JobStatus) Channel: $(targetChannel) Build: $(Build.BuildNumber) Commit: $(Build.SourceVersion) ``` ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### Common Issues [Section titled “Common Issues”](#common-issues) **Pipeline fails with “Capgo CLI not found”:** ```yaml # Ensure global installation - script: | npm install -g @capgo/cli which capgo || echo "Capgo CLI not found in PATH" displayName: 'Install and verify Capgo CLI' ``` **Authentication errors:** ```yaml # Verify token is correctly set - script: | echo "Token length: ${#CAPGO_TOKEN}" if [ -z "$CAPGO_TOKEN" ]; then echo "CAPGO_TOKEN is not set" exit 1 fi displayName: 'Verify Capgo token' env: CAPGO_TOKEN: $(CAPGO_TOKEN) ``` **Build artifacts not found:** ```yaml # List available artifacts for debugging - script: | ls -la $(System.ArtifactsDirectory) find $(System.ArtifactsDirectory) -name "*.js" -o -name "*.html" displayName: 'Debug artifacts' ``` ### Debug Pipeline [Section titled “Debug Pipeline”](#debug-pipeline) Add debugging steps to troubleshoot issues: ```yaml - script: | echo "Build.SourceBranch: $(Build.SourceBranch)" echo "Build.BuildNumber: $(Build.BuildNumber)" echo "Target Channel: $(targetChannel)" displayName: 'Debug Pipeline Variables' - script: | npx @capgo/cli app debug --apikey $(CAPGO_TOKEN) displayName: 'Debug Capgo App Status' ``` ## Next Steps [Section titled “Next Steps”](#next-steps) * Learn about [Channels](/docs/live-updates/channels/) to manage different deployment environments * Explore [Custom Storage](/docs/live-updates/custom-storage/) for advanced deployment scenarios * Set up [Encryption](/docs/live-updates/encryption/) for secure deployments * Configure [Update Behavior](/docs/live-updates/update-behavior/) to customize how updates are applied With Azure DevOps integration, you can automate your Capgo deployments and ensure consistent, reliable updates to your mobile app users. ## Keep going from Azure DevOps Integration [Section titled “Keep going from Azure DevOps Integration”](#keep-going-from-azure-devops-integration) If you are using **Azure DevOps Integration** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # Bitbucket Pipelines Integration > Learn how to integrate Capgo Live Updates with Bitbucket Pipelines for automated deployment of your app updates. Integrate Capgo Live Updates with Bitbucket Pipelines to automatically deploy your app updates whenever you push code changes. This guide covers setting up automated builds, testing, and deployment workflows. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) Before setting up Bitbucket Pipelines integration, ensure you have: * A Bitbucket account with a repository * A Capgo account with an app configured * Node.js and npm/yarn configured in your project ## Setting Up Bitbucket Pipelines [Section titled “Setting Up Bitbucket Pipelines”](#setting-up-bitbucket-pipelines) ### Step 1: Configure Repository Variables [Section titled “Step 1: Configure Repository Variables”](#step-1-configure-repository-variables) First, set up the necessary variables in your Bitbucket repository: 1. Navigate to your Bitbucket repository 2. Go to **Repository settings** → **Pipelines** → **Repository variables** 3. Add the following variables: | Variable Name | Value | Secured | | ------------- | -------------------- | ------- | | `CAPGO_TOKEN` | Your Capgo API token | ✅ Yes | Tip Get your Capgo API token from [console.capgo.app/apikeys](https://console.capgo.app/apikeys). Your app ID is already configured in your `capacitor.config.ts` file. ## Simple [Section titled “Simple”](#simple) Basic configuration that deploys to production on every push to the main branch: ```yaml # bitbucket-pipelines.yml - Simple Configuration image: node:22 pipelines: branches: main: - step: name: Build and Deploy to Production script: - npm ci - npm run test - npm run build - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production artifacts: - dist/** ``` ## Advanced [Section titled “Advanced”](#advanced) ### Feature Branch Deployments [Section titled “Feature Branch Deployments”](#feature-branch-deployments) Deploy feature branches to test channels for review and testing: ```yaml # Feature branch deployment pipelines: branches: feature/*: - step: name: Deploy Feature Branch script: - npm ci - npm run test - npm run build - BRANCH_NAME=$(echo $BITBUCKET_BRANCH | sed 's/[^a-zA-Z0-9-]/-/g') - CHANNEL_NAME="feature-$BRANCH_NAME" - npm install -g @capgo/cli - npx @capgo/cli channel create $CHANNEL_NAME --apikey $CAPGO_TOKEN || true - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME artifacts: - dist/** ``` Tip **Testing with Channels**: After deploying to a feature channel, you can test the update in your app by configuring it to use that specific channel. Learn more about [configuring channels in your app](/docs/live-updates/channels/#configuring-the-channel-in-your-app). ### Using Encryption [Section titled “Using Encryption”](#using-encryption) If you’re using [Capgo’s encryption feature](/docs/live-updates/encryption/), you’ll need to store your private key securely in your CI/CD environment. After [setting up encryption keys](/docs/live-updates/encryption/#setting-up-encryption) locally, add your private key to Bitbucket variables: ```shell # Display your private key content (copy this output) cat .capgo_key_v2 ``` Add this content as `CAPGO_PRIVATE_KEY` in your Bitbucket repository variables (mark as secured), then use it in pipelines: ```yaml # Deploy with encryption - step: name: Deploy to Capgo with Encryption script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --key-data-v2 "$CAPGO_PRIVATE_KEY" --channel production ``` Caution **Security Best Practices:** * Never commit the `.capgo_key_v2` file to version control * Store the private key only in secure CI/CD secret management * Use different keys for different environments ### Multi-Channel Configuration [Section titled “Multi-Channel Configuration”](#multi-channel-configuration) For comprehensive information about setting up and managing multiple deployment channels, see the [Channels documentation](/docs/live-updates/channels/). Complete configuration with multiple environments and pull request deployments: ```yaml # bitbucket-pipelines.yml - Advanced Multi-Channel Configuration image: node:22 definitions: steps: - step: &build-step name: Build Application script: - npm ci - npm run test - npm run build artifacts: - dist/** - step: &deploy-step name: Deploy to Capgo script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME pipelines: branches: main: - step: <<: *build-step - step: <<: *deploy-step name: Deploy to Production deployment: production trigger: manual script: - export CHANNEL_NAME=production - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME develop: - step: <<: *build-step - step: <<: *deploy-step name: Deploy to Development deployment: development script: - export CHANNEL_NAME=development - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME pull-requests: '**': - step: <<: *build-step - step: name: Deploy PR to Test Channel script: - CHANNEL_NAME="pr-$BITBUCKET_PR_ID" - npm install -g @capgo/cli - npx @capgo/cli channel create $CHANNEL_NAME --apikey $CAPGO_TOKEN || true - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME artifacts: - dist/** ``` ### Multi-Environment Pipeline [Section titled “Multi-Environment Pipeline”](#multi-environment-pipeline) For complex deployment scenarios with staging and production environments: ```yaml # Multi-environment pipeline image: node:22 pipelines: branches: main: - step: name: Build script: - npm ci - npm run test - npm run build artifacts: - dist/** - step: name: Deploy to Staging deployment: staging script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel staging - step: name: Deploy to Production deployment: production trigger: manual script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production develop: - step: name: Build and Deploy to Development script: - npm ci - npm run test - npm run build - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel development artifacts: - dist/** ``` ### Branch-Based Deployment Strategy [Section titled “Branch-Based Deployment Strategy”](#branch-based-deployment-strategy) Automatically deploy different branches to appropriate channels: ```yaml # Dynamic channel deployment image: node:22 definitions: scripts: - script: &determine-channel | if [ "$BITBUCKET_BRANCH" = "main" ]; then export CHANNEL_NAME="production" elif [ "$BITBUCKET_BRANCH" = "develop" ]; then export CHANNEL_NAME="staging" else export CHANNEL_NAME="development" fi echo "Deploying to channel: $CHANNEL_NAME" pipelines: default: - step: name: Build and Deploy script: - npm ci - npm run test - npm run build - *determine-channel - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME artifacts: - dist/** ``` ### Parallel Pipeline Execution [Section titled “Parallel Pipeline Execution”](#parallel-pipeline-execution) Optimize build times with parallel steps: ```yaml # Parallel execution pipeline image: node:22 pipelines: branches: main: - parallel: - step: name: Run Tests script: - npm ci - npm run test - step: name: Lint Code script: - npm ci - npm run lint - step: name: Build Application script: - npm ci - npm run build artifacts: - dist/** - step: name: Deploy to Production deployment: production script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production ``` ## Security Best Practices [Section titled “Security Best Practices”](#security-best-practices) ### Repository Variables [Section titled “Repository Variables”](#repository-variables) 1. **Secured Variables**: Always mark API tokens as secured 2. **Environment Variables**: Use deployment-specific variables when needed 3. **Access Control**: Limit repository access to authorized team members 4. **Token Rotation**: Regularly rotate your Capgo API tokens ### Deployment Environments [Section titled “Deployment Environments”](#deployment-environments) Configure deployment environments for better security: ```yaml # Deployment with environment restrictions pipelines: branches: main: - step: name: Deploy to Production deployment: production trigger: manual script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production ``` ## Monitoring and Notifications [Section titled “Monitoring and Notifications”](#monitoring-and-notifications) ### Slack Integration [Section titled “Slack Integration”](#slack-integration) Add Slack notifications to your pipeline: ```yaml # Pipeline with Slack notifications pipelines: branches: main: - step: name: Build and Deploy script: - npm ci - npm run test - npm run build - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production after-script: - | if [ $BITBUCKET_EXIT_CODE -eq 0 ]; then curl -X POST -H 'Content-type: application/json' \ --data '{"text":"✅ Capgo deployment successful for '$BITBUCKET_BRANCH'"}' \ $SLACK_WEBHOOK_URL else curl -X POST -H 'Content-type: application/json' \ --data '{"text":"❌ Capgo deployment failed for '$BITBUCKET_BRANCH'"}' \ $SLACK_WEBHOOK_URL fi ``` ### Email Notifications [Section titled “Email Notifications”](#email-notifications) Configure email notifications through Bitbucket’s built-in features or using external services: ```yaml # Email notification step - step: name: Send Notification script: - | curl -X POST \ -H "Content-Type: application/json" \ -d '{ "to": "team@yourcompany.com", "subject": "Capgo Deployment Status", "body": "Deployment of '$BITBUCKET_BRANCH' completed with status: '$BITBUCKET_EXIT_CODE'" }' \ $EMAIL_SERVICE_URL condition: result: [successful, failed] ``` ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### Common Issues [Section titled “Common Issues”](#common-issues) **Pipeline fails with “Capgo CLI not found”:** ```yaml # Debug CLI installation - step: name: Debug CLI script: - npm install -g @capgo/cli - which capgo || echo "Capgo CLI not found" - npx @capgo/cli --version ``` **Authentication errors:** ```yaml # Verify token configuration - step: name: Debug Auth script: - | if [ -z "$CAPGO_TOKEN" ]; then echo "CAPGO_TOKEN is not set" exit 1 fi echo "Token length: ${#CAPGO_TOKEN}" ``` **Build artifacts not found:** ```yaml # List build outputs - step: name: Debug Build script: - ls -la dist/ - find dist/ -type f -name "*.js" -o -name "*.html" ``` ### Debug Pipeline [Section titled “Debug Pipeline”](#debug-pipeline) Add debugging information to troubleshoot issues: ```yaml # Debug pipeline pipelines: branches: main: - step: name: Debug Information script: - echo "Branch: $BITBUCKET_BRANCH" - echo "Commit: $BITBUCKET_COMMIT" - echo "Build: $BITBUCKET_BUILD_NUMBER" - env | grep BITBUCKET_ | sort - step: name: Build and Deploy script: - npm ci - npm run test - npm run build - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production ``` ### Pipeline Validation [Section titled “Pipeline Validation”](#pipeline-validation) Enable pipeline validation to catch configuration errors: ```yaml # Enable pipeline validation options: docker: true size: 2x pipelines: branches: main: - step: name: Validate Pipeline script: - echo "Pipeline validation successful" - step: name: Build and Deploy script: # ... deployment steps ``` ## Next Steps [Section titled “Next Steps”](#next-steps) * Learn about [Channels](/docs/live-updates/channels/) to manage different deployment environments * Explore [Custom Storage](/docs/live-updates/custom-storage/) for advanced deployment scenarios * Set up [Encryption](/docs/live-updates/encryption/) for secure deployments * Configure [Update Behavior](/docs/live-updates/update-behavior/) to customize how updates are applied With Bitbucket Pipelines integration, you can automate your Capgo deployments and ensure consistent, reliable updates to your mobile app users. ## Keep going from Bitbucket Pipelines Integration [Section titled “Keep going from Bitbucket Pipelines Integration”](#keep-going-from-bitbucket-pipelines-integration) If you are using **Bitbucket Pipelines Integration** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # GitHub Actions Integration > Learn how to integrate Capgo Live Updates with GitHub Actions for automated deployment of your app updates. Integrate Capgo Live Updates with GitHub Actions to automatically deploy your app updates whenever you push code changes. This guide covers setting up automated builds, testing, and deployment workflows using GitHub’s powerful CI/CD platform. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) Before setting up GitHub Actions integration, ensure you have: * A GitHub repository with your app’s source code * A Capgo account with an app configured * Node.js and npm/yarn configured in your project * GitHub Actions enabled for your repository ## Setting Up GitHub Secrets [Section titled “Setting Up GitHub Secrets”](#setting-up-github-secrets) ### Step 1: Configure Repository Secrets [Section titled “Step 1: Configure Repository Secrets”](#step-1-configure-repository-secrets) Set up the necessary secrets in your GitHub repository: 1. Navigate to your GitHub repository 2. Go to **Settings** → **Secrets and variables** → **Actions** 3. Click **New repository secret** and add the following: | Secret Name | Value | | ------------- | -------------------- | | `CAPGO_TOKEN` | Your Capgo API token | Tip Get your Capgo API token from [console.capgo.app/apikeys](https://console.capgo.app/apikeys). Your app ID is already configured in your `capacitor.config.ts` file. ## Simple Production Deployment [Section titled “Simple Production Deployment”](#simple-production-deployment) Start with this basic configuration that deploys to production on every push to the main branch: ```yaml # Simple GitHub Actions Workflow for Capgo Live Updates name: Deploy to Capgo on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - name: Install, test and build run: | npm ci npm run test npm run build - name: Deploy to Capgo run: | npm install -g @capgo/cli npx @capgo/cli bundle upload --channel production env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} # For encrypted uploads, add: --key-data-v2 "${{ secrets.CAPGO_PRIVATE_KEY }}" ``` ## Advanced Multi-Channel Configuration [Section titled “Advanced Multi-Channel Configuration”](#advanced-multi-channel-configuration) ### Feature Branch Deployments [Section titled “Feature Branch Deployments”](#feature-branch-deployments) Deploy feature branches to temporary channels for testing: ```yaml # Feature branch deployment name: Deploy Feature Branch to Capgo on: push: branches: - 'feature/**' jobs: deploy-feature: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: | npm ci npm run test npm run build - name: Deploy to feature channel run: | CHANNEL_NAME=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]') npm install -g @capgo/cli npx @capgo/cli channel create $CHANNEL_NAME --apikey ${{ secrets.CAPGO_TOKEN }} || true npx @capgo/cli bundle upload --apikey ${{ secrets.CAPGO_TOKEN }} --channel $CHANNEL_NAME ``` ### Using Encryption [Section titled “Using Encryption”](#using-encryption) If you’re using [Capgo’s encryption feature](/docs/live-updates/encryption/), you’ll need to store your private key securely in your CI/CD environment. After [setting up encryption keys](/docs/live-updates/encryption/#setting-up-encryption) locally, add your private key to GitHub secrets: ```shell # Display your private key content (copy this output) cat .capgo_key_v2 ``` Add this content as `CAPGO_PRIVATE_KEY` in your GitHub repository secrets, then use it in workflows: ```yaml # Deploy with encryption - name: Deploy to Capgo with Encryption run: | npm install -g @capgo/cli npx @capgo/cli bundle upload --apikey ${{ secrets.CAPGO_TOKEN }} --key-data-v2 "${{ secrets.CAPGO_PRIVATE_KEY }}" --channel production ``` Caution **Security Best Practices:** * Never commit the `.capgo_key_v2` file to version control * Store the private key only in secure CI/CD secret management * Use different keys for different environments ### Multi-Channel Configuration [Section titled “Multi-Channel Configuration”](#multi-channel-configuration) For comprehensive information about setting up and managing multiple deployment channels, see the [Channels documentation](/docs/live-updates/channels/). Complete workflow with development, pull requests, and production deployments: ```yaml # Complete multi-environment workflow name: Deploy to Capgo on: push: branches: [main, develop] pull_request: branches: [main, develop] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - run: | npm ci npm run test npm run build - uses: actions/upload-artifact@v6 with: name: dist path: dist/ deploy-development: if: github.ref == 'refs/heads/develop' needs: build runs-on: ubuntu-latest environment: development steps: - uses: actions/setup-node@v6 with: node-version: '24' - uses: actions/download-artifact@v4 with: name: dist path: dist/ - run: | npm install -g @capgo/cli npx @capgo/cli bundle upload --apikey ${{ secrets.CAPGO_TOKEN }} --channel development deploy-pr: if: github.event_name == 'pull_request' needs: build runs-on: ubuntu-latest steps: - uses: actions/setup-node@v6 with: node-version: '24' - uses: actions/download-artifact@v4 with: name: dist path: dist/ - name: Deploy to PR channel run: | CHANNEL_NAME="pr-${{ github.event.number }}" npm install -g @capgo/cli npx @capgo/cli channel create $CHANNEL_NAME --apikey ${{ secrets.CAPGO_TOKEN }} || true npx @capgo/cli bundle upload --apikey ${{ secrets.CAPGO_TOKEN }} --channel $CHANNEL_NAME - name: Comment PR uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `🚀 This PR has been deployed to Capgo channel: \`pr-${{ github.event.number }}\`\n\nTo test this update in your app, configure it to use this channel. [Learn how to configure channels →](/docs/live-updates/channels/#configuring-the-channel-in-your-app)` }) deploy-production: if: github.ref == 'refs/heads/main' needs: build runs-on: ubuntu-latest environment: production steps: - uses: actions/setup-node@v6 with: node-version: '24' - uses: actions/download-artifact@v4 with: name: dist path: dist/ - run: | npm install -g @capgo/cli npx @capgo/cli bundle upload --apikey ${{ secrets.CAPGO_TOKEN }} --channel production ``` Tip **Testing with Channels**: After deploying to a PR or development channel, you can test the update in your app by configuring it to use that specific channel. Learn more about [configuring channels in your app](/docs/live-updates/channels/#configuring-the-channel-in-your-app). ### Cleanup Feature Channels [Section titled “Cleanup Feature Channels”](#cleanup-feature-channels) Automatically clean up feature channels when branches are deleted: ```yaml name: Cleanup Feature Channels on: delete: jobs: cleanup: runs-on: ubuntu-latest if: github.event.ref_type == 'branch' && startsWith(github.event.ref, 'feature/') steps: - uses: actions/setup-node@v6 with: node-version: '24' - name: Delete Capgo channel run: | CHANNEL_NAME=$(echo "${{ github.event.ref }}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]') npm install -g @capgo/cli npx @capgo/cli channel delete $CHANNEL_NAME --apikey ${{ secrets.CAPGO_TOKEN }} || true ``` ## Security and Best Practices [Section titled “Security and Best Practices”](#security-and-best-practices) ### Environment Protection Rules [Section titled “Environment Protection Rules”](#environment-protection-rules) Set up environment protection rules in GitHub: 1. Go to **Settings** → **Environments** in your repository 2. Create environments: `development`, `staging`, `production` 3. For production environment, add: * **Required reviewers**: Add team members who must approve deployments * **Wait timer**: Add a delay before deployment (optional) * **Deployment branches**: Restrict to `main` branch only ### Secure Secrets Management [Section titled “Secure Secrets Management”](#secure-secrets-management) Use environment-specific secrets: ```yaml # Use different secrets per environment deploy-production: environment: production steps: - name: Deploy to Production run: | npx @capgo/cli bundle upload \ --apikey ${{ secrets.CAPGO_PROD_TOKEN }} \ --app ${{ secrets.CAPGO_PROD_APP_ID }} \ --channel production ``` ## Monitoring and Notifications [Section titled “Monitoring and Notifications”](#monitoring-and-notifications) ### Slack Integration [Section titled “Slack Integration”](#slack-integration) Add Slack notifications to your workflow: ```yaml name: Deploy with Notifications jobs: deploy: runs-on: ubuntu-latest steps: # ... deployment steps - name: Notify Slack on Success if: success() uses: 8398a7/action-slack@v3 with: status: success text: '✅ Capgo deployment successful!' fields: repo,message,commit,author,action,eventName,ref,workflow env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - name: Notify Slack on Failure if: failure() uses: 8398a7/action-slack@v3 with: status: failure text: '❌ Capgo deployment failed!' fields: repo,message,commit,author,action,eventName,ref,workflow env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} ``` ### Discord Integration [Section titled “Discord Integration”](#discord-integration) Send notifications to Discord: ```yaml - name: Discord notification if: always() uses: Ilshidur/action-discord@master with: args: | Capgo deployment ${{ job.status }}! App: ${{ secrets.CAPGO_APP_ID }} Channel: ${{ github.ref_name }} Commit: ${{ github.sha }} env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} ``` ### Email Notifications [Section titled “Email Notifications”](#email-notifications) Configure email notifications: ```yaml - name: Send email notification if: failure() uses: dawidd6/action-send-mail@v3 with: server_address: smtp.gmail.com server_port: 465 username: ${{ secrets.EMAIL_USERNAME }} password: ${{ secrets.EMAIL_PASSWORD }} subject: 'Capgo Deployment Failed - ${{ github.repository }}' to: team@yourcompany.com from: ci-cd@yourcompany.com body: | Deployment failed for ${{ github.repository }} Branch: ${{ github.ref_name }} Commit: ${{ github.sha }} Workflow: ${{ github.workflow }} ``` ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### Debug Workflow [Section titled “Debug Workflow”](#debug-workflow) Add debugging steps to troubleshoot issues: ```yaml - name: Debug environment run: | echo "Node version: $(node --version)" echo "NPM version: $(npm --version)" echo "Working directory: $(pwd)" echo "Files in dist/: $(ls -la dist/ || echo 'No dist directory')" echo "Environment variables:" env | grep -E "(GITHUB_|CAPGO_)" | sort - name: Test Capgo CLI run: | npx @capgo/cli --version npx @capgo/cli app debug --apikey ${{ secrets.CAPGO_TOKEN }} --app ${{ secrets.CAPGO_APP_ID }} ``` ### Common Issues and Solutions [Section titled “Common Issues and Solutions”](#common-issues-and-solutions) **Workflow fails with “CAPGO\_TOKEN not found”:** ```yaml - name: Verify secrets run: | if [ -z "${{ secrets.CAPGO_TOKEN }}" ]; then echo "ERROR: CAPGO_TOKEN secret is not set" exit 1 fi echo "CAPGO_TOKEN is set (length: ${#CAPGO_TOKEN})" env: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} ``` **Build artifacts not found:** ```yaml - name: Debug artifacts run: | echo "Checking for build artifacts..." ls -la dist/ || echo "No dist directory found" find . -name "*.js" -o -name "*.html" | head -10 ``` **Network connectivity issues:** ```yaml - name: Test connectivity run: | ping -c 3 api.capgo.io || echo "Ping failed" curl -I https://api.capgo.io/health || echo "Health check failed" ``` ## Reusable Workflows [Section titled “Reusable Workflows”](#reusable-workflows) Create reusable workflows for consistency across projects: .github/workflows/reusable-capgo-deploy.yml ```yaml name: Reusable Capgo Deploy on: workflow_call: inputs: environment: required: true type: string channel: required: true type: string secrets: CAPGO_TOKEN: required: true CAPGO_APP_ID: required: true jobs: deploy: runs-on: ubuntu-latest environment: ${{ inputs.environment }} steps: - uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' - name: Install and build run: | npm ci npm run build - name: Deploy to Capgo run: | npm install -g @capgo/cli npx @capgo/cli bundle upload \ --apikey ${{ secrets.CAPGO_TOKEN }} \ --app ${{ secrets.CAPGO_APP_ID }} \ --channel ${{ inputs.channel }} ``` Use the reusable workflow: .github/workflows/deploy.yml ```yaml name: Deploy App on: push: branches: [main, develop] jobs: deploy-dev: if: github.ref == 'refs/heads/develop' uses: ./.github/workflows/reusable-capgo-deploy.yml with: environment: development channel: development secrets: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} CAPGO_APP_ID: ${{ secrets.CAPGO_APP_ID }} deploy-prod: if: github.ref == 'refs/heads/main' uses: ./.github/workflows/reusable-capgo-deploy.yml with: environment: production channel: production secrets: CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }} CAPGO_APP_ID: ${{ secrets.CAPGO_APP_ID }} ``` ## Next Steps [Section titled “Next Steps”](#next-steps) * Learn about [Channels](/docs/live-updates/channels/) to manage different deployment environments * Explore [Custom Storage](/docs/live-updates/custom-storage/) for advanced deployment scenarios * Set up [Encryption](/docs/live-updates/encryption/) for secure deployments * Configure [Update Behavior](/docs/live-updates/update-behavior/) to customize how updates are applied With GitHub Actions integration, you can leverage GitHub’s powerful CI/CD platform to create sophisticated deployment workflows with built-in security, monitoring, and collaboration features for your Capgo Live Updates. ## Keep going from GitHub Actions Integration [Section titled “Keep going from GitHub Actions Integration”](#keep-going-from-github-actions-integration) If you are using **GitHub Actions Integration** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitLab CI/CD Integration](/docs/live-updates/integrations/gitlab-ci/) for the implementation detail in GitLab CI/CD Integration. # GitLab CI/CD Integration > Learn how to integrate Capgo Live Updates with GitLab CI/CD for automated deployment of your app updates. Integrate Capgo Live Updates with GitLab CI/CD to automatically deploy your app updates whenever you push code changes. This guide covers setting up automated builds, testing, and deployment workflows. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) Before setting up GitLab CI/CD integration, ensure you have: * A GitLab account with a project repository * A Capgo account with an app configured * Node.js and npm/yarn configured in your project ## Setting Up GitLab CI/CD [Section titled “Setting Up GitLab CI/CD”](#setting-up-gitlab-cicd) ### Step 1: Configure Environment Variables [Section titled “Step 1: Configure Environment Variables”](#step-1-configure-environment-variables) First, set up the necessary variables in your GitLab project: 1. Navigate to your GitLab project 2. Go to **Settings** → **CI/CD** → **Variables** 3. Add the following variables: | Variable Name | Value | Protected | Masked | | ------------- | -------------------- | --------- | ------ | | `CAPGO_TOKEN` | Your Capgo API token | ✅ Yes | ✅ Yes | Tip Get your Capgo API token from [console.capgo.app/apikeys](https://console.capgo.app/apikeys). Your app ID is already configured in your `capacitor.config.ts` file. ## Simple [Section titled “Simple”](#simple) Basic configuration that deploys to production on every push to the main branch: ```yaml # .gitlab-ci.yml - Simple Configuration image: node:22 stages: - build - deploy variables: npm_config_cache: "$CI_PROJECT_DIR/.npm" build: stage: build script: - npm ci - npm run test - npm run build artifacts: paths: - dist/ expire_in: 1 hour only: - main deploy_production: stage: deploy script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production # For encrypted uploads, add: --key-data-v2 "$CAPGO_PRIVATE_KEY" dependencies: - build only: - main ``` ## Advanced [Section titled “Advanced”](#advanced) ### Feature Branch Deployments [Section titled “Feature Branch Deployments”](#feature-branch-deployments) Deploy feature branches to test channels for review and testing: ```yaml # Feature branch deployment deploy_feature: stage: deploy script: - npm install -g @capgo/cli - CHANNEL_NAME="feature-$(echo $CI_COMMIT_REF_NAME | sed 's/[^a-zA-Z0-9-]/-/g')" - npx @capgo/cli channel create $CHANNEL_NAME --apikey $CAPGO_TOKEN || true - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME dependencies: - build only: - /^feature\/.*$/ environment: name: feature/$CI_COMMIT_REF_NAME url: https://your-app.com/channels/$CHANNEL_NAME ``` Tip **Testing with Channels**: After deploying to a feature channel, you can test the update in your app by configuring it to use that specific channel. Learn more about [configuring channels in your app](/docs/live-updates/channels/#configuring-the-channel-in-your-app). ### Using Encryption [Section titled “Using Encryption”](#using-encryption) If you’re using [Capgo’s encryption feature](/docs/live-updates/encryption/), you’ll need to store your private key securely in your CI/CD environment. After [setting up encryption keys](/docs/live-updates/encryption/#setting-up-encryption) locally, add your private key to GitLab variables: ```shell # Display your private key content (copy this output) cat .capgo_key_v2 ``` Add this content as `CAPGO_PRIVATE_KEY` in your GitLab project variables (mark as protected and masked), then use it in pipelines: ```yaml # Deploy with encryption deploy_production: script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --key-data-v2 "$CAPGO_PRIVATE_KEY" --channel production ``` Caution **Security Best Practices:** * Never commit the `.capgo_key_v2` file to version control * Store the private key only in secure CI/CD secret management * Use different keys for different environments ### Multi-Channel Configuration [Section titled “Multi-Channel Configuration”](#multi-channel-configuration) For comprehensive information about setting up and managing multiple deployment channels, see the [Channels documentation](/docs/live-updates/channels/). Complete configuration with multiple environments and merge request deployments: ```yaml # .gitlab-ci.yml - Advanced Multi-Channel Configuration image: node:22 stages: - build - deploy variables: npm_config_cache: "$CI_PROJECT_DIR/.npm" # Build stage build: stage: build script: - npm ci - npm run test - npm run build artifacts: paths: - dist/ expire_in: 24 hours # Deploy to development channel deploy_development: stage: deploy script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel development dependencies: - build only: - develop environment: name: development # Deploy merge requests to test channels deploy_mr: stage: deploy script: - npm install -g @capgo/cli - CHANNEL_NAME="mr-$CI_MERGE_REQUEST_IID" - npx @capgo/cli channel create $CHANNEL_NAME --apikey $CAPGO_TOKEN || true - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL_NAME dependencies: - build only: - merge_requests environment: name: review/$CI_MERGE_REQUEST_IID url: https://your-app.com/channels/mr-$CI_MERGE_REQUEST_IID on_stop: cleanup_mr # Cleanup MR channels when MR is closed cleanup_mr: stage: deploy script: - npm install -g @capgo/cli - npx @capgo/cli channel delete mr-$CI_MERGE_REQUEST_IID --apikey $CAPGO_TOKEN || true when: manual environment: name: review/$CI_MERGE_REQUEST_IID action: stop only: - merge_requests # Deploy to staging deploy_staging: stage: deploy script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel staging dependencies: - build only: - develop environment: name: staging # Deploy to production deploy_production: stage: deploy script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production dependencies: - build only: - main environment: name: production ``` ### Multi-Environment with Manual Approval [Section titled “Multi-Environment with Manual Approval”](#multi-environment-with-manual-approval) For production deployments requiring manual approval: ```yaml deploy_production: stage: deploy script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production dependencies: - build only: - main when: manual environment: name: production ``` ### Branch-Based Deployment Strategy [Section titled “Branch-Based Deployment Strategy”](#branch-based-deployment-strategy) Deploy different branches to appropriate channels automatically: ```yaml # Dynamic channel deployment based on branch deploy: stage: deploy script: - npm install -g @capgo/cli - | if [ "$CI_COMMIT_REF_NAME" = "main" ]; then CHANNEL="production" elif [ "$CI_COMMIT_REF_NAME" = "develop" ]; then CHANNEL="staging" else CHANNEL="development" fi - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel $CHANNEL dependencies: - build environment: name: $CHANNEL ``` ## Security Best Practices [Section titled “Security Best Practices”](#security-best-practices) ### Protected Variables [Section titled “Protected Variables”](#protected-variables) 1. **Mark Sensitive Variables**: Always mark API tokens as protected and masked 2. **Branch Protection**: Use protected variables for production deployments 3. **Access Control**: Limit variable access to maintainers only 4. **Regular Rotation**: Rotate API tokens regularly ### Secure Pipeline Configuration [Section titled “Secure Pipeline Configuration”](#secure-pipeline-configuration) ```yaml # Use protected variables for production deploy_production: stage: deploy script: - npm install -g @capgo/cli - npx @capgo/cli bundle upload --apikey $CAPGO_TOKEN --channel production only: refs: - main variables: - $CI_COMMIT_REF_PROTECTED == "true" ``` ## Monitoring and Notifications [Section titled “Monitoring and Notifications”](#monitoring-and-notifications) ### Slack Integration [Section titled “Slack Integration”](#slack-integration) Add Slack notifications to your pipeline: ```yaml notify_success: stage: .post image: alpine:latest before_script: - apk add --no-cache curl script: - | curl -X POST -H 'Content-type: application/json' \ --data '{"text":"✅ Capgo deployment successful for '"$CI_COMMIT_REF_NAME"'"}' \ $SLACK_WEBHOOK_URL when: on_success notify_failure: stage: .post image: alpine:latest before_script: - apk add --no-cache curl script: - | curl -X POST -H 'Content-type: application/json' \ --data '{"text":"❌ Capgo deployment failed for '"$CI_COMMIT_REF_NAME"'"}' \ $SLACK_WEBHOOK_URL when: on_failure ``` ### Email Notifications [Section titled “Email Notifications”](#email-notifications) Configure email notifications in your GitLab project settings or use the API: ```yaml notify_email: stage: .post script: - | curl --request POST \ --header "PRIVATE-TOKEN: $GITLAB_API_TOKEN" \ --form "to=team@yourcompany.com" \ --form "subject=Capgo Deployment Status" \ --form "body=Deployment of $CI_COMMIT_REF_NAME completed with status: $CI_JOB_STATUS" \ "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/emails" when: always ``` ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### Common Issues [Section titled “Common Issues”](#common-issues) **Pipeline fails with “Capgo CLI not found”:** ```yaml # Debug CLI installation debug_cli: script: - npm install -g @capgo/cli - which capgo || echo "Capgo CLI not found" - npx @capgo/cli --version ``` **Authentication errors:** ```yaml # Verify token configuration debug_auth: script: - | if [ -z "$CAPGO_TOKEN" ]; then echo "CAPGO_TOKEN is not set" exit 1 fi echo "Token length: ${#CAPGO_TOKEN}" ``` **Build artifacts not found:** ```yaml # List build outputs debug_build: script: - ls -la dist/ - find dist/ -type f -name "*.js" -o -name "*.html" ``` ### Debug Pipeline [Section titled “Debug Pipeline”](#debug-pipeline) Add debugging information to troubleshoot issues: ```yaml debug: stage: build script: - echo "Branch: $CI_COMMIT_REF_NAME" - echo "Commit: $CI_COMMIT_SHA" - echo "Build: $CI_PIPELINE_ID" - env | grep CI_ | sort only: - branches ``` ## Next Steps [Section titled “Next Steps”](#next-steps) * Learn about [Channels](/docs/live-updates/channels/) to manage different deployment environments * Explore [Custom Storage](/docs/live-updates/custom-storage/) for advanced deployment scenarios * Set up [Encryption](/docs/live-updates/encryption/) for secure deployments * Configure [Update Behavior](/docs/live-updates/update-behavior/) to customize how updates are applied With GitLab CI/CD integration, you can automate your Capgo deployments and ensure consistent, reliable updates to your mobile app users. ## Keep going from GitLab CI/CD Integration [Section titled “Keep going from GitLab CI/CD Integration”](#keep-going-from-gitlab-cicd-integration) If you are using **GitLab CI/CD Integration** to plan CI/CD automation, connect it with [Capgo CI/CD](/ci_cd/) for the product workflow in Capgo CI/CD, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, [Capgo Integrations](/integrations/) for the product workflow in Capgo Integrations, [CI/CD Integration](/docs/getting-started/cicd-integration/) for the implementation detail in CI/CD Integration, and [GitHub Actions Integration](/docs/live-updates/integrations/github-actions/) for the implementation detail in GitHub Actions Integration. # Native + OTA Channel Workflow > How to use --fail-on-incompatible with dev and production channels, and what to do when you intentionally ship a bundle that needs new native code. A common Capgo setup uses a **dev** channel and a **production** channel. CI uploads every OTA bundle to `dev`, then promotes to `production` when you are ready. Teams often add `--fail-on-incompatible` so CI cannot ship a live update that needs new native code by accident. This page answers the follow-up: **what do you do when you *intentionally* need a bundle that is incompatible with the channel’s current native packages?** If you need the background on why Capgo compares native packages, start with [Native Compatibility](/docs/live-updates/compatibility/). For a full CI branch that picks OTA vs Capgo Build automatically, see [Auto OTA or Native](/docs/builder/ci-ota-or-native/). ## Recommended channel layout [Section titled “Recommended channel layout”](#recommended-channel-layout) This guide assumes the `dev` and `production` channels already exist. Create them first if needed: ```bash npx @capgo/cli@latest channel add production com.example.app npx @capgo/cli@latest channel add dev com.example.app ``` | Channel | Who gets it | Typical upload | | ------------ | -------------------- | ------------------------------------------------------ | | `dev` | Internal / QA builds | Every CI push of JS (and intentional native baselines) | | `production` | Store users | Promoted or uploaded only when release-ready | `--fail-on-incompatible` is a good default on both channels for **everyday OTA uploads**. It compares the native packages in the bundle you are uploading against the bundle **currently live on that channel**. If they differ, the upload exits non-zero and nothing ships. ## Everyday OTA (keep the flag) [Section titled “Everyday OTA (keep the flag)”](#everyday-ota-keep-the-flag) When the change is JavaScript-only and native packages match the channel: ```bash npx @capgo/cli@latest bundle upload com.example.app \ --channel production \ --fail-on-incompatible \ --auto-min-update-version ``` `--fail-on-incompatible` blocks accidental native drift. `--auto-min-update-version` is required on every upload once the channel uses the `metadata` strategy (recommended below). If the channel is not on `metadata` yet, you can omit `--auto-min-update-version` until you switch. Optional CI gate before upload: ```bash npx @capgo/cli@latest bundle releaseType com.example.app --channel production # → OTA safe to upload with --fail-on-incompatible # → native stop; ship a native binary first (see below) ``` ## Intentional native bump (drop the flag once) [Section titled “Intentional native bump (drop the flag once)”](#intentional-native-bump-drop-the-flag-once) You **cannot** upload a bundle that needs new native code while keeping `--fail-on-incompatible`. That flag exists to block exactly that case. When a plugin, Capacitor version, or other native dependency changed on purpose: 1. Ship the matching **native binary** (App Store / Play Store, or [Capgo Build](/docs/builder/)). 2. Upload the matching JS bundle **without** `--fail-on-incompatible`. 3. Prefer `--auto-min-update-version` with the channel on the `metadata` strategy so devices still on the old binary do not receive the new bundle until they install the new app. 4. After that baseline upload, put `--fail-on-incompatible` back on normal OTA CI (and keep `--auto-min-update-version` while the channel stays on `metadata`). 1) **One-time per channel: enable metadata gating** ```bash npx @capgo/cli@latest channel set production com.example.app --disable-auto-update metadata ``` Repeat for `dev` if that channel also receives intentional native baselines. After this switch, every upload to the channel must include `--auto-min-update-version` or `--min-update-version`. 2) **Ship the native binary** Build and submit the iOS/Android app that includes the new plugins or native changes. Until users install that binary, they cannot safely run a bundle that depends on those native packages. 3) **Upload the matching OTA baseline (no `--fail-on-incompatible`)** ```bash npx @capgo/cli@latest bundle upload com.example.app \ --channel production \ --auto-min-update-version ``` This records the new native packages on the channel. Later `bundle releaseType` / `--fail-on-incompatible` checks use that baseline. 4) **Resume guarded OTA uploads** Subsequent JS-only releases use both flags again: ```bash npx @capgo/cli@latest bundle upload com.example.app \ --channel production \ --fail-on-incompatible \ --auto-min-update-version ``` Tip Treat the native-baseline upload as a **dedicated CI job** (or a manual release step), not as an exception you sprinkle into the default OTA job. The default job should always keep `--fail-on-incompatible`, and on a `metadata` channel it should also keep `--auto-min-update-version`. ## FAQ [Section titled “FAQ”](#faq) ### Can I keep `--fail-on-incompatible` and still push a native-incompatible bundle? [Section titled “Can I keep --fail-on-incompatible and still push a native-incompatible bundle?”](#can-i-keep---fail-on-incompatible-and-still-push-a-native-incompatible-bundle) No. If the upload’s native packages differ from the channel’s live bundle, the flag fails the command on purpose. For an intentional native bump, omit the flag on that one upload (and use `--auto-min-update-version` when you can). ### Is a one-time upload without the flag the right approach? [Section titled “Is a one-time upload without the flag the right approach?”](#is-a-one-time-upload-without-the-flag-the-right-approach) Yes. That is the supported way to advance the channel’s native baseline after you ship a new binary. Keep the flag on every other OTA upload so accidental native drift still fails CI. ### Do I upload to `dev` first, then `production`? [Section titled “Do I upload to dev first, then production?”](#do-i-upload-to-dev-first-then-production) Yes, if that matches your process. Run the same rules **per channel**: the compatibility check is against whatever is live on the target channel. Promote or re-upload to `production` only after `dev` looks good, and use a native-baseline upload (no `--fail-on-incompatible`) on each channel that needs the new native packages recorded. ### What if I upload the new native bundle with the flag still on? [Section titled “What if I upload the new native bundle with the flag still on?”](#what-if-i-upload-the-new-native-bundle-with-the-flag-still-on) CI fails and Capgo does not ship that upload. That is the expected outcome. Either the change was accidental (fix the native packages and retry as OTA), or it was intentional (use the native path above). ### Which flag goes on which job? [Section titled “Which flag goes on which job?”](#which-flag-goes-on-which-job) | Path | When | Upload flags | | --------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------- | | OTA | JS-only; native packages match the channel | `--fail-on-incompatible` + `--auto-min-update-version` (required if the channel is on `metadata`) | | Native baseline | New native binary + matching JS bundle | **No** `--fail-on-incompatible`; keep `--auto-min-update-version` | ## Related [Section titled “Related”](#related) [ Native Compatibility](/docs/live-updates/compatibility/) [How Capgo detects native package drift and what incompatible means for devices.](/docs/live-updates/compatibility/) [ Auto OTA or Native](/docs/builder/ci-ota-or-native/) [Wire `bundle releaseType` into GitHub Actions or GitLab so CI picks the right path.](/docs/builder/ci-ota-or-native/) [ Version Targeting](/docs/live-updates/version-targeting/) [Channels, semver rules, and the metadata strategy for delivery floors.](/docs/live-updates/version-targeting/) [ CLI: bundle](/docs/cli/reference/bundle/) [Reference for upload, compatibility, releaseType, and related flags.](/docs/cli/reference/bundle/) ## Keep going from Native + OTA Channel Workflow [Section titled “Keep going from Native + OTA Channel Workflow”](#keep-going-from-native--ota-channel-workflow) If you are using **Native + OTA Channel Workflow** to keep live updates safe across native releases, connect it with [Native Compatibility](/docs/live-updates/compatibility/) for the package comparison rules, [Auto OTA or Native](/docs/builder/ci-ota-or-native/) for CI branching, [Version Targeting](/docs/live-updates/version-targeting/) for metadata floors, and the [Capgo CLI bundle reference](/docs/cli/reference/bundle/) for upload flags. # Progressive rollouts > Release a bundle to a random, sticky subset of a channel before promoting it to every device. A progressive rollout keeps a channel’s **stable bundle** in place while delivering a separate **rollout target** to a controlled subset of devices. It is useful when you want real production validation without switching the whole channel at once. ![Progressive rollout controls in a Capgo channel](/progressive-rollout.webp) Configure the rollout target, percentage, cache duration, and auto-pause policy from a channel’s Information tab. ## How progressive rollouts work [Section titled “How progressive rollouts work”](#how-progressive-rollouts-work) Each channel can have two bundle links: * **Stable bundle** — the normal bundle assigned to the channel. * **Rollout target** — the candidate bundle that is released gradually. A rollout needs a stable bundle. In the dashboard, assign the stable bundle before choosing the target; with the Public API, an existing channel can supply `version` and `rolloutVersion` in the same POST request. Capgo makes a random decision for each eligible device, then caches it using a hash of the device ID and the rollout ID. That makes the cohort sticky for the configured cache duration instead of changing on every update check. Sticky does not mean permanent The default rollout-decision cache duration is 30 days. After it expires, a device can be selected again. Changing the rollout target creates a new rollout ID and starts a new cohort. You can set the cache duration from 60 seconds to 365 days. ### Percentage changes [Section titled “Percentage changes”](#percentage-changes) Capgo preserves existing decisions when it can: * **Increase a percentage** — devices already selected stay selected; only a random subset of previously unselected devices is added. * **Decrease a percentage** — a random subset of the selected cohort returns to the stable bundle. * **Set the percentage to 0%** — no new devices are selected. Devices already running the enabled rollout target continue to receive that target until you disable, roll back, or change the target. * **Pause** — stops new devices from entering while devices already running the enabled target remain on it. * **Disable** — stops resolving the rollout target; update checks use the stable bundle. ## Run a rollout [Section titled “Run a rollout”](#run-a-rollout) 1. Upload and assign a tested bundle as the channel’s stable bundle. 2. Upload the candidate bundle without replacing the stable bundle. 3. Open the channel’s **Information** tab, set the candidate as the **Target**, choose a small percentage, and enable the rollout. 4. Monitor the rollout in [Observe](/docs/webapp/observe/), [Log Insights](/docs/webapp/log-insights/), and the channel history. Increase the percentage only after the cohort is healthy. 5. When it is ready, promote the target to stable. If it is not healthy, pause or roll it back. ### CLI example [Section titled “CLI example”](#cli-example) Start a rollout for bundle `1.3.0` at 5%: ```bash npx @capgo/cli@latest channel set production com.example.app \ --rollout-bundle 1.3.0 \ --rollout-percentage 5 \ --rollout-enable ``` Increase it without reseating devices already selected: ```bash npx @capgo/cli@latest channel set production com.example.app \ --rollout-percentage 25 ``` The bundle upload command can set its upload as a rollout target in one step when the channel already has a stable bundle: ```bash npx @capgo/cli@latest bundle upload com.example.app \ --path ./dist \ --channel production \ --rollout 5 ``` See the complete [channel CLI reference](/docs/cli/reference/channel/) and [bundle CLI reference](/docs/cli/reference/bundle/) for every rollout option. ## Pause, roll back, or promote [Section titled “Pause, roll back, or promote”](#pause-roll-back-or-promote) | Action | What it does | | ------------- | ---------------------------------------------------------------------------------------------------- | | **Pause** | Stops new devices from entering the rollout. Devices already on the enabled target stay there. | | **Resume** | Allows new eligible devices to enter again. | | **Disable** | Stops resolving the rollout target and uses the stable bundle. | | **Roll back** | Clears the target, disables the rollout, resets the percentage to 0%, and returns devices to stable. | | **Promote** | Makes the rollout target the stable bundle, then clears rollout state. | Use one terminal action at a time: ```bash # Stop adding devices while you investigate npx @capgo/cli@latest channel set production com.example.app --rollout-pause # Make the candidate stable for everyone npx @capgo/cli@latest channel set production com.example.app --rollout-promote # Discard the candidate and return to stable npx @capgo/cli@latest channel set production com.example.app --rollout-rollback ``` Keep the target bundle available until you promote it or roll it back. Bundles linked as a stable bundle or rollout target are protected from deletion. ## Auto-pause policy [Section titled “Auto-pause policy”](#auto-pause-policy) Capgo can evaluate an enabled rollout every five minutes and act when its failure signal crosses your threshold. It measures installs and failures for the rollout target in the selected channel and time window, then uses a Wilson confidence lower bound rather than the raw failure rate alone. Auto-pause is disabled by default. Configure these fields in the channel’s **Information** tab or with `channel set`: * **Failure rate threshold** in basis points (`500` = 5%). A threshold is required for the policy to trigger. * **Window** in minutes (default: 60). * **Confidence** between `0` and `1` (default: `0.95`). * Optional minimum attempts and failures, to avoid acting on tiny samples. * **Cooldown** in minutes (default: 60), which prevents repeated actions. * **Action**: `pause`, `rollback`, or `notify`. `pause` stops new rollout exposure, `rollback` clears the target and returns to stable, and `notify` sends a rollout alert without changing rollout delivery. ```bash npx @capgo/cli@latest channel set production com.example.app \ --auto-pause-enabled \ --auto-pause-failure-rate-bps 500 \ --auto-pause-window-minutes 60 \ --auto-pause-confidence 0.95 \ --auto-pause-min-attempts 100 \ --auto-pause-min-failures 5 \ --auto-pause-action pause \ --auto-pause-cooldown-minutes 120 ``` ## API and dashboard controls [Section titled “API and dashboard controls”](#api-and-dashboard-controls) You can manage the same feature through the [Public Channels API](/docs/public-api/channels/) or the dashboard: 1. Open an app, then **Channels**. 2. Choose the channel. 3. Open **Information**. 4. Use the **Progressive rollout** section to choose the target, percentage, cache duration, and auto-pause policy. For general channel routing and device precedence, see [Channels](/docs/live-updates/channels/). For emergency bundle recovery outside a progressive rollout, see [Rolling back a live update](/docs/live-updates/rollbacks/). # Rollbacks > Learn how to manage rollbacks in Capgo, allowing you to revert to previous app versions seamlessly when needed. While Capgo’s live updates allow you to quickly deliver improvements and fixes to your users, there may be situations where you need to roll back to a previous version of your app. Perhaps a new update introduced an unexpected critical issue, or maybe you want to revert a specific change while you work on a fix. Capgo provides several ways to manage a channel’s builds and control the version of your app that users receive, including both manual rollback options and automatic safety mechanisms. ## Automatic Rollback Protection [Section titled “Automatic Rollback Protection”](#automatic-rollback-protection) Capgo includes a built-in safety mechanism to protect your users from broken updates. If a JavaScript error occurs before the `notifyAppReady()` method is called, the plugin will automatically roll back to the previous working version. ### How Automatic Rollback Works [Section titled “How Automatic Rollback Works”](#how-automatic-rollback-works) When a new update is downloaded and applied, Capgo expects your app to call `notifyAppReady()` within a configurable timeframe to confirm that the update loaded successfully. This method signals that: * The JavaScript bundle loaded without critical errors * Your app’s core functionality is working * The update is safe to keep If `notifyAppReady()` is not called due to a JavaScript crash or critical error, Capgo will: 1. Detect that the update failed to initialize properly 2. Automatically revert to the previous working bundle 3. Mark the problematic update as failed to prevent it from being applied again Tip Make sure to call `notifyAppReady()` in your app’s initialization code after your core components have loaded successfully. This ensures the automatic rollback protection works as intended. ```javascript import { CapacitorUpdater } from '@capgo/capacitor-updater' // Call this after your app has successfully initialized await CapacitorUpdater.notifyAppReady() ``` This automatic protection helps ensure that even if you accidentally push a broken update, your users won’t be stuck with a non-functional app. ### Configuring the Timeout [Section titled “Configuring the Timeout”](#configuring-the-timeout) You can configure how long Capgo waits for `notifyAppReady()` to be called by setting the `appReadyTimeout` in your Capacitor configuration: ```json { "plugins": { "CapacitorUpdater": { "appReadyTimeout": 10000 } } } ``` The `appReadyTimeout` value is specified in milliseconds. The default timeout is typically 10 seconds, but you can adjust this based on your app’s initialization requirements. If your app takes longer to load due to complex initialization processes, you may want to increase this value. ## Rolling Back to a Previous Bundle [Section titled “Rolling Back to a Previous Bundle”](#rolling-back-to-a-previous-bundle) Every time you upload a new build and assign it to a channel, Capgo keeps a history of those builds. If you need to revert a specific update, you can select one of these previous builds to redeploy to the channel. ![Rollback UI interface](/rollback_ui.webp) The primary way to roll back is through the rollback interface, which is located in the 4th tab (History) when viewing a channel in the Capgo Dashboard. This tab provides a comprehensive view of all available builds for the channel, allowing you to easily select and revert to any previous version. To roll back using the History tab: 1. Log in to the [Capgo Dashboard](https://app.capgo.io). 2. Navigate to the “Channels” section. 3. Click the name of the channel you want to roll back. 4. Go to the 4th tab (History) in the channel view. 5. Find the build you want to revert to in the build history. 6. Select that build to make it the active build for the channel. 7. Confirm that you want to roll back to this build. ### Alternative Method: Using the Crown Icon [Section titled “Alternative Method: Using the Crown Icon”](#alternative-method-using-the-crown-icon) As a second way, you can also roll back directly from the first tab by clicking the crown icon next to any build in the channel’s build history: 1. In the first tab of the channel view, find the build you want to revert to. 2. Click the crown icon next to that build to make it the active build for the channel. ![Channel management options](/select_bundle.webp) 3. Confirm that you want to roll back to this build. Note Rolling back to a previous build only affects the selected channel. If you have multiple channels (e.g. Production, Staging, etc.), you’ll need to repeat the rollback process for each affected channel. After rolling back, devices configured to listen to the updated channel will receive the previous build the next time they check for an update. The rolled-back build will be treated as a new update, so the usual update flow and conditions apply. ## Accelerate a Critical Rollback with Notifications [Section titled “Accelerate a Critical Rollback with Notifications”](#accelerate-a-critical-rollback-with-notifications) Repointing a channel normally takes effect the next time a device checks for an update. Capgo Notifications can send a silent update-check notification to a supported app while it is in the background. With the updater integration enabled, the app can check, download, and install the rollback according to its configured update mode. This is an acceleration path, not a forced fleet command. Delivery remains best-effort and depends on operating-system background scheduling, network availability, and device state. It cannot update an offline or force-quit app, so it cannot promise a fixed time to reach every device. To set up this path, follow [Notifications: Enable Silent Update Checks](/docs/plugins/notifications/getting-started/#11-enable-silent-update-checks). ## Unlinking a Channel [Section titled “Unlinking a Channel”](#unlinking-a-channel) If you want to temporarily halt updates on a channel while you investigate an issue, you can unlink the channel from its current build. To unlink a channel: 1. Navigate to the channel in the Capgo Dashboard. 2. Click the “Unlink” button next to the current build. 3. Confirm that you want to unlink the channel. Once a channel is unlinked, it will not distribute any new updates. Devices configured to that channel will stay on their current build until the channel is linked to a build again. This is useful if you’ve identified a problem with an update but aren’t yet sure which build you want to roll back to. Unlinking the channel gives you time to investigate without pushing out further updates. ## Forcing the Built-In Bundle [Section titled “Forcing the Built-In Bundle”](#forcing-the-built-in-bundle) In more severe situations, you may want to revert all devices on a channel back to the web build that was originally packaged with your app’s native binary. This is known as the “built-in bundle”. To force the built-in bundle on a channel: 1. Navigate to the channel in the Capgo Dashboard. 2. Click the “Built-in Bundle” button. 3. Confirm that you want to force the built-in bundle. When you force the built-in bundle, all devices configured to that channel will revert back to the original packaged web build on their next update check. This happens regardless of what build they’re currently on. This is a more aggressive rollback option than reverting to a specific previous build, as it discards all live updates released since the app was last published to the app stores. Caution Be cautious when forcing the built-in bundle, as it will affect all devices on the channel. Make sure you’ve considered the impact and have a plan to move forward before taking this action. ## Monitoring and Responding to Issues [Section titled “Monitoring and Responding to Issues”](#monitoring-and-responding-to-issues) To catch issues quickly and minimize the impact of problematic updates, it’s important to have a plan for monitoring your releases and responding to problems. Some strategies include: For a rollout that is still limited to a cohort, use [Progressive rollouts](/docs/live-updates/progressive-rollouts/) to pause exposure or clear its target before changing the stable bundle for the whole channel. * Monitoring crash reports and user feedback immediately after releasing an update * Using phased rollouts or a staged channel system to test updates on a smaller group before wide release * Having a clear decision process for when to roll back, unlink, or force the built-in bundle, and who has the authority to do so * Communicating to users about the issue and the resolution, if appropriate By combining careful monitoring with the ability to quickly manage problematic updates, you can deliver a continuously improving app experience while minimizing disruptions for your users. ## Keep going from Rollbacks [Section titled “Keep going from Rollbacks”](#keep-going-from-rollbacks) If you are using **Rollbacks** to plan rollback and version control, connect it with [Version Targeting](/docs/live-updates/version-targeting/) for the implementation detail in Version Targeting, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, [bundle](/docs/cli/reference/bundle/) for the implementation detail in bundle, [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, and [Rollback Strategies for Capacitor Live Updates](/blog/rollback-strategies-for-capacitor-live-updates/) for the practical context in Rollback Strategies for Capacitor Live Updates. # Test Native Builds Without Live Updates > Verify the web assets bundled in a native build without receiving a previously deployed live update. When testing a new native binary, make sure it starts from the web assets bundled in that binary—not from a previously downloaded live update. Use one or combine the safeguards below. ## 1. Bump the Native Baseline Version [Section titled “1. Bump the Native Baseline Version”](#1-bump-the-native-baseline-version) Set `CapacitorUpdater.version` from the version used for your native release, and increase it for every native build. A newer native baseline makes the installed binary distinct from older bundles and, with the default `resetWhenUpdate: true`, removes downloaded bundles when the newer native app is installed. ```typescript import type { CapacitorConfig } from '@capacitor/cli'; import pkg from './package.json'; const config: CapacitorConfig = { plugins: { CapacitorUpdater: { // Keep this aligned with, and increase it for, every native build. version: pkg.version, autoUpdate: 'atBackground', }, }, }; export default config; ``` For example, a binary built with `version: '1.4.1'` has a higher native baseline than an existing `1.4.0` bundle. Do not reuse a native version when you need to verify the bundled assets. ## 2. Block Emulator and Development-Build Updates in the Console [Section titled “2. Block Emulator and Development-Build Updates in the Console”](#2-block-emulator-and-development-build-updates-in-the-console) Open your app in the Capgo console, go to **Channels**, select the channel used by the build, and open the **Information** tab. Turn **off** both **Allow development build** and **Allow Emulators**. ![Capgo channel Information tab showing the Allow development build and Allow Emulators settings](/native-build-live-updates-channel-settings.webp) These controls are in the channel Information tab. Disable both highlighted settings to keep development builds and emulators on their bundled web assets. Caution The screenshot shows where to find the settings; its highlighted toggles are enabled. Turn both toggles off for a channel that must not deliver live updates to development builds or emulators. This channel policy blocks update delivery only for the selected build types. Production-signed physical devices can still receive updates according to the channel’s other settings. ## 3. Enable Live Updates Only in Native CI Builds [Section titled “3. Enable Live Updates Only in Native CI Builds”](#3-enable-live-updates-only-in-native-ci-builds) For teams that want local, emulator, and developer builds to be safe by default, make live updates opt-in through an environment variable. The config below disables update checks unless `CAPGO_LIVE_UPDATES` is exactly `true`: ```typescript import type { CapacitorConfig } from '@capacitor/cli'; import pkg from './package.json'; const liveUpdatesEnabled = process.env.CAPGO_LIVE_UPDATES === 'true'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'Example App', plugins: { CapacitorUpdater: { // Bump package.json for every native build. version: pkg.version, // Local builds are off; native CI explicitly enables live updates. autoUpdate: liveUpdatesEnabled ? 'atBackground' : false, }, }, }; export default config; ``` Set the variable only in the CI step that synchronizes and builds the native app: ```yaml - run: CAPGO_LIVE_UPDATES=true npx cap sync - run: ./build-native-app.sh ``` Run `npx cap sync` after setting the variable because Capacitor copies this configuration into the native projects during sync. Without the variable, local builds and emulator builds keep `autoUpdate: false` and do not check for live updates. ## Quick Checklist [Section titled “Quick Checklist”](#quick-checklist) 1. Increase the version used by `CapacitorUpdater.version` for the native binary. 2. Disable **Allow development build** and **Allow Emulators** on the channel when testing those build types. 3. Build locally without `CAPGO_LIVE_UPDATES`. 4. Set `CAPGO_LIVE_UPDATES=true` only before `npx cap sync` in the native CI job that should receive live updates. ## Related [Section titled “Related”](#related) * [Channels](/docs/live-updates/channels/) — Channel routing and policies. * [Update Behavior](/docs/live-updates/update-behavior/) — When updates are checked and applied. * [Version Targeting](/docs/live-updates/version-targeting/) — Keep bundles compatible with native versions. # Update Behavior > Explore the comprehensive update behavior of Capgo, designed to deliver seamless updates to your app users without interrupting their experience. When you release an update to your Capgo app, you probably want your users to receive that update as soon as possible. But you also don’t want to disrupt their experience by forcing them to wait for a download or restart the app in the middle of a session. Capgo’s update behavior is designed to strike a balance between delivering updates quickly and minimizing disruption to your users. ## Default Update Flow [Section titled “Default Update Flow”](#default-update-flow) By default, here’s how Capgo handles app updates: 1. When the app moves to the foreground, the Capgo plugin checks to see if a new update is available. While the app stays open, it also checks again on a repeating timer controlled by `periodCheckDelay` (default 10 minutes). 2. If an update is found, it’s downloaded in the background while the user continues using the current version of the app. 3. Once the download completes, Capgo waits for the user to background the app. 4. When the user next brings the app to the foreground, they’ll be running the updated version. This flow ensures that users are always running the latest version of your app, without ever being interrupted by update prompts or forced to wait for downloads. Tip Capgo checks for updates whenever the app moves to the foreground and on a repeating timer while the app stays open. `periodCheckDelay` controls that interval (default 10 minutes). ## Why This Approach? [Section titled “Why This Approach?”](#why-this-approach) Applying updates on a background or kill event has a few key benefits for user experience: * Users aren’t interrupted by update prompts or forced to wait for downloads in the middle of a session. * Updates are applied seamlessly in between sessions, so the experience of launching the app is always fresh. * You can deliver updates frequently without worrying about disrupting active users. The main downside is that if a user backgrounds and quickly resumes your app, they may lose any unsaved state since the update was applied in between those actions. To mitigate this, we recommend: * Saving state frequently and restoring it gracefully when the app resumes. * Avoiding very frequent updates that modify large parts of the app state. * Considering customizing the update behavior for sensitive flows (see below). ## Customizing When Updates Are Applied [Section titled “Customizing When Updates Are Applied”](#customizing-when-updates-are-applied) In some cases, you may want more control over exactly when an update is applied. For example, you might want to ensure a user completes an in-progress flow before updating, or coordinate an app update with a server-side change. Capgo provides a `setDelay` function that lets you specify conditions that must be met before an update is installed: ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater'; await CapacitorUpdater.setMultiDelay({ delayConditions: [ { kind: 'date', value: '2023-06-01T00:00:00.000Z', }, { kind: 'background', value: '60000', }, ], }); ``` This example would delay installing an update until after June 1, 2023 AND the app has been backgrounded for at least 60 seconds. The available delay conditions are: * `date`: Wait until after a specific date/time to apply the update. * `background`: Wait a minimum duration after the app is backgrounded to apply the update. * `nativeVersion`: Wait for a native binary with a minimum version to be installed before applying the update. * `kill`: Wait until the next app kill event to apply the update. You can mix and match these conditions to precisely control when an update is installed. Danger Note that the `kill` condition currently triggers the update after the first kill event, not the next background event like the other conditions. This inconsistency will be fixed in a future release. ## Applying Updates Immediately [Section titled “Applying Updates Immediately”](#applying-updates-immediately) For critical updates or apps with very simple state, you may want to apply an update as soon as it’s downloaded, without waiting for a background or kill event. Capgo supports this via the `autoUpdate` policy in your Capacitor config. Recommended: Use Delta (Manifest) Updates with Instant Apply When using an instant apply mode, we **strongly recommend** enabling [Delta (manifest) Updates](/docs/live-updates/differentials/) to minimize download times and improve the user experience. Delta (manifest) updates only download changed files instead of the entire bundle, which is especially important when updates are applied immediately while users are actively using your app. **Why this matters for instant apply modes:** * **Faster updates**: Smaller downloads mean updates complete quickly, reducing the time users see loading screens * **Better mobile experience**: Users on cellular networks or slower connections won’t face long wait times * **Lower bandwidth usage**: Only changed files are downloaded, saving data for both you and your users When `autoUpdate` is set to `"atInstall"`, `"onLaunch"`, or `"always"` in your `capacitor.config`, the CLI detects it. In non-interactive environments it sends Delta (manifest) updates automatically, and in interactive environments it prompts you to confirm before uploading. Legacy `directUpdate` config is still detected. Use `--no-delta` to force a full bundle upload. To enable Delta (manifest) updates, simply use the `--delta` flag when uploading bundles: ```shell npx @capgo/cli@latest bundle upload --delta ``` Learn more in the [Delta (manifest) Updates documentation](/docs/live-updates/differentials/). `autoUpdate` is set in your `capacitor.config.ts` file, not in JavaScript code. It supports these values: * `false` or `'off'`: Disable automatic update checks * `true` or `'atBackground'` (default): Check and download automatically on each foreground check, then apply the update the next time the app moves to background * `'atInstall'`: Apply immediately only after a fresh install or native app store update; otherwise use `"atBackground"` behavior * `'onLaunch'`: Apply immediately only when the app is brought to the foreground from a killed state (cold start). After that first check, fall back to `"atBackground"` behavior * `'always'`: Check on every foreground transition and apply immediately whenever an update is available * `'onlyDownload'`: Check and download automatically, emit `updateAvailable`, and never set the next bundle or apply an update automatically ## Test a Native Build Without Live Updates [Section titled “Test a Native Build Without Live Updates”](#test-a-native-build-without-live-updates) See [Test Native Builds Without Live Updates](/docs/live-updates/testing-native-builds-without-live-updates/) for the native-version, channel-policy, and CI configuration safeguards. ```typescript import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'always', // or 'atInstall' for updates only on app install/update autoSplashscreen: true, keepUrlPathAfterReload: true, }, SplashScreen: { launchAutoHide: false, // Required when using instant apply with autoSplashscreen }, }, }; export default config; ``` Note **Important**: instant apply modes only apply updates when the plugin actually checks for them. By default, checks run when the app moves to the foreground and on a repeating timer while the app stays open. `periodCheckDelay` controls that interval (default 10 minutes). With `autoUpdate: 'always'`, Capgo checks on every foreground transition and immediately applies an update as soon as the download completes during that check, even if the user is actively using the app. Periodic checks controlled by `periodCheckDelay` can trigger the same immediate apply behavior while the app stays open. Note that because `autoUpdate` is a native configuration, instant apply modes require some additional handling in your JavaScript code. Caution When using an instant apply mode with `autoSplashscreen`, you must set `launchAutoHide: false` in the SplashScreen configuration (as shown above) to prevent the splash screen from hiding automatically. This ensures you have full control over when the splash screen is hidden after the update process completes. ## Downloading Automatically Without Applying [Section titled “Downloading Automatically Without Applying”](#downloading-automatically-without-applying) If you want Capgo to check and download updates automatically but never apply them automatically, use `autoUpdate: 'onlyDownload'`: ```typescript const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'onlyDownload', }, }, }; ``` In this mode, the plugin emits `updateAvailable` after a bundle is downloaded. Your app can then decide when to call `CapacitorUpdater.set()` or show its own update prompt. ## Automatic Splashscreen Handling [Section titled “Automatic Splashscreen Handling”](#automatic-splashscreen-handling) To make instant apply modes easier to use, Capgo provides an `autoSplashscreen` option that automatically handles hiding the splashscreen for you (available since version 7.6.0): ```typescript const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'always', // or 'atInstall' autoSplashscreen: true, // Automatically hide splashscreen keepUrlPathAfterReload: true, }, SplashScreen: { launchAutoHide: false, }, }, }; ``` When `autoSplashscreen` is enabled: * The plugin automatically hides the splashscreen when an update is applied * The plugin automatically hides the splashscreen when no update is needed * You don’t need to manually listen for `appReady` events or call `SplashScreen.hide()` ### Manual Splashscreen Handling [Section titled “Manual Splashscreen Handling”](#manual-splashscreen-handling) If you prefer manual control or need custom logic, you can disable `autoSplashscreen` and handle it yourself: ```js import { CapacitorUpdater } from '@capgo/capacitor-updater'; import { SplashScreen } from '@capacitor/splash-screen'; CapacitorUpdater.addListener('appReady', () => { // Hide splash screen SplashScreen.hide(); }); CapacitorUpdater.notifyAppReady(); ``` The `appReady` event fires once the app has finished initializing and applying any pending updates. This is the point at which it’s safe to show your app’s UI, as it ensures the user will see the latest version. In addition to handling the `appReady` event, we recommend setting the `keepUrlPathAfterReload` configuration option to `true` when using an instant apply mode. This preserves the current URL path when the app is reloaded due to an update, helping maintain the user’s location in the app and reducing disorientation. If you don’t handle the `appReady` event and set `keepUrlPathAfterReload` when using an instant apply mode, the user may briefly see a stale version of the app, be taken back to the initial route, or see a flicker as the update is applied. Using an instant apply mode can be useful for delivering critical bug fixes or security patches, but it comes with some tradeoffs: * The user may see a brief flicker or loading state as the update is applied if you don’t properly handle the splashscreen (either with `autoSplashscreen` or manual `appReady` event handling). * If the update modifies the app state or UI, the user may see a disruptive change in the middle of a session. * The user’s location in the app may be lost if `keepUrlPathAfterReload` is not set, potentially disorienting them. * You’ll need to carefully handle saving and restoring state to ensure a smooth transition. If you do enable instant apply, we recommend: * Using `autoSplashscreen: true` for the simplest setup, or manually handling the `appReady` event if you need custom logic. * Setting `keepUrlPathAfterReload` to `true` to preserve the user’s location in the app. * Saving and restoring the app state as needed to avoid losing user progress. * Thoroughly testing your app’s update behavior to ensure there are no jarring transitions, lost state, or disorienting location changes. In most cases, the default update behavior provides the best balance of delivering updates quickly and minimizing disruption. But for apps with specific needs, Capgo provides the flexibility to customize when and how updates are applied. ## Keep going from Update Behavior [Section titled “Keep going from Update Behavior”](#keep-going-from-update-behavior) If you are using **Update Behavior** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Types](/docs/live-updates/update-types/) for the implementation detail in Update Types, and [Getting Started](/docs/plugins/updater/getting-started/) for the implementation detail in Getting Started. # Update Types > A comprehensive reference of all OTA update types Capgo provides: apply timing, delay conditions, version blocking, and delivery methods. Capgo supports several types of over-the-air (OTA) updates. This page lists and explains all of them so you can choose the right combination for your app. ## Apply Timing [Section titled “Apply Timing”](#apply-timing) Controls **when** an update is applied after it is downloaded. The plugin checks for updates when the app moves to the foreground and on a repeating timer while the app stays open. `periodCheckDelay` controls that interval (default 10 minutes). | Type | Description | Use Case | | ------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | **autoUpdate: `atBackground`** | Check and download on each foreground check, apply when the app moves to background | Most apps; minimal disruption | | **autoUpdate: `atInstall`** | Apply immediately only after a fresh install or native app store update; otherwise use `atBackground` | New users get latest; existing users use background apply | | **autoUpdate: `onLaunch`** | Apply immediately only on cold start (killed → foreground); then fall back to `atBackground` | Balance between freshness and session stability | | **autoUpdate: `always`** | Check on every foreground transition and apply immediately whenever an update is available | Critical fixes, apps with simple state | | **autoUpdate: `onlyDownload`** | Check and download automatically, emit `updateAvailable`, and never apply automatically | Apps that show their own update prompt or control exactly when to call `set()` | Configure in `capacitor.config.ts`: ```typescript plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', // default; true is still accepted // or: 'off' | 'atInstall' | 'onLaunch' | 'always' | 'onlyDownload' } } ``` Tip For full details and splashscreen handling, see [Update Behavior](/docs/live-updates/update-behavior/). ## Delay Conditions [Section titled “Delay Conditions”](#delay-conditions) Conditions that must be met **before** an update is installed. Use `setMultiDelay` to combine them (all conditions must be satisfied). | Condition | Description | Example | | ----------------- | ------------------------------------------------------ | ----------------------------------------- | | **date** | Wait until after a specific date/time | Coordinate with server-side release | | **background** | Wait a minimum duration (ms) after app is backgrounded | Avoid applying during quick app switches | | **nativeVersion** | Require a minimum native binary version | Block updates on incompatible native code | | **kill** | Wait until the next app kill event | Apply only on full restart | ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater'; await CapacitorUpdater.setMultiDelay({ delayConditions: [ { kind: 'date', value: '2023-06-01T00:00:00.000Z' }, { kind: 'background', value: '60000' }, ], }); ``` Danger The `kill` condition triggers after the first kill event, not the next background like the others. This will be fixed in a future release. ## Version Blocking (Channel Policy) [Section titled “Version Blocking (Channel Policy)”](#version-blocking-channel-policy) Controls which [**semver updates**](/semver_tester/) a channel will auto-deliver. Set via `--disable-auto-update` on channels. | Strategy | Blocks | Allows | Use Case | | ------------ | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | | **none** | Nothing | Any target bundle version | Default; full auto-update | | **major** | Higher major than `version_build`, for example `1.2.3 -> 2.0.0` | Same major, for example `1.2.3 -> 1.9.0` or `1.2.3 -> 1.2.4` | Prevent breaking changes from reaching old native code | | **minor** | Different major or minor than `version_build`, for example `1.2.3 -> 1.3.0` | Same major and minor, for example `1.2.3 -> 1.2.4` | Keep updates inside one native minor line | | **patch** | Any major, minor, or patch number change, for example `1.0.0 -> 1.0.1` | Only suffix changes while `MAJOR.MINOR.PATCH` stays identical, for example `1.0.0-beta.1 -> 1.0.0-beta.2` or `1.0.0+build.1 -> 1.0.0+build.2` | Strictest mode: no core version movement | | **metadata** | Missing `min_update_version`, or `version_build` below it | Target bundle whose `min_update_version` is less than or equal to `version_build` | Custom compatibility rules per bundle | These checks compare the target bundle against the native baseline sent as `version_build`, not the currently installed downloaded bundle sent as `version_name`. ```bash npx @capgo/cli channel set production --disable-auto-update major ``` Caution `patch` and `metadata` require careful setup. See [CLI commands](/docs/cli/commands/#disable-updates-strategy) and [Version Targeting](/docs/live-updates/version-targeting/) for details. ## Delivery Types [Section titled “Delivery Types”](#delivery-types) How the **bundle is transferred** to the device. | Type | Description | When to Use | | -------------------- | --------------------------------- | ---------------------------------------------------------- | | **Full bundle** | Entire JS bundle is downloaded | First install, large changes, or when delta is unavailable | | **Delta (manifest)** | Only changed files are downloaded | Most updates; faster and bandwidth-friendly | ```bash # Full bundle (default) npx @capgo/cli bundle upload --channel production # Delta updates npx @capgo/cli bundle upload --channel production --delta ``` Tip When using instant apply modes (`atInstall`, `onLaunch`, or `always`), enable [Delta updates](/docs/live-updates/differentials/) to minimize download time and improve UX. ## Quick Reference [Section titled “Quick Reference”](#quick-reference) | Category | Types | | -------------------- | ------------------------------------------------------------------------ | | **Apply timing** | `off`, `atBackground`, `atInstall`, `onLaunch`, `always`, `onlyDownload` | | **Delay conditions** | `date`, `background`, `nativeVersion`, `kill` | | **Version blocking** | `none`, `major`, `minor`, `patch`, `metadata` | | **Delivery** | Full bundle, Delta (manifest) | ## Related [Section titled “Related”](#related) * [Update Behavior](/docs/live-updates/update-behavior/) — Configure apply timing and delays * [Version Targeting](/docs/live-updates/version-targeting/) — Channel-based version routing * [Delta (manifest) Updates](/docs/live-updates/differentials/) — Enable partial downloads * [Channels](/docs/live-updates/channels/) — Channel configuration and precedence ## Keep going from Update Types [Section titled “Keep going from Update Types”](#keep-going-from-update-types) If you are using **Update Types** to plan live update delivery, connect it with [Capgo Live Updates](/live-update/) for the product workflow in Capgo Live Updates, [Overview](/docs/live-updates/) for the implementation detail in Overview, [Features](/docs/live-updates/features/) for the implementation detail in Features, [Update Behavior](/docs/live-updates/update-behavior/) for the implementation detail in Update Behavior, and [Getting Started](/docs/plugins/updater/getting-started/) for the implementation detail in Getting Started. # Version Targeting > Automatically deliver compatible updates to users based on their native app version This guide explains how to automatically deliver the latest compatible bundle to users based on their native app version, **similar to Ionic AppFlow’s approach**. This ensures simplified update management and faster rollouts while preventing compatibility issues. Migrating from Ionic AppFlow? If you’re coming from Ionic AppFlow, this guide is especially important for you. AppFlow automatically matched updates to native versions, and Capgo provides the same capability with even more control and flexibility. See the [AppFlow Migration Guide](/docs/upgrade/from-appflow-to-capgo/) for step-by-step migration instructions. ## Overview [Section titled “Overview”](#overview) Capgo’s version targeting system allows you to: * **Automatically deliver compatible updates** to users based on their native app version * **Prevent breaking changes** from reaching incompatible app versions * **Manage multiple app versions** simultaneously without complex logic * **Seamlessly roll out updates** to specific user segments ### Why Version Targeting Matters (Especially for AppFlow Users) [Section titled “Why Version Targeting Matters (Especially for AppFlow Users)”](#why-version-targeting-matters-especially-for-appflow-users) If you’re familiar with **Ionic AppFlow**, you know how critical it is to ensure users receive only compatible updates. AppFlow automatically matched live update bundles to native app versions, preventing incompatible JavaScript from being delivered to older native code. **Capgo provides the same safety guarantees**, with additional features: * More granular control over version matching * Multiple strategies (channels, semver, native constraints) * Better visibility into version distribution * API and CLI control alongside dashboard management This approach is particularly useful when: * You have users on different major versions of your app (e.g., v1.x, v2.x, v3.x) * You need to maintain backward compatibility while rolling out breaking changes * You want to prevent newer bundles from breaking older native code * You’re migrating users gradually from one version to another * **You’re migrating from AppFlow** and want to maintain the same update safety ## How It Works [Section titled “How It Works”](#how-it-works) Capgo uses a multi-layered approach to match users with compatible updates: 1. **Native Version Constraints**: Prevent bundles from being delivered to incompatible native versions 2. **Channel-Based Routing**: Route different app versions to different update channels 3. **Semantic Versioning Controls**: Automatically block updates across major/minor/patch boundaries 4. **Device-Level Overrides**: Target specific devices or user groups ### Version Matching Flow [Section titled “Version Matching Flow”](#version-matching-flow) ```mermaid graph TD A[User Opens App] --> B{Check Device Override} B -->|Override Set| C[Use Override Channel] B -->|No Override| D{Check local plugin channel} D -->|setChannel value| E[Use local setChannel channel] D -->|No local channel| F{Check defaultChannel in App} F -->|Has defaultChannel| G[Use App's defaultChannel] F -->|No defaultChannel| H[Use Cloud Default Channel] C --> I{Check Version Constraints} E --> I G --> I H --> I I -->|Compatible| J[Deliver Update] I -->|Incompatible| K[Skip Update] ``` ## Strategy 1: Channel-Based Version Routing [Section titled “Strategy 1: Channel-Based Version Routing”](#strategy-1-channel-based-version-routing) This is the **recommended approach** for managing breaking changes and major version updates. It’s similar to AppFlow’s delivery model. ### Example Scenario [Section titled “Example Scenario”](#example-scenario) * **App v1.x** (100,000 users) → `production` channel * **App v2.x** (50,000 users with breaking changes) → `v2` channel * **App v3.x** (10,000 beta users) → `v3` channel ### Implementation [Section titled “Implementation”](#implementation) #### Step 1: Configure Channels for Each Major Version [Section titled “Step 1: Configure Channels for Each Major Version”](#step-1-configure-channels-for-each-major-version) ```typescript // capacitor.config.ts for version 1.x builds import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.example.app', appName: 'Example App', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', defaultChannel: 'production', // or omit for default } } }; export default config; ``` ```typescript // capacitor.config.ts for version 2.x builds const config: CapacitorConfig = { appId: 'com.example.app', appName: 'Example App', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', defaultChannel: 'v2', // Routes v2 users automatically } } }; ``` ```typescript // capacitor.config.ts for version 3.x builds const config: CapacitorConfig = { appId: 'com.example.app', appName: 'Example App', plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', defaultChannel: 'v3', // Routes v3 users automatically } } }; ``` #### Step 2: Create Channels [Section titled “Step 2: Create Channels”](#step-2-create-channels) ```bash # Create channels for each major version npx @capgo/cli channel create production npx @capgo/cli channel create v2 npx @capgo/cli channel create v3 # Enable self-assignment so apps can switch channels npx @capgo/cli channel set production --self-assign npx @capgo/cli channel set v2 --self-assign npx @capgo/cli channel set v3 --self-assign ``` #### Step 3: Upload Version-Specific Bundles [Section titled “Step 3: Upload Version-Specific Bundles”](#step-3-upload-version-specific-bundles) ```bash # For v1.x users (from v1-maintenance branch) git checkout v1-maintenance npm run build npx @capgo/cli bundle upload --channel production # For v2.x users (from v2-maintenance or main branch) git checkout main npm run build npx @capgo/cli bundle upload --channel v2 # For v3.x users (from beta/v3 branch) git checkout beta npm run build npx @capgo/cli bundle upload --channel v3 ``` Automatic Routing When users open the app, they automatically connect to their designated channel based on the `defaultChannel` in their installed app bundle. No JavaScript code changes required! ### Benefits [Section titled “Benefits”](#benefits) * **Zero code changes** - Channel routing happens automatically * **Clear separation** - Each version has its own update pipeline * **Flexible targeting** - Push updates to specific version groups * **Safe rollouts** - Breaking changes never reach incompatible versions ## Strategy 2: Semantic Versioning Controls [Section titled “Strategy 2: Semantic Versioning Controls”](#strategy-2-semantic-versioning-controls) Use Capgo’s built-in [semantic versioning controls](/semver_tester/) to prevent updates across version boundaries. ### Disable Auto-Update Across Major Versions [Section titled “Disable Auto-Update Across Major Versions”](#disable-auto-update-across-major-versions) ```bash # Create a channel that blocks major version updates npx @capgo/cli channel create stable --disable-auto-update major ``` This configuration means: * Users on app version **1.2.3** will receive updates up to **1.9.9** * Users will **NOT** receive version **2.0.0** automatically * Prevents breaking changes from reaching older native code * The comparison uses the native baseline sent as `version_build` ### Granular Control Options [Section titled “Granular Control Options”](#granular-control-options) ```bash # Block target bundles outside the native major.minor line (1.2.x won't get 1.3.0) npx @capgo/cli channel set stable --disable-auto-update minor # Block target bundles outside the exact native MAJOR.MINOR.PATCH core (1.2.3 won't get 1.2.4) npx @capgo/cli channel set stable --disable-auto-update patch # Allow all updates npx @capgo/cli channel set stable --disable-auto-update none ``` Semantic Versioning Required This strategy only works if you follow [semantic versioning (semver)](/semver_tester/) for your app versions. Ensure your version numbers follow the `MAJOR.MINOR.PATCH` format. ## Strategy 3: Native Version Constraints [Section titled “Strategy 3: Native Version Constraints”](#strategy-3-native-version-constraints) Specify a minimum native app version (`min_update_version`) on each bundle so Capgo only delivers it to devices whose native binary is new enough. This uses the channel **metadata** strategy (`--disable-auto-update metadata`) plus `--min-update-version` or `--auto-min-update-version` on upload. There is no `--native-version` CLI flag. ### Enable metadata targeting on the channel [Section titled “Enable metadata targeting on the channel”](#enable-metadata-targeting-on-the-channel) ```bash # one-time: require min_update_version metadata on uploads to this channel npx @capgo/cli@latest channel set production --disable-auto-update metadata ``` ### Set a minimum native version on upload [Section titled “Set a minimum native version on upload”](#set-a-minimum-native-version-on-upload) When uploading a bundle, pass the lowest native version that may receive it: ```bash # This bundle requires native version 2.0.0 or higher npx @capgo/cli@latest bundle upload \ --channel production \ --min-update-version "2.0.0" ``` Or let Capgo set the floor from native package compatibility: ```bash npx @capgo/cli@latest bundle upload \ --channel production \ --auto-min-update-version ``` How It Works With the metadata strategy, devices whose native baseline (`version_build`) is below the bundle’s `min_update_version` skip the update. Only devices on that version or higher receive it. See [Compatibility](/docs/live-updates/compatibility/) for `--auto-min-update-version` details. ### Use Cases [Section titled “Use Cases”](#use-cases) 1. **New Native Plugin Required** ```bash # Bundle needs Camera plugin added in v2.0.0 npx @capgo/cli@latest bundle upload \ --channel production \ --min-update-version "2.0.0" ``` 2. **Breaking Native API Changes** ```bash # Bundle uses new Capacitor 6 APIs npx @capgo/cli@latest bundle upload \ --channel production \ --min-update-version "3.0.0" ``` 3. **Gradual Migration** ```bash # one-time: enable metadata gating on beta npx @capgo/cli@latest channel set beta --disable-auto-update metadata # Test bundle only on latest native version npx @capgo/cli@latest bundle upload \ --channel beta \ --min-update-version "2.5.0" ``` ## Strategy 4: Auto-Downgrade Prevention [Section titled “Strategy 4: Auto-Downgrade Prevention”](#strategy-4-auto-downgrade-prevention) Prevent users from receiving bundles older than their current native version. ### Enable in Channel Settings [Section titled “Enable in Channel Settings”](#enable-in-channel-settings) In the Capgo dashboard: 1. Go to **Channels** → Select your channel 2. Enable **“Disable auto downgrade under native”** 3. Save changes Or via CLI: ```bash npx @capgo/cli@latest channel set production --no-downgrade ``` ### Example [Section titled “Example”](#example) * User’s device: Native version **1.2.5** * Channel bundle: Version **1.2.3** * **Result**: Update is blocked (would be a downgrade) This is useful when: * Users manually installed a newer version from the app store * You need to ensure users always have the latest security patches * You want to prevent regression bugs ## Strategy 5: Device-Level Targeting [Section titled “Strategy 5: Device-Level Targeting”](#strategy-5-device-level-targeting) Override channel assignment for specific devices or user groups. ### Force Specific Version for Testing [Section titled “Force Specific Version for Testing”](#force-specific-version-for-testing) ```typescript import { CapacitorUpdater } from '@capgo/capacitor-updater' // Force beta testers to use v3 channel async function assignBetaTesters() { const deviceId = await CapacitorUpdater.getDeviceId() // Check if user is beta tester if (isBetaTester(userId)) { await CapacitorUpdater.setChannel({ channel: 'v3' }) } } ``` ### Dashboard Device Override [Section titled “Dashboard Device Override”](#dashboard-device-override) In the Capgo dashboard: 1. Go to **Devices** → Find device 2. Click **Set Channel** or **Set Version** 3. Override with specific channel or bundle version 4. Device will receive updates from overridden source Testing Updates Use device overrides to test updates on your own device before rolling out to all users. ## Complete AppFlow-Style Workflow [Section titled “Complete AppFlow-Style Workflow”](#complete-appflow-style-workflow) Here’s a complete example combining all strategies: ### 1. Initial Setup (App v1.0.0) [Section titled “1. Initial Setup (App v1.0.0)”](#1-initial-setup-app-v100) ```bash # Create production channel, then enable metadata min-version gating npx @capgo/cli@latest channel add production npx @capgo/cli@latest channel set production \ --disable-auto-update metadata \ --no-downgrade ``` capacitor.config.ts ```typescript const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', defaultChannel: 'production', } } }; ``` ### 2. Release Breaking Change (App v2.0.0) [Section titled “2. Release Breaking Change (App v2.0.0)”](#2-release-breaking-change-app-v200) ```bash # Create v2 channel for new version npx @capgo/cli@latest channel add v2 npx @capgo/cli@latest channel set v2 \ --disable-auto-update metadata \ --no-downgrade \ --self-assign # Create git branch for v1 maintenance git checkout -b v1-maintenance git push origin v1-maintenance ``` ```typescript // capacitor.config.ts for v2.0.0 const config: CapacitorConfig = { plugins: { CapacitorUpdater: { autoUpdate: 'atBackground', defaultChannel: 'v2', // New users get v2 channel } } }; ``` ### 3. Push Updates to Both Versions [Section titled “3. Push Updates to Both Versions”](#3-push-updates-to-both-versions) ```bash # Update v1.x users (bug fix) git checkout v1-maintenance # Make changes npx @capgo/cli@latest bundle upload \ --channel production \ --min-update-version "1.0.0" # Update v2.x users (new feature) git checkout main # Make changes npx @capgo/cli@latest bundle upload \ --channel v2 \ --min-update-version "2.0.0" ``` ### 4. Monitor Version Distribution [Section titled “4. Monitor Version Distribution”](#4-monitor-version-distribution) Use the Capgo dashboard to track: * How many users are on v1 vs v2 * Bundle adoption rates per version * Errors or crashes per version ### 5. Deprecate Old Version [Section titled “5. Deprecate Old Version”](#5-deprecate-old-version) Once v1 usage drops below threshold: ```bash # Stop uploading to production channel # Optional: Delete v1 maintenance branch git branch -d v1-maintenance # Move all remaining users to default # (They'll need to update via app store) ``` ## Channel Precedence [Section titled “Channel Precedence”](#channel-precedence) When multiple channel configurations exist, Capgo uses this precedence order: 1. **Device Override** (Dashboard or API) - Highest priority and visible in the Device Override UI 2. **Local plugin channel** via `setChannel()` - Stored on the device only and not shown in the Device Override UI 3. **defaultChannel** in capacitor.config.ts 4. **Default Channel** (Cloud setting) - Lowest priority Precedence Example If a user’s app has `defaultChannel: 'v2'` but you override their device to `'beta'` in the dashboard, they’ll receive updates from the `'beta'` channel. The Device Override UI only lists overrides set from the dashboard or Public API. Calling `setChannel()` from the app validates the channel with the backend, then stores it locally on the device. ## Best Practices [Section titled “Best Practices”](#best-practices) ### 1. Always Set defaultChannel for Major Versions [Section titled “1. Always Set defaultChannel for Major Versions”](#1-always-set-defaultchannel-for-major-versions) ```typescript // ✅ Good: Each major version has explicit channel // v1.x → production // v2.x → v2 // v3.x → v3 // ❌ Bad: Relying on dynamic channel switching // All versions → production, switch manually ``` ### 2. Use Semantic Versioning [Section titled “2. Use Semantic Versioning”](#2-use-semantic-versioning) ```bash # ✅ Good 1.0.0 → 1.0.1 → 1.1.0 → 2.0.0 # ❌ Bad 1.0 → 1.1 → 2 → 2.5 ``` ### 3. Maintain Separate Branches [Section titled “3. Maintain Separate Branches”](#3-maintain-separate-branches) ```bash # ✅ Good: Separate branches per major version main (v3.x) v2-maintenance (v2.x) v1-maintenance (v1.x) # ❌ Bad: Single branch for all versions ``` ### 4. Test Before Rollout [Section titled “4. Test Before Rollout”](#4-test-before-rollout) ```bash # one-time: create beta and enable metadata gating # (production is set up in the complete workflow above) npx @capgo/cli@latest channel add beta npx @capgo/cli@latest channel set beta --disable-auto-update metadata # Test on beta channel first npx @capgo/cli@latest bundle upload \ --channel beta \ --auto-min-update-version # Monitor for issues, then promote to production npx @capgo/cli@latest bundle upload \ --channel production \ --auto-min-update-version ``` ### 5. Monitor Version Distribution [Section titled “5. Monitor Version Distribution”](#5-monitor-version-distribution) Regularly check your dashboard: * Are users upgrading to newer native versions? * Are old versions still getting high traffic? * Should you deprecate old channels? ## Comparison with Ionic AppFlow [Section titled “Comparison with Ionic AppFlow”](#comparison-with-ionic-appflow) For teams migrating from **Ionic AppFlow**, here’s how Capgo’s version targeting compares: | Feature | Ionic AppFlow | Capgo | | ------------------------------ | ----------------------------------------- | ------------------------------------------------------------------------------------ | | **Version-based routing** | Automatic based on native version | Automatic via `defaultChannel` + multiple strategies | | **Semantic versioning** | Basic support | Advanced with `--disable-auto-update` (major/minor/patch) | | **Native version constraints** | Manual configuration in AppFlow dashboard | Built-in `--min-update-version` / `--auto-min-update-version` with metadata channels | | **Channel management** | Web UI + CLI | Web UI + CLI + API | | **Device overrides** | Limited device-level control | Full control via Dashboard/API | | **Auto-downgrade prevention** | Yes | Yes via `--no-downgrade` | | **Multi-version maintenance** | Manual branch/channel management | Automated with channel precedence | | **Self-hosting** | No | Yes (full control) | | **Version analytics** | Basic | Detailed per-version metrics | AppFlow Parity and Beyond Capgo provides **all the version targeting capabilities** that AppFlow offered, plus additional control mechanisms. If you relied on AppFlow’s automatic version matching, you’ll find Capgo equally safe with more flexibility. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### Users Not Receiving Updates [Section titled “Users Not Receiving Updates”](#users-not-receiving-updates) Check the following: 1. **Channel Assignment**: Verify device is on correct channel ```typescript const channel = await CapacitorUpdater.getChannel() console.log('Current channel:', channel) ``` 2. **Version Constraints**: Check if bundle has native version requirements * Dashboard → Bundles → Check “Native Version” column 3. **Semver Settings**: Verify channel’s `disable-auto-update` setting ```bash npx @capgo/cli channel list ``` 4. **Device Override**: Check if device has manual override * Dashboard → Devices → Search for device → Check channel/version ### Bundle Delivered to Wrong Version [Section titled “Bundle Delivered to Wrong Version”](#bundle-delivered-to-wrong-version) 1. **Review defaultChannel**: Ensure correct channel in `capacitor.config.ts` 2. **Check Bundle Upload**: Verify bundle was uploaded to intended channel 3. **Inspect min update version**: Confirm `--min-update-version` (or `--auto-min-update-version`) was set and the channel uses `--disable-auto-update metadata` ### Breaking Changes Affecting Old Versions [Section titled “Breaking Changes Affecting Old Versions”](#breaking-changes-affecting-old-versions) 1. **Immediate Fix**: Override affected devices to safe bundle * Dashboard → Devices → Bulk select → Set Version 2. **Long-term Fix**: Create versioned channels and maintain separate branches 3. **Prevention**: Always test updates on representative devices before rollout ## Migration from Ionic AppFlow [Section titled “Migration from Ionic AppFlow”](#migration-from-ionic-appflow) If you’re migrating from **Ionic AppFlow**, version targeting works very similarly in Capgo, with improved flexibility: ### Concept Mapping [Section titled “Concept Mapping”](#concept-mapping) | AppFlow Concept | Capgo Equivalent | Notes | | ------------------------------ | ---------------------------------------------------- | --------------------------------- | | **Deploy Channel** | Capgo Channel | Same concept, more powerful | | **Native Version Lock** | `--min-update-version` / `--auto-min-update-version` | More granular control | | **Channel Priority** | Channel precedence (override → cloud → default) | More transparent precedence | | **Deployment Target** | Channel + semver controls | Multiple strategies available | | **Production Channel** | `production` channel (or any name) | Flexible naming | | **Git-based deployment** | CLI bundle upload from branch | Same workflow | | **Automatic version matching** | `defaultChannel` + version constraints | Enhanced with multiple strategies | ### Key Differences for AppFlow Users [Section titled “Key Differences for AppFlow Users”](#key-differences-for-appflow-users) 1. **More Control**: Capgo gives you multiple strategies (channels, semver, native version) that can be combined 2. **Better Visibility**: Dashboard shows version distribution and compatibility issues 3. **API Access**: Full programmatic control over version targeting 4. **Self-Hosting**: Option to run your own update server with same version logic ### Migration Steps [Section titled “Migration Steps”](#migration-steps) 1. **Map your AppFlow channels** to Capgo channels (usually 1:1) 2. **Set `defaultChannel`** in `capacitor.config.ts` for each major version 3. **Configure semver rules** if you want automatic blocking at version boundaries 4. **Upload version-specific bundles** using `--min-update-version` (channel must use metadata strategy) 5. **Monitor version distribution** in Capgo dashboard Complete Migration Guide For complete migration instructions including SDK replacement and API mapping, see the [AppFlow to Capgo Migration Guide](/docs/upgrade/from-appflow-to-capgo/). ## Advanced Patterns [Section titled “Advanced Patterns”](#advanced-patterns) ### Gradual Rollout by Version [Section titled “Gradual Rollout by Version”](#gradual-rollout-by-version) ```typescript // Gradually migrate v1 users to v2 async function migrateUsers() { const deviceId = await CapacitorUpdater.getDeviceId() const rolloutPercentage = 10 // Start with 10% // Hash device ID to get deterministic percentage const hash = hashCode(deviceId) % 100 if (hash < rolloutPercentage) { // User is in rollout group - migrate to v2 await CapacitorUpdater.setChannel({ channel: 'v2' }) } } ``` ### Feature Flags by Version [Section titled “Feature Flags by Version”](#feature-flags-by-version) ```typescript // Enable features based on native version async function checkFeatureAvailability() { const info = await CapacitorUpdater.getDeviceId() const nativeVersion = info.nativeVersion if (compareVersions(nativeVersion, '2.0.0') >= 0) { // Enable features requiring v2.0.0+ enableNewCameraFeature() } } ``` ### A/B Testing Across Versions [Section titled “A/B Testing Across Versions”](#ab-testing-across-versions) ```typescript // Run A/B tests within same native version async function assignABTest() { const nativeVersion = await getNativeVersion() if (nativeVersion.startsWith('2.')) { // Only A/B test on v2 users const variant = Math.random() < 0.5 ? 'v2-test-a' : 'v2-test-b' await CapacitorUpdater.setChannel({ channel: variant }) } } ``` ## Summary [Section titled “Summary”](#summary) Capgo provides multiple strategies for version-specific update delivery: 1. **Channel-Based Routing**: Automatic version separation via `defaultChannel` 2. **Semantic Versioning**: Prevent updates across major/minor/patch boundaries 3. **Native Version Constraints**: Require minimum native version for bundles 4. **Auto-Downgrade Prevention**: Never deliver older bundles to newer native versions 5. **Device Overrides**: Manual control for testing and targeting By combining these strategies, you can achieve AppFlow-style automatic update delivery with even more flexibility and control. Choose the approach that best fits your app’s versioning and deployment workflow. For more details on specific features: * [Breaking Changes Guide](/docs/live-updates/breaking-changes/) - Detailed channel versioning strategy * [Channel Management](/docs/live-updates/channels/) - Complete channel configuration reference * [Update Behavior](/docs/live-updates/update-behavior/) - Native version delays and conditions ## Keep going from Version Targeting [Section titled “Keep going from Version Targeting”](#keep-going-from-version-targeting) If you are using **Version Targeting** to plan channel routing and staged rollout, connect it with [Channels](/docs/live-updates/channels/) for the implementation detail in Channels, [Channels](/docs/public-api/channels/) for the implementation detail in Channels, [Channels](/docs/webapp/channels/) for the implementation detail in Channels, [Beta Testing Solution](/solutions/beta-testing/) for the product workflow in Beta Testing Solution, and [Version Targeting Solution](/solutions/version-targeting/) for the product workflow in Version Targeting Solution. # Capacitor Plugins by Capgo > Explore our comprehensive collection of Capacitor plugins to extend your app's native capabilities with powerful features. Welcome to the Capgo Capacitor Plugins collection. This landing page is generated from the live plugin registry plus the docs tree so newly documented plugins show up here automatically. ## Capgo Cloud - Live Updates [Section titled “Capgo Cloud - Live Updates”](#capgo-cloud---live-updates) [Capacitor Updater ](/docs/plugins/updater/)The core plugin powering Capgo Cloud. Deliver instant updates to your Capacitor apps without waiting for app store review. The Updater plugin is the foundation of Capgo Cloud and lets you: * Deploy JavaScript, HTML, CSS, and asset changes in minutes. * Roll out updates to targeted user groups with channels. * Monitor adoption and failure signals from the Capgo console. * Secure releases with encryption and code signing. ## Plugin Directory [Section titled “Plugin Directory”](#plugin-directory) 147 plugins currently resolve from the live Capgo registry. Dedicated docs open when available, and repository links remain visible for the rest. [Accelerometer ](https://github.com/Cap-go/capacitor-accelerometer/)Read device accelerometer for motion detection and orientation tracking Opens the plugin repository until a dedicated docs page is available. [AdMob ](https://github.com/Cap-go/capacitor-admob/)Monetize your app with Google AdMob banner, interstitial, and rewarded ads Opens the plugin repository until a dedicated docs page is available. [Age Range ](https://github.com/Cap-go/capacitor-age-range/)Cross-platform age range detection using Google Play Age Signals (Android) and Apple DeclaredAgeRange (iOS) Opens the plugin repository until a dedicated docs page is available. [Age Signals ](https://github.com/Cap-go/capacitor-android-age-signals/)Google Play Age Signals API wrapper - detect supervised accounts and verified users Opens the plugin repository until a dedicated docs page is available. [Alarm ](https://github.com/Cap-go/capacitor-alarm/)Schedule native alarms and notifications even when app is closed Opens the plugin repository until a dedicated docs page is available. [Android Inline Install ](https://github.com/Cap-go/capacitor-android-inline-install/)Install app updates directly within the app without leaving to Play Store Opens the plugin repository until a dedicated docs page is available. [Android Kiosk ](https://github.com/Cap-go/capacitor-android-kiosk/)Lock Android devices into kiosk mode with launcher functionality and hardware key control Opens the plugin repository until a dedicated docs page is available. [Android SMS Retriever ](https://github.com/Cap-go/capacitor-android-sms-retriever/)Read one app-targeted verification SMS without SMS permissions and request SIM phone number hints on Android Opens the plugin repository until a dedicated docs page is available. [App Attest ](https://github.com/Cap-go/capacitor-app-attest/)Capacitor plugin for cross-platform device attestation using Apple App Attest and Google Play Integrity Standard Opens the plugin repository until a dedicated docs page is available. [App Tracking Transparency ](https://github.com/Cap-go/capacitor-app-tracking-transparency/)Request and check iOS App Tracking Transparency permission for IDFA access Opens the plugin repository until a dedicated docs page is available. [AppInsights ](https://github.com/Cap-go/capacitor-appinsights/)Track app usage, performance metrics, and user behavior with Apptopia AppInsights Opens the plugin repository until a dedicated docs page is available. [AppsFlyer ](https://github.com/Cap-go/capacitor-appsflyer/)Add AppsFlyer attribution, analytics, deferred deep links, and OneLink support to your Capacitor app Opens the plugin repository until a dedicated docs page is available. [Asset Cache ](https://github.com/Cap-go/capacitor-asset-cache/)Cache CDN images and videos in persistent app storage and bind them as local media sources Opens the plugin repository until a dedicated docs page is available. [Audio Recorder ](https://github.com/Cap-go/capacitor-audio-recorder/)Record audio on iOS, Android, and Web with simple controls and formats Opens the plugin repository until a dedicated docs page is available. [Audio Session ](https://github.com/Cap-go/capacitor-audiosession/)Configure iOS audio session for background playback, mixing, and routing control Opens the plugin repository until a dedicated docs page is available. [Auto ](https://github.com/Cap-go/capacitor-auto/)Bridge Capacitor apps with CarPlay and Android Auto template surfaces for two-way car communication Opens the plugin repository until a dedicated docs page is available. [Autofill Save Password ](https://github.com/Cap-go/capacitor-autofill-save-password/)Prompt users to save passwords to device autofill for seamless login experience Opens the plugin repository until a dedicated docs page is available. [Background Geolocation ](https://github.com/Cap-go/capacitor-background-geolocation/)Accurate background location tracking with native iOS and Android geofencing plus transition webhooks Opens the plugin repository until a dedicated docs page is available. [Background Task ](https://github.com/Cap-go/capacitor-background-task/)Schedule periodic background fetch tasks on iOS and Android with Expo-style task registration Opens the plugin repository until a dedicated docs page is available. [Barometer ](https://github.com/Cap-go/capacitor-barometer/)Access device barometer for atmospheric pressure and altitude readings Opens the plugin repository until a dedicated docs page is available. [Bluetooth Low Energy ](https://github.com/Cap-go/capacitor-bluetooth-low-energy/)Full-featured BLE plugin for scanning, connecting, reading, writing, and receiving notifications from Bluetooth devices Opens the plugin repository until a dedicated docs page is available. [Brightness ](https://github.com/Cap-go/capacitor-brightness/)Control device screen brightness programmatically with support for app-specific and system-wide control Opens the plugin repository until a dedicated docs page is available. [Calendar ](https://github.com/Cap-go/capacitor-calendar/)Manage native calendar events on iOS and Android, with iOS Reminders support Opens the plugin repository until a dedicated docs page is available. [Camera Preview ](https://github.com/Cap-go/capacitor-camera-preview/)Display live camera feed as overlay with customizable controls and capture capabilities Opens the plugin repository until a dedicated docs page is available. [Capacitor Patch ](https://github.com/Cap-go/capacitor-patch/)Apply version-gated Capacitor core, CLI, plugin, and native project patches during cap sync and update Opens the plugin repository until a dedicated docs page is available. [Capacitor+ Core ](https://github.com/Cap-go/capacitor-plus/)Capacitor+ is an automated, always-synced fork of Capacitor with merged community PRs and rapid releases Opens the plugin repository until a dedicated docs page is available. [Compass ](https://github.com/Cap-go/capacitor-compass/)Read device compass heading in degrees with continuous updates and permission handling Opens the plugin repository until a dedicated docs page is available. [Contacts ](https://github.com/Cap-go/capacitor-contacts/)Access and manage device contacts with read and write capabilities Opens the plugin repository until a dedicated docs page is available. [Contentsquare ](https://github.com/Cap-go/capacitor-contentsquare/)Integrate Contentsquare mobile analytics, consent gating, screen tracking, transactions, and session replay controls in Capacitor Opens the plugin repository until a dedicated docs page is available. [Cordova Updater ](https://github.com/Cap-go/cordova-updater/)OTA live updates for Cordova iOS and Android with the same API as capacitor-updater Opens the plugin repository until a dedicated docs page is available. [Crisp ](https://github.com/Cap-go/capacitor-crisp/)Integrate Crisp live chat and customer support directly into your mobile app Opens the plugin repository until a dedicated docs page is available. [Data Storage ](https://github.com/Cap-go/capacitor-data-storage-sqlite/)Store data locally using SQLite database with simple key-value API and encryption support Opens the plugin repository until a dedicated docs page is available. [Date Picker ](https://github.com/Cap-go/capacitor-date-picker/)Native date, time, date-time, year-month, and range picker for iOS, Android, and Web Opens the plugin repository until a dedicated docs page is available. [Device Info ](https://github.com/Cap-go/capacitor-device-info/)Read CPU, memory, GPU, storage, thermal state, and onboard sensor metrics from Capacitor apps Opens the plugin repository until a dedicated docs page is available. [Document Scanner ](https://github.com/Cap-go/capacitor-document-scanner/)Scan documents with auto edge detection, perspective correction, and PDF export Opens the plugin repository until a dedicated docs page is available. [Downloader ](https://github.com/Cap-go/capacitor-downloader/)Download large files in background with progress tracking and pause/resume support Opens the plugin repository until a dedicated docs page is available. [Electron Updater ](https://github.com/Cap-go/electron-updater/)OTA live updates for Electron apps with the same API surface as capacitor-updater Opens the plugin repository until a dedicated docs page is available. [Env ](https://github.com/Cap-go/capacitor-env/)Securely manage environment variables and configuration across different build environments Opens the plugin repository until a dedicated docs page is available. [Facebook Analytics ](https://github.com/Cap-go/capacitor-facebook-analytics/)Meta/Facebook App Events analytics with standard events, purchase logging, currency parameters, and advertiser tracking controls Opens the plugin repository until a dedicated docs page is available. [Fast SQL ](https://github.com/Cap-go/capacitor-fast-sql/)High-performance native SQLite with custom protocol for efficient sync operations and IndexedDB replacement Opens the plugin repository until a dedicated docs page is available. [FFmpeg ](https://github.com/Cap-go/capacitor-ffmpeg/)Video encoding and processing powered by FFmpeg for compression and conversion Opens the plugin repository until a dedicated docs page is available. [File ](https://github.com/Cap-go/capacitor-file/)Full-featured file system plugin for reading, writing, and managing files and directories Opens the plugin repository until a dedicated docs page is available. [File Compressor ](https://github.com/Cap-go/capacitor-file-compressor/)Capacitor plugin for efficient image compression supporting PNG, JPEG, and WebP formats across iOS, Android, and Web platforms Opens the plugin repository until a dedicated docs page is available. [File Picker ](https://github.com/Cap-go/capacitor-file-picker/)Pick files, images, videos, and directories with full native support for iOS and Android including HEIC conversion Opens the plugin repository until a dedicated docs page is available. [File Sharer ](https://github.com/Cap-go/capacitor-file-sharer/)Share and save files from base64 data or local paths across Android, iOS, and Web Opens the plugin repository until a dedicated docs page is available. [Firebase Analytics ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/analytics)Capacitor plugin for Firebase Analytics Opens the plugin repository until a dedicated docs page is available. [Firebase App ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/app)Capacitor plugin for Firebase App Opens the plugin repository until a dedicated docs page is available. [Firebase App Check ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/app-check)Capacitor plugin for Firebase App Check Opens the plugin repository until a dedicated docs page is available. [Firebase Authentication ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/authentication)Capacitor plugin for Firebase Authentication Opens the plugin repository until a dedicated docs page is available. [Firebase Crashlytics ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/crashlytics)Capacitor plugin for Firebase Crashlytics Opens the plugin repository until a dedicated docs page is available. [Firebase Firestore ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/firestore)Capacitor plugin for Firebase Cloud Firestore Opens the plugin repository until a dedicated docs page is available. [Firebase Functions ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/functions)Capacitor plugin for Firebase Cloud Functions Opens the plugin repository until a dedicated docs page is available. [Firebase Messaging ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/messaging)Capacitor plugin for Firebase Cloud Messaging (FCM) Opens the plugin repository until a dedicated docs page is available. [Firebase Performance ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/performance)Capacitor plugin for Firebase Performance Monitoring Opens the plugin repository until a dedicated docs page is available. [Firebase Remote Config ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/remote-config)Capacitor plugin for Firebase Remote Config Opens the plugin repository until a dedicated docs page is available. [Firebase Storage ](https://github.com/Cap-go/capacitor-firebase/tree/main/packages/storage)Capacitor plugin for Firebase Cloud Storage Opens the plugin repository until a dedicated docs page is available. [Flash ](https://github.com/Cap-go/capacitor-flash/)Control device flashlight and torch with simple on/off toggle functionality Opens the plugin repository until a dedicated docs page is available. [GTM ](https://github.com/Cap-go/capacitor-gtm/)Google Tag Manager integration for analytics and tracking Opens the plugin repository until a dedicated docs page is available. [Health ](https://github.com/Cap-go/capacitor-health/)Access health and fitness data from native health platforms Opens the plugin repository until a dedicated docs page is available. [iBeacon ](https://github.com/Cap-go/capacitor-ibeacon/)iBeacon plugin for Capacitor - proximity detection and beacon region monitoring Opens the plugin repository until a dedicated docs page is available. [In App Browser ](https://github.com/Cap-go/capacitor-inappbrowser/)Open managed in-app WebViews with native UI layering, private sessions, downloads, proxying, and messaging Opens the plugin repository until a dedicated docs page is available. [In App Review ](https://github.com/Cap-go/capacitor-in-app-review/)Prompt users to submit app store ratings and reviews without leaving your app using native iOS and Android APIs Opens the plugin repository until a dedicated docs page is available. [Incoming Call Kit ](https://github.com/Cap-go/capacitor-incoming-call-kit/)Present native incoming-call UI with iOS CallKit and Android full-screen notifications Opens the plugin repository until a dedicated docs page is available. [Indicator ](https://github.com/Cap-go/capacitor-home-indicator/)Hide or show iOS home indicator for fullscreen and immersive app experiences Opens the plugin repository until a dedicated docs page is available. [Install Referrer ](https://github.com/Cap-go/capacitor-install-referrer/)Read Google Play install referrer data and Apple AdServices attribution from Capacitor Opens the plugin repository until a dedicated docs page is available. [Intent Launcher ](https://github.com/Cap-go/capacitor-intent-launcher/)Launch Android intents, open system settings, and interact with other apps using the Intent system Opens the plugin repository until a dedicated docs page is available. [Intercom ](https://github.com/Cap-go/capacitor-intercom/)Integrate Intercom live chat, help center, and support workflows in your Capacitor app Opens the plugin repository until a dedicated docs page is available. [Intune ](https://github.com/Cap-go/capacitor-intune/)Microsoft Intune MAM, app protection policy, app config, and MSAL authentication for Capacitor Opens the plugin repository until a dedicated docs page is available. [Is Root ](https://github.com/Cap-go/capacitor-is-root/)Detect rooted Android or jailbroken iOS devices to enhance app security Opens the plugin repository until a dedicated docs page is available. [IVS Player ](https://github.com/Cap-go/capacitor-ivs-player/)Stream ultra-low latency live video using Amazon Interactive Video Service (IVS) Opens the plugin repository until a dedicated docs page is available. [JW Player ](https://github.com/Cap-go/capacitor-jw-player/)Embed JW Player for professional video streaming with ads and analytics support Opens the plugin repository until a dedicated docs page is available. [Keep Awake ](https://github.com/Cap-go/capacitor-keep-awake/)Prevent device screen from dimming or sleeping for video players, navigation, and presentations Opens the plugin repository until a dedicated docs page is available. [Launch Navigator ](https://github.com/Cap-go/capacitor-launch-navigator/)Open navigation apps like Google Maps or Apple Maps with directions to destinations Opens the plugin repository until a dedicated docs page is available. [Light Sensor ](https://github.com/Cap-go/capacitor-light-sensor/)Access the ambient light sensor to measure illuminance levels in lux with real-time updates Opens the plugin repository until a dedicated docs page is available. [Live Activities ](https://github.com/Cap-go/capacitor-live-activities/)Manage iOS Live Activities and Dynamic Island layouts from Capacitor with JSON-driven templates Opens the plugin repository until a dedicated docs page is available. [Live Reload ](https://github.com/Cap-go/capacitor-live-reload/)Connect to your dev server for instant hot reloading during development Opens the plugin repository until a dedicated docs page is available. [LLM ](https://github.com/Cap-go/capacitor-llm/)Run Large Language Models locally on-device with Apple Intelligence and MLX support Opens the plugin repository until a dedicated docs page is available. [Media Session ](https://github.com/Cap-go/capacitor-media-session/)Control media playback from lock screen and notification center Opens the plugin repository until a dedicated docs page is available. [Mock Location Detector ](https://github.com/Cap-go/capacitor-mock-location-detector/)Detect simulated GPS locations and developer tooling that enables spoofing apps Opens the plugin repository until a dedicated docs page is available. [MQTT ](https://github.com/Cap-go/capacitor-mqtt/)MQTT support for real-time messaging across iOS, Android, and Web. Opens the plugin repository until a dedicated docs page is available. [Mute ](https://github.com/Cap-go/capacitor-mute/)Detect device mute switch state for iOS devices to handle audio playback appropriately Opens the plugin repository until a dedicated docs page is available. [Mux Player ](https://github.com/Cap-go/capacitor-mux-player/)Stream adaptive bitrate video with Mux player for optimized playback quality Opens the plugin repository until a dedicated docs page is available. [Native Audio ](https://github.com/Cap-go/capacitor-native-audio/)Play short audio files with low latency using native audio engine for games and apps Opens the plugin repository until a dedicated docs page is available. [Native Biometric ](https://github.com/Cap-go/capacitor-native-biometric/)Secure authentication using Face ID, Touch ID, and Android biometric APIs Opens the plugin repository until a dedicated docs page is available. [Native Geocoder ](https://github.com/Cap-go/capacitor-nativegeocoder/)Convert addresses to coordinates and coordinates to addresses using native geocoding Opens the plugin repository until a dedicated docs page is available. [Native Loader ](https://github.com/Cap-go/capacitor-native-loader/)Show native animated loaders, transparent overlays, Lottie assets, and WebView-resizing loading states from JavaScript or native code Opens the plugin repository until a dedicated docs page is available. [Native Market ](https://github.com/Cap-go/capacitor-native-market/)Deep link users directly to your app page on Google Play Store or Apple App Store Opens the plugin repository until a dedicated docs page is available. [Native Navigation ](https://github.com/Cap-go/capacitor-native-navigation/)Render native navbars, tabbars, and transition shells over a full-screen Capacitor WebView Opens the plugin repository until a dedicated docs page is available. [Native Purchases ](https://github.com/Cap-go/capacitor-native-purchases/)Implement native in-app purchases, subscriptions, and iOS StoreKit commitment billing plans with a simple API Opens the plugin repository until a dedicated docs page is available. [Navigation Bar ](https://github.com/Cap-go/capacitor-navigation-bar/)Customize Android navigation bar color and visibility for immersive UI experiences Opens the plugin repository until a dedicated docs page is available. [Network Diagnostics ](https://github.com/Cap-go/capacitor-network-diagnostics/)Run native network diagnostics for URL reachability, TCP ports, WebSocket handshakes, speed, and packet loss Opens the plugin repository until a dedicated docs page is available. [NFC ](https://github.com/Cap-go/capacitor-nfc/)Native NFC tag discovery, reading and writing for Capacitor apps on iOS and Android Opens the plugin repository until a dedicated docs page is available. [Notifications ](https://github.com/Cap-go/capgo/tree/main/packages/capacitor-notifications/)Send native iOS and Android push notifications from Capgo with user lookup, badges, stats, and silent update checks Opens the plugin repository until a dedicated docs page is available. [Passkey ](https://github.com/Cap-go/capacitor-passkey/)Keep browser-style WebAuthn code in Capacitor while native passkey calls and host patching are handled for you Opens the plugin repository until a dedicated docs page is available. [Pay ](https://github.com/Cap-go/capacitor-pay/)Accept payments with Apple Pay and Google Pay for seamless checkout experience Opens the plugin repository until a dedicated docs page is available. [PDF Generator ](https://github.com/Cap-go/capacitor-pdf-generator/)Create PDF documents from HTML templates for invoices, reports, and receipts Opens the plugin repository until a dedicated docs page is available. [Pedometer ](https://github.com/Cap-go/capacitor-pedometer/)Track steps, distance, pace, cadence, and floors with device pedometer sensors Opens the plugin repository until a dedicated docs page is available. [Persistent Account ](https://github.com/Cap-go/capacitor-persistent-account/)Preserve user authentication and account data across app reinstalls and updates Opens the plugin repository until a dedicated docs page is available. [Persistent UUID ](https://github.com/Cap-go/capacitor-persistent-uuid/)Generate and persist one app-scoped UUID across reinstalls, app updates, and OS updates Opens the plugin repository until a dedicated docs page is available. [Persona ](https://github.com/Cap-go/capacitor-persona/)Launch Persona identity verification inquiries with native iOS and Android SDKs Opens the plugin repository until a dedicated docs page is available. [Photo Library ](https://github.com/Cap-go/capacitor-photo-library/)Browse, save, and manage photos and videos in device photo library with permissions Opens the plugin repository until a dedicated docs page is available. [Pretty Toast ](https://github.com/Cap-go/capacitor-pretty-toast/)Native-first pretty toast notifications for Capacitor and the web Opens the plugin repository until a dedicated docs page is available. [Printer ](https://github.com/Cap-go/capacitor-printer/)Capacitor plugin for printing documents, HTML, PDFs, images and web views Opens the plugin repository until a dedicated docs page is available. [Privacy Screen ](https://github.com/Cap-go/capacitor-privacy-screen/)Protect app content in Android screenshots and obscure the iOS app switcher snapshot Opens the plugin repository until a dedicated docs page is available. [Proximity ](https://github.com/Cap-go/capacitor-proximity/)Enable native proximity monitoring so your app can react when the device is near a face, hand, or surface Opens the plugin repository until a dedicated docs page is available. [Purchases ](https://github.com/RevenueCat/purchases-capacitor/)Implement in-app subscriptions and purchases with RevenueCat SDK for cross-platform monetization Opens the plugin repository until a dedicated docs page is available. [RealtimeKit ](https://github.com/Cap-go/capacitor-realtimekit/)Cloudflare Calls integration with built-in UI for video meetings and real-time communication Opens the plugin repository until a dedicated docs page is available. [reCAPTCHA ](https://github.com/Cap-go/capacitor-recaptcha/)Generate Web reCAPTCHA or reCAPTCHA Enterprise tokens plus native Enterprise mobile tokens Opens the plugin repository until a dedicated docs page is available. [Ricoh360 Camera ](https://github.com/Cap-go/capacitor-ricoh360-camera-plugin/)Control Ricoh Theta 360-degree cameras for immersive panoramic photography Opens the plugin repository until a dedicated docs page is available. [RudderStack ](https://github.com/Cap-go/capacitor-rudderstack/)RudderStack analytics, identity resolution, screen tracking, and delivery controls for Capacitor Opens the plugin repository until a dedicated docs page is available. [Screen Orientation ](https://github.com/Cap-go/capacitor-screen-orientation/)Screen orientation plugin with support for bypassing orientation lock Opens the plugin repository until a dedicated docs page is available. [Screen Recorder ](https://github.com/Cap-go/capacitor-screen-recorder/)Capture screen recordings with audio for tutorials, demos, and bug reports Opens the plugin repository until a dedicated docs page is available. [Shake ](https://github.com/Cap-go/capacitor-shake/)Detect shake gestures on device for triggering actions like undo or feedback Opens the plugin repository until a dedicated docs page is available. [Share Target ](https://github.com/Cap-go/capacitor-share-target/)Receive shared content from other apps - text, images, and files Opens the plugin repository until a dedicated docs page is available. [Sheets ](https://github.com/Cap-go/capacitor-sheets/)Framework-agnostic sheets, drawers, dialogs, and overlay primitives optimized for Capacitor apps Opens the plugin repository until a dedicated docs page is available. [SIM ](https://github.com/Cap-go/capacitor-sim/)Retrieve SIM card information including carrier name, country code, and phone number Opens the plugin repository until a dedicated docs page is available. [Social Login ](https://github.com/Cap-go/capacitor-social-login/)Authenticate users with Google, Facebook, and Apple Sign-In for easy social login Opens the plugin repository until a dedicated docs page is available. [Speech Recognition ](https://github.com/Cap-go/capacitor-speech-recognition/)Natural, low-latency speech recognition with streaming partial results and cross-platform parity Opens the plugin repository until a dedicated docs page is available. [Speech Synthesis ](https://github.com/Cap-go/capacitor-speech-synthesis/)Synthesize speech from text with full control over language, voice, pitch, rate, and volume. Opens the plugin repository until a dedicated docs page is available. [SSL Pinning ](https://github.com/Cap-go/capacitor-ssl-pinning/)Pin HTTPS connections to bundled certificates for CapacitorHttp on iOS and Android Opens the plugin repository until a dedicated docs page is available. [Streamcall ](https://github.com/Cap-go/capacitor-streamcall/)Integrate video calling and live streaming with Stream SDK for real-time communication Opens the plugin repository until a dedicated docs page is available. [Stripe ](https://github.com/Cap-go/capacitor-stripe-pay/)Capacitor plugin for Stripe Payment Sheet, Apple Pay, and Google Pay. Opens the plugin repository until a dedicated docs page is available. [Stripe Identity ](https://github.com/Cap-go/capacitor-stripe-identity/)Capacitor plugin for Stripe Identity verification. Opens the plugin repository until a dedicated docs page is available. [Stripe Terminal ](https://github.com/Cap-go/capacitor-stripe-terminal/)Capacitor plugin for Stripe Terminal in-person payments. Opens the plugin repository until a dedicated docs page is available. [Supabase ](https://github.com/Cap-go/capacitor-supabase/)Native Supabase authentication, JWT access, and basic database helpers for Capacitor Opens the plugin repository until a dedicated docs page is available. [Text Interaction ](https://github.com/Cap-go/capacitor-textinteraction/)Enable advanced text selection, copy-paste, and interaction features in web views Opens the plugin repository until a dedicated docs page is available. [Transitions ](https://github.com/Cap-go/capacitor-transitions/)Add Ionic-style page transitions and iOS edge swipe-back gestures without Ionic UI Opens the plugin repository until a dedicated docs page is available. [Twilio Video ](https://github.com/Cap-go/capacitor-twilio-video/)Join Twilio Video rooms from Capacitor with native audio, camera, and room lifecycle events Opens the plugin repository until a dedicated docs page is available. [Twilio Voice ](https://github.com/Cap-go/capacitor-twilio-voice/)Make and receive VoIP calls with Twilio Voice for in-app calling functionality Opens the plugin repository until a dedicated docs page is available. [Updater ](https://github.com/Cap-go/capacitor-updater/)Deploy Ionic and Capacitor live updates instantly to your users without app store review delays Opens the plugin repository until a dedicated docs page is available. [Uploader ](https://github.com/Cap-go/capacitor-uploader/)Upload large files reliably in background with progress tracking and retry support Opens the plugin repository until a dedicated docs page is available. [Usage Stats Manager ](https://github.com/Cap-go/capacitor-android-usagestatsmanager/)Access Android usage statistics to track app usage time and screen time analytics Opens the plugin repository until a dedicated docs page is available. [UWB ](https://github.com/Cap-go/capacitor-uwb/)Ultra-Wideband ranging for peer distance and direction on iOS Nearby Interaction and Android Jetpack UWB Opens the plugin repository until a dedicated docs page is available. [Verisoul ](https://github.com/Cap-go/capacitor-verisoul/)Collect Verisoul native fraud-prevention sessions from Capacitor apps on iOS and Android Opens the plugin repository until a dedicated docs page is available. [Video Player ](https://github.com/Cap-go/capacitor-video-player/)Native video playback with subtitles, fullscreen, and comprehensive controls Opens the plugin repository until a dedicated docs page is available. [Video Thumbnails ](https://github.com/Cap-go/capacitor-video-thumbnails/)Generate thumbnail images from local and remote video files at specific timestamps Opens the plugin repository until a dedicated docs page is available. [Volume Buttons ](https://github.com/Cap-go/capacitor-volume-buttons/)Capture hardware volume button presses for custom app controls and shortcuts Opens the plugin repository until a dedicated docs page is available. [Watch ](https://github.com/Cap-go/capacitor-watch/)Apple Watch communication with bidirectional messaging between iPhone and watchOS apps Opens the plugin repository until a dedicated docs page is available. [WebView Crash ](https://github.com/Cap-go/capacitor-webview-crash/)Restart crashed WebViews natively and recycle long-running WebViews on a fixed interval Opens the plugin repository until a dedicated docs page is available. [WebView Guardian ](https://github.com/Cap-go/capacitor-webview-guardian/)Detect when the WebView was killed in the background and relaunch it on foreground Opens the plugin repository until a dedicated docs page is available. [WebView Version Checker ](https://github.com/Cap-go/capacitor-webview-version-checker/)Capacitor plugin for checking Android WebView version freshness and guiding users to native update flows Opens the plugin repository until a dedicated docs page is available. [WeChat ](https://github.com/Cap-go/capacitor-wechat/)WeChat SDK for Capacitor - enables authentication, sharing, payments, and mini-programs Opens the plugin repository until a dedicated docs page is available. [Widget Kit ](https://github.com/Cap-go/capacitor-widget-kit/)Build WidgetKit and Live Activity surfaces from Capacitor with SVG frames, timers, action hotspots, or full-native widget state sync Opens the plugin repository until a dedicated docs page is available. [WiFi ](https://github.com/Cap-go/capacitor-wifi/)Manage WiFi connectivity for your Capacitor app Opens the plugin repository until a dedicated docs page is available. [YouTube Player ](https://github.com/Cap-go/capacitor-youtube-player/)Embed YouTube videos with full player API control and event handling Opens the plugin repository until a dedicated docs page is available. [Zebra DataWedge ](https://github.com/Cap-go/capacitor-zebra-datawedge/)Manage Zebra DataWedge profiles, notifications, queries, and scan triggers on Zebra Android devices Opens the plugin repository until a dedicated docs page is available. [Zip ](https://github.com/Cap-go/capacitor-zip/)A free Capacitor plugin for zipping and unzipping files on iOS, Android, and Web. Opens the plugin repository until a dedicated docs page is available. ## Keep going from Capacitor Plugins by Capgo [Section titled “Keep going from Capacitor Plugins by Capgo”](#keep-going-from-capacitor-plugins-by-capgo) If you are using **Capacitor Plugins by Capgo** to plan native plugin work, connect it with [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives, [Capgo Native Builds](/native-build/) for the product workflow in Capgo Native Builds, and [Capacitor Plugins: What You Need to Know](/blog/capacitor-plugins-what-you-need-to-know/) for the practical context in Capacitor Plugins: What You Need to Know. # @capgo/capacitor-accelerometer > Capacitor plugin contract for working with the device accelerometer. ## Overview [Section titled “Overview”](#overview) Capacitor plugin contract for working with the device accelerometer. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `getMeasurement` - Get the most recent accelerometer sample that was recorded by the native layer. * `isAvailable` - Check if the current device includes an accelerometer sensor. * `startMeasurementUpdates` - Begin streaming accelerometer updates to the JavaScript layer. * `stopMeasurementUpdates` - Stop streaming accelerometer updates started via . ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------------- | ------------------------------------------------------------------------------- | | `getMeasurement` | Get the most recent accelerometer sample that was recorded by the native layer. | | `isAvailable` | Check if the current device includes an accelerometer sensor. | | `startMeasurementUpdates` | Begin streaming accelerometer updates to the JavaScript layer. | | `stopMeasurementUpdates` | Stop streaming accelerometer updates started via . | | `checkPermissions` | Return the current permission state for accessing motion data. | | `requestPermissions` | Request permission to access motion data if supported by the platform. | | `addListener` | Listen for measurement updates. | | `removeAllListeners` | Remove all listeners that have been registered on the plugin. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-accelerometer](https://github.com/Cap-go/capacitor-accelerometer/). ## Keep going from @capgo/capacitor-accelerometer [Section titled “Keep going from @capgo/capacitor-accelerometer”](#keep-going-from-capgocapacitor-accelerometer) If you are using **@capgo/capacitor-accelerometer** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-accelerometer](/plugins/capacitor-accelerometer/) for the native capability in Using @capgo/capacitor-accelerometer, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # Getting Started > Install @capgo/capacitor-accelerometer and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-accelerometer` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-accelerometer bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `getMeasurement` [Section titled “getMeasurement”](#getmeasurement) Get the most recent accelerometer sample that was recorded by the native layer. ```typescript import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer'; await CapacitorAccelerometer.getMeasurement(); ``` ### `isAvailable` [Section titled “isAvailable”](#isavailable) Check if the current device includes an accelerometer sensor. ```typescript import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer'; await CapacitorAccelerometer.isAvailable(); ``` ### `startMeasurementUpdates` [Section titled “startMeasurementUpdates”](#startmeasurementupdates) Begin streaming accelerometer updates to the JavaScript layer. Call with the `measurement` event to receive the updates. ```typescript import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer'; await CapacitorAccelerometer.startMeasurementUpdates(); ``` ### `stopMeasurementUpdates` [Section titled “stopMeasurementUpdates”](#stopmeasurementupdates) Stop streaming accelerometer updates started via . ```typescript import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer'; await CapacitorAccelerometer.stopMeasurementUpdates(); ``` ### `checkPermissions` [Section titled “checkPermissions”](#checkpermissions) Return the current permission state for accessing motion data. On platforms without explicit permissions this resolves to `granted`. ```typescript import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer'; await CapacitorAccelerometer.checkPermissions(); ``` ### `requestPermissions` [Section titled “requestPermissions”](#requestpermissions) Request permission to access motion data if supported by the platform. ```typescript import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer'; await CapacitorAccelerometer.requestPermissions(); ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `GetMeasurementResult` [Section titled “GetMeasurementResult”](#getmeasurementresult) Alias for the most recent measurement. ```typescript export type GetMeasurementResult = Measurement; ``` ### `IsAvailableResult` [Section titled “IsAvailableResult”](#isavailableresult) Result returned by . ```typescript export interface IsAvailableResult { /** * Whether an accelerometer sensor is available on the device. * * @since 1.0.0 */ isAvailable: boolean; } ``` ### `PermissionStatus` [Section titled “PermissionStatus”](#permissionstatus) Permission information returned by and . ```typescript export interface PermissionStatus { /** * The permission state for accessing motion data on the current platform. * * @since 1.0.0 */ accelerometer: AccelerometerPermissionState; } ``` ### `MeasurementEvent` [Section titled “MeasurementEvent”](#measurementevent) Event payload emitted when is active. ```typescript export type MeasurementEvent = Measurement; ``` ### `Measurement` [Section titled “Measurement”](#measurement) The x, y and z axis acceleration values reported by the device motion sensors. ```typescript export interface Measurement { /** * The acceleration on the x-axis in G's. * * @since 1.0.0 */ x: number; /** * The acceleration on the y-axis in G's. * * @since 1.0.0 */ y: number; /** * The acceleration on the z-axis in G's. * * @since 1.0.0 */ z: number; } ``` ### `AccelerometerPermissionState` [Section titled “AccelerometerPermissionState”](#accelerometerpermissionstate) Permission state union including `limited` for platforms that can throttle motion access. ```typescript export type AccelerometerPermissionState = PermissionState | 'limited'; ``` ### `PermissionState` [Section titled “PermissionState”](#permissionstate) Platform permission states supported by Capacitor. ```typescript export type PermissionState = 'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'; ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-accelerometer](/plugins/capacitor-accelerometer/) for the native capability in Using @capgo/capacitor-accelerometer, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-admob > AdMob Plus Plugin interface for displaying Google AdMob ads in Capacitor apps. ## Overview [Section titled “Overview”](#overview) AdMob Plus Plugin interface for displaying Google AdMob ads in Capacitor apps. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `start` - Initialize and start the AdMob SDK. * `configure` - Configure AdMob settings. * `configRequest` - Configure ad request settings. * `adCreate` - Create a new ad instance. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------------------ | --------------------------------------------------------- | | `start` | Initialize and start the AdMob SDK. | | `configure` | Configure AdMob settings. | | `configRequest` | Configure ad request settings. | | `adCreate` | Create a new ad instance. | | `adIsLoaded` | Check if an ad is loaded and ready to be shown. | | `adLoad` | Load an ad. | | `adShow` | Show a loaded ad. | | `adHide` | Hide a currently displayed ad. | | `trackingAuthorizationStatus` | Get the current tracking authorization status (iOS only). | | `requestTrackingAuthorization` | Request tracking authorization from the user (iOS only). | | `addListener` | Add a listener for ad events. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-admob](https://github.com/Cap-go/capacitor-admob/). ## Keep going from @capgo/capacitor-admob [Section titled “Keep going from @capgo/capacitor-admob”](#keep-going-from-capgocapacitor-admob) If you are using **@capgo/capacitor-admob** to plan native plugin work, connect it with [Using @capgo/capacitor-admob](/plugins/capacitor-admob/) for the native capability in Using @capgo/capacitor-admob, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-admob and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-admob` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-admob bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { AdMob } from '@capgo/capacitor-admob'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `start` [Section titled “start”](#start) Initialize and start the AdMob SDK. ```typescript import { AdMob } from '@capgo/capacitor-admob'; await AdMob.start(); ``` ### `configure` [Section titled “configure”](#configure) Configure AdMob settings. ```typescript import { AdMob } from '@capgo/capacitor-admob'; await AdMob.configure({ appMuted: false, appVolume: 0.5 }); ``` ### `configRequest` [Section titled “configRequest”](#configrequest) Configure ad request settings. ```typescript import { AdMob } from '@capgo/capacitor-admob'; await AdMob.configRequest({ maxAdContentRating: MaxAdContentRating.PG, tagForChildDirectedTreatment: true, testDeviceIds: ['test-device-id'] }); ``` ### `adCreate` [Section titled “adCreate”](#adcreate) Create a new ad instance. ```typescript import { AdMob } from '@capgo/capacitor-admob'; await AdMob.adCreate({ adUnitId: 'ca-app-pub-3940256099942544/1033173712' }); ``` ### `adIsLoaded` [Section titled “adIsLoaded”](#adisloaded) Check if an ad is loaded and ready to be shown. ```typescript import { AdMob } from '@capgo/capacitor-admob'; const isLoaded = await AdMob.adIsLoaded({ id: 1 }); if (isLoaded) { await AdMob.adShow({ id: 1 }); } ``` ### `adLoad` [Section titled “adLoad”](#adload) Load an ad. ```typescript import { AdMob } from '@capgo/capacitor-admob'; await AdMob.adLoad({ id: 1 }); ``` ### `adShow` [Section titled “adShow”](#adshow) Show a loaded ad. ```typescript import { AdMob } from '@capgo/capacitor-admob'; await AdMob.adShow({ id: 1 }); ``` ### `adHide` [Section titled “adHide”](#adhide) Hide a currently displayed ad. ```typescript import { AdMob } from '@capgo/capacitor-admob'; await AdMob.adHide({ id: 1 }); ``` ### `trackingAuthorizationStatus` [Section titled “trackingAuthorizationStatus”](#trackingauthorizationstatus) Get the current tracking authorization status (iOS only). ```typescript import { AdMob } from '@capgo/capacitor-admob'; const { status } = await AdMob.trackingAuthorizationStatus(); if (status === TrackingAuthorizationStatus.notDetermined) { await AdMob.requestTrackingAuthorization(); } ``` ### `requestTrackingAuthorization` [Section titled “requestTrackingAuthorization”](#requesttrackingauthorization) Request tracking authorization from the user (iOS only). ```typescript import { AdMob } from '@capgo/capacitor-admob'; const { status } = await AdMob.requestTrackingAuthorization(); console.log('User tracking status:', status); ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `AdMobConfig` [Section titled “AdMobConfig”](#admobconfig) Configuration options for AdMob. ```typescript export type AdMobConfig = { /** Whether the app should be muted */ appMuted?: boolean; /** The app volume (0.0 to 1.0) */ appVolume?: number; }; ``` ### `RequestConfig` [Section titled “RequestConfig”](#requestconfig) Configuration for ad requests. ```typescript export type RequestConfig = { /** Maximum ad content rating */ maxAdContentRating?: MaxAdContentRating; /** Whether to use the same app key */ sameAppKey?: boolean; /** Tag for child-directed treatment (true, false, or null for unspecified) */ tagForChildDirectedTreatment?: boolean | null; /** Tag for under age of consent (true, false, or null for unspecified) */ tagForUnderAgeOfConsent?: boolean | null; /** Array of test device IDs */ testDeviceIds?: string[]; }; ``` ### `MobileAdOptions` [Section titled “MobileAdOptions”](#mobileadoptions) Base options for mobile ads. ```typescript export type MobileAdOptions = { /** The ad unit ID from AdMob */ adUnitId: string; }; ``` ### `TrackingAuthorizationStatus` [Section titled “TrackingAuthorizationStatus”](#trackingauthorizationstatus-1) Tracking authorization status for iOS App Tracking Transparency. ```typescript export enum TrackingAuthorizationStatus { /** User has not yet received an authorization request */ notDetermined = 0, /** User restricted, device is unable to provide authorization */ restricted = 1, /** User denied authorization */ denied = 2, /** User authorized access */ authorized = 3, } ``` ### `MaxAdContentRating` [Section titled “MaxAdContentRating”](#maxadcontentrating) Maximum ad content rating enum used to restrict ads based on content rating. ```typescript export enum MaxAdContentRating { /** General Audiences */ G = 'G', /** Mature Audiences */ MA = 'MA', /** Parental Guidance */ PG = 'PG', /** Teen */ T = 'T', /** Unspecified rating */ UNSPECIFIED = '', } ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-admob](/plugins/capacitor-admob/) for the native capability in Using @capgo/capacitor-admob, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-age-range > Cross-platform age range detection plugin. ## Overview [Section titled “Overview”](#overview) Cross-platform age range detection plugin. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `requestAgeRange` - Request the user’s age range. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------ | ---------------------------------------- | | `requestAgeRange` | Request the user’s age range. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-age-range](https://github.com/Cap-go/capacitor-age-range/). ## Keep going from @capgo/capacitor-age-range [Section titled “Keep going from @capgo/capacitor-age-range”](#keep-going-from-capgocapacitor-age-range) If you are using **@capgo/capacitor-age-range** to plan store approval and distribution, connect it with [Using @capgo/capacitor-age-range](/plugins/capacitor-age-range/) for the native capability in Using @capgo/capacitor-age-range, [@capgo/capacitor-in-app-review](/docs/plugins/in-app-review/) for the implementation detail in @capgo/capacitor-in-app-review, [Using @capgo/capacitor-in-app-review](/plugins/capacitor-in-app-review/) for the native capability in Using @capgo/capacitor-in-app-review, [@capgo/capacitor-native-market](/docs/plugins/native-market/) for the implementation detail in @capgo/capacitor-native-market, and [Using @capgo/capacitor-native-market](/plugins/capacitor-native-market/) for the native capability in Using @capgo/capacitor-native-market. # Getting Started > Install @capgo/capacitor-age-range and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-age-range` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-age-range bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { AgeRange } from '@capgo/capacitor-age-range'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `requestAgeRange` [Section titled “requestAgeRange”](#requestagerange) Request the user’s age range. On Android: queries Google Play Age Signals API (no user prompt). On iOS: presents the system DeclaredAgeRange dialog (requires iOS 26.2+). ```typescript import { AgeRange } from '@capgo/capacitor-age-range'; const result = await AgeRange.requestAgeRange({ ageGates: [13, 16, 18] }); if (result.status === 'SHARING') { console.log('Age range:', result.ageLower, '-', result.ageUpper); } ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `RequestAgeRangeOptions` [Section titled “RequestAgeRangeOptions”](#requestagerangeoptions) Options for the age range request. ```typescript export interface RequestAgeRangeOptions { /** * Age thresholds for the request. * * On iOS: these are passed to `requestAgeRange(ageGates:)` as the * age boundaries presented in the system dialog. Common values: [13, 16, 18]. * * On Android: this parameter is ignored (Play Age Signals returns * predefined ranges: 0-12, 13-15, 16-17, 18+). * * @default [13, 16, 18] * @since 8.0.0 */ ageGates?: number[]; } ``` ### `AgeRangeResult` [Section titled “AgeRangeResult”](#agerangeresult) Result of the age range request. ```typescript export interface AgeRangeResult { /** * The outcome status of the age range request. * * @since 8.0.0 */ status: AgeRangeStatus; /** * Inclusive lower bound of the user's age range. * * Present when age data is available. * * @since 8.0.0 */ ageLower?: number; /** * Inclusive upper bound of the user's age range. * * May be absent if the user is in the highest age bracket (e.g. 18+). * * @since 8.0.0 */ ageUpper?: number; /** * How the age was declared/determined. * * On iOS: 'SELF_DECLARED' or 'GUARDIAN_DECLARED'. * On Android: 'SUPERVISED' (guardian-managed) or 'VERIFIED' (Google-verified 18+). * * @since 8.0.0 */ declarationSource?: DeclarationSource; /** * Android-only. The user's Google Play verification status. * * @since 8.0.0 */ androidUserStatus?: AndroidUserStatus; /** * Android-only. Effective date for the most recent guardian-approved change. * * @since 8.0.0 */ mostRecentApprovalDate?: string; /** * Android-only. Install identifier for supervised installs in Google Play. * * @since 8.0.0 */ installId?: string; } ``` ### `AgeRangeStatus` [Section titled “AgeRangeStatus”](#agerangestatus) Top-level status of the age range request. ```typescript export type AgeRangeStatus = /** * The user shared their age range (iOS) or age signals are available (Android). */ | 'SHARING' /** * The user declined to share their age range. */ | 'DECLINED_SHARING' /** * The age range API is not available on this device/OS version. */ | 'NOT_AVAILABLE' /** * An error occurred while requesting the age range. */ | 'ERROR'; ``` ### `DeclarationSource` [Section titled “DeclarationSource”](#declarationsource) How the age range was declared or determined. ```typescript export type DeclarationSource = /** The user self-declared their age (iOS). */ | 'SELF_DECLARED' /** A guardian declared the user's age (iOS Family Sharing or Android supervised). */ | 'GUARDIAN_DECLARED' /** Google has verified the user is 18+ (Android only). */ | 'VERIFIED' /** Source is unknown or not provided by the platform. */ | 'UNKNOWN'; ``` ### `AndroidUserStatus` [Section titled “AndroidUserStatus”](#androiduserstatus) Android-specific Google Play user status values. ```typescript export type AndroidUserStatus = | 'VERIFIED' | 'SUPERVISED' | 'SUPERVISED_APPROVAL_PENDING' | 'SUPERVISED_APPROVAL_DENIED' | 'UNKNOWN' | 'EMPTY'; ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-age-range](/plugins/capacitor-age-range/) for the native capability in Using @capgo/capacitor-age-range, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-android-age-signals > Capacitor interface for retrieving Play Age Signals. ## Overview [Section titled “Overview”](#overview) Capacitor interface for retrieving Play Age Signals. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `checkAgeSignals` - Request the current Play Age Signals for the active user. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------ | --------------------------------------------------------- | | `checkAgeSignals` | Request the current Play Age Signals for the active user. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Reference Values [Section titled “Reference Values”](#reference-values) Use these error codes to decide whether to retry, prompt the user to update Google Play components, or treat the device as unsupported. ### Error Codes [Section titled “Error Codes”](#error-codes) | Value | Meaning | | -------------------------------- | -------------------------------------------------------------------------------- | | `API_NOT_AVAILABLE` | Play Age Signals API is not available, often because the Play Store is outdated. | | `PLAY_STORE_NOT_FOUND` | Google Play Store is not installed on the device. | | `NETWORK_ERROR` | Network connection failed while requesting the signal. | | `PLAY_SERVICES_NOT_FOUND` | Google Play services are missing or unavailable. | | `CANNOT_BIND_TO_SERVICE` | The plugin could not bind to the Play Store service. | | `PLAY_STORE_VERSION_OUTDATED` | Google Play Store must be updated. | | `PLAY_SERVICES_VERSION_OUTDATED` | Google Play services must be updated. | | `CLIENT_TRANSIENT_ERROR` | Temporary client-side device error; retry may succeed. | | `APP_NOT_OWNED` | The app was not installed through Google Play. | | `INTERNAL_ERROR` | Unknown internal error from the API. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-android-age-signals](https://github.com/Cap-go/capacitor-android-age-signals/). ## Keep going from @capgo/capacitor-android-age-signals [Section titled “Keep going from @capgo/capacitor-android-age-signals”](#keep-going-from-capgocapacitor-android-age-signals) If you are using **@capgo/capacitor-android-age-signals** to plan store approval and distribution, connect it with [@capgo/capacitor-in-app-review](/docs/plugins/in-app-review/) for the implementation detail in @capgo/capacitor-in-app-review, [Using @capgo/capacitor-in-app-review](/plugins/capacitor-in-app-review/) for the native capability in Using @capgo/capacitor-in-app-review, [@capgo/capacitor-native-market](/docs/plugins/native-market/) for the implementation detail in @capgo/capacitor-native-market, [Using @capgo/capacitor-native-market](/plugins/capacitor-native-market/) for the native capability in Using @capgo/capacitor-native-market, and [Capacitor OTA Updates: App Store Approval Guide](/blog/capacitor-ota-updates-app-store-approval-guide/) for the practical context in Capacitor OTA Updates: App Store Approval Guide. # Getting Started > Install @capgo/capacitor-android-age-signals and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-android-age-signals` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-android-age-signals bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { AgeSignals } from '@capgo/capacitor-android-age-signals'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `checkAgeSignals` [Section titled “checkAgeSignals”](#checkagesignals) Request the current Play Age Signals for the active user. Only available on Android devices with Google Play installed. ```typescript import { AgeSignals } from '@capgo/capacitor-android-age-signals'; await AgeSignals.checkAgeSignals(); ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `CheckAgeSignalsResult` [Section titled “CheckAgeSignalsResult”](#checkagesignalsresult) Structured result returned by . ```typescript export interface CheckAgeSignalsResult { /** * The user's verification status as reported by Google Play. * * @since 0.0.1 */ userStatus: UserStatus; /** * Inclusive lower bound of the supervised user's age range. * * Present only when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED`. * * @since 0.0.1 * @example 13 */ ageLower?: number; /** * Inclusive upper bound of the supervised user's age range. * * Present only when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED` * and the user's age is reported as less than 18. * * @since 0.0.1 * @example 15 */ ageUpper?: number; /** * Effective date for the most recent significant change that received guardian approval. * * Present only when `userStatus` is `SUPERVISED_APPROVAL_PENDING` or `SUPERVISED_APPROVAL_DENIED`. * * @since 0.0.1 * @example "2024-01-15" */ mostRecentApprovalDate?: string; /** * Identifier assigned to supervised installs in Google Play for revocation notifications. * * Present only when `userStatus` is `SUPERVISED`, `SUPERVISED_APPROVAL_PENDING`, or `SUPERVISED_APPROVAL_DENIED`. * * @since 0.0.1 * @example "abc123xyz" */ installId?: string; } ``` ### `UserStatus` [Section titled “UserStatus”](#userstatus) Status values reported by Google Play Age Signals. ```typescript export enum UserStatus { /** * The user is over 18 and their age has been verified by Google. * * @since 0.0.1 */ Verified = 'VERIFIED', /** * The user has a supervised Google Account managed by a guardian. * * Use `ageLower` and `ageUpper` to determine the user's age range. * * @since 0.0.1 */ Supervised = 'SUPERVISED', /** * The supervised user has pending significant changes awaiting guardian approval. * * Use `ageLower` and `ageUpper` to determine the user's age range and `mostRecentApprovalDate` * to identify the most recent approved change. * * @since 0.0.1 */ SupervisedApprovalPending = 'SUPERVISED_APPROVAL_PENDING', /** * The supervised user's guardian denied one or more significant changes. * * Use `ageLower` and `ageUpper` to determine the user's age range and `mostRecentApprovalDate` * to identify the last approved change. * * @since 0.0.1 */ SupervisedApprovalDenied = 'SUPERVISED_APPROVAL_DENIED', /** * The user is not verified or supervised in supported regions. * * You should prompt the user to resolve their status in the Play Store. * * @since 0.0.1 */ Unknown = 'UNKNOWN', /** * All other users return this value. * * @since 0.0.1 */ Empty = 'EMPTY', } ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, [Devices](/docs/public-api/devices/) for the implementation detail in Devices, and [Bundles](/docs/public-api/bundles/) for the implementation detail in Bundles. # @capgo/capacitor-alarm > Capacitor Alarm Plugin interface for managing native OS alarms. ## Overview [Section titled “Overview”](#overview) Capacitor Alarm Plugin interface for managing native OS alarms. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `createAlarm` - Create a native OS alarm using the platform clock app. On Android this uses the Alarm Clock intent; on iOS this uses AlarmKit if available (iOS 16+). * `openAlarms` - Open the platform’s native alarm list UI, if available. * `getOSInfo` - Get information about the OS and capabilities. * `requestPermissions` - Request relevant permissions for alarm usage on the platform. On Android, may route to settings for exact alarms. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `createAlarm` | Create a native OS alarm using the platform clock app. On Android this uses the Alarm Clock intent; on iOS this uses AlarmKit if available (iOS 16+). | | `openAlarms` | Open the platform’s native alarm list UI, if available. | | `getOSInfo` | Get information about the OS and capabilities. | | `requestPermissions` | Request relevant permissions for alarm usage on the platform. On Android, may route to settings for exact alarms. | | `checkPermissions` | Check the current permission state for native alarm access without triggering UI. On iOS this reports AlarmKit readiness; on Android it reports capability details. | | `getPluginVersion` | Get the native Capacitor plugin version. | | `getAlarms` | Get a list of alarms scheduled by this app. On iOS 26+, returns alarms from AlarmKit. On Android, this is not supported as the system does not provide an API to query alarms. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-alarm](https://github.com/Cap-go/capacitor-alarm/). ## Keep going from @capgo/capacitor-alarm [Section titled “Keep going from @capgo/capacitor-alarm”](#keep-going-from-capgocapacitor-alarm) If you are using **@capgo/capacitor-alarm** to plan native plugin work, connect it with [Using @capgo/capacitor-alarm](/plugins/capacitor-alarm/) for the native capability in Using @capgo/capacitor-alarm, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-alarm and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-alarm` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-alarm bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { CapgoAlarm } from '@capgo/capacitor-alarm'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `createAlarm` [Section titled “createAlarm”](#createalarm) Create a native OS alarm using the platform clock app. On Android this uses the Alarm Clock intent; on iOS this uses AlarmKit if available (iOS 16+). ```typescript import { CapgoAlarm } from '@capgo/capacitor-alarm'; const result = await CapgoAlarm.createAlarm({ hour: 7, minute: 30, label: 'Wake up', skipUi: false, vibrate: true }); console.log('Alarm created:', result.success); ``` ### `openAlarms` [Section titled “openAlarms”](#openalarms) Open the platform’s native alarm list UI, if available. ```typescript import { CapgoAlarm } from '@capgo/capacitor-alarm'; const result = await CapgoAlarm.openAlarms(); if (result.success) { console.log('Alarms UI opened'); } ``` ### `getOSInfo` [Section titled “getOSInfo”](#getosinfo) Get information about the OS and capabilities. ```typescript import { CapgoAlarm } from '@capgo/capacitor-alarm'; const info = await CapgoAlarm.getOSInfo(); console.log('Platform:', info.platform); console.log('Supports native alarms:', info.supportsNativeAlarms); if (info.platform === 'android') { console.log('Can schedule exact alarms:', info.canScheduleExactAlarms); } ``` ### `requestPermissions` [Section titled “requestPermissions”](#requestpermissions) Request relevant permissions for alarm usage on the platform. On Android, may route to settings for exact alarms. ```typescript import { CapgoAlarm } from '@capgo/capacitor-alarm'; const result = await CapgoAlarm.requestPermissions({ exactAlarm: true }); if (result.granted) { console.log('Permissions granted'); } else { console.log('Permissions denied'); } ``` ### `checkPermissions` [Section titled “checkPermissions”](#checkpermissions) Check the current permission state for native alarm access without triggering UI. On iOS this reports AlarmKit readiness; on Android it reports capability details. ```typescript import { CapgoAlarm } from '@capgo/capacitor-alarm'; const status = await CapgoAlarm.checkPermissions(); console.log('AlarmKit allowed?', status.details?.alarmKit); ``` ### `getAlarms` [Section titled “getAlarms”](#getalarms) Get a list of alarms scheduled by this app. On iOS 26+, returns alarms from AlarmKit. On Android, this is not supported as the system does not provide an API to query alarms. ```typescript import { CapgoAlarm } from '@capgo/capacitor-alarm'; const { alarms } = await CapgoAlarm.getAlarms(); console.log('Scheduled alarms:', alarms); alarms.forEach(alarm => { console.log(`Alarm ${alarm.id}: ${alarm.hour}:${alarm.minute} - ${alarm.label}`); }); ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `NativeAlarmCreateOptions` [Section titled “NativeAlarmCreateOptions”](#nativealarmcreateoptions) Options for creating a native OS alarm via the platform clock app. ```typescript export interface NativeAlarmCreateOptions { /** Hour of day in 24h format (0-23) */ hour: number; /** Minute of hour (0-59) */ minute: number; /** Optional label for the alarm */ label?: string; /** Android only: attempt to skip UI if possible */ skipUi?: boolean; /** Android only: set alarm to vibrate */ vibrate?: boolean; } ``` ### `NativeActionResult` [Section titled “NativeActionResult”](#nativeactionresult) Result of a native action. ```typescript export interface NativeActionResult { /** Whether the action was successful */ success: boolean; /** Optional message with additional information */ message?: string; } ``` ### `OSInfo` [Section titled “OSInfo”](#osinfo) Returned info about current OS and capabilities. ```typescript export interface OSInfo { /** Platform identifier: 'ios' | 'android' | 'web' */ platform: string; /** OS version string */ version: string; /** Whether the platform exposes a native alarm app integration */ supportsNativeAlarms: boolean; /** Whether scheduling local notifications is supported */ supportsScheduledNotifications: boolean; /** Android only: whether exact alarms are allowed */ canScheduleExactAlarms?: boolean; } ``` ### `PermissionResult` [Section titled “PermissionResult”](#permissionresult) Result of a permissions request. ```typescript export interface PermissionResult { /** Overall grant for requested scope */ granted: boolean; /** Optional details by permission key */ details?: Record; /** Optional human readable diagnostic */ message?: string; } ``` ### `AlarmInfo` [Section titled “AlarmInfo”](#alarminfo) Information about a scheduled alarm. ```typescript export interface AlarmInfo { /** Unique identifier for the alarm */ id: string; /** Hour of day in 24h format (0-23) */ hour: number; /** Minute of hour (0-59) */ minute: number; /** Optional label for the alarm */ label?: string; /** Whether the alarm is enabled */ enabled?: boolean; } ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-alarm](/plugins/capacitor-alarm/) for the native capability in Using @capgo/capacitor-alarm, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-android-inline-install > Android Inline Install Plugin for triggering Google Play in-app install flows. ## Overview [Section titled “Overview”](#overview) Android Inline Install Plugin for triggering Google Play in-app install flows. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `startInlineInstall` - Start an inline install flow using the Google Play overlay. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | -------------------- | ----------------------------------------------------------- | | `startInlineInstall` | Start an inline install flow using the Google Play overlay. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-android-inline-install](https://github.com/Cap-go/capacitor-android-inline-install/). ## Keep going from @capgo/capacitor-android-inline-install [Section titled “Keep going from @capgo/capacitor-android-inline-install”](#keep-going-from-capgocapacitor-android-inline-install) If you are using **@capgo/capacitor-android-inline-install** to plan native plugin work, connect it with [Using @capgo/capacitor-android-inline-install](/plugins/capacitor-android-inline-install/) for the native capability in Using @capgo/capacitor-android-inline-install, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-android-inline-install and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-android-inline-install` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-android-inline-install bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { AndroidInlineInstall } from '@capgo/capacitor-android-inline-install'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `startInlineInstall` [Section titled “startInlineInstall”](#startinlineinstall) Start an inline install flow using the Google Play overlay. Note: Only eligible apps can use Inline Install. See: ```typescript import { AndroidInlineInstall } from '@capgo/capacitor-android-inline-install'; const result = await AndroidInlineInstall.startInlineInstall({ id: 'com.example.app', referrer: 'my-referrer', overlay: true, fallback: true }); if (result.started) { console.log('Install flow started'); if (result.fallbackUsed) { console.log('Using fallback Play Store link'); } } ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `StartInlineInstallOptions` [Section titled “StartInlineInstallOptions”](#startinlineinstalloptions) Options for starting an inline install flow. ```typescript export interface StartInlineInstallOptions { /** Package name of the app to be installed (target app). */ id: string; /** Referrer string to pass to Play. Optional but recommended. */ referrer?: string; /** * Package name of your app (caller). Defaults to the current app package * if omitted. */ callerId?: string; /** Optional Custom Store Listing ID. */ csl_id?: string; /** Whether to request the Play overlay. Defaults to true. */ overlay?: boolean; /** If true, falls back to full Play Store deep link when overlay unavailable. Defaults to true. */ fallback?: boolean; } ``` ### `StartInlineInstallResult` [Section titled “StartInlineInstallResult”](#startinlineinstallresult) Result of starting an inline install flow. ```typescript export interface StartInlineInstallResult { /** True when the inline install intent has been started. */ started: boolean; /** True if a fallback deep link was used instead of inline overlay. */ fallbackUsed?: boolean; } ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-android-inline-install](/plugins/capacitor-android-inline-install/) for the native capability in Using @capgo/capacitor-android-inline-install, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-android-kiosk > Capacitor Android Kiosk Plugin for controlling kiosk mode and launcher functionality. This plugin is Android-only. For iOS kiosk mode, use the device's Guided Access feature. ## Overview [Section titled “Overview”](#overview) Capacitor Android Kiosk Plugin for controlling kiosk mode and launcher functionality. This plugin is Android-only. For iOS kiosk mode, use the device’s Guided Access feature. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `isInKioskMode` - Checks if the app is currently running in kiosk mode. * `isSetAsLauncher` - Checks if the app is set as the device launcher (home app). * `enterKioskMode` - Enters kiosk mode, hiding system UI and blocking hardware buttons. Also starts a foreground keep-alive service so the app is less likely to be killed by the system. The app must be set as the device launcher for this to work effectively. * `exitKioskMode` - Exits kiosk mode, restoring normal system UI and hardware button functionality. Also stops the foreground keep-alive service started in enterKioskMode(). ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `isInKioskMode` | Checks if the app is currently running in kiosk mode. | | `isSetAsLauncher` | Checks if the app is set as the device launcher (home app). | | `enterKioskMode` | Enters kiosk mode, hiding system UI and blocking hardware buttons. Also starts a foreground keep-alive service so the app is less likely to be killed by the system. The app must be set as the device launcher for this to work effectively. | | `exitKioskMode` | Exits kiosk mode, restoring normal system UI and hardware button functionality. Also stops the foreground keep-alive service started in enterKioskMode(). | | `setAsLauncher` | Opens the device’s home screen settings to allow user to set this app as the launcher. This is required for full kiosk mode functionality. | | `setAllowedKeys` | Sets which hardware keys are allowed to function in kiosk mode. By default, all hardware keys are blocked in kiosk mode. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-android-kiosk](https://github.com/Cap-go/capacitor-android-kiosk/). ## Keep going from @capgo/capacitor-android-kiosk [Section titled “Keep going from @capgo/capacitor-android-kiosk”](#keep-going-from-capgocapacitor-android-kiosk) If you are using **@capgo/capacitor-android-kiosk** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-android-kiosk](/plugins/capacitor-android-kiosk/) for the native capability in Using @capgo/capacitor-android-kiosk, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # Getting Started > Install @capgo/capacitor-android-kiosk and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-android-kiosk` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-android-kiosk bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { CapacitorAndroidKiosk } from '@capgo/capacitor-android-kiosk'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `isInKioskMode` [Section titled “isInKioskMode”](#isinkioskmode) Checks if the app is currently running in kiosk mode. ```typescript import { CapacitorAndroidKiosk } from '@capgo/capacitor-android-kiosk'; const { isInKioskMode } = await CapacitorAndroidKiosk.isInKioskMode(); console.log('Kiosk mode active:', isInKioskMode); ``` ### `isSetAsLauncher` [Section titled “isSetAsLauncher”](#issetaslauncher) Checks if the app is set as the device launcher (home app). ```typescript import { CapacitorAndroidKiosk } from '@capgo/capacitor-android-kiosk'; const { isLauncher } = await CapacitorAndroidKiosk.isSetAsLauncher(); console.log('Is launcher:', isLauncher); ``` ### `enterKioskMode` [Section titled “enterKioskMode”](#enterkioskmode) Enters kiosk mode, hiding system UI and blocking hardware buttons. Also starts a foreground keep-alive service so the app is less likely to be killed by the system. The app must be set as the device launcher for this to work effectively. ```typescript import { CapacitorAndroidKiosk } from '@capgo/capacitor-android-kiosk'; await CapacitorAndroidKiosk.enterKioskMode(); ``` ### `exitKioskMode` [Section titled “exitKioskMode”](#exitkioskmode) Exits kiosk mode, restoring normal system UI and hardware button functionality. Also stops the foreground keep-alive service started in enterKioskMode(). ```typescript import { CapacitorAndroidKiosk } from '@capgo/capacitor-android-kiosk'; await CapacitorAndroidKiosk.exitKioskMode(); console.log('Exited kiosk mode'); ``` ### `setAsLauncher` [Section titled “setAsLauncher”](#setaslauncher) Opens the device’s home screen settings to allow user to set this app as the launcher. This is required for full kiosk mode functionality. ```typescript import { CapacitorAndroidKiosk } from '@capgo/capacitor-android-kiosk'; await CapacitorAndroidKiosk.setAsLauncher(); // User will be prompted to select this app as the home app ``` ### `setAllowedKeys` [Section titled “setAllowedKeys”](#setallowedkeys) Sets which hardware keys are allowed to function in kiosk mode. By default, all hardware keys are blocked in kiosk mode. ```typescript import { CapacitorAndroidKiosk } from '@capgo/capacitor-android-kiosk'; // Allow volume keys only await CapacitorAndroidKiosk.setAllowedKeys({ volumeUp: true, volumeDown: true, back: false, home: false, recent: false }); ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `EnterKioskModeOptions` [Section titled “EnterKioskModeOptions”](#enterkioskmodeoptions) Optional flags for `enterKioskMode`. ```typescript export interface EnterKioskModeOptions { /** * After reboot, start the app so you can call `enterKioskMode()` again. Best-effort only (OEM * behavior, force-stop). Omit to keep the saved value. Cleared when you call `exitKioskMode()`. */ restoreAfterReboot?: boolean; /** * Periodically tries to bring the app to the foreground. Skipped while the screen is off. Often * blocked from the background on some devices—being the default launcher, relaxing battery limits, * and allowing exact alarms (where required) improve odds. Omit to keep the saved value. */ relaunch?: boolean; /** Minutes between relaunch attempts when `relaunch` is on. Range 5–60; default 15. */ relaunchIntervalMinutes?: number; } ``` ### `AllowedKeysOptions` [Section titled “AllowedKeysOptions”](#allowedkeysoptions) Configuration options for allowed hardware keys in kiosk mode. ```typescript export interface AllowedKeysOptions { /** * Allow volume up button * @default false */ volumeUp?: boolean; /** * Allow volume down button * @default false */ volumeDown?: boolean; /** * Allow back button * @default false */ back?: boolean; /** * Allow home button * @default false */ home?: boolean; /** * Allow recent apps button * @default false */ recent?: boolean; /** * Allow power button * @default false */ power?: boolean; /** * Allow camera button (if present) * @default false */ camera?: boolean; /** * Allow menu button (if present) * @default false */ menu?: boolean; } ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-android-kiosk](/plugins/capacitor-android-kiosk/) for the native capability in Using @capgo/capacitor-android-kiosk, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-android-sms-retriever > Read one app-targeted verification SMS without SMS permissions and request SIM phone number hints on Android. ## Overview [Section titled “Overview”](#overview) `@capgo/capacitor-android-sms-retriever` wraps Google Play services SMS Retriever and Phone Number Hint APIs for Android-only Capacitor verification flows. The plugin lets your app listen for a single verification SMS addressed to your app without requesting SMS permissions. It can also show Android’s native Phone Number Hint UI so users can choose a SIM-based phone number without typing it manually. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `startWatch` - Start a five-minute SMS Retriever watch for one verification SMS. * `stopWatch` - Stop the active SMS Retriever watch. * `getHashString` - Read the 11-character app hash used in verification SMS messages. * `getPhoneNumber` - Open Android Phone Number Hint and return the selected phone number. * `smsReceived` - Listen for the retrieved verification SMS. * `smsRetrieverTimeout` - Listen for the five-minute timeout. * `smsRetrieverError` - Listen for runtime errors from Android or Google Play services. ## Platform Support [Section titled “Platform Support”](#platform-support) | Platform | Support | | -------- | ---------------- | | Android | Supported | | iOS | Unsupported stub | | Web | Unsupported stub | ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ----------------------------------------- | ------------------------------------------------------ | | `startWatch` | Start listening for one verification SMS. | | `stopWatch` | Stop the active watch. | | `getHashString` | Return the 11-character app hash. | | `getPhoneNumber` | Show Phone Number Hint and return the selected number. | | `addListener('smsReceived', ...)` | Receive the retrieved SMS payload. | | `addListener('smsRetrieverTimeout', ...)` | Handle timeout events. | | `addListener('smsRetrieverError', ...)` | Handle retriever errors. | | `getPluginVersion` | Return the native plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-android-sms-retriever](https://github.com/Cap-go/capacitor-android-sms-retriever/). ## Keep going from @capgo/capacitor-android-sms-retriever [Section titled “Keep going from @capgo/capacitor-android-sms-retriever”](#keep-going-from-capgocapacitor-android-sms-retriever) If you are using **@capgo/capacitor-android-sms-retriever** to plan native plugin work, connect it with [Using @capgo/capacitor-android-sms-retriever](/plugins/capacitor-android-sms-retriever/) for the native capability in Using @capgo/capacitor-android-sms-retriever, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-android-sms-retriever and use Android SMS Retriever in a Capacitor app. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-android-sms-retriever` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-android-sms-retriever bunx cap sync android ``` ## Import [Section titled “Import”](#import) ```typescript import { AndroidSmsRetriever } from '@capgo/capacitor-android-sms-retriever'; ``` ## Android Requirements [Section titled “Android Requirements”](#android-requirements) SMS Retriever requires Google Play services on the Android device. The plugin does not request `READ_SMS` or `RECEIVE_SMS` permissions. Your verification SMS must include the app hash returned by `getHashString()`. Generate the hash for the signing key used to distribute the app. Debug, release, and Play App Signing builds can have different hashes. ## Listen For A Verification SMS [Section titled “Listen For A Verification SMS”](#listen-for-a-verification-sms) ```typescript import { AndroidSmsRetriever } from '@capgo/capacitor-android-sms-retriever'; const received = await AndroidSmsRetriever.addListener('smsReceived', ({ message }) => { const code = message.match(/\b\d{6}\b/)?.[0]; console.log('Verification code:', code); }); const timeout = await AndroidSmsRetriever.addListener('smsRetrieverTimeout', () => { console.log('SMS Retriever timed out'); }); const errors = await AndroidSmsRetriever.addListener('smsRetrieverError', ({ message }) => { console.error('SMS Retriever error:', message); }); await AndroidSmsRetriever.startWatch(); // Remove listeners when the verification flow is done. await received.remove(); await timeout.remove(); await errors.remove(); ``` ## Stop Watching [Section titled “Stop Watching”](#stop-watching) ```typescript await AndroidSmsRetriever.stopWatch(); ``` ## Get The App Hash [Section titled “Get The App Hash”](#get-the-app-hash) ```typescript const { hash } = await AndroidSmsRetriever.getHashString(); console.log(hash); ``` Use this hash at the end of the verification SMS sent by your backend. ## Request A Phone Number Hint [Section titled “Request A Phone Number Hint”](#request-a-phone-number-hint) ```typescript const { phoneNumber } = await AndroidSmsRetriever.getPhoneNumber(); console.log(phoneNumber); ``` Android shows the native Phone Number Hint UI and returns the phone number selected by the user. ## Example SMS [Section titled “Example SMS”](#example-sms) ```text <#> 123456 is your verification code. FA+9qCX9VSu ``` Replace the final line with the hash for your app signing key. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan native plugin work, connect it with [Using @capgo/capacitor-android-sms-retriever](/plugins/capacitor-android-sms-retriever/) for the native capability in Using @capgo/capacitor-android-sms-retriever, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # @capgo/capacitor-android-usagestatsmanager > Capacitor plugin for accessing Android UsageStatsManager API. ## Overview [Section titled “Overview”](#overview) Capacitor plugin for accessing Android UsageStatsManager API. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `queryAndAggregateUsageStats` - Queries and aggregates usage stats for the given time range. * `isUsageStatsPermissionGranted` - Checks if the usage stats permission is granted. * `openUsageStatsSettings` - Open the usage stats settings screen. This will open the usage stats settings screen, which allows the user to grant the usage stats permission. This will always open the settings screen, even if the permission is already granted. * `queryAllPackages` - Queries all installed packages on the device. Requires the QUERY\_ALL\_PACKAGES permission. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `queryAndAggregateUsageStats` | Queries and aggregates usage stats for the given time range. | | `isUsageStatsPermissionGranted` | Checks if the usage stats permission is granted. | | `openUsageStatsSettings` | Open the usage stats settings screen. This will open the usage stats settings screen, which allows the user to grant the usage stats permission. This will always open the settings screen, even if the permission is already granted. | | `queryAllPackages` | Queries all installed packages on the device. Requires the QUERY\_ALL\_PACKAGES permission. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-android-usagestatsmanager](https://github.com/Cap-go/capacitor-android-usagestatsmanager/). ## Keep going from @capgo/capacitor-android-usagestatsmanager [Section titled “Keep going from @capgo/capacitor-android-usagestatsmanager”](#keep-going-from-capgocapacitor-android-usagestatsmanager) If you are using **@capgo/capacitor-android-usagestatsmanager** to plan native plugin work, connect it with [Using @capgo/capacitor-android-usagestatsmanager](/plugins/capacitor-android-usagestatsmanager/) for the native capability in Using @capgo/capacitor-android-usagestatsmanager, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-android-usagestatsmanager and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-android-usagestatsmanager` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-android-usagestatsmanager bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { CapacitorUsageStatsManager } from '@capgo/capacitor-android-usagestatsmanager'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `queryAndAggregateUsageStats` [Section titled “queryAndAggregateUsageStats”](#queryandaggregateusagestats) Queries and aggregates usage stats for the given time range. ```typescript import { CapacitorUsageStatsManager } from '@capgo/capacitor-android-usagestatsmanager'; const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000; const now = Date.now(); const stats = await UsageStatsManager.queryAndAggregateUsageStats({ beginTime: oneDayAgo, endTime: now }); for (const [packageName, usageData] of Object.entries(stats)) { console.log(`${packageName}: ${usageData.totalTimeInForeground}ms`); } ``` ### `isUsageStatsPermissionGranted` [Section titled “isUsageStatsPermissionGranted”](#isusagestatspermissiongranted) Checks if the usage stats permission is granted. ```typescript import { CapacitorUsageStatsManager } from '@capgo/capacitor-android-usagestatsmanager'; const { granted } = await UsageStatsManager.isUsageStatsPermissionGranted(); if (!granted) { await UsageStatsManager.openUsageStatsSettings(); } ``` ### `openUsageStatsSettings` [Section titled “openUsageStatsSettings”](#openusagestatssettings) Open the usage stats settings screen. This will open the usage stats settings screen, which allows the user to grant the usage stats permission. This will always open the settings screen, even if the permission is already granted. ```typescript import { CapacitorUsageStatsManager } from '@capgo/capacitor-android-usagestatsmanager'; await UsageStatsManager.openUsageStatsSettings(); ``` ### `queryAllPackages` [Section titled “queryAllPackages”](#queryallpackages) Queries all installed packages on the device. Requires the QUERY\_ALL\_PACKAGES permission. ```typescript import { CapacitorUsageStatsManager } from '@capgo/capacitor-android-usagestatsmanager'; const { packages } = await UsageStatsManager.queryAllPackages(); packages.forEach(pkg => { console.log(`${pkg.appName} (${pkg.packageName}): v${pkg.versionName}`); }); ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `UsageStatsOptions` [Section titled “UsageStatsOptions”](#usagestatsoptions) Options for querying usage statistics. ```typescript export interface UsageStatsOptions { /** * The inclusive beginning of the range of stats to include in the results. * Defined in terms of "Unix time" */ beginTime: number; /** * The exclusive end of the range of stats to include in the results. * Defined in terms of "Unix time" */ endTime: number; } ``` ### `UsageStats` [Section titled “UsageStats”](#usagestats) Usage statistics for an Android app. ```typescript export interface UsageStats { /** * The first timestamp of the usage stats. */ firstTimeStamp: number; /** * The last timestamp of the usage stats. */ lastTimeStamp: number; /** * Only available on Android Q (API level 29) and above. * Will be undefined on lower Android versions. */ lastTimeForegroundServiceUsed?: number; /** * The last time the app was used. */ lastTimeUsed: number; /** * Only available on Android Q (API level 29) and above. * Will be undefined on lower Android versions. */ lastTimeVisible?: number; /** * The name of the package. */ packageName: string; /** * Only available on Android Q (API level 29) and above. * Will be undefined on lower Android versions. */ totalForegroundServiceUsed?: number; /** * The total time the app was in the foreground. */ totalTimeInForeground: number; /** * Only available on Android Q (API level 29) and above. * Will be undefined on lower Android versions. */ totalTimeVisible?: number; } ``` ### `UsageStatsPermissionResult` [Section titled “UsageStatsPermissionResult”](#usagestatspermissionresult) Result of a usage stats permission check. ```typescript export interface UsageStatsPermissionResult { /** * Whether the usage stats permission is granted. */ granted: boolean; } ``` ### `PackageInfo` [Section titled “PackageInfo”](#packageinfo) Represents basic information about an installed package. ```typescript export interface PackageInfo { /** Package name */ packageName: string; /** App display name */ appName: string; /** Version name string */ versionName: string; /** Version code number */ versionCode: number; /** First install time in milliseconds since epoch */ firstInstallTime: number; /** Last update time in milliseconds since epoch */ lastUpdateTime: number; } ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-android-usagestatsmanager](/plugins/capacitor-android-usagestatsmanager/) for the native capability in Using @capgo/capacitor-android-usagestatsmanager, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-app-attest > Unified cross-platform attestation plugin for Capacitor. ## Overview [Section titled “Overview”](#overview) Unified cross-platform attestation plugin for Capacitor. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `isSupported` - Checks whether native attestation is available on this device. * `prepare` - Prepares attestation state and returns the key handle used for later calls. * `createAttestation` - Creates a registration attestation token bound to a backend-issued challenge. * `createAssertion` - Creates a request assertion token bound to a request payload. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------- | ----------------------------------------------------------------------------- | | `isSupported` | Checks whether native attestation is available on this device. | | `prepare` | Prepares attestation state and returns the key handle used for later calls. | | `createAttestation` | Creates a registration attestation token bound to a backend-issued challenge. | | `createAssertion` | Creates a request assertion token bound to a request payload. | | `storeKeyId` | Stores/prepares a key identifier for reuse. | | `getStoredKeyId` | Returns the currently stored/prepared key identifier. | | `clearStoredKeyId` | Clears stored/prepared key identifiers. | | `generateKey` | Legacy alias for `prepare()`. | | `attestKey` | Legacy alias for `createAttestation()`. | | `generateAssertion` | Legacy alias for `createAssertion()`. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-app-attest](https://github.com/Cap-go/capacitor-app-attest/). ## Keep going from @capgo/capacitor-app-attest [Section titled “Keep going from @capgo/capacitor-app-attest”](#keep-going-from-capgocapacitor-app-attest) If you are using **@capgo/capacitor-app-attest** to plan security and compliance, connect it with [Using @capgo/capacitor-app-attest](/plugins/capacitor-app-attest/) for the native capability in Using @capgo/capacitor-app-attest, [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, and [Capgo Security](/security/) for the product workflow in Capgo Security. # Android Setup & Backend Verification > Configure Google Play Integrity Standard API on Android and verify integrity tokens on your backend. ## Android native system used [Section titled “Android native system used”](#android-native-system-used) On Android, this plugin uses **Google Play Integrity Standard API**: * `prepareIntegrityToken` during `prepare()` * `requestStandardIntegrityToken` for `createAttestation()` and `createAssertion()` ## Requirements [Section titled “Requirements”](#requirements) * Android app distributed through Google Play ecosystem * Google Play services available on device * Play Integrity API enabled for your app * Google Cloud project number configured ## Google setup [Section titled “Google setup”](#google-setup) 1. Enable **Play Integrity API** in your Google Cloud project. 2. Open Play Console and configure Play Integrity access for your app. 3. Provide `cloudProjectNumber` to the plugin. ## Capacitor config [Section titled “Capacitor config”](#capacitor-config) capacitor.config.ts ```ts plugins: { AppAttest: { cloudProjectNumber: '123456789012', }, } ``` You can also pass `cloudProjectNumber` per call in method options. ## Client flow [Section titled “Client flow”](#client-flow) ```typescript import { AppAttest } from '@capgo/capacitor-app-attest'; const { keyId } = await AppAttest.prepare({ cloudProjectNumber: '123456789012', }); const attestation = await AppAttest.createAttestation({ keyId, challenge: 'backend-registration-challenge', }); const assertion = await AppAttest.createAssertion({ keyId, payload: 'backend-request-payload', }); ``` `token` is a Play Integrity token and must be decoded server-side. ## Backend workflow (Android) [Section titled “Backend workflow (Android)”](#backend-workflow-android) ### Registration (`createAttestation`) [Section titled “Registration (createAttestation)”](#registration-createattestation) 1. Backend creates one-time `challenge`. 2. App calls `createAttestation({ keyId, challenge })`. 3. Backend calls Google `decodeIntegrityToken` API. 4. Backend verifies at minimum: * `requestDetails.requestHash === base64url(SHA256(challenge))` * `appIntegrity.packageName` equals your Android application id * `appIntegrity.certificateSha256Digest` contains your release signing cert digest * integrity verdicts match your security policy ### Request protection (`createAssertion`) [Section titled “Request protection (createAssertion)”](#request-protection-createassertion) 1. Backend creates one-time `payload`. 2. App calls `createAssertion({ keyId, payload })`. 3. Backend decodes token and checks `requestHash === base64url(SHA256(payload))`. 4. Enforce replay prevention (single-use + TTL) and integrity verdict policy. ## Android schema [Section titled “Android schema”](#android-schema) ```mermaid sequenceDiagram participant App as Android App participant Plugin as AppAttest plugin participant PlaySDK as Play Integrity SDK participant BE as Backend participant Google as decodeIntegrityToken API App->>Plugin: prepare(cloudProjectNumber) Plugin->>PlaySDK: prepareIntegrityToken() PlaySDK-->>Plugin: provider handle (keyId) BE->>App: one-time challenge App->>Plugin: createAttestation(keyId, challenge) Plugin->>PlaySDK: requestStandardIntegrityToken(requestHash) PlaySDK-->>Plugin: integrity token Plugin-->>App: token + platform + format + keyId App->>BE: token + challenge + keyId BE->>Google: decodeIntegrityToken(token) Google-->>BE: decoded payload BE->>BE: verify requestHash + app identity + verdicts BE->>App: one-time payload App->>Plugin: createAssertion(keyId, payload) Plugin->>PlaySDK: requestStandardIntegrityToken(requestHash) PlaySDK-->>Plugin: integrity token App->>BE: token + payload + keyId BE->>Google: decodeIntegrityToken(token) Google-->>BE: decoded payload BE->>BE: verify requestHash + replay policy ``` ## Minimal backend payload contract [Section titled “Minimal backend payload contract”](#minimal-backend-payload-contract) Registration: ```json { "platform": "android", "format": "google-play-integrity-standard", "keyId": "string", "challenge": "string", "token": "string" } ``` Assertion: ```json { "platform": "android", "format": "google-play-integrity-standard", "keyId": "string", "payload": "string", "token": "string" } ``` ## Keep going from Android Setup & Backend Verification [Section titled “Keep going from Android Setup & Backend Verification”](#keep-going-from-android-setup--backend-verification) If you are using **Android Setup & Backend Verification** to plan security and compliance, connect it with [Using @capgo/capacitor-app-attest](/plugins/capacitor-app-attest/) for the native capability in Using @capgo/capacitor-app-attest, [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, and [Capgo Security](/security/) for the product workflow in Capgo Security. # Getting Started > Learn how to install and use App Attest with a unified API for iOS and Android attestation. ## Installation [Section titled “Installation”](#installation) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-app-attest` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: 1. **Install the package** ```sh bun add @capgo/capacitor-app-attest ``` 2. **Sync native projects** ```sh bunx cap sync ``` 3. **Configure platform requirements** * Complete [iOS setup](/docs/plugins/app-attest/ios/) for App Attest capability and backend verification flow. * Complete [Android setup](/docs/plugins/app-attest/android/) for Play Integrity Standard and backend verification flow. ## Why use this plugin [Section titled “Why use this plugin”](#why-use-this-plugin) This plugin provides one cross-platform API while keeping native platform security: * iOS: Apple App Attest (`DeviceCheck`) * Android: Google Play Integrity Standard API * No custom client-side crypto scheme * Normalized outputs for backend checks ## Usage [Section titled “Usage”](#usage) ```typescript import { AppAttest } from '@capgo/capacitor-app-attest'; const support = await AppAttest.isSupported(); if (!support.isSupported) { throw new Error(`Attestation not supported on ${support.platform}`); } const prepared = await AppAttest.prepare(); const registration = await AppAttest.createAttestation({ keyId: prepared.keyId, challenge: 'backend-one-time-registration-challenge', }); const assertion = await AppAttest.createAssertion({ keyId: prepared.keyId, payload: 'backend-one-time-request-payload', }); console.log(registration.platform, registration.format, registration.token); console.log(assertion.platform, assertion.format, assertion.token); ``` ## Unified response shape [Section titled “Unified response shape”](#unified-response-shape) `createAttestation()` and `createAssertion()` return the same key fields on iOS and Android: | Field | Type | Description | | ---------- | ----------------------------- | ------------------------------------------------------ | | `platform` | `'ios' \| 'android' \| 'web'` | Native platform that produced the token | | `format` | `AttestationFormat` | `apple-app-attest` or `google-play-integrity-standard` | | `keyId` | `string` | Key/provider handle used for attestation | | `token` | `string` | Token to verify on your backend | ## Backend requirement [Section titled “Backend requirement”](#backend-requirement) Attestation is only useful when verified server-side. * Never trust client-only success. * Require one-time challenge/payload values from your backend. * Verify `token`, app identity, and replay protections in backend logic. Use the platform-specific backend guides: * [iOS setup and backend verification](/docs/plugins/app-attest/ios/) * [Android setup and backend verification](/docs/plugins/app-attest/android/) ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan security and compliance, connect it with [Using @capgo/capacitor-app-attest](/plugins/capacitor-app-attest/) for the native capability in Using @capgo/capacitor-app-attest, [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, and [Capgo Security](/security/) for the product workflow in Capgo Security. # iOS Setup & Backend Verification > Configure Apple App Attest on iOS and verify attestation/assertion payloads on your backend. ## iOS native system used [Section titled “iOS native system used”](#ios-native-system-used) On iOS, this plugin uses **Apple App Attest** from the `DeviceCheck` framework. ## Requirements [Section titled “Requirements”](#requirements) * iOS 14+ * Physical device recommended for real validation flows * Xcode target with App Attest capability enabled ## Xcode setup [Section titled “Xcode setup”](#xcode-setup) 1. Open your iOS app target in Xcode. 2. Go to **Signing & Capabilities**. 3. Click **+ Capability** and add **App Attest**. No custom iOS permissions are required in `Info.plist` for App Attest itself. ## Client flow [Section titled “Client flow”](#client-flow) ```typescript import { AppAttest } from '@capgo/capacitor-app-attest'; const { keyId } = await AppAttest.prepare(); const attestation = await AppAttest.createAttestation({ keyId, challenge: 'backend-registration-challenge', }); const assertion = await AppAttest.createAssertion({ keyId, payload: 'backend-request-payload', }); ``` Send `attestation.token` and `assertion.token` to your backend. Do not validate them in the app. ## Backend workflow (iOS) [Section titled “Backend workflow (iOS)”](#backend-workflow-ios) ### Registration (`createAttestation`) [Section titled “Registration (createAttestation)”](#registration-createattestation) 1. Backend creates one-time `challenge`. 2. App calls `createAttestation({ keyId, challenge })`. 3. Backend verifies App Attest attestation: * certificate chain is valid and anchored to Apple App Attest * app identity matches your app (`bundleId`, team) * `clientDataHash` matches `SHA256(challenge)` 4. Store device key state (`keyId`, public key, and verifier metadata). ### Request protection (`createAssertion`) [Section titled “Request protection (createAssertion)”](#request-protection-createassertion) 1. Backend creates one-time `payload` (or canonical request hash input). 2. App calls `createAssertion({ keyId, payload })`. 3. Backend verifies assertion signature with previously stored key material. 4. Enforce replay protection and nonce TTL checks. ## iOS schema [Section titled “iOS schema”](#ios-schema) ```mermaid sequenceDiagram participant App as iOS App participant Plugin as AppAttest plugin participant Apple as Apple App Attest participant BE as Backend BE->>App: one-time challenge App->>Plugin: prepare() Plugin->>Apple: generateKey() Apple-->>Plugin: keyId App->>Plugin: createAttestation(keyId, challenge) Plugin->>Apple: attestKey(keyId, SHA256(challenge)) Apple-->>Plugin: attestation token Plugin-->>App: token + platform + format + keyId App->>BE: token + challenge + keyId BE->>BE: verify Apple attestation rules BE->>App: one-time payload App->>Plugin: createAssertion(keyId, payload) Plugin->>Apple: generateAssertion(keyId, SHA256(payload)) Apple-->>Plugin: assertion token Plugin-->>App: token + platform + format + keyId App->>BE: token + payload + keyId BE->>BE: verify signature + replay policy ``` ## Minimal backend payload contract [Section titled “Minimal backend payload contract”](#minimal-backend-payload-contract) Registration: ```json { "platform": "ios", "format": "apple-app-attest", "keyId": "string", "challenge": "string", "token": "string" } ``` Assertion: ```json { "platform": "ios", "format": "apple-app-attest", "keyId": "string", "payload": "string", "token": "string" } ``` ## Keep going from iOS Setup & Backend Verification [Section titled “Keep going from iOS Setup & Backend Verification”](#keep-going-from-ios-setup--backend-verification) If you are using **iOS Setup & Backend Verification** to plan security and compliance, connect it with [Using @capgo/capacitor-app-attest](/plugins/capacitor-app-attest/) for the native capability in Using @capgo/capacitor-app-attest, [Encryption](/docs/live-updates/encryption/) for the implementation detail in Encryption, [Compliance](/docs/live-updates/compliance/) for the implementation detail in Compliance, [Capgo Security Scanner](/security-scanner/) for the product workflow in Capgo Security Scanner, and [Capgo Security](/security/) for the product workflow in Capgo Security. # @capgo/capacitor-app-tracking-transparency > Capacitor App Tracking Transparency Plugin. ## Overview [Section titled “Overview”](#overview) Capacitor App Tracking Transparency Plugin. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `getStatus` - Gets the current tracking authorization status without prompting the user. * `requestPermission` - Requests user authorization to access app-related data for tracking. Displays the native iOS tracking permission dialog. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------- | ------------------------------------------------------------------------------------------------------------------------ | | `getStatus` | Gets the current tracking authorization status without prompting the user. | | `requestPermission` | Requests user authorization to access app-related data for tracking. Displays the native iOS tracking permission dialog. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-app-tracking-transparency](https://github.com/Cap-go/capacitor-app-tracking-transparency/). ## Keep going from @capgo/capacitor-app-tracking-transparency [Section titled “Keep going from @capgo/capacitor-app-tracking-transparency”](#keep-going-from-capgocapacitor-app-tracking-transparency) If you are using **@capgo/capacitor-app-tracking-transparency** to plan native plugin work, connect it with [Using @capgo/capacitor-app-tracking-transparency](/plugins/capacitor-app-tracking-transparency/) for the native capability in Using @capgo/capacitor-app-tracking-transparency, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-app-tracking-transparency and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-app-tracking-transparency` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-app-tracking-transparency bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { AppTrackingTransparency } from '@capgo/capacitor-app-tracking-transparency'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `getStatus` [Section titled “getStatus”](#getstatus) Gets the current tracking authorization status without prompting the user. ```typescript import { AppTrackingTransparency } from '@capgo/capacitor-app-tracking-transparency'; const { status } = await AppTrackingTransparency.getStatus(); if (status === 'authorized') { console.log('Tracking is authorized'); } ``` ### `requestPermission` [Section titled “requestPermission”](#requestpermission) Requests user authorization to access app-related data for tracking. Displays the native iOS tracking permission dialog. Note: This method will only show the dialog once. Subsequent calls will return the stored authorization status without showing the dialog. ```typescript import { AppTrackingTransparency } from '@capgo/capacitor-app-tracking-transparency'; const { status } = await AppTrackingTransparency.requestPermission(); switch (status) { case 'authorized': console.log('User authorized tracking'); break; case 'denied': console.log('User denied tracking'); break; case 'restricted': console.log('Tracking is restricted'); break; case 'notDetermined': console.log('Status not determined'); break; } ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `AppTrackingStatusResponse` [Section titled “AppTrackingStatusResponse”](#apptrackingstatusresponse) Response object containing the tracking authorization status. ```typescript export interface AppTrackingStatusResponse { /** * The current tracking authorization status. * * @since 1.0.0 */ status: AppTrackingStatus; } ``` ### `AppTrackingStatus` [Section titled “AppTrackingStatus”](#apptrackingstatus) Possible values for the tracking authorization status. ```typescript export type AppTrackingStatus = 'authorized' | 'denied' | 'notDetermined' | 'restricted'; ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-app-tracking-transparency](/plugins/capacitor-app-tracking-transparency/) for the native capability in Using @capgo/capacitor-app-tracking-transparency, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-appinsights > A wrapper around the https://github.com/apptopia/appinsights SDK. ## Overview [Section titled “Overview”](#overview) A wrapper around the SDK. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `init` - Initialize the AppInsights SDK. * `setUserId` - Set or update the user ID after initialization. * `getState` - Get the current state of the SDK. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ------------------ | ----------------------------------------------- | | `init` | Initialize the AppInsights SDK. | | `setUserId` | Set or update the user ID after initialization. | | `getState` | Get the current state of the SDK. | | `getPluginVersion` | Get the native Capacitor plugin version. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-appinsights](https://github.com/Cap-go/capacitor-appinsights/). ## Keep going from @capgo/capacitor-appinsights [Section titled “Keep going from @capgo/capacitor-appinsights”](#keep-going-from-capgocapacitor-appinsights) If you are using **@capgo/capacitor-appinsights** to plan native plugin work, connect it with [Using @capgo/capacitor-appinsights](/plugins/capacitor-appinsights/) for the native capability in Using @capgo/capacitor-appinsights, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-appinsights and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-appinsights` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-appinsights bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { CapacitorAppInsights } from '@capgo/capacitor-appinsights'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `init` [Section titled “init”](#init) Initialize the AppInsights SDK ```typescript import { CapacitorAppInsights } from '@capgo/capacitor-appinsights'; await CapacitorAppInsights.init({} as { partnerId: string; // Provided by our business unit partnerKey: string; // Provided by our business unit }); ``` ### `setUserId` [Section titled “setUserId”](#setuserid) Set or update the user ID after initialization ```typescript import { CapacitorAppInsights } from '@capgo/capacitor-appinsights'; await CapacitorAppInsights.setUserId({} as { userId: string }); ``` ### `getState` [Section titled “getState”](#getstate) Get the current state of the SDK ```typescript import { CapacitorAppInsights } from '@capgo/capacitor-appinsights'; await CapacitorAppInsights.getState(); ``` ## Type Reference [Section titled “Type Reference”](#type-reference) ### `PanelSDKState` [Section titled “PanelSDKState”](#panelsdkstate) ```typescript export interface PanelSDKState { initCompleted: boolean; // SDK initialization status jobScheduled: boolean; // Background job scheduling status permissionAcquired: boolean; // Required permissions status } ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-appinsights](/plugins/capacitor-appinsights/) for the native capability in Using @capgo/capacitor-appinsights, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-appsflyer > Capacitor plugin for AppsFlyer attribution, analytics, and deep links. ## Overview [Section titled “Overview”](#overview) Capacitor plugin for AppsFlyer attribution, analytics, and deep links. ## Core Capabilities [Section titled “Core Capabilities”](#core-capabilities) * `initSDK` - Use this method to initialize and start AppsFlyer SDK. This API should be called as soon as the app launched. * `startSDK` - Use this method to start AppsFlyer SDK, only on manual start mode. * `logEvent` - Log an in-app event. * `setCustomerUserId` - Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and other devices’ IDs. This ID is available in raw-data reports and in the Postback APIs for cross-referencing with your internal IDs. ## Public API [Section titled “Public API”](#public-api) | Method | Description | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `addListener('conversion_callback', listener)` | Listen for conversion callbacks, including `onConversionDataSuccess` and `onConversionDataFail`, with `OnConversionDataResult` payloads. | | `addListener('oaoa_callback', listener)` | Listen for app-open attribution callbacks, including `onAppOpenAttribution` and `onAttributionFailure`, with `OnAppOpenAttribution` payloads. | | `addListener('udl_callback', listener)` | Listen for unified deep link callbacks with `OnDeepLink` payloads. | | `initSDK` | Use this method to initialize and start AppsFlyer SDK. This API should be called as soon as the app launched. | | `startSDK` | Use this method to start AppsFlyer SDK, only on manual start mode. | | `logEvent` | Log an in-app event. | | `setCustomerUserId` | Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and other devices’ IDs. This ID is available in raw-data reports and in the Postback APIs for cross-referencing with your internal IDs. | | `setCurrencyCode` | Sets the currency used for in-app purchases. Provide a three-character ISO 4217 code. | | `updateServerUninstallToken` | Pass GCM/FCM tokens on Android or APNs tokens on iOS when another plugin collected them. Use this to forward uninstall measurement tokens to AppsFlyer. | | `setAppInviteOneLink` | Sets the OneLink ID used as the base link for invite attribution. | | `setOneLinkCustomDomain` | Registers branded OneLink domains so AppsFlyer can resolve attribution parameters hidden in short links. | | `appendParametersToDeepLinkingURL` | Enables attribution for App Links deep links without OneLink. Call this method before `startSDK()`. Include at least `pid` and `is_retargeting=true` in the parameters map. | | `setResolveDeepLinkURLs` | Use this when an AppsFlyer OneLink is wrapped inside another Universal Link. It lets the SDK resolve the wrapped URL so deep linking still works correctly. | | `addPushNotificationDeepLinkPath` | Configures how the SDK extracts deep link values from push notification payloads. | | `setSharingFilter` | Stops events from propagating to the specified AppsFlyer partners. | | `setSharingFilterForAllPartners` | Stops events from propagating to all AppsFlyer partners. Overwrites setSharingFilter. | | `setSharingFilterForPartners` | Stops events from propagating to the specified AppsFlyer partners. | | `setAdditionalData` | Sets additional key-value data to send to AppsFlyer. | | `getAppsFlyerUID` | Get AppsFlyer’s unique device ID (created for every new install of an app). | | `anonymizeUser` | End User Opt-Out from AppsFlyer analytics (Anonymize user data). | | `stop` | Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. Useful when implementing user opt-in/opt-out. | | `disableSKAdNetwork` | Opt-out of SKAdNetwork. | | `disableAdvertisingIdentifier` | Disables collection of various Advertising IDs by the SDK. This includes Apple Identity for Advertisers (IDFA), Google Advertising ID (GAID), OAID and Amazon Advertising ID (AAID). | | `disableCollectASA` | Opt-out of Apple Search Ads attributions. | | `setHost` | Set a custom host. | | `generateInviteLink` | Allowing your existing users to invite their friends and contacts as new users to your app. | | `validateAndLogInAppPurchaseAndroid` | API for server verification of in-app purchases. An af\_purchase event with the relevant values will be automatically logged if the validation is successful. | | `validateAndLogInAppPurchaseIos` | See the source definitions for current behavior. | | `getSdkVersion` | Get the AppsFlyer SDK version used in app. | | `enableFacebookDeferredApplinks` | Enable the collection of Facebook Deferred AppLinks. Requires Facebook SDK and Facebook app on target/client device. This API must be invoked before initializing the AppsFlyer SDK in order to function properly. | | `sendPushNotificationData` | Measure and get data from push-notification campaigns. | | `setCurrentDeviceLanguage` | Set the language of the device. The data will be displayed in Raw Data Reports. | | `logCrossPromoteImpression` | Logs an impression as part of a cross-promotion campaign. Make sure to use the promoted app ID as it appears in the AppsFlyer dashboard. | | `setUserEmails` | Set the user emails and encrypt them. | | `logLocation` | Manually log the location of the user. | | `setPhoneNumber` | Will be sent as an SHA-256 encrypted string. | | `setPartnerData` | Allows sending custom data for partner integration purposes. | | `logInvite` | Use to log a user-invite in-app event (af\_invite). | | `setDisableNetworkData` | Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device. | | `enableTCFDataCollection` | Use to opt-in/out the automatic collection of consent data, for users who use a CMP. Flag value will be persisted between app sessions. | | `setConsentData` | Use this to set user consent data manually. If your app doesn’t use a CMP compatible with TCF v2.2, use the following method to manually provide the consent data directly to the SDK. | | `logAdRevenue` | By attributing ad revenue, app owners gain the complete view of user LTV and campaign ROI. Ad revenue is generated by displaying ads on rewarded videos, offer walls, interstitials, and banners in an app. You can use this method to log your ad revenue. | | `setConsentDataV2` | Use this to set user consent data manually. If your app doesn’t use a CMP compatible with TCF v2.2, use the following method to manually provide the consent data directly to the SDK. | | `isSDKStarted` | Use this method to check whether the AppsFlyer SDK has already been started in the current session. | | `isSDKStopped` | Use this method to check whether the AppsFlyer SDK is currently stopped. | | `disableAppSetId` | Disables AppSet ID collection. If called before SDK init, App Set ID will not be collected. If called after init, App Set ID will be collected but not sent in request payloads. Android only. | | `validateAndLogInAppPurchaseV2` | API for server verification of in-app purchases V2. An af\_purchase event with the relevant values will be automatically logged if the validation is successful. | ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This reference is synced from `src/definitions.ts` in [capacitor-appsflyer](https://github.com/Cap-go/capacitor-appsflyer/). ## Keep going from @capgo/capacitor-appsflyer [Section titled “Keep going from @capgo/capacitor-appsflyer”](#keep-going-from-capgocapacitor-appsflyer) If you are using **@capgo/capacitor-appsflyer** to plan native plugin work, connect it with [Using @capgo/capacitor-appsflyer](/plugins/capacitor-appsflyer/) for the native capability in Using @capgo/capacitor-appsflyer, [Capgo Plugin Directory](/plugins/) for the product workflow in Capgo Plugin Directory, [Capacitor Plugins by Capgo](/docs/plugins/) for the implementation detail in Capacitor Plugins by Capgo, [Adding or Updating Plugins](/docs/contributing/adding-plugins/) for the implementation detail in Adding or Updating Plugins, and [Ionic Enterprise Plugin Alternatives](/ionic-enterprise-plugins/) for the product workflow in Ionic Enterprise Plugin Alternatives. # Getting Started > Install @capgo/capacitor-appsflyer and start using its current Capacitor API. ## Install [Section titled “Install”](#install) You can use our AI-Assisted Setup to install the plugin. Add the Capgo skills to your AI tool using the following command: ```bash npx skills add https://github.com/Cap-go/capgo-skills --skill capacitor-plugins ``` Then use the following prompt: ```text Use the `capacitor-plugins` skill from `Cap-go/capgo-skills` to install the `@capgo/capacitor-appsflyer` plugin in my project. ``` If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below: ```bash bun add @capgo/capacitor-appsflyer bunx cap sync ``` ## Import [Section titled “Import”](#import) ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; import type { AFAdRevenueData, AFAndroidInAppPurchase, AFAnonymizeUser, AFAppendToDeepLink, AFConsentData, AFConsentOptions, AFCuid, AFCurrency, AFData, AFDisable, AFEmails, AFEnableTCFDataCollection, AFEvent, AFFbDAL, AFFilters, AFHost, AFInit, AFIosInAppPurchase, AFLanguage, AFLatLng, AFLinkGenerator, AFLogInvite, AFOnelinkDomain, AFOnelinkID, AFPartnerData, AFPath, AFPhone, AFPromotion, AFPurchaseDetailsV2, AFPushPayload, AFUninstall, AFUrls, } from '@capgo/capacitor-appsflyer'; ``` ## API Overview [Section titled “API Overview”](#api-overview) ### `initSDK` [Section titled “initSDK”](#initsdk) Use this method to initialize and start AppsFlyer SDK. This API should be called as soon as the app launches. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.initSDK({} as AFInit); ``` ### `startSDK` [Section titled “startSDK”](#startsdk) Use this method to start AppsFlyer SDK, only on manual start mode. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.startSDK(); ``` ### `logEvent` [Section titled “logEvent”](#logevent) Log an in-app event. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.logEvent({} as AFEvent); ``` ### `setCustomerUserId` [Section titled “setCustomerUserId”](#setcustomeruserid) Setting your own customer ID enables you to cross-reference your own unique ID with AppsFlyer’s unique ID and other devices’ IDs. This ID is available in raw-data reports and in the Postback APIs for cross-referencing with your internal IDs. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setCustomerUserId({} as AFCuid); ``` ### `setCurrencyCode` [Section titled “setCurrencyCode”](#setcurrencycode) Sets the currency used for in-app purchases. Provide a three-character ISO 4217 code. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setCurrencyCode({} as AFCurrency); ``` ### `updateServerUninstallToken` [Section titled “updateServerUninstallToken”](#updateserveruninstalltoken) Pass GCM/FCM tokens on Android or APNs tokens on iOS when another plugin collected them. Use this to forward uninstall measurement tokens to AppsFlyer. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.updateServerUninstallToken({} as AFUninstall); ``` ### `setAppInviteOneLink` [Section titled “setAppInviteOneLink”](#setappinviteonelink) Sets the OneLink ID used as the base link for invite attribution. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setAppInviteOneLink({} as AFOnelinkID); ``` ### `setOneLinkCustomDomain` [Section titled “setOneLinkCustomDomain”](#setonelinkcustomdomain) Registers branded OneLink domains so AppsFlyer can resolve attribution parameters hidden in short links. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setOneLinkCustomDomain({} as AFOnelinkDomain); ``` ### `appendParametersToDeepLinkingURL` [Section titled “appendParametersToDeepLinkingURL”](#appendparameterstodeeplinkingurl) Enables attribution for App Links deep links without OneLink. Call this method before `startSDK()`. Include at least `pid` and `is_retargeting=true` in the parameters map. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.appendParametersToDeepLinkingURL({} as AFAppendToDeepLink); ``` ### `setResolveDeepLinkURLs` [Section titled “setResolveDeepLinkURLs”](#setresolvedeeplinkurls) Use this when an AppsFlyer OneLink is wrapped inside another Universal Link. It lets the SDK resolve the wrapped URL so deep linking still works correctly. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setResolveDeepLinkURLs({} as AFUrls); ``` ### `addPushNotificationDeepLinkPath` [Section titled “addPushNotificationDeepLinkPath”](#addpushnotificationdeeplinkpath) Configures how the SDK extracts deep link values from push notification payloads. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.addPushNotificationDeepLinkPath({} as AFPath); ``` ### `setSharingFilter` [Section titled “setSharingFilter”](#setsharingfilter) Stops events from propagating to the specified AppsFlyer partners. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setSharingFilter({} as AFFilters); ``` ### `setSharingFilterForAllPartners` [Section titled “setSharingFilterForAllPartners”](#setsharingfilterforallpartners) Stops events from propagating to all AppsFlyer partners. Overwrites setSharingFilter. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setSharingFilterForAllPartners(); ``` ### `setSharingFilterForPartners` [Section titled “setSharingFilterForPartners”](#setsharingfilterforpartners) Stops events from propagating to the specified AppsFlyer partners. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setSharingFilterForPartners({} as AFFilters); ``` ### `setAdditionalData` [Section titled “setAdditionalData”](#setadditionaldata) Sets additional key-value data to send to AppsFlyer. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setAdditionalData({} as AFData); ``` ### `getAppsFlyerUID` [Section titled “getAppsFlyerUID”](#getappsflyeruid) Get AppsFlyer’s unique device ID (created for every new install of an app). ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.getAppsFlyerUID(); ``` ### `anonymizeUser` [Section titled “anonymizeUser”](#anonymizeuser) End User Opt-Out from AppsFlyer analytics (Anonymize user data). ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.anonymizeUser({} as AFAnonymizeUser); ``` ### `stop` [Section titled “stop”](#stop) Once this API is invoked, our SDK no longer communicates with our servers and stops functioning. Useful when implementing user opt-in/opt-out. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.stop(); ``` ### `disableSKAdNetwork` [Section titled “disableSKAdNetwork”](#disableskadnetwork) Opt-out of SKAdNetwork ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.disableSKAdNetwork({} as AFDisable); ``` ### `disableAdvertisingIdentifier` [Section titled “disableAdvertisingIdentifier”](#disableadvertisingidentifier) Disables collection of various Advertising IDs by the SDK. This includes Apple Identity for Advertisers (IDFA), Google Advertising ID (GAID), OAID and Amazon Advertising ID (AAID). ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.disableAdvertisingIdentifier({} as AFDisable); ``` ### `disableCollectASA` [Section titled “disableCollectASA”](#disablecollectasa) Opt-out of Apple Search Ads attributions. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.disableCollectASA({} as AFDisable); ``` ### `setHost` [Section titled “setHost”](#sethost) Set a custom host. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setHost({} as AFHost); ``` ### `generateInviteLink` [Section titled “generateInviteLink”](#generateinvitelink) Allowing your existing users to invite their friends and contacts as new users to your app ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.generateInviteLink({} as AFLinkGenerator); ``` ### `validateAndLogInAppPurchaseAndroid` [Section titled “validateAndLogInAppPurchaseAndroid”](#validateandloginapppurchaseandroid) API for server verification of in-app purchases. An af\_purchase event with the relevant values will be automatically logged if the validation is successful. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.validateAndLogInAppPurchaseAndroid({} as AFAndroidInAppPurchase); ``` ### `validateAndLogInAppPurchaseIos` [Section titled “validateAndLogInAppPurchaseIos”](#validateandloginapppurchaseios) See the source definitions for the current contract. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.validateAndLogInAppPurchaseIos({} as AFIosInAppPurchase); ``` ### `getSdkVersion` [Section titled “getSdkVersion”](#getsdkversion) Get the AppsFlyer SDK version used in app. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.getSdkVersion(); ``` ### `enableFacebookDeferredApplinks` [Section titled “enableFacebookDeferredApplinks”](#enablefacebookdeferredapplinks) Enable the collection of Facebook Deferred AppLinks. Requires Facebook SDK and Facebook app on target/client device. This API must be invoked before initializing the AppsFlyer SDK in order to function properly. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.enableFacebookDeferredApplinks({} as AFFbDAL); ``` ### `sendPushNotificationData` [Section titled “sendPushNotificationData”](#sendpushnotificationdata) Measure and get data from push-notification campaigns. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.sendPushNotificationData({} as AFPushPayload); ``` ### `setCurrentDeviceLanguage` [Section titled “setCurrentDeviceLanguage”](#setcurrentdevicelanguage) Set the language of the device. The data will be displayed in Raw Data Reports ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setCurrentDeviceLanguage({} as AFLanguage); ``` ### `logCrossPromoteImpression` [Section titled “logCrossPromoteImpression”](#logcrosspromoteimpression) Logs an impression as part of a cross-promotion campaign. Make sure to use the promoted app ID as it appears in the AppsFlyer dashboard. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.logCrossPromoteImpression({} as AFPromotion); ``` ### `setUserEmails` [Section titled “setUserEmails”](#setuseremails) Set the user emails and encrypt them. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setUserEmails({} as AFEmails); ``` ### `logLocation` [Section titled “logLocation”](#loglocation) Manually log the location of the user ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.logLocation({} as AFLatLng); ``` ### `setPhoneNumber` [Section titled “setPhoneNumber”](#setphonenumber) Will be sent as an SHA-256 encrypted string. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setPhoneNumber({} as AFPhone); ``` ### `setPartnerData` [Section titled “setPartnerData”](#setpartnerdata) Allows sending custom data for partner integration purposes. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setPartnerData({} as AFPartnerData); ``` ### `logInvite` [Section titled “logInvite”](#loginvite) Use to log a user-invite in-app event (af\_invite). ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.logInvite({} as AFLogInvite); ``` ### `setDisableNetworkData` [Section titled “setDisableNetworkData”](#setdisablenetworkdata) Use to opt-out of collecting the network operator name (carrier) and sim operator name from the device. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setDisableNetworkData({} as AFDisable); ``` ### `enableTCFDataCollection` [Section titled “enableTCFDataCollection”](#enabletcfdatacollection) Use to opt-in/out the automatic collection of consent data, for users who use a CMP. Flag value will be persisted between app sessions. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.enableTCFDataCollection({} as AFEnableTCFDataCollection); ``` ### `setConsentData` [Section titled “setConsentData”](#setconsentdata) Use this to set user consent data manually. If your app doesn’t use a CMP compatible with TCF v2.2, use the following method to manually provide the consent data directly to the SDK. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setConsentData({} as AFConsentData); ``` ### `logAdRevenue` [Section titled “logAdRevenue”](#logadrevenue) By attributing ad revenue, app owners gain the complete view of user LTV and campaign ROI. Ad revenue is generated by displaying ads on rewarded videos, offer walls, interstitials, and banners in an app. You can use this method to log your ad revenue. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.logAdRevenue({} as AFAdRevenueData); ``` ### `setConsentDataV2` [Section titled “setConsentDataV2”](#setconsentdatav2) Use this to set user consent data manually. If your app doesn’t use a CMP compatible with TCF v2.2, use the following method to manually provide the consent data directly to the SDK. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.setConsentDataV2({} as AFConsentOptions); ``` ### `isSDKStarted` [Section titled “isSDKStarted”](#issdkstarted) Use this method to check whether the AppsFlyer SDK has already been started in the current session. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.isSDKStarted(); ``` ### `isSDKStopped` [Section titled “isSDKStopped”](#issdkstopped) Use this method to check whether the AppsFlyer SDK is currently stopped. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.isSDKStopped(); ``` ### `disableAppSetId` [Section titled “disableAppSetId”](#disableappsetid) Disables AppSet ID collection. If called before SDK init, App Set ID will not be collected. If called after init, App Set ID will be collected but not sent in request payloads. Android only. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.disableAppSetId(); ``` ### `validateAndLogInAppPurchaseV2` [Section titled “validateAndLogInAppPurchaseV2”](#validateandloginapppurchasev2) API for server verification of in-app purchases V2. An af\_purchase event with the relevant values will be automatically logged if the validation is successful. ```typescript import { AppsFlyer } from '@capgo/capacitor-appsflyer'; await AppsFlyer.validateAndLogInAppPurchaseV2({} as AFPurchaseDetailsV2); ``` ## Source Of Truth [Section titled “Source Of Truth”](#source-of-truth) This page is generated from the plugin’s `src/definitions.ts`. Re-run the sync when the public API changes upstream. ## Keep going from Getting Started [Section titled “Keep going from Getting Started”](#keep-going-from-getting-started) If you are using **Getting Started** to plan dashboard and API operations, connect it with [Using @capgo/capacitor-appsflyer](/plugins/capacitor-appsflyer/) for the native capability in Using @capgo/capacitor-appsflyer, [API Overview](/docs/public-api/) for the implementation detail in API Overview, [Introduction](/docs/webapp/) for the implementation detail in Introduction, [API Keys](/docs/public-api/api-keys/) for the implementation detail in API Keys, and [Devices](/docs/public-api/devices/) for the implementation detail in Devices. # @capgo/capacitor-asset-cache > Cache heavy CDN media in app-owned persistent storage and bind images or videos to local webview URLs. Local-only display sources `src`, `resolve`, and `bind` return a source only after a local file exists. Your img or video tag receives a local webview URL. Persistent native storage Cached assets live in app-owned persistent storage, not the platform cache folder that the system may evict under pressure. Protected CDN support Pass headers to the native fetch for signed or authenticated assets while the web element still loads only the local file. Framework-friendly binding Bind native cache resolution to plain HTML, React refs, Vue refs, or any framework that can assign an img or video src. ## Overview [Section titled “Overview”](#overview) `@capgo/capacitor-asset-cache` caches large images, videos, and other CDN assets in app-owned persistent storage, then gives the web app a local source URL for display. The normal path is: 1. Configure a CDN base URL once, or pass an absolute URL per asset. 2. Call `AssetCache.bind(element, path)` or `AssetCache.src(path)`. 3. The plugin fetches or revalidates the remote asset natively. 4. The element receives a local webview URL only after the local file is ready. Note Successful display APIs are local-only. If the plugin cannot create or reuse a local file, `src(...)` and `resolve(...)` reject and `bind(...)` marks the element as `error`. ## When To Use It [Section titled “When To Use It”](#when-to-use-it) Use Asset Cache when your app displays heavy remote media that should survive normal storage pressure: * onboarding or marketing videos served from a CDN * hero images, galleries, or image sequences reused across sessions * protected media that requires request headers * offline-tolerant screens where a previously fetched local asset is enough * Capacitor apps where `` and `