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

@otaupdate/cli

v2.1.1

Published

CLI for publishing React Native over-the-air updates

Downloads

907

Readme

ota — CLI

Publish and manage React Native over-the-air updates.

npm install -g @otaupdate/cli     # or prefix any command with: npx @otaupdate/cli …

The whole workflow

ota login          # once per machine
ota init           # once per app
npm run ota:prod   # every time you ship

ota init writes ota.config.js and the ota:* npm scripts, so no day-to-day command takes an app name, a key, a platform or a version — they are read from the config, your app version and your git state.

Authenticate

ota login                                  # email + password, then the 6-digit code
ota login --api-key ota_xxx                # CI / scripting — no 2FA prompt
ota whoami
ota logout

Credentials are written to ~/.ota/config.json (mode 0600). The CLI already knows which server to talk to; --server is only for an internal deployment.

In CI, skip login entirely and set one secret:

export OTA_API_KEY=ota_xxx

Named profiles keep two accounts or organizations apart:

ota login --api-key ota_prod --profile prod
ota status --profile prod

Connect an app

ota init                       # detects the stack, creates the project, prints the keys
ota init --project my-app      # or attach to a project that already exists
ota init --org <orgId> --yes   # non-interactive (an organization id, not a slug)

It leaves behind:

  • ota.config.js — project slug, platforms, runtime-version policy. Committed; it holds no secrets.
  • npm scripts — ota:staging, ota:prod, ota:prod:mandatory, ota:promote, ota:rollback, ota:doctor. An existing script of yours is never overwritten; ours is added as <name>:ota instead.
  • One SDK key per channel (production, staging), printed once and readable again from the dashboard. That key goes into your native build — see the SDK README.

Re-running ota init repairs the config and scripts rather than creating a second project.

Releasing

npm run ota:staging                                       # ota release --channel staging
npm run ota:prod                                          # ota release --channel production
ota release --channel production --rollout 20 -m "Fix checkout crash"

It detects Expo vs bare React Native, runs the right bundler (expo export:embed or react-native bundle) for each configured platform, zips the output with its assets, and uploads it. The release note, commit, branch, author and CI run URL are captured automatically.

| Flag | Default | Meaning | |---|---|---| | -c, --channel <name> | staging | Channel to publish to | | -p, --platform <os> | both | Limit to android or ios | | -m, --message <text> | last commit subject | Release note | | -r, --rollout <pct> | 100 | Percentage of devices served, 1–100 | | --mandatory | off | Devices install before continuing | | --runtime-version <v> | your app version | Which native builds this bundle targets | | --allow-dirty | off | Publish with uncommitted changes | | --allow-duplicate | off | Publish even if byte-identical to the current release |

The runtime version is the native app version the bundle is compatible with. Devices on other binary versions never receive the release — the most common cause of "I published but nothing happened".

A dirty working tree is refused by default: a bundle built from uncommitted code exists on no branch, so nobody can reproduce what shipped.

Operating a release

ota status                                        # the last ten releases and what each is doing
ota promote --from staging --to production        # same bytes, no rebuild, no upload
ota rollback --channel production                 # both platforms
ota rollback --channel production --platform ios  # one platform
ota rollback --channel production --to 11         # back to a release you name
ota doctor                                        # why isn't my update arriving?

rollback republishes an earlier bundle as a new release at 100% and stops serving the bad one, so devices already running the bad build get the fix on their next check. Without --to it goes back one release; --to <number> restores the release you name, including one that was itself rolled back. The dashboard has the same picker on the channel page.

A published release's rollout percentage is fixed. To widen it, publish again at the higher percentage or promote from another channel.

doctor checks the environment, the project and its bundle identifiers, the git state and the scripts, and names the fix for each failure. It exits non-zero when something is broken.

Keys and members

ota api-key create github-actions       # shown once
ota api-key list
ota api-key revoke <id>

ota member list
ota member add [email protected] developer --initial-password 'temp-pass-123'
ota member role [email protected] admin
ota member rm [email protected]

ota org list
ota org add "Acme"                      # user session only, not an API key

API keys are scoped to one organization and cannot manage other keys or members — that needs a user session.

Scripting

Every command supports --format json:

ota status --format json | jq -r '.releases[0].release_number'

Errors print as JSON in that mode too, with a stable code to branch on (FREE_PLAN_RELEASE_LIMIT_REACHED, PLAN_APP_LIMIT_REACHED, SUBSCRIPTION_PAST_DUE, …) and a details.upgradeUrl where relevant. The exit code is non-zero.

GitHub Actions

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
  with:
    node-version: 20
- run: npm ci
- run: npx @otaupdate/cli release --channel production --rollout 10 --format json
  env:
    OTA_API_KEY: ${{ secrets.OTA_API_KEY }}

Nothing else is needed: ota.config.js is in the repo, and the commit, branch and run URL are read from the CI environment (GitHub Actions, GitLab CI and Bitrise are recognised).

Global flags

| Flag | Environment variable | Meaning | |---|---|---| | --api-key <key> | OTA_API_KEY | Authenticate one command with a key | | --server <url> | OTA_SERVER_URL | Point at a non-default server | | --profile <name> | — | Use a named credential profile | | --format <human\|json> | — | Output format | | — | OTA_DEBUG=1 | Print stack traces on failure |

Upgrading from 1.x

ota app …, ota deployment … and the old ota release <app> <bundle> were removed in 2.0.0, along with the API they called. Run ota init once per app to create the project, then use the commands above.