npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

capgo-update-lite-cli

v0.6.0

Published

CLI for publishing Capacitor bundles to a capgo-update-lite OTA server.

Readme

capgo-update-lite-cli

CLI for publishing Capacitor OTA bundles to a capgo-update-lite server, plus admin commands to inspect apps, bundles, and client telemetry.

It runs a full set of preflight checks before touching the server: semver sanity, package.json alignment, capacitor.config match, server reachability, duplicate/downgrade detection, notifyAppReady() source scan, dist-dir validation, and zip size/integrity.

Install-free usage

pnpx capgo-update-lite-cli <subcommand> [...args]
# or
npx capgo-update-lite-cli <subcommand> [...args]

The package name on npm is capgo-update-lite-cli. If you install it globally, the installed binary is capgo-update-lite.

Quick start

# 1. scaffold a config file in your Capacitor project root
pnpx capgo-update-lite-cli init

# 2. set the admin token once per shell
export CAPGO_ADMIN_TOKEN=<bearer-token>

# 3. register the app (one-time)
pnpx capgo-update-lite-cli apps add com.example.app --name "Example"

# 4. publish a bundle (version sourced from package.json)
pnpx capgo-update-lite-cli publish

With a capgo-update.config.json in place, the only thing the publish flow needs at runtime is the admin token (env). The bundle version is read from package.json; if it matches the active bundle on the channel, the CLI prompts for a patch/minor/major bump and writes the result back.

Shell completions

The CLI ships a complete <shell> subcommand that emits a tab-completion script for bash, zsh, fish, and powershell. The init wizard offers to install completions automatically; to install or re-install manually:

# bash
echo 'eval "$(capgo-update-lite complete bash)"' >> ~/.bashrc

# zsh
echo 'eval "$(capgo-update-lite complete zsh)"' >> ~/.zshrc

# fish
capgo-update-lite complete fish > ~/.config/fish/completions/capgo-update-lite.fish

# powershell
capgo-update-lite complete powershell >> $PROFILE

What gets completed:

  • Static enums--platforms, --platform, --state, --disable-auto-update.
  • App IDs--app / --app-id (and the positional on apps get / apps set-policy) hit GET /admin/apps.
  • Channels--channel enumerates distinct channels seen on the resolved app's bundles.
  • Bundle versions — the positional on bundles promote <version> lists state=active rows for the resolved (appId, channel) scope.

Dynamic completions need CAPGO_SERVER_URL + CAPGO_ADMIN_TOKEN available at TAB time (env or in capgo-update.config.json in the cwd). They use a 5-minute on-disk cache at ${XDG_CACHE_HOME:-~/.cache}/capgo-update-lite/; CLI write commands (apps add / set-policy, bundles delete / edit / promote, publish) invalidate the matching entries automatically. Each completion fetch has a 1.5 s timeout and falls back silently to "no completions" on any error — TAB never hangs the shell prompt.

Subcommands

Every subcommand inherits the three global flags (--server-url, --admin-token, --config). They also honour the matching CAPGO_* env vars and the keys in the config file.

publish

Zip a dist directory and upload it as a new bundle.

pnpx capgo-update-lite-cli publish [options]

The bundle version defaults to package.json's version field. If it matches the active bundle on the target channel, the CLI prompts for a patch/minor/major bump and writes the new value back to package.json before publishing. Pass --bundle-version (or set CAPGO_VERSION) to override.

Options specific to publish:

| Flag | Purpose | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | --app-id <id> | Reverse-domain app identifier (or set in config / CAPGO_APP_ID) | | --bundle-version <semver> | Bundle version (defaults to package.json version) | | --dist-dir <path> | Built web bundle directory (or set in config / CAPGO_DIST_DIR) | | -c, --channel <name> | Release channel (default production) | | -p, --platforms <list> | Comma-separated list of ios,android,electron | | --link <url> | Release notes / changelog URL | | --comment <text> | Operator-authored note | | --activate / --no-activate | Activate on commit (default: activate) | | --dry-run | Run preflight and build the zip, skip all server writes | | --skip-preflight | Bypass preflight checks (escape hatch) | | --no-code-check | Skip the notifyAppReady() source scan | | --version-exists-ok | Exit 0 if the version is already published (CI-friendly) | | --package-json <path> | Override auto-detection of package.json | | --capacitor-config <path> | Override auto-detection of capacitor.config.(ts\|js\|json) | | --min-android-build <semver> | Minimum native Android versionName required by this bundle | | --min-ios-build <semver> | Minimum native iOS CFBundleShortVersionString required by this bundle | | --auto-min-update-build | Inherit min builds from the previous bundle when native deps are unchanged; bump to detected native versions when they changed | | --android-project <path> | Path to Android project root (default ./android) | | --ios-project <path> | Path to iOS project root (default ./ios) |

