A React Native Update command line tool for bundling, uploading native packages, publishing OTA versions, and managing apps/packages.
- Single
pushy/crescCLI entrypoint - Backward-compatible command set
- Programmatic provider API for build scripts and CI/CD
- TypeScript type definitions
npm install react-native-update-clinpx pushy help
npx pushy list
npx pushy bundle --platform ios
npx pushy publish --platform ios --name 1.0.0
npx pushy uploadIpa ./app.ipaimport { CLIProviderImpl } from 'react-native-update-cli';
const provider = new CLIProviderImpl();
const bundleResult = await provider.bundle({
platform: 'ios',
dev: false,
sourcemap: true,
});
if (!bundleResult.success) {
throw new Error(bundleResult.error);
}
const publishResult = await provider.publish({
filePath: '.pushy/output/ios.ppk',
platform: 'ios',
name: 'v1.2.3',
description: 'Bug fixes and improvements',
rollout: 100,
});bundle: Bundle JavaScript code and optionally publishhdiff: Generate hdiff between two PPK fileshdiffFromApk: Generate hdiff from APK fileshdiffFromApp: Generate hdiff from APP fileshdiffFromIpa: Generate hdiff from IPA files
publish: Publish a new versionversions: List versionsupdate: Update version package rulesupdateVersionInfo: Update version metadatadeleteVersion: Delete a version
createApp: Create an appapps: List appsselectApp: Select an appdeleteApp: Delete an app
uploadIpa: Upload IPA filesuploadApk: Upload APK filesuploadAab: Upload AAB filesuploadApp: Upload APP filesparseApp: Parse APP file informationparseIpa: Parse IPA file informationparseApk: Parse APK file informationparseAab: Parse AAB file informationextractApk: Extract a universal APK from an AABpackages: List packagesdeletePackage: Delete a package
login: Loginlogout: Logoutme: Show current user information
interface CLIProvider {
bundle(options: BundleOptions): Promise<CommandResult>;
publish(options: PublishOptions): Promise<CommandResult>;
upload(options: UploadOptions): Promise<CommandResult>;
getSelectedApp(
platform?: Platform,
): Promise<{ appId: string; platform: Platform }>;
listApps(platform?: Platform): Promise<CommandResult>;
createApp(name: string, platform: Platform): Promise<CommandResult>;
listVersions(appId: string): Promise<CommandResult>;
updateVersion(
appId: string,
versionId: string,
updates: Partial<Version>,
): Promise<CommandResult>;
getPlatform(platform?: Platform): Promise<Platform>;
loadSession(): Promise<Session>;
}publish requires a generated .ppk path via filePath. Provider list methods return data in CommandResult.data and do not enter interactive paging.
export PUSHY_REGISTRY=https://your-api-endpoint.com
export NO_INTERACTIVE=trueWhen ios/sentry.properties or android/sentry.properties exists, bundle uploads sourcemaps for OTA packages. The default matching path is Sentry Debug IDs; the CLI no longer infers release/dist from the native package.
React Native projects should use @sentry/react-native/metro in metro.config.js so the generated bundle and sourcemap share the same Debug ID. For Hermes, the CLI copies the packager sourcemap Debug ID to the composed Hermes sourcemap and uploads with:
sentry-cli sourcemaps upload --debug-id-referenceFor older self-hosted Sentry versions or older @sentry/cli versions without Debug ID support, pass explicit legacy release/dist values:
npx pushy bundle --platform android --name "4.1" --sentry-release "com.example@1.0.0+10+pushy:4.1" --sentry-dist "pushy:4.1"In legacy mode, the app runtime must report exactly the same Sentry release and dist values.
Create update.json in your React Native project:
{
"ios": {
"appId": "your-ios-app-id",
"appKey": "your-ios-app-key"
},
"android": {
"appId": "your-android-app-id",
"appKey": "your-android-app-key"
}
}All provider methods return CommandResult; check success before consuming data. The CLI supports ios, android, and harmony platforms.