Model or dataset
Cap-go/capacitor-updater avatar
Cap-go/capacitor-updater

capacitor-updater: shipping JavaScript fixes past the app store review

Capacitor plugin for Instant updates: Ship updates, fixes, changes, and features within minutes

876 stars157 forksJavaMPL-2.0

At a glance

What is it?
Capacitor Updater is a Capacitor plugin that downloads and applies web asset bundles at runtime, so a JavaScript, HTML or CSS fix reaches installed apps without a store review. The interesting part is the safety machinery around that: a readiness signal that triggers rollback, delta updates, checksums and channels that can target a single device.
Who is it for?
Use capacitor-updater when your app is mostly web assets and you need to ship a JavaScript or CSS fix faster than a store review allows, because the plugin handles bundle download, application and rollback as one flow. Do not adopt it expecting to ship native code changes, since the mechanism replaces web assets only, and note that it changes your app's update model in ways your store agreement may care about.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is the review queue, not the download

The README states the motivation directly. App store review processes can take days or weeks, blocking critical bug fixes and updates from reaching your users, and Capacitor Updater solves that by pushing JavaScript, HTML and CSS updates directly to users without app store review. That framing matters because it tells you exactly what the plugin can and cannot do. A Capacitor app is a native shell around web assets, so the assets are the part that can be swapped at runtime. Native code cannot be, and the plugin does not pretend otherwise. The README positions the project as an open-source alternative to Appflow, Codepush and Capawesome, and the listed reasons are instant updates, delta updates, rollback protection, self-hosting, use in more than 3000 production apps, and being the most starred Capacitor plugin on GitHub.

notifyAppReady is the safety mechanism and the trap

Safe rollouts are built on one method. notifyAppReady() confirms that a bundle works, and otherwise the app rolls back to the last working one. That is a two-phase commit with a watchdog: the app starts the new bundle, and if the application signals that it came up healthy, the update is kept, while a bundle that never signals is replaced by the previous one. The mechanism is sound and it is also the thing most likely to be got wrong, because the call has to happen at a point where the app is genuinely healthy rather than merely started. An app that calls it too early, before the feature that the bundle contains has actually run, has disabled its own rollback. The failure mode of getting this wrong is silent, which is why a monitoring view of which bundles failed to signal readiness is worth more than the rollback itself.

Bundle control and channels

Two APIs cover the manual and the automatic paths. Bundle control gives you download(), next(), set(), list(), delete() and reset() for manual flows, so an application can drive the update itself rather than letting the plugin do it on a schedule. Channels give you setChannel(), getChannel() and listChannels() for environments and for per-device QA, and the README describes the use as setting the channel to a specific device to do QA or debug one user. That is the mechanism that makes a live-update system survivable: production users follow one channel, a tester follows another, and a single misbehaving device can be moved without affecting anybody else. The features list puts the same point more plainly, with channel support to manage different environments and auto update to download and set the latest bundle automatically.

Delta updates, checksums and optional encryption

Delta updates and security are grouped together in the key features list. Only changed files are downloaded, checksums are verified, and encryption is optional. The delta part is the difference between an update that is fast and one that is not, since a JavaScript bundle in a Capacitor app is often a large set of assets where a small change would otherwise mean re-downloading everything. The checksum on every update is what makes the channel and bundle mechanism trustworthy, because it is what tells the client that the bytes it received are the bytes the server intended. Encryption is optional rather than mandatory, which is an honest choice given that the payloads are web assets that often contain no secrets, and it means the deployment decision about whether to turn it on belongs to whoever operates the update endpoint rather than to the plugin.

Preview sessions for testing a bundle on a device

Preview sessions are the third API family and they exist because testing a live update without shipping it is otherwise awkward. startPreviewSession(), setPreview() and resetPreview() let you point a device at a bundle that no channel carries, try it, and then undo the experiment. Combined with per-device channels, you get two ways to isolate: a preview session for a temporary state, and a channel assignment for a durable one. The difference matters operationally. A channel is a routing rule that persists, so forgetting to move a device back off a test channel leaves it stranded. A preview session is a mode you enter and leave, so the reset is the normal end state rather than an exception. The README describes the feature as testing bundles on a device, which undersells how useful it is for anything beyond a smoke test.

A plugin with native code on both platforms