init

Interactive wizard that scaffolds capgo-update.config.json in the current directory.

pnpx capgo-update-lite-cli init [--force] [--path <path>] \
  [--app-id <id>] [--server-url <url>] [--channel <name>] [--dist-dir <path>] \
  [--no-validate]

Prompts (each is skipped when the matching value is already provided via flag, env, or an existing config file):

  • App ID — reverse-domain identifier (com.example.app).
  • Server URL — public URL of your deployed worker.
  • Channel — defaults to production.
  • Dist directory — auto-detects ./build, ./dist, ./www, ./out, ./public in the cwd; each option's hint says whether it contains index.html. Falls back to a free-form path prompt if no candidates exist.

Then verifies the configuration against the server:

  • Asks for an admin token at a hidden password prompt. Leave empty to fall back to a public health check only — GET /health, no admin endpoints touched.
  • With a token: pings /health, then GET /admin/apps with the bearer token to verify auth. If your appId isn't registered yet, the wizard offers to register it inline (same path as apps add) — confirm + display-name prompt + POST /admin/apps. The display-name default is derived from the appId's last segment (com.example.member_appMember App), editable.
  • The token is used once and discarded; it is never written to capgo-update.config.json. If CAPGO_ADMIN_TOKEN (or --admin-token) is already set, the wizard reuses that and skips the password prompt.
  • Pass --no-validate to skip the verification step entirely (e.g. when scripting init in a context with no network access).

The template includes appId, serverUrl, channel, distDir, platforms (default ["ios", "android"]), and autoMinUpdateBuild: true. The admin token is intentionally absent — keep it in CAPGO_ADMIN_TOKEN.

apps list

List apps registered on the server.

pnpx capgo-update-lite-cli apps list [--json]

apps add

Register a new app.

pnpx capgo-update-lite-cli apps add <app-id> --name <display-name>

apps set-policy

Update an app's compatibility policy. Only the flags you pass are changed; omit a flag to leave that field untouched.

pnpx capgo-update-lite-cli apps set-policy <app-id> \
  [--name <display-name>] \
  [--disable-auto-update none|patch|minor|major] \
  [--disable-auto-update-under-native | --no-disable-auto-update-under-native] \
  [--min-plugin-version <semver>|null] \
  [--fail-min-devices <n>|null] \
  [--fail-warn-rate <0..1>|null] \
  [--fail-risk-rate <0..1>|null] \
  [--fail-rate-threshold <0..1>|null]

--min-plugin-version null clears the floor. Without --no-disable-auto-update-under-native the under-native guard stays at whatever value the server holds. The --fail-* flags override the broken-bundle severity ladder per-app — pass null to clear an override and fall back to env / server default. Order is enforced server-side: warn ≤ risk ≤ disable. Set --fail-rate-threshold 0 (or --fail-min-devices 0) to disable auto-disable for this app while keeping severity classification for the dashboard / bundles health.

bundles list

List bundles, optionally filtered.

pnpx capgo-update-lite-cli bundles list [--app <id>] [-c <channel>] [-s <state>] [--active | --no-active] [--json]

bundles delete

Delete a bundle. Soft-delete by default (row stays, marked deleted). Pass --purge to also remove the R2 object. Purge is unrecoverable.

pnpx capgo-update-lite-cli bundles delete <bundle-id> [--purge]

bundles promote

Activate an existing bundle for an (app, channel) pair, with no re-upload.

pnpx capgo-update-lite-cli bundles promote <version> --app <id> [-c <channel>]

Errors if zero or multiple bundles match the version on the channel.

bundles health

Show the broken-bundle severity ladder. Without an app-id, summarises every app that has at least one non-healthy bundle (most-urgent first). With an app-id, lists each bundle of that app classified into healthy | noisy | warning | at_risk | auto_disabled | manually_disabled, alongside the resolved per-app thresholds.

pnpx capgo-update-lite-cli bundles health [app-id] [--json]

bundles reactivate

Restore an auto-disabled (or manually-disabled) bundle: flips state=active + active=true, atomically deactivates siblings on the same channel, and stamps blacklist_reset_at = now() so previously-failed devices get another chance via the /updates blacklist gate.

pnpx capgo-update-lite-cli bundles reactivate <bundle-id>

stats

List recent client telemetry events.

pnpx capgo-update-lite-cli stats [--app <id>] [--action <name>] [--since <iso>] [--until <iso>] [--limit <n>] [--offset <n>] [--json]

Actions include update, set, and other events the plugin reports. --limit accepts 1..1000 (default 100).

probe

Send a synthetic POST /updates to smoke-test the server end-to-end from the client perspective.

