Skip to content

Repository files navigation

React Native paper plane

React Native Paperplane

npm version

Tiny CLI to bump iOS build numbers, build/export with Xcode, and upload to TestFlight.

License: MIT

Features

  • One-command TestFlight release flow for iOS
  • Supports app.config.ts, app.config.js, and app.json (text-only parsing)
  • Dry run mode and clean git enforcement
  • Deterministic output paths for build artifacts
  • Release prerequisites checked before build-number changes or commits
  • Upload passwords redacted from command failures and child-process output

Requirements

  • Node 18+ or Bun
  • Xcode Command Line Tools
  • Transporter app installed and signed in (for iTMSTransporter)
  • Repo with ios/ and an Xcode workspace
  • One of: app.config.ts, app.config.js, app.json

Install

npm install -D react-native-paperplane
# or
bun add -d react-native-paperplane

Quick start

npx react-native-paperplane --dry-run
npx react-native-paperplane

Bun alternative:

bunx react-native-paperplane --dry-run
bunx react-native-paperplane

Local development

# run locally without publishing
bun src/cli.js --help
# or
node src/cli.js --help

Optional global-style bin for development:

npm link
paperplane --help

Run the offline regression tests with npm test (Node 18+). The tests use fake Git/Xcode/Transporter commands and dummy credentials; they do not build an app or contact App Store Connect.

Xcode 27 and release safety

Paperplane uses the selected Xcode's iphoneos SDK and the supported app-store-connect export method; it does not pin an iOS SDK version. Export options omit obsolete Bitcode keys. The app itself must satisfy the selected SDK's requirements, including UIKit scene support when building with iOS 27. For Expo apps, regenerate the native project and reconcile Pods after updating native dependencies; Paperplane does not run Expo prebuild or CocoaPods for you.

Before changing either build number or making the release commit, a real run checks Xcode, the iPhoneOS SDK, and Git author/committer identities. Upload runs also check credentials and the local Transporter executable. --skip-upload does not require upload credentials or Transporter. --dry-run remains a non-mutating preview without build/upload prerequisite checks.

Preflight cannot guarantee signing, export, or Apple's acceptance of an upload. Failures after the build-number commit still leave that commit in place; inspect the current build number before retrying. Password redaction protects Paperplane's console output, not operating-system process argument visibility or logs written directly by external tools.

Usage

paperplane [options]

Options

  • --build-number <n>: Set explicit build number (default: current + 1)
  • --message <msg>: Override git commit message
  • --dry-run: Show actions without modifying files or running build/upload
  • --allow-dirty: Skip clean git check
  • --skip-upload: Build/export only; skip upload
  • -h, --help: Show help

Environment variables

Required for upload (Apple ID auth only):

  • ASC_APPLE_ID
  • ASC_APP_PASSWORD

Optional:

  • ASC_ITC_PROVIDER

iOS overrides:

  • IOS_APP_NAME
  • IOS_SCHEME
  • IOS_WORKSPACE

Project assumptions

  • ios/ contains an Xcode workspace (or set IOS_WORKSPACE).
  • Info.plist is at ios//Info.plist.
  • Build number is read from text in app.config.ts, app.config.js, or app.json.

Output paths

Artifacts are written to:

ios/build/testflight/<runId>/

Examples

# dry run
paperplane --dry-run

# explicit build number
paperplane --build-number 42

# build only, no upload
paperplane --skip-upload

FAQ

Why Bun? Bun is fast and works great for CLI workflows. This package also runs on Node 18+.

Transporter errors? Install Transporter from the Mac App Store and sign in once.

Publishing checklist

  • Confirm the package name is available on npm: npm view react-native-paperplane.
  • Update package.json version.
  • Run a quick help check: node src/cli.js --help.
  • Dry pack: npm pack and sanity-check the tarball contents.
  • Publish: npm publish --access public.

Notes:

  • --access public is only required for scoped packages, but harmless for unscoped.
                                                                                    :
                                                                   =               ..=
                                                                                 +
                                                               =..=                     @%@..%@@
                                                                               +%%@.....+%@...@
                                                                        @@@..:...-:.+%@@.-..@
                                                  -             @%@.-........-..#++@....--@@
                                                        %@%@...:.....-......#++%@..:...:.@     .
                                                #%%@....+.-....=.:.+.. .#+*@%..-....:..@       =
                                         @@@.....-................=.#++=%@..=...-:::=.@
                                 @%%=...::...*......*....:......++==%@........:=::-.@    -    +
                       =    @@..::.-.:::...... ...-.......-.@*++@%........::=::--.*@     .
                       .        @@.::::.:.......+.......@+%++@#.........=#::::=..@
                       +  +        @%.....*.:. ...-..++*+%%..........:=:::.+:-.@@
                          +    .       @+.......#++++@%.....-...=.----.-=---..@     =
                        +      .        @+@%.**+++%@......#..=.--:.-+-:=--+.@@
                                        @=+@.***%......:....*:---:::%:.--.=@
                                         @-@:+*@.%@ ......::::.=:::--:-..@@
                                    +     ---=+@==#%#%..:.:.::-.:*::-..@@
                                          @:-+*.===*%#*@..:....::::+..@@
                                           @%=@+==-+==@@ @%.....*...@@
                                           @@+.:-=-@@      @%..=...@%
                                            @@.-@@           @@..@@
                                            #:@           *     @%

                    PPPPPP     AAA    PPPPPP   EEEEEEE  RRRRRR   PPPPPP   L          AAA    N    N   EEEEEEE
                    P     P   A   A   P     P  E        R    R   P     P  L         A   A   NN   N   E
                    P     P  A     A  P     P  E        R    R   P     P  L        A     A  N N  N   E
                    PPPPPP   A     A  PPPPPP   EEEEEE   RRRRRR   PPPPPP   L        A     A  N  N N   EEEEEE
                    P        AAAAAAA  P        E        R  R     P        L        AAAAAAA  N   NN   E
                    P        A     A  P        E        R   R    P        L        A     A  N    N   E
                    P        A     A  P        EEEEEEE  R    R   P        LLLLLLL  A     A  N    N   EEEEEEE

About

push to TestFlight without opening Xcode

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages