From rn-launch-harness
Configures EAS Build for iOS/Android binaries and EAS Update for OTA in Expo React Native projects, including eas.json setup, app.config verification, and local build tests.
npx claudepluginhub tjdrhs90/rn-launch-harness --plugin rn-launch-harnessThis skill is limited to using the following tools:
Build iOS/Android binaries via EAS Build and configure EAS Update for OTA.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Guides code writing, review, and refactoring with Karpathy-inspired rules to avoid overcomplication, ensure simplicity, surgical changes, and verifiable success criteria.
Executes ctx7 CLI to fetch up-to-date library documentation, manage AI coding skills (install/search/generate/remove/suggest), and configure Context7 MCP. Useful for current API refs, skill handling, or agent setup.
Share bugs, ideas, or general feedback.
Build iOS/Android binaries via EAS Build and configure EAS Update for OTA.
Called by the orchestrator as Phase 8.
docs/harness/config.mdeas-cli installed (npm install -g eas-cli)eas login)# Initialize EAS if not already done
eas init
Check if eas.json exists. If not, create with all required config:
{
"cli": {
"version": ">= 15.0.0",
"appVersionSource": "remote"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal"
},
"production": {
"autoIncrement": true,
"env": {
"GRADLE_OPTS": "-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g"
}
}
},
"submit": {
"production": {
"ios": {
"ascAppId": "",
"appleTeamId": ""
},
"android": {
"serviceAccountKeyPath": "",
"track": "internal"
}
}
}
}
CRITICAL: Android GRADLE_OPTS
The production.env.GRADLE_OPTS setting is mandatory. Without it, Android local builds frequently fail with OutOfMemoryError or Metaspace errors during Gradle compilation:
"env": {
"GRADLE_OPTS": "-Dorg.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g"
}
This allocates 4GB heap + 1GB metaspace for the Gradle JVM. Adjust if your machine has less RAM (minimum -Xmx2g).
Configure EAS Update for over-the-air JS bundle updates (no store re-submission needed):
# Initialize EAS Update
eas update:configure
This adds to app.config.ts:
updates: {
url: "https://u.expo.dev/[PROJECT_ID]",
},
runtimeVersion: {
policy: "appVersion",
},
And adds expo-updates to plugins:
plugins: [
"expo-router",
"expo-updates", // ← added
// ...
],
Install the dependency:
npx expo install expo-updates
Why OTA matters:
Verify all required settings:
name, slug, versionios.bundleIdentifier (from config.md)android.package (same as iOS)android.versionCodeupdates.url, runtimeVersion)Local build catches errors faster than cloud build:
# Android local build first (catches Gradle/dependency issues)
eas build --local --platform android --profile production
Common Android local build failures and fixes:
| Error | Fix |
|---|---|
OutOfMemoryError / Metaspace | Increase GRADLE_OPTS in eas.json |
SDK location not found | Set ANDROID_HOME env var |
NDK not found | Install NDK via Android Studio SDK Manager |
minSdkVersion conflict | Check expo-build-properties plugin |
Duplicate class | Run cd android && ./gradlew clean |
# iOS local build (requires Xcode + macOS)
eas build --local --platform ios --profile production
Common iOS local build failures:
| Error | Fix |
|---|---|
No signing certificate | EAS manages this automatically in cloud build |
Pod install failed | cd ios && pod install --repo-update |
Xcode version mismatch | Update Xcode or set image in eas.json |
If local build fails with signing issues, skip to cloud build (EAS handles provisioning automatically).
# iOS production build
eas build --platform ios --profile production --non-interactive
# Android production build
eas build --platform android --profile production --non-interactive
Wait for build completion. Record build URLs.
eas build:list --limit 2
# Create production update channel (if not exists)
eas channel:create production
# Verify update config
eas update --branch production --message "Initial release" --non-interactive
docs/harness/handoff/build-result.md:
# EAS Build Result
## iOS
- Profile: production
- Status: [SUCCESS/FAILED]
- Build URL: https://expo.dev/...
- Binary: .ipa
## Android
- Profile: production
- Status: [SUCCESS/FAILED]
- Build URL: https://expo.dev/...
- Binary: .aab
## EAS Update
- Channel: production
- Runtime Version: [version]
- Status: [CONFIGURED/FAILED]
## Build Config
- bundleIdentifier: com.xxx.xxx
- package: com.xxx.xxx
- version: 1.0.0
- buildNumber/versionCode: 1
- GRADLE_OPTS: -Xmx4g -XX:MaxMetaspaceSize=1g
Git commit:
git add eas.json app.config.ts
git commit -m "chore: configure EAS build + update profiles"
current_phase: screenshot
next_role: rn-harness-screenshot
eas.json must exist with all profilesGRADLE_OPTS must be set in production build envapp.config.ts must have bundleIdentifier/packageexpo-updates installed, updates.url set)