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

@betadrop/cli

v0.4.0

Published

BetaDrop CLI — publish iOS/Android builds, check they will install, and manage links, devices and webhooks from your terminal or CI.

Readme

@betadrop/cli

npm version Node License: MIT

Ship a build to a tester in one command. betadrop publish app.ipa uploads an iOS .ipa or Android .apk to BetaDrop and prints an over-the-air install link plus a scannable QR code — no TestFlight review wait, no Play track, no tester accounts. Your tester opens the link on their phone and installs from the browser.

npm install -g @betadrop/cli
betadrop login
betadrop publish ./build/MyApp.ipa
Uploading MyApp.ipa…
  ████████████████████ 100% · 24.3/24.3 MB

✓ Published to BetaDrop

  MyApp  v1.2.0 (ios)
  Install link  https://betadrop.app/install/?i=abc123

  Scan with your phone:
  [compact QR code printed here]

Hand over the link, or hold up the QR code. That is the whole loop.

When this is the right tool

| Instead of | What changes | | --- | --- | | TestFlight external testing | No Beta App Review between your build and a tester's phone, and no TestFlight app or invite to accept. Ad-hoc signing rules still apply — see Troubleshooting. | | Play internal testing | No Play Console upload, no track, no tester list to keep in sync — you hand out a URL. | | Diawi / similar OTA services | Same idea, scriptable: one command, a QR code in your terminal, and a standing link that never changes. | | Firebase App Distribution | No Firebase project, no tester SDK, no invite acceptance — the link works in a plain mobile browser. |

Both platforms, one command, one account.


Quick Start

Get up and running in under 2 minutes.

Option A — Browser login (recommended)

betadrop login
# → Choose "Continue with Google" or "Continue with Email"
# → A browser tab opens — approve the request
# → A QR code is printed so you can open the approval page on your phone instead

Option B — API token

# 1. Create a token: betadrop.app → Settings → Developer → API tokens → Create token
# 2. Log in with the token
betadrop login --token bd_live_xxxxxxxxxxxxxxxxxxxx

# 3. Publish — the install link and QR code print instantly
betadrop publish ./build/MyApp.ipa

The install link and a scannable QR code are printed in the terminal after every successful betadrop publish. QR codes are suppressed in --ci and --json modes.

Commands

| Command | Description | |---------|-------------| | betadrop login | Authenticate interactively (browser or API token). Already logged in? You'll be asked what to do. | | betadrop login --token bd_live_… | Non-interactive token login. | | betadrop whoami | Show the authenticated user, active token name, expiry, and last-used date. --json for machine output. | | betadrop logout | Revoke the stored token server-side and remove local credentials. No-op when BETADROP_TOKEN is set — see Configuration. | | betadrop publish <file> | Upload an .ipa or .apk and print its install link + QR code. | | betadrop inspect <file> | Check a build will install from a link — provisioning profile type and expiry, signing, testOnly/debuggable — without publishing it. Exits 1 on a failing check. | | betadrop builds list · show <id> · delete <id…> · restore <id> | Build history and cleanup. list takes --platform, --status, --page, --per-page. | | betadrop links list · point <slug> <build-id> | Standing links: see what each serves, promote an already-uploaded build. | | betadrop devices list · export · invite | The iOS device registry. export writes the tab-separated file Apple's portal and fastlane register_devices take. | | betadrop feedback <build-id> | What testers reported on a build. --json to pipe it into an issue tracker. | | betadrop tokens list · create <name> · revoke <id> | API tokens. create --read-only mints one that can list and inspect but never publish. | | betadrop webhooks list · add <url> · test · deliveries · enable · disable · remove | Send build events to your own endpoint, Slack or Discord. |

Every read command takes --json.

Tip: You can use bd and betadrop interchangeably for all commands (e.g. betadrop login, betadrop publish).

betadrop publish options

| Flag | Description | |------|-------------| | --name <name> | Override the build name. | | --notes <notes> | Release notes for this build. | | --standing-link <slug> | Point a standing link at this build the moment it is live, so that one URL — and any "Download from BetaDrop" button embedded with it — serves the new build with nothing to click. Pro and Studio plans; the name must already be claimed on your account. A name that cannot be used fails the command before anything is uploaded. | | --channel <slug> | Deprecated alias for --standing-link, accepted permanently and hidden from --help. If both are given, --standing-link wins. | | --expires-in-days <n> | Stop the install link working after n days. Clamped to your plan's maximum, and the command says so when it is. | | --max-downloads <n> | Stop it after n downloads. | | --max-devices <n> | Stop it after n different devices. Combine any of these three and the link stops at whichever comes first. | | --no-expiry | Keep the link working until you delete the build (paid plans). | | --app-version <v> · --build-number <n> · --bundle-id <id> | Override what BetaDrop reads out of the file — useful when CI stamps the build number after packaging. | | --ci | Non-interactive: no spinner/progress/QR code; the install URL is the last line of stdout. With a standing link, the line above it is channel-url=<url> — that key is unchanged, because released GitHub Action versions parse it. | | --json | Output { id, short_id, install_url } as JSON (no QR code). With a standing link, adds channel: { id, slug, label, url } — the key keeps its old name so existing parsers keep working. |

If the build uploads but the standing link could not be moved (it was released mid-publish, say), the install URL is still printed, a warning: goes to stderr, and the command exits non-zero — a pipeline that asked for one must not go green when it did not move.

One link that never changes

Every publish mints a new install link, which means re-sending it to everyone. A standing link is a fixed URL you re-point at each new build:

betadrop publish ./build/MyApp.ipa --standing-link acmebeta

Send it once. Every later publish swaps what it installs, and nobody has to be told again. Standing links are a Pro and Studio feature — claim the name in the dashboard first.

Put a download button on your README

Every build's install link can be wrapped in a "Download from BetaDrop" button — one Markdown image link, no script:

[![Download MyApp from BetaDrop](https://betadrop.app/badge/download-dark.svg)](https://betadrop.app/install/acmebeta?ref=badge)

Copy it from the embed panel under the install link (post-upload screen or the build's Share tab). Point it at a standing link and betadrop publish --standing-link acmebeta keeps the button current on every publish. Details: https://betadrop.app/download-button/.

Check a build before you ship it

betadrop inspect ./build/MyApp.ipa && betadrop publish ./build/MyApp.ipa --ci

inspect reads the build on BetaDrop's servers and throws it away — nothing is stored and it needs only a read-only token. It fails on the mistakes that otherwise surface as a tester saying "it won't install": an App Store or expired provisioning profile, a profile for a different bundle ID, an unsigned or testOnly APK, or a v1-only signature on an app targeting Android 11+. --strict fails on warnings too (a development profile, debuggable).

Tell Slack, Discord or your own service

betadrop webhooks add https://hooks.slack.com/services/T000/B000/XXXX
betadrop webhooks add https://ci.example.com/betadrop --events build.published,build.expiring

Slack and Discord URLs are recognised and get chat messages; anything else receives signed JSON. Events: build.published, standing_link.updated, build.expiring, build.file_missing and tester.installed. Payloads and signature verification: https://betadrop.app/docs/webhooks/.

Register test devices from a script

betadrop devices invite --name "Sam" --email [email protected]   # BetaDrop emails the link
betadrop devices export -o devices.txt                          # Apple's portal / fastlane format

Already logged in?

Running betadrop login when a session exists shows a prompt:

You are already logged in as [email protected].
? What would you like to do?
❯ Continue as [email protected]
  Sign in with a different account
  Log out and sign in again

Choosing "Sign in with a different account" starts a fresh login flow and replaces the session.
Choosing "Log out and sign in again" revokes the current token first, then logs in fresh.


Configuration

Set these environment variables to override the defaults:

| Variable | Default | Description | |----------|---------|-------------| | BETADROP_TOKEN | (none) | API token to authenticate with. Wins over the stored credentials file — use it in CI. | | BETADROP_API_URL | https://api.betadrop.app | API server URL (for self-hosted). | | BETADROP_APP_URL | https://betadrop.app | Frontend host used to build install links. |

CI usage (no login required)

BETADROP_TOKEN=bd_live_xxxxxxxxxxxxxxxxxxxx betadrop publish ./build/MyApp.ipa --ci

To keep one link current across every CI publish, claim a standing link once in the dashboard and pass it each time:

BETADROP_TOKEN=bd_live_xxxxxxxxxxxxxxxxxxxx betadrop publish ./build/MyApp.ipa --ci --standing-link acmebeta
# stdout:
#   channel-url=https://betadrop.app/install/?i=acmebeta
#   https://betadrop.app/install/?i=Ab3xYz

With BETADROP_TOKEN set, betadrop login does nothing but print a notice, and betadrop logout cannot revoke the token server-side — it only tells you to revoke it in the dashboard. Rotate CI tokens at betadrop.app → Settings → Developer → API tokens.

On GitHub Actions, skip the install step entirely and use betadrop-app/upload-action — it wraps this same CLI and puts the link on the run summary and the pull request.


Troubleshooting

betadrop: command not found (or bd: command not found)
Run npm install -g @betadrop/cli and make sure your npm global bin directory is in PATH (npm prefix -g shows the path — the bin directory is <prefix>/bin, or the prefix itself on Windows).

Your token is invalid, expired, or was revoked
Run betadrop login to authenticate again. If you are in CI, rotate the secret and update BETADROP_TOKEN.

Could not reach BetaDrop
Check your internet connection. If BETADROP_API_URL is set, verify it points at a running server.

Upload stalled — no data for 60s
Your connection dropped mid-upload. The CLI will retry automatically on server errors. Check your network and run again.

QR code looks garbled
Use a modern terminal that renders Unicode block characters: iTerm2, Windows Terminal, Alacritty, or Ghostty. If your terminal can't render them, use the printed URL directly — they carry the same link.

The iOS build downloads on the phone but will not open
An ad-hoc .ipa only installs on devices that were in the provisioning profile when it was signed — publishing it does not change that. Send the tester the UDID checker, which reads the UDID off the iPhone itself (no Mac, no cable), then add the device in the Apple Developer portal and re-sign.


Also from BetaDrop

The same publish step, on the other two surfaces — one account, one set of API tokens:

| | | |---|---| | betadrop-app/upload-action | Publish from a GitHub Actions workflow. The install link lands on the run summary and, optionally, in a pull-request comment that updates itself on every push. | | @betadrop/mcpsource | MCP server — publish builds, list history and manage tokens by asking Claude, Cursor or Copilot, without leaving the editor. |


Requirements

  • Node.js 18+
  • A BetaDrop account — the free tier needs no card. Retention and file-size ceilings by plan are on the pricing page.

Development

npm install
npm run build      # bundle to dist/bd.js
npm run typecheck  # type-check without emitting
node dist/bd.js --help

Issues and pull requests: https://github.com/betadrop-app/betadrop-cli. If this saved you a TestFlight round-trip, a ⭐ helps other mobile teams find it.

License

MIT