pnpx capgo-update-lite-cli probe [--app <id>] [--platform ios|android|electron] [--current-version <semver>] [--device-id <uuid>] [-c <channel>]

Defaults to platform ios and current version 0.0.0 (which forces an update-available response if a bundle exists). When --app is absent, the command falls back to the config or reads appId out of capacitor.config.*.

Configuration layers

Every value resolves via four routes. Precedence, highest wins:

  1. CLI flag
  2. Environment variable (CAPGO_*)
  3. JSON config file (./capgo-update.config.json auto-loaded, or --config <path>)
  4. Built-in defaults (channel=production, activate=true, codeCheck=true)

For publish specifically, when --bundle-version / CAPGO_VERSION / version are all absent, the bundle version is sourced from package.json's version field. If that version matches the bundle currently active on the channel, the CLI prompts (Cancel / Increase patch version / Increase minor version / Increase major version) and writes the bumped value back to package.json before publishing. In non-interactive contexts (no TTY, e.g. CI), the prompt is replaced by a hard fail — bump package.json ahead of time or pass --bundle-version / --version-exists-ok explicitly.

The admin token follows the same three-route rule. Prefer the environment variable:

  • --admin-token on the command line is visible in ps output.
  • "adminToken" in the config file is fine if the file is gitignored.
  • CAPGO_ADMIN_TOKEN is the safest default.

Config file example