The package metadata shows what the plugin is made of. It publishes the Android source tree with its proguard rules and build.gradle, the iOS sources under ios/Sources/, a podspec named CapgoCapacitorUpdater and a Package.swift for Swift Package Manager, and the built JavaScript bundles. The entry points are the CommonJS build at dist/plugin.cjs.js, the ES module at dist/esm/index.js with its type declarations, and a standalone file at dist/plugin.js for unpkg. The JavaScript entry is thin, which is the point of the plugin architecture: the work happens in the native layer on each platform. The primary language field on the repository is Java, which reflects the Android side, while the iOS side is Swift. The verify script runs all three platforms, with xcodebuild for iOS, gradlew for Android and a bun build for the web.

Installing the plugin and wiring an agent to it

The plugin is published to npm as @capgo/capacitor-updater, with the package metadata recording version 8.53.0, the MPL-2.0 licence and the author as Martin Donadieu. The README also documents a path for teams that work with AI coding agents, which is unusual for a plugin of this kind. Capgo provides skills and a hosted MCP server so that coding agents can set up and operate Capacitor apps including this plugin. The skills are installed with a single command.

bash
npx skills add Cap-go/capgo-skills

The hosted MCP server lives at https://api.capgo.app/mcp, with its documentation on the Capgo site, and there are separate agent setup guides and a page on AI tools for Capacitor. The plugin also ships an api.md file at the repository root documenting its API surface, which is where to look for the full method list and their parameters. The point of the agent integration is that configuring a live-update channel and a readiness check is exactly the kind of multi-file, convention-dependent setup that an agent can be pointed at, and the hosted MCP server gives it a documented way to do that rather than guessing.

Where capacitor-updater is the wrong choice

Four limits apply. It only replaces web assets, so a bug in your Kotlin or Swift still waits for a store review, and a team whose pain is mostly native code will find this the wrong tool. The web target is a stub for development, so anything you build against the web platform behaviour is not what ships. It changes your app's update model, and the store rules on shipping executable content outside review vary by platform and by policy, so a plugin cannot make that question go away and a team that has not checked is taking on a policy risk that has nothing to do with the code. And the default configuration points at the vendor's cloud, which means the update path is infrastructure you do not control unless you self-host it, and the plugin's MPL-2.0 licence covers the code while the service terms cover the service, which are two different documents.

Editorial conclusion

Use capacitor-updater when your app is mostly web assets and you need to ship a JavaScript or CSS fix faster than a store review allows, because the plugin handles bundle download, application and rollback as one flow. Do not adopt it expecting to ship native code changes, since the mechanism replaces web assets only, and note that it changes your app's update model in ways your store agreement may care about. Verify first that your app meets the platform rules for shipping code outside review, that you have a channel strategy that isolates testing from production users, that notifyAppReady is actually called and monitored, since rollback depends on it, and whether you self-host the update endpoint, because the default configuration points at the vendor's cloud and the plugin's licence terms are separate from the service terms.

Frequently asked questions

What does the capacitor-updater plugin do?

It ships live updates to a Capacitor app by pushing JavaScript, HTML and CSS changes to users without waiting for app store review. The plugin downloads and applies the latest bundle from Capgo Cloud or from your own update server.

How does the rollback protection work?

notifyAppReady() confirms that a bundle works, and otherwise the app rolls back to the last working one. The app starts the new bundle and the update is kept only if the readiness call arrives, so the call has to be placed at a point where the app is genuinely healthy.

What are channels used for in capacitor-updater?

Channels manage different environments, and a channel can be set to a specific device for QA or for debugging one user. The API is setChannel(), getChannel() and listChannels(), so production users and testers can follow different bundles.

Which platforms does capacitor-updater support?

iOS and Android, with web a stub for development. The published package includes the Android sources with their build.gradle and proguard rules, the iOS sources, a podspec and a Package.swift.

Can I self-host the update server instead of using Capgo Cloud?

Yes. The README lists cloud and self-hosted support, with auto update downloading and applying the latest bundle from Capgo Cloud or from your own update server. The licence field on the repository says MPL-2.0 for the plugin code.

Official sources

  1. Cap-go/capacitor-updater on GitHub
  2. License: MPL-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cap-go-capacitor-updater.svg)](https://hysenlabs.com/projects/cap-go-capacitor-updater)

Was this useful?