9.8 KiB
AGENTS Instructions
Prerequisites
- Node.js 22.x (
nvm use), Yarn via Corepack (corepack enable && corepack prepare yarn@stable --activate) - macOS/iOS:
- Xcode and Command Line Tools, CocoaPods (Ruby installed)
- From
app/ios:bundle install && bundle exec pod installor fromapp:npx pod-install
- Android:
- Android SDK + Emulator, ANDROID_HOME configured, JDK 17 (set JAVA_HOME)
- Helpful: Watchman (macOS),
yarn installat repo root
Pre-PR Checklist
Before creating a PR for the mobile app:
Code Quality
yarn nicepasses (fixes linting and formatting)yarn typespasses (TypeScript validation)yarn testpasses (unit tests)- No nested
require('react-native')calls in tests (causes OOM in CI) - check withgrep -r "require('react-native')" app/tests/and verify no nested patterns - App builds successfully on target platforms
Mobile-Specific Validation
- iOS build succeeds:
yarn ios(simulator) - Android build succeeds:
yarn android(emulator/device) - Web build succeeds:
yarn web - No sensitive data in logs (PII, credentials, tokens)
- Environment variables properly configured (check
.envsetup) - E2E tests run in CI (not required locally - CI will run E2E tests automatically)
AI Review Preparation
- Complex native module changes documented
- Platform-specific code paths explained
- Security-sensitive operations flagged
- Performance implications noted (including test memory patterns if tests were modified)
Post-PR Validation
After PR creation:
Automated Checks
- CI pipeline passes all stages
- No new linting/formatting issues
- Type checking passes
- Build artifacts generated successfully
Mobile-Specific Checks
- App launches without crashes
- Core functionality works on target platforms
- No memory leaks introduced (including test memory patterns - see Test Memory Optimization section)
- Bundle size within acceptable limits
- No nested
require('react-native')calls in tests (causes OOM in CI) - Native modules work correctly (if native code was modified)
- Platform-specific code paths tested (iOS/Android/Web)
Review Integration
- Address CodeRabbitAI feedback
- Resolve any security warnings
- Confirm no sensitive data exposed
Recommended Workflow
# Fix formatting and linting issues
yarn nice
# Lint source files
yarn lint
# Check types
yarn types
# Run tests
yarn test
Workflow Commands
Pre-PR Validation
# Run all checks before PR
yarn nice
yarn lint
yarn types
yarn test
yarn ios # Test iOS build
yarn android # Test Android build
Post-PR Cleanup
# After addressing review feedback
yarn nice # Fix any formatting issues
yarn test # Ensure tests still pass
yarn types # Verify type checking
Running the App
yarn ios- Run on iOS simulator (builds dependencies automatically)yarn android- Run on Android emulator/device (builds dependencies automatically)yarn web- Run web version
Development Tips
- Use
yarn build:depsto build all workspace dependencies before running the app - For iOS: Ensure Xcode scheme is set to "OpenPassport" (see memory)
- For Android: Ensure emulator is running or device is connected before
yarn android - Metro bundler starts automatically; use
yarn startto run it separately
iOS Simulator Selection
yarn ios now selects a simulator by UDID, shuts down stale booted simulators, explicitly boots the chosen device, waits for boot completion, then starts the React Native iOS build against that simulator.
| Env var | Purpose |
|---|---|
IOS_SIMULATOR_DEVICE |
Case-insensitive iPhone name substring filter, for example iPhone 16 Pro |
IOS_SIMULATOR_RUNTIME |
iOS runtime version filter, for example 18.4 or 18-4 |
Default device priority when no env vars are set:
iPhone 16 ProiPhone 16iPhone 15 ProiPhone 15- First available iPhone on the newest installed iOS runtime
IOS_SIMULATOR_DEVICE uses a case-insensitive substring match. If multiple devices match, the launcher uses the first match from the newest matching runtime after applying the default priority order.
Examples:
yarn ios
IOS_SIMULATOR_DEVICE="iPhone 16 Pro" yarn ios
IOS_SIMULATOR_RUNTIME="18.4" yarn ios
IOS_SIMULATOR_DEVICE="iPhone 15" IOS_SIMULATOR_RUNTIME="18-4" yarn ios
If a pinned simulator cannot be found, the launcher exits with a readable error that includes the available iPhone simulators for the matching runtimes.
The launcher currently shuts down all booted simulators before booting the selected one. If you keep other simulators open for unrelated work, relaunch them after yarn ios.
E2E Testing
The app uses Maestro for end-to-end testing. E2E tests run automatically in CI/CD pipelines - they are not required to run locally.
CI/CD E2E Testing
- E2E tests run automatically in GitHub Actions workflows
- iOS and Android E2E tests run on PRs and main branch
- No local setup required - CI handles all E2E test execution
Local E2E Testing (Optional)
If you need to run E2E tests locally for debugging:
Prerequisites:
- Maestro CLI installed:
curl -Ls "https://get.maestro.mobile.dev" | bash - iOS: Simulator running or device connected
- Android: Emulator running or device connected
- App built and installed on target device/simulator
Running Locally:
# iOS E2E tests
yarn test:e2e:ios
# Android E2E tests
yarn test:e2e:android
# Or use the local test script (handles setup automatically)
./scripts/test-e2e-local.sh ios
./scripts/test-e2e-local.sh android
E2E Test Files:
- iOS:
tests/e2e/launch.ios.flow.yaml - Android:
tests/e2e/launch.android.flow.yaml
Environment Variables
The app uses react-native-dotenv for environment configuration.
Setup
- Create
.envfile inapp/directory (see.env.exampleif available) - Environment variables are loaded via
@envimport - For secrets: Use
.env.secrets(gitignored) for local development - In CI: Environment variables are set in workflow files
Common Environment Variables
GOOGLE_SIGNIN_ANDROID_CLIENT_ID- Google Sign-In configuration- Various API endpoints and keys (check
app/env.tsfor full list)
Testing with Environment Variables
- Tests use mocked environment variables (see
jest.setup.js) - E2E tests use actual environment configuration
- Never commit
.env.secretsor sensitive values
Deployment
Mobile Deployment
The app uses Fastlane for iOS and Android deployment.
Deployment Commands
# Deploy both platforms (requires confirmation)
yarn mobile-deploy
# Deploy iOS only
yarn mobile-deploy:ios
# Deploy Android only
yarn mobile-deploy:android
# Force local deployment (for testing deployment scripts)
yarn mobile-local-deploy
Deployment Prerequisites
- See
app/docs/MOBILE_DEPLOYMENT.mdfor detailed deployment guide - Required secrets configured in CI/CD or
.env.secretsfor local - iOS: App Store Connect API keys, certificates, provisioning profiles
- Android: Play Store service account, keystore
Deployment Checklist
- Version bumped in
package.jsonandapp.json - Changelog updated
- All unit tests pass (
yarn test) - Build succeeds for target platform
- Required secrets/environment variables configured
- Fastlane configuration verified
- CI E2E tests pass (automatically run in CI, no local action needed)
Test Memory Optimization
CRITICAL: Never create nested require('react') or require('react-native') calls in tests. This causes out-of-memory (OOM) errors in CI/CD pipelines that hide actual test failures.
Automated Enforcement
The project has multiple layers of protection:
- ESLint Rule: Blocks
require('react')andrequire('react-native')in test files - Pre-commit Script: Run
node scripts/check-test-requires.cjsto validate - CI Fast-Fail: GitHub Actions checks for nested requires before running tests
Quick Check
Before committing, verify no nested requires:
# Automated check (recommended)
node scripts/check-test-requires.cjs
# Manual check
grep -r "require('react')" app/tests/
grep -r "require('react-native')" app/tests/
Best Practices
- Always use ES6
importstatements - Never userequire('react')orrequire('react-native')in test files - Put all imports at the top of the file - No dynamic imports in hooks
- Avoid
require()calls inbeforeEach/afterEachhooks - React and React Native are already mocked in
jest.setup.js- use imports in test files
Detailed Guidelines
See .cursor/rules/test-memory-optimization.mdc for comprehensive guidelines, examples, and anti-patterns.
Linear Issue Interaction
When working with Linear issues during development:
save_commentfor: status updates, progress notes, blockers, linking PRs, corrections, decision recordssave_issuefor: changing status, priority, assignee, labels (structured fields only)create_documentfor: attaching specs as Linear documents
Never overwrite an issue description. Descriptions are the original scope set at creation time. All subsequent context goes in comments. If the description has a factual error, add a comment explaining the correction — do not silently rewrite it.
SDK Architecture
The Self Wallet app serves as a test environment for the SDK refactor. For SDK architecture context:
- SDK Overview — System architecture, bridge protocol, decision matrix (read-only reference)
- Implementation specs — Canonical source is
specs/projects/sdk/workstreams/<scope>/plans/(version-controlled). Linear documents attached to issues are mirrored copies for tracking/discovery. When in doubt, trust the repo spec.