- name
- argent-react-native-app-workflow
- description
- Step-by-step workflows for developing or debugging React Native apps on iOS simulator or Android emulator. Use when starting the app, debugging Metro, fixing builds, diagnosing runtime errors, or running tests.
## 1. Starting the React Native App
### 1.1 Explore Configuration (MANDATORY — Do This First)
**Before running commands**, read the project's build and run configuration from the `argent-environment-inspector` subagent result.
Do NOT default to `npx react-native start` or `npx react-native run-ios` without first checking for custom scripts and workflows.
**Manual fallback** (if neither the agent nor the tool is available): read ALL `package.json` scripts — look for custom scripts like `start:local`, `start:dev`, `ios`, `build:ios`, flavors, etc. Custom scripts take priority over default commands. Also check `metro.config.js` for non-default port or watchFolders. For iOS builds, prefer opening `.xcworkspace` over `.xcodeproj` (CocoaPods generates the workspace).
**If the project structure is convoluted, ask the user before proceeding.**
**Remember the workflow:** Once you discover the project's build/run workflow, save it to project memory so you don't need to re-discover it each time.
**Checklist before start:**
- [ ] `node_modules` present (if not: `bun install`)
- [ ] For iOS: `ios/Podfile` exists; if `ios/Pods` missing or stale, run `cd ios && pod install && cd ..`
- [ ] No conflicting Metro on default port (see 1.2)
### 1.2 Start Metro
1. Check whether metro is already running on port found in configuration and if it is - do not start another server. Refer to point 2.1.
1. **Use the project's custom start script if one exists** (e.g. `npm run start:local`, `yarn start:dev`). In this monorepo:
```bash
bun mobile start
```
Fall back to `npx react-native start` only if no project script exists. Optional: `bun mobile start --reset-cache` if cache issues are suspected.
1. **Verify Metro is ready**: use the `debugger-status` tool to verify Metro is running and reachable.
1. **Projects with flavors or custom configs**: Use project-specific start script if present (e.g. `npm run start:local`), and start Metro **before** running the app.
### 1.3 Run the App
In a **separate** terminal (Metro keeps running in the first):
**Use the project's custom build/run script if one exists** (e.g. `npm run ios`, `npm run android`, `yarn ios:debug`). Only fall back to the default if no custom scripts are defined:
```bash
npx react-native run-ios # iOS
npx react-native run-android # Android
```
Optional: specify the target device, e.g. `npx react-native run-ios --simulator="iPhone 16"` or `npx react-native run-android --deviceId=<serial>`.
**Android only**: after install, run `adb -s <serial> reverse tcp:8081 tcp:8081` so the emulator/device can reach Metro on your host. Repeat if the device restarts or adb drops.
**Agent checklist:**
- [ ] Metro is already running and shows "ready"
- [ ] Command run from project root
- [ ] If the device isn't booted: use `boot-device` with the iOS `udid` or Android `avdName`. Refer to the `argent-ios-simulator-setup` / `argent-android-emulator-setup` skill.
- [ ] Android: `adb -s <serial> reverse tcp:8081 tcp:8081` done.
---
## 2. Ensuring / Debugging Metro
### 2.1 Check for Existing Metro
Before starting Metro, avoid "port already in use" errors. Default port to check is :8081, infer the port from documentation:
```bash
lsof -i :PORT
```
- **No output** → Port free; safe to start Metro.
- **Output with PID** → Another process is using the port.
Use the `debugger-status` tool to check whether the process on that port is actually a Metro server. If not Metro — ask the user whether you may kill the process.
To kill a Metro process, use the `stop-metro` tool (requires user confirmation).
### 2.2 Confirm Correct Server Connection
- **App must point at the same host/port as the running Metro.** Default: same machine, port 8081.
- **iOS Simulator:** By default uses localhost; no extra config needed for same-machine Metro.
**Verify Metro is reachable:** use the `debugger-status` tool.
### 2.3 Reload the App (Ensure New Bundle)
After code or config changes, the app must load the new bundle:
| Method | How |
| ----------- | ------------------------------------------------------------------------------------------------- |
| Reload tool | Use the `debugger-reload-metro` tool |
| Restart app | Use the `restart-app` tool, or kill the app in simulator and run `npx react-native run-ios` again |
**Agent checklist:**
- [ ] Only one Metro process (no duplicate on port)
- [ ] App was started after Metro was ready
- [ ] When needing to reload: refer to 2.3
---
## 3. Build / Install / Retry (React Native & iOS Native)
### 3.1 When Build Fails (e.g. xcodebuild exit code 65)
**Order of operations (simplest first):**
1. Clean build folder, then retry the build command
2. Clear caches and reinstall dependencies: reset Metro cache, `watchman watch-del-all`, remove `node_modules` + lockfile, `bun install`, then `cd ios && rm -rf build Pods Podfile.lock && pod install --repo-update`
3. CocoaPods issues: `pod deintegrate` then `pod install --repo-update`
4. Open `ios/*.xcworkspace` in Xcode for detailed errors in the Report navigator
### 3.2 When to Ask the User
**After 2-3 failed build or run attempts, STOP and ask the user for guidance.** The user may know about required env vars, Xcode version requirements, custom build configurations, monorepo-specific setup, or required external services.
If the project structure is convoluted and the correct build approach is not obvious, **ask the user early** rather than guessing.
### 3.3 Saving Build Workflow for Later
Once you discover the correct build/run workflow for a project, **save it to project memory**. Capture: commands to start Metro, commands to build/run the app, and any required environment setup.
### 3.4 When to Reinstall vs Refresh
| Situation | Action |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------- |
| JS/React only changed | Use `debugger-reload-metro` tool. No rebuild. |
| Native code or `pod install` / project config changed | Rebuild: `npx react-native run-ios` (Metro can stay running). |
| `node_modules` or `package.json` changed | `bun install`, then if native deps changed run `cd ios && pod install`. Then rebuild. |
| App needs reinstalling from .app path | Use `reinstall-app` tool with UDID, bundle ID, and .app path. |
| Persistent native build errors | Full clean + reinstall (step 2 above). |
### 3.5 Device Control
| Action | Tool / Command |
| -------------------------- | ---------------------------------------------------------------------- |
| List devices | `list-devices` tool (iOS + Android) |
| Boot an iOS simulator | `boot-device` tool with `udid` |
| Boot an Android emulator | `boot-device` tool with `avdName` |
| Launch an app | `launch-app` tool (pass device id + bundle id / package name) |
| Restart an app | `restart-app` tool (pass device id + bundle id / package name) |
| Open a URL / deep link | `open-url` tool (pass device id + URL) |
| Rotate device | `rotate` tool |
| Stop simulator server | `stop-simulator-server` tool (iOS UDID or Android serial — one device) |
| Stop all simulator servers | `stop-all-simulator-servers` tool (iOS + Android) |
For full simulator setup workflow, refer to the `argent-ios-simulator-setup` skill.
### 3.6 Verifying Local Release-Variant Builds — Stale-Code Gotchas
**Applies to Android local release-variant builds** (`bun mobile android:<flavor>:release:local`, i.e. `apps/mobile/scripts/runAndroidLocal.sh`). Release variants **embed the JS bundle in the APK**, so a verify-on-device loop can silently test **old code** through **two independent caching layers**. Each makes a change look like it had "no effect" when it was never in the installed APK. **Both must be defeated — disabling one alone is not enough.** `runAndroidLocal.sh` handles both by default; this section is for recognizing the symptoms if a build looks stale or you build with another command.
#### Gotcha 1 — EAS build cache reinstalls a stale APK
`apps/mobile/app.config.ts` sets `experiments.buildCacheProvider: 'eas'`. `expo run:android` computes a **native** fingerprint and, on a match, downloads + installs a cached APK instead of building. A **JS-only** change does not move the native fingerprint, so for a release variant it reinstalls an APK with old JS.
- **Symptom (logs):** `Searching builds with matching fingerprint on EAS servers` → `Successfully downloaded cached build` → install path under `…/eas-build-run-cache/….apk`.
- **Detection:** you changed only JS/TS, yet the install line points at an `eas-build-run-cache` path.
- **Fix:** build via `runAndroidLocal.sh` — it exports `EXPO_LOCAL_NO_BUILD_CACHE=1`, which gates the provider off in `app.config.ts` so a real build runs. Confirm `› Building app...` in the logs (not "downloaded cached build"). If invoking `expo run:android` directly, export `EXPO_LOCAL_NO_BUILD_CACHE=1` yourself.
#### Gotcha 2 — gradle `createBundle<Variant>JsAndAssets` stays UP-TO-DATE
Even with the EAS cache off, gradle's incremental check misses changes to monorepo JS sources (e.g. `packages/uniswap/**`), so the bundle task stays `UP-TO-DATE` and the APK embeds the **previously-bundled** `index.android.bundle`.
- **Symptom (logs):** `> Task :app:createBundleDevReleaseJsAndAssets UP-TO-DATE`.
- **Detection:** compare the embedded bundle mtime to your edit time:
```bash
ls -la apps/mobile/android/app/build/generated/assets/createBundle<Variant>JsAndAssets/index.android.bundle
```
- **Fix:** `runAndroidLocal.sh` deletes the bundle task outputs by default (pass `--no-clean-js` to skip for native-only rebuilds). To clear them manually, remove:
- `apps/mobile/android/app/build/generated/assets/createBundle<Variant>JsAndAssets`
- `apps/mobile/android/app/build/generated/res/createBundle<Variant>JsAndAssets`
- `apps/mobile/android/app/build/intermediates/assets/<variant>`
A successful regen logs `> Task :app:createBundle<Variant>JsAndAssets` (no `UP-TO-DATE`) and `Writing bundle output to …`. `<Variant>` is the capitalized gradle variant (`DevRelease`, `BetaRelease`, `ProdRelease`); `<variant>` is the camelCase form (`devRelease`, …).
---
## 4. Runtime Problems in the App
### 4.1 Where to Look
| Problem type | Tool / Where to look |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **JavaScript errors / logs** | Use `debugger-log-registry` to get a summary and log file path, then `Grep`/`Read` to search. |
| **React component hierarchy** | Use `debugger-component-tree` tool for a text tree, or `debugger-inspect-element` at specific logical pixel coordinates (not normalized 0-1). |
| **Visual state of the app** | Use `screenshot` tool to capture the current screen, but prefer `describe` or `debugger-component-tree` for actual navigation and target discovery. If a permission prompt or system-owned modal overlay is not exposed reliably, then fall back to `screenshot`. |
Ver en GitHub