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

@basiljohn/appdeploy

v0.1.1

Published

Local-first EAS iOS/Android build & submit: avoid cloud build quota using your Mac and Apple/Google credentials (Keychain-backed).

Readme

appdeploy

CLI for local-first Expo EAS workflows: run eas build --local on your machine to avoid EAS cloud build quota, then submit to TestFlight or Google Play using credentials you control.

  • iOS (macOS only): App Store Connect API key (Issuer, Key ID, Team ID, .p8) is stored in the macOS Keychain (no Apple ID password in the tool).
  • Android: A Google Play service account JSON is written to .appdeploy/google-service-account.json and, on macOS, also saved in Keychain. Add .appdeploy/ to .gitignore if you do not commit secrets.

This does not remove: Apple Developer Program fees, App Store / Play review, or the requirement to use a Mac for iOS store binaries. It does avoid using Expo’s shared build servers for compiles, which is where the free plan monthly limits apply.

Prerequisites

  1. Expo project with eas.json and a valid build profile (for example production). Install EAS: npm i -g eas-cli and eas login (EAS is still the orchestration layer; local builds are documented).
  2. Apple (iOS): Enrolled in the Apple Developer Program ($99/yr). Create an App Store Connect API key with App Manager (or similar) access.
  3. Google (Android): Service account with Play API access, linked in Play Console, per Expo’s guide.

Install

From the npm registry (package @basiljohn/appdeploy, version 0.1.1):

npm i -g @basiljohn/appdeploy
appdeploy --help

In an Expo app as a dev dependency (recommended so the version is pinned):

npm i -D @basiljohn/[email protected]
npx appdeploy doctor

The global/local CLI command is still appdeploy (the bin name), not the scoped package name.

From a git clone of this repo:

npm install && npm run build
npm i -g .
# or: npm link
appdeploy --help

Quick start: iOS

  1. In your Expo app directory:

    appdeploy ios setup

    You will be asked for Issuer ID, Key ID, Team ID, and the path to AuthKey_xxx.p8 (one-time; stored in Keychain as appdeploy.asc).

  2. Ensure your App Store app exists and you know the App Store Connect app Apple ID (numeric) — this is not the bundle id; see expo.fyi/asc-app-id.

  3. In eas.json, add a submit profile (often matching your build profile name) with at least ascAppId and appleTeamId:

    {
      "submit": {
        "production": {
          "ios": {
            "ascAppId": "1234567890",
            "appleTeamId": "AB12XYZ34S"
          }
        }
      }
    }

    Optional: you can use .appdeploy/appdeploy.config.json (see Configuration) to keep ascAppId out of the main eas.json if you prefer.

  4. Local build (uses your Mac CPU, not EAS cloud workers):

    appdeploy ios build --profile production
  5. Submit the generated .ipa:

    appdeploy ios submit --path ./path/to/app.ipa --profile production
  6. One-shot build + write artifact to .appdeploy/local-build.ipa + submit:

    appdeploy ios ship

The submit and ship steps set the same ASC API environment variables that eas expects: EXPO_ASC_API_KEY_PATH, EXPO_ASC_KEY_ID, EXPO_ASC_ISSUER_ID, and EXPO_APPLE_TEAM_ID (from your Keychain data).

Quick start: Android

  1. appdeploy android setup — pick your service account JSON. This writes .appdeploy/google-service-account.json.

  2. In eas.json, point the submit profile at that file and choose a track:

    {
      "submit": {
        "production": {
          "android": {
            "serviceAccountKeyPath": ".appdeploy/google-service-account.json",
            "track": "internal"
          }
        }
      }
    }
  3. appdeploy android build --profile production

  4. appdeploy android submit --path ./path/to/app.aab

  5. Or appdeploy android ship (output: .appdeploy/local-build.aab; if your eas.json profile builds an APK instead, use android build and android submit --path to that file).

EAS login vs “fully local” native build

  • eas build --local (what this CLI runs) is the supported way to run the same EAS build pipeline on your machine. It still uses your Expo account for project identity and, if you use EAS managed credentials, to sync signing. It does not consume EAS cloud build minutes.
  • Full escape hatch: npx expo prebuild and open Xcode / Android Studio yourself, then upload with Transporter (iOS) or eas submit with a path to the archive. appdeploy is aimed at the eas path so you keep one consistent workflow with eas.json.

Configuration (optional)

Create .appdeploy/appdeploy.config.json in the project root to override or supplement submit metadata (merged with eas.json for known fields):

{
  "ascAppId": "1234567890",
  "appleTeamId": "AB12XYZ34S",
  "serviceAccountKeyPath": ".appdeploy/google-service-account.json"
}

You can also use a top-level appdeploy.config.json in the project root; both are supported. Team ID is already stored when you run appdeploy ios setup; the submit path still requires ascAppId in eas non-interactive mode, so you must set it in eas.json or in one of these config files (see submit reference).

Commands

| Command | Description | |--------|-------------| | appdeploy doctor | iOS (mac) + Android tool checks: Node, Xcode, CocoaPods, eas, ANDROID_HOME | | appdeploy ios setup | Keychain wizard for App Store Connect API key | | appdeploy ios build | eas build --local --platform ios | | appdeploy ios submit --path <ipa> | eas submit with Keychain-sourced EXPO_ASC_* | | appdeploy ios ship | local build to .appdeploy/local-build.ipa + submit | | appdeploy android setup | Write Play service account to project (+ Keychain on macOS) | | appdeploy android build | eas build --local --platform android | | appdeploy android submit --path <aab\|apk> | eas submit after ensuring JSON exists on disk | | appdeploy android ship | local AAB to .appdeploy/local-build.aab + submit |

Flags: --log <file> appends a tee of eas output (ANSI stripped). --skip-doctor skips preflight. --profile / -e select the EAS profile (default production).

Security notes

  • Prefer App Store Connect API keys; do not use your main Apple ID password in automation. Rotate keys in App Store Connect if a machine is lost.
  • Treat .appdeploy/ and Keychain data as sensitive. Use .gitignore for generated JSON in CI clones.

Development

npm install
npm run build
node dist/cli.js doctor

License

MIT