Quickstart
You will get from zero to a live OTA update in three commands. There is no AppDelegate editing, no Info.plist hand-patching, no pod install debugging. swiftpatch init does all of it for you.
Prerequisites:
- React Native 0.76+ (Hermes recommended)
- Node.js 20+
- A Swiftpatch account (free)
- CocoaPods for iOS builds
Step 1 — Install the SDK and CLI
# In your React Native project
npm install @swiftpatch/react-native
# Global CLI
npm install -g swiftpatch-cli
Then log in (opens a browser):
swiftpatch login
Step 2 — Wire everything up
npx swiftpatch init
This command does all of the setup for you:
- Detects whether your project is bare React Native, Expo bare, or a monorepo.
- Creates (or links) an app in your Swiftpatch dashboard.
- Generates an Ed25519 signing keypair at
.swiftpatch/keys/. - Patches
AppDelegate.mmorAppDelegate.swiftto load OTA bundles. - Patches
MainApplication.ktorMainApplication.javato load OTA bundles on Android. - Adds
SwiftPatchDeploymentKeytoInfo.plistandswiftpatch_deployment_keytostrings.xml. - Registers
com.swiftpatch.bg-refreshinBGTaskSchedulerPermittedIdentifiersand addsfetch+processingtoUIBackgroundModes. - Writes a project config to
.swiftpatchrc. - Adds
.swiftpatch/,swiftpatch-artifacts/, andswiftpatch-private.pemto.gitignore.
Every patched file is wrapped in // swiftpatch-begin / // swiftpatch-end markers. The insertion is additive — your existing code is never rewritten, just wrapped with a block that calls Swiftpatch first and falls through to the default bundle loader if Swiftpatch returns nothing.
swiftpatch init is idempotent. If markers already exist, it skips the patch. If you want to remove everything cleanly, run swiftpatch unlink.
If you prefer to copy-paste the snippets yourself, run swiftpatch init --manual. The CLI will still generate keys, write .swiftpatchrc, and update .gitignore — it just prints the native snippets for you to apply by hand.
Re-pod on iOS if you changed anything:
cd ios && pod install && cd ..
Step 3 — Wrap your app
import { SwiftPatchProvider } from '@swiftpatch/react-native';
export default function Root() {
return (
<SwiftPatchProvider config={{ debug: __DEV__ }}>
<App />
</SwiftPatchProvider>
);
}
You do not need to pass the deployment key — the SDK reads it from Info.plist / strings.xml that swiftpatch init wrote.
The provider ships with sensible defaults:
autoShowBanner(defaulttrue) — renders a polite<UpdateBanner />when an update is ready.blockOnMandatory(defaulttrue) — renders a full-screen<UpdateBlocker />if the release is marked mandatory.- No further wiring required.
See SwiftPatchProvider reference for the full prop surface, or UI components if you want to theme the banner.
Step 4 — Ship your first update
Make any JS-only change (fix a typo, change a color, adjust a prop). Then:
swiftpatch deploy -p ios --hermes
This command:
- Runs
react-native bundlewith--reset-cachecleanly. - Compiles to Hermes bytecode.
- Signs the bundle with your Ed25519 private key.
- Uploads to Cloudflare R2.
- Creates a release at
app.swiftpatch.io.
Within seconds you will see the release appear in the dashboard. Relaunch your app — the update downloads in the background and the banner appears when it is ready to apply.
Run the same command with -p android. You can deploy both in parallel:
swiftpatch deploy -p ios --hermes & swiftpatch deploy -p android --hermes
What just happened
- Your app cold-started and called the check-for-update API with the device's current bundle hash.
- The server responded with a delta patch descriptor (a bsdiff file against your current bundle).
- The SDK downloaded the patch (typically 60–98% smaller than the full bundle), verified the Ed25519 signature, applied
bspatchon-device, and re-verified the resulting SHA-256. - The banner appeared. When you tapped "Apply now," the SDK swapped the active bundle slot and restarted the JS runtime.
- Your app is now running the new code.
If anything at any step had failed — bad signature, hash mismatch, network error, bsdiff corruption — the SDK would have silently fallen back to a full download, then to the previous stable slot, then to the store-bundled JavaScript. Your users never see a crash.
Next steps
- SDK installation — understand what
swiftpatch initpatched. - SDK provider reference — customize the Provider's behavior.
- UI components — theme or replace the banner / blocker / onboarding.
- Staged rollouts — ship to 5% of users first.
- CI/CD integration — automate
swiftpatch deployfrom GitHub Actions.