React Native shares JSX and hooks with React on the web and shares almost nothing else, which is exactly why agents go wrong here: they carry web assumptions across a boundary that looks invisible in the source. An agent needs to know that there is no DOM, that styling is a constrained flexbox subset rather than CSS, and that any dependency containing native code requires a rebuild rather than a Metro refresh. It also needs to know whether the New Architecture is enabled, since that affects which third party libraries work at all.
Scoped read and write access to the project.
The agent needs to see whether ios/ and android/ exist and are committed before it recommends anything involving native code.
History, diffs, and blame.
Native directory history reveals whether the project maintains its native folders by hand or regenerates them, which changes every native answer.
Reads issues, pull requests, and releases from GitHub.
Native module compatibility, especially around the New Architecture, is usually documented only in a library's open issues.
Pulls crash reports and stack traces from Sentry.
Native crashes never reproduce in the packager, so the symbolicated device trace is the only real evidence.
These are the failures that repeat across sessions, so each one belongs in .mcp.json.
To react to keyboard visibility, app foreground state, or dimension changes, agents write a useEffect with an interval or a one-shot read, because that pattern is everywhere in web React training data. The platform emits events for all three, and the subscription version is both cheaper and correct. Add to your rules file: 'Use the platform event APIs, Keyboard, AppState, and Dimensions listeners, rather than polling in useEffect, and always return the subscription remove function from the effect.'
Agents produce StyleSheet objects containing grid, position fixed, box-shadow, calc, or a percentage where only a number is accepted. Many of these are silently ignored rather than throwing, so the layout is simply wrong on device and correct in the agent's head. Write: 'Layout is flexbox only. No grid, no position fixed, no CSS shorthand strings. Shadows use shadowColor with shadowOffset and shadowOpacity on iOS plus elevation on Android.'
localStorage, document, window.matchMedia, and DOM event listeners appear regularly in agent output for React Native, usually inside a utility file where nothing signals the platform. These fail at runtime on device rather than at build time. Add: 'There is no DOM and no localStorage. Persistence uses the project's storage library, platform differences use Platform.select, and any code touching window or document is a mistake.'
An agent adds a package containing native modules, restarts Metro, sees the module is null, and then starts debugging the JavaScript. The actual requirement is a pod install on iOS and a fresh native build on both platforms. State it: 'Any dependency with native code requires cd ios && pod install and a full rebuild, not a Metro reload. If a native module resolves as undefined, rebuild before changing any application code.'
Agents map over an array of items inside a ScrollView because it is the shortest working code, which mounts every row at once and makes memory and scroll performance degrade with list length. On a mid-range Android device this is very visible. Add: 'Any list that can exceed roughly twenty items uses FlatList or SectionList with a stable keyExtractor. Never map an unbounded array inside a ScrollView.'
Rather than reading route params, agents put the selected item into Redux or a context so the next screen can read it, which breaks deep links, back navigation, and state restoration because the store and the navigator disagree. Write: 'Screen inputs are passed as route params and read with the navigation hooks. Global state holds server and session data only, never the identity of the currently viewed screen.'