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

@appforge-ci/cli

v0.3.13

Published

`appforge` — the customer-facing CLI: sign up/log in, manage apps, trigger/watch builds, buy build-token top-ups, start an in-browser device-test session. No fleet commands — that's a separate tool, `appforge-admin` (`packages/admin-cli`), for the platfor

Readme

@appforge-ci/cli

appforge — the customer-facing CLI: sign up/log in, manage apps, trigger/watch builds, buy build-token top-ups, start an in-browser device-test session. No fleet commands — that's a separate tool, appforge-admin (packages/admin-cli), for the platform operator only.

Install

On a machine that already has this repo cloned:

pnpm install                        # once, from the repo root
pnpm --filter @appforge-ci/cli build
cd packages/cli && npm link         # symlinks `appforge` onto PATH

From npm, once published: .github/workflows/publish.yml publishes this package (tag-triggered), but needs an NPM_TOKEN repo secret that isn't configured yet — until a version is actually published, npm install -g @appforge-ci/cli will 404. The npm link path above is what works today.

Usage

appforge signup --email [email protected] --org "My Org"   # or: appforge login --email [email protected]
appforge login --email [email protected] --totp-code 123456   # if 2FA is enabled (--recovery-code also works)
appforge apps create --name demo --platform flutter --repo-url https://github.com/you/app.git
appforge apps list
appforge apps update <appId> [--name] [--repo-url] [--default-branch]   # fix a stale field without recreating the app
appforge apps webhook-secret <appId>        # the secret GitHub's webhook "Secret" field needs
appforge apps delete <appId>                # permanently delete an app and its builds/OTA history
appforge apps secrets set <appId> --name KEYSTORE_PASSWORD   # --value omitted -> prompted, echo off (never in shell history); injected as $KEYSTORE_PASSWORD on every build for this app
appforge apps secrets list <appId>          # names only, never values
appforge apps secrets unset <appId> --name KEYSTORE_PASSWORD
appforge fleet-secrets set JWT_SECRET        # value omitted -> prompted, echo off (never in shell history)
appforge fleet-secrets list                  # names only, never values
appforge fleet-secrets unset JWT_SECRET_PREVIOUS
appforge orgs rename --name "New Org Name"  # fix a typo'd/stale org name (e.g. a placeholder from signup)
appforge orgs set-build-webhook --url https://example.com/hook  # POST build id/status/appId/costTokens/artifacts on every build's completion
appforge orgs set-build-webhook --clear     # turn build-status notifications back off
appforge build trigger --app-id <appId>
appforge build list --app-id <appId>
appforge build logs <buildId> --follow
appforge build artifact <buildId>
appforge build cancel <buildId>
appforge build explain <buildId>       # AI explanation for a failed build (needs ANTHROPIC_API_KEY on the deployment)
appforge build analyze-smoke-test <buildId>  # re-run AI analysis of the build's smoke-test screenshots
appforge build test <buildId>          # in-browser device test session, on a succeeded build
appforge init                          # draft an appforge.yaml from what's actually in the current repo
appforge billing balance
appforge billing packs
appforge billing topup --pack starter          # via LHV Paytech, see docs/payments-lhv.md
appforge billing ledger                        # every balance change (top-ups, charges, refunds), newest first
appforge billing usage                         # billing mode + this period's accrued usage, on postpaid
appforge billing setup-card                    # save a card — required before switching to postpaid
appforge billing mode <prepaid|postpaid-monthly>
appforge billing invoices                      # monthly invoices (postpaid billing only)
appforge ota channels --app <appId>         # list channels and each one's active release
appforge ota releases --app <appId> [--channel production]
appforge ota promote <buildId> --app <appId> [--channel production] [--rollout 25] [--mandatory]
appforge ota set-rollout <releaseId> --app <appId> --rollout 50   # progress an existing release's rollout in place
appforge ota app-key --app <appId>          # generate/rotate the manifest key a shipped app embeds
appforge ota activate <releaseId> --app <appId> --channel production  # jump directly to a specific release
appforge ota activate --app <appId> --channel production --clear      # deactivate the channel instead
appforge ota rollback --app <appId> --channel production               # step back exactly one release
appforge tokens list                        # every API token for this org — id, label, created/last-used (never the token value)
appforge tokens revoke <tokenId>            # permanently revoke one — 'appforge login' again mints a fresh one
appforge vpn status [--json]                # the org's site-to-site VPN tunnel (any member)
appforge vpn create --name hq --endpoint vpn.example.com:51820 --gateway-key <base64> --lan 10.20.0.0/16 [--dns 10.20.0.2 --domain corp.example.com] [--tunnel-cidr 169.254.200.0/30]
appforge vpn peer-config                    # re-show the [Peer] block for your gateway (prints a secret; admin, audited)
appforge vpn rotate-keys [--yes]            # new AppForge keys; tunnel returns to pending (a disabled tunnel stays disabled) until you update your gateway
appforge vpn disable [--yes] | enable       # disable cancels + refunds queued VPN builds
appforge vpn delete [--yes]
appforge vpn events [--json]                # newest first
appforge vpn test [--json]                 # start a build-free handshake test of the gateway (owner/admin; nothing charged; once per 5 minutes)
appforge vpn test --status [--json]        # the latest test's verdict (any member); exits 0 only on handshake_ok
appforge apps update <appId> --vpn          # opt an app in (--no-vpn to opt out; org owner/admin)

Site-to-site VPN

You describe your own WireGuard gateway; AppForge's Mac dials out to it for builds of apps that opted in. vpn create prints a [Peer] block to paste into your gateway; update the gateway again after rotating keys or changing LAN/tunnel ranges. It contains a secret (the preshared key) — treat it like a password, and only create, peer-config and rotate-keys print it. All changes need an org owner/admin; any member can read status/events. vpn test checks that your gateway accepts the handshake without building anything: it releases the tunnel's keys to one build machine for the test (see docs/vpn.md, "Test tunnel"), and vpn test --status prints the verdict and when it ran. Limits: tools that ignore proxy settings (raw sockets, UDP, ICMP, xcodebuild, simulators) don't use the tunnel; SSH git remotes (ssh://user@host/path or user@host:path) go through it when you pin your server's host keys (vpn ssh-hosts set) and install the app's deploy key (apps deploy-key show), while a bare ssh in a build script is not routed; your gateway must accept inbound UDP on its endpoint port; status becomes ready after the first successful VPN build (vpn test checks the handshake alone; a build is the end-to-end check); builds appear from the tunnel's AppForge-side /30 address, so allow-list it or masquerade.

--api-url (default http://localhost:8787, or set APPFORGE_API_URL) only needs passing on login/signup — after that it's saved to ~/.appforge/config.json and reused. See the root README.md's Quick start for the full local-dev flow and docs/self-hosting.md for pointing this at a real deployment.

login prompts interactively for a 2FA code if the account has it enabled and neither --totp-code nor --recovery-code was passed — see docs/security.md's "2FA (TOTP)" note.