Drop capgo-update.config.json in the directory where you run the CLI (typically your mobile app's project root). The CLI auto-loads it; pass --config <path> to point at a different file.

{
    "appId": "com.example.app",
    "serverUrl": "https://ota.example.com",
    "distDir": "./build",
    "channel": "production",
    "platforms": ["ios", "android"],
    "activate": true
}

With the config file present and CAPGO_ADMIN_TOKEN exported, publish shortens to:

pnpx capgo-update-lite-cli publish

The bundle version is sourced from package.json automatically; the bump prompt handles the case where it matches the active bundle.

Full option reference

Rows marked "publish-only" are only read by the publish subcommand. Everything else is global.

| CLI flag | Env var | Config key | Scope | Notes | | ------------------------------ | ----------------------------- | -------------------- | ------------ | -------------------------------------------------------------------------------------------------------------- | | --server-url <url> | CAPGO_SERVER_URL | serverUrl | global | OTA server base URL | | --admin-token <token> | CAPGO_ADMIN_TOKEN | adminToken | global | Bearer token for /admin/* | | --config <path> | CAPGO_CONFIG | n/a | global | JSON config path | | --app-id <id> | CAPGO_APP_ID | appId | publish-only | Reverse-domain app identifier | | --bundle-version <semver> | CAPGO_VERSION | version | publish-only | Bundle version. Defaults to package.json version. Named to avoid commander's reserved root --version flag. | | --dist-dir <path> | CAPGO_DIST_DIR | distDir | publish-only | Built web bundle directory (must contain index.html) | | -c, --channel <name> | CAPGO_CHANNEL | channel | most | Default production | | -p, --platforms <list> | CAPGO_PLATFORMS | platforms | publish-only | ios,android,electron (comma-separated on CLI and env) | | --link <url> | CAPGO_LINK | link | publish-only | Release notes / changelog URL | | --comment <text> | CAPGO_COMMENT | comment | publish-only | Operator-authored note | | --activate / --no-activate | CAPGO_ACTIVATE | activate | publish-only | Default true; env accepts true/false/1/0/yes/no/on/off | | --dry-run | CAPGO_DRY_RUN | dryRun | publish-only | Run preflight and zip, skip all server writes | | --skip-preflight | CAPGO_SKIP_PREFLIGHT | skipPreflight | publish-only | Bypass preflight checks | | --no-code-check | n/a | codeCheck | publish-only | Skip notifyAppReady() source scan (config key defaults to true) | | --version-exists-ok | n/a | n/a | publish-only | Exit 0 if the version is already published | | --package-json <path> | CAPGO_PACKAGE_JSON | packageJson | publish-only | Override auto-detection of package.json | | --capacitor-config <path> | CAPGO_CAPACITOR_CONFIG | capacitorConfig | publish-only | Override auto-detection of capacitor.config.(ts\|js\|json) | | --min-android-build <semver> | CAPGO_MIN_ANDROID_BUILD | minAndroidBuild | publish-only | Minimum native Android versionName required by this bundle | | --min-ios-build <semver> | CAPGO_MIN_IOS_BUILD | minIosBuild | publish-only | Minimum native iOS CFBundleShortVersionString required by this bundle | | --auto-min-update-build | CAPGO_AUTO_MIN_UPDATE_BUILD | autoMinUpdateBuild | publish-only | Inherit min builds from prev bundle if native deps unchanged; bump otherwise | | --android-project <path> | CAPGO_ANDROID_PROJECT | androidProject | publish-only | Native Android project root (default ./android) | | --ios-project <path> | CAPGO_IOS_PROJECT | iosProject | publish-only | Native iOS project root (default ./ios) | | -V, --version | n/a | n/a | global | Print CLI version | | -h, --help | n/a | n/a | global | Show help (supported on every subcommand) |

Preflight checks (publish only)

All of these can be bypassed with --skip-preflight. Checks that rely on local files auto-detect from the current working directory and silently skip if the file is absent.

  • Version autoresolve. When --bundle-version is absent, sources the version from package.json. Compares against the active bundle on the channel: newer ⇒ continue; older ⇒ fail (downgrade); equal + sourced ⇒ prompt for patch/minor/major bump and write back to package.json; equal + explicit ⇒ fail unless --version-exists-ok.
  • Version validity. The resolved version must parse as MAJOR[.MINOR[.PATCH]] (Apple's CFBundleShortVersionString rules — 110, 110.0, 1.2.3 are all accepted; missing segments default to 0).
  • package.json alignment. Bundle version must be >= the package.json version. Major bumps emit a warning so you can confirm the native shell supports the new bundle.
  • capacitor.config.(ts|js|json) alignment. Its appId must match the configured appId. The CapacitorUpdater.updateUrl, if set, should start with the server URL (warning only).
  • Native build resolution. Reads versionName from android/app/build.gradle(.kts) to default min_android_build. For iOS, walks Info.plist → project.pbxproj.xcconfigxcodebuild (macOS only) to resolve CFBundleShortVersionString, even when it's a $(MARKETING_VERSION) placeholder. Explicit --min-android-build / --min-ios-build override. Fails if neither explicit value nor a native project is available, with a layer-by-layer trace of what was tried.
  • Server ping. GET / with a 5s timeout.
  • App registered. GET /admin/apps must include the configured appId (requires an admin token).
  • Dist validation. distDir/index.html must exist. Cloudflare adapter artifacts (_worker.js, _routes.json) must not, which catches accidental web builds.
  • notifyAppReady() source scan. At least one .js file under distDir must reference notifyAppReady. Without that call the plugin rolls back after 10 seconds. Disable with --no-code-check if your build minifies the symbol away.
  • Zip integrity. The generated ZIP is re-parsed to verify structural validity.
  • Size bounds. Less than 1 KB fails (likely an empty build). Over 50 MB warns (slow on cellular). Over 500 MB fails.

Compatibility guards

Every uploaded bundle carries three pieces of native-compatibility metadata. The server uses them to decide whether a given device should receive the bundle:

  • min_android_build: minimum Android versionName the native shell must report.
  • min_ios_build: minimum iOS CFBundleShortVersionString the native shell must report.
  • native_packages: fingerprint of @capacitor/*, @capacitor-community/*, @ionic-enterprise/*, cordova-plugin-*, and capacitor-* / capacitor-plugin-* deps from package.json, with resolved versions at publish time.

If the device's version_build (what the plugin reports from the native project) is lower than the matching min_*_build, /updates returns below_min_native_build and the plugin keeps its current bundle.

How --auto-min-update-build decides

With --auto-min-update-build (or autoMinUpdateBuild: true in config), the CLI queries the previously-active bundle on (appId, channel) and compares its native_packages fingerprint with the current one:

  • Fingerprint unchanged: inherit min_android_build / min_ios_build from the previous bundle. No native shell reship needed.
  • Fingerprint changed (added, removed, or version-bumped native dep): set the min builds to the detected native versions (android/app/build.gradle and ios/App/App/Info.plist) and print which packages changed.
  • No previous bundle: use the detected native versions.

Per-app policies

The server also enforces three per-app policies stored on the apps row. Configure them via PATCH /admin/apps/<app-id>:

  • disable_auto_update: none (default), patch, minor, or major. Blocks auto-updates at or above the configured class.
  • disable_auto_update_under_native: boolean (default true). Refuses to serve a bundle whose semver is lower than the device's native version_build.
  • min_plugin_version: semver string or null. Devices running an older @capgo/capacitor-updater plugin are rejected with unsupported_plugin_version.

Publish flow

  1. Resolve config from CLI, env, and file.
  2. Run preflight.
  3. Zip <dist-dir> in memory with DEFLATE compression (cross-platform, no zip binary required).
  4. POST /admin/bundles/init, receive a presigned R2 URL.
  5. PUT the zip directly to R2.
  6. POST /admin/bundles/commit with { bundle_id, checksum, activate }.

On --dry-run, steps 4 through 6 are printed as a preview and skipped.

Exit codes

  • 0 on success, or when --version-exists-ok short-circuits a duplicate.
  • 1 on any error: missing config, preflight failure, non-2xx response, IO failure, and so on.