|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +Instructions for AI coding agents working in the React Native Node-API repo. |
| 4 | + |
| 5 | +This is a **monorepo** that brings Node-API support to React Native, enabling native addons written in C/C++/Rust to run on React Native across iOS and Android. |
| 6 | + |
| 7 | +## Package-Specific Instructions |
| 8 | + |
| 9 | +**IMPORTANT**: Before working on any package, always check for and read package-specific instruction files (`AGENTS.md` or `copilot-instructions.md`) in the package directory. These contain critical preferences and patterns for that specific package. |
| 10 | + |
| 11 | +## Architecture Overview |
| 12 | + |
| 13 | +**Core Flow**: JS `require("./addon.node")` → Babel transform → `requireNodeAddon()` TurboModule call → native library loading → Node-API module initialization |
| 14 | + |
| 15 | +### Package Architecture |
| 16 | + |
| 17 | +See the [README.md](README.md#packages) for detailed descriptions of each package and their roles in the system. Key packages include: |
| 18 | + |
| 19 | +- `packages/host` - Core Node-API runtime and Babel plugin |
| 20 | +- `packages/cmake-rn` - CMake wrapper for native builds |
| 21 | +- `packages/cmake-file-api` - TypeScript wrapper for CMake File API with Zod validation |
| 22 | +- `packages/ferric` - Rust/Cargo wrapper with napi-rs integration |
| 23 | +- `packages/gyp-to-cmake` - Legacy binding.gyp compatibility |
| 24 | +- `apps/test-app` - Integration testing harness |
| 25 | + |
| 26 | +## Environment & Bootstrap |
| 27 | + |
| 28 | +- **Node.js 24 is required** — pinned in `.nvmrc` as `lts/krypton` (matching CI); `package.json`'s `devEngines` requires Node `^24` and pnpm `^10`, and the package manager refuses to install with an older runtime. With nvm: `nvm install && nvm use`. |
| 29 | +- **pnpm is the package manager** — pinned in `package.json`'s `packageManager` field. Let Corepack (bundled with Node) provide it: `corepack enable`, then use `pnpm`. |
| 30 | +- Standard setup for the Node.js tooling packages: |
| 31 | + |
| 32 | + ```bash |
| 33 | + pnpm install # Install workspace dependencies |
| 34 | + pnpm run build # Incremental TypeScript build (tsc --build) |
| 35 | + ``` |
| 36 | + |
| 37 | +- On Claude Code on the web, `.claude/hooks/session-start.sh` performs the above automatically (selecting the `.nvmrc` version via nvm and pnpm via Corepack) at session start. |
| 38 | +- **Native (iOS/Android) builds are not part of the default bootstrap.** `pnpm run bootstrap` and the native `bootstrap` scripts compile artifacts that require the Android NDK / Apple toolchains, which are absent on a generic Linux worker. Focus on the Node.js tooling packages; pass an explicit target (e.g. `pnpm exec ferric --apple`) only when the corresponding SDK is installed. |
| 39 | + |
| 40 | +## Prefer an upstream fix over a local workaround |
| 41 | + |
| 42 | +When a build/runtime failure looks like a known upstream bug, before writing a |
| 43 | +patch or workaround: |
| 44 | + |
| 45 | +1. Find where the fix actually landed and **verify at the source** — the |
| 46 | + changelog, lockfile, or the dependency's own manifest/podspec for a _specific |
| 47 | + installable version_, not the version list and not a related package's |
| 48 | + timeline (a fork or platform variant may carry a fix on a line its upstream |
| 49 | + never did). |
| 50 | +2. If an installable version within our constraints contains the fix, prefer the |
| 51 | + **smallest** bump that includes it (patch > minor > major) over a workaround. |
| 52 | +3. Treat the upgrade as a hypothesis under test: say so, and be ready to revert — |
| 53 | + every upgrade adds new unknown-bug surface. If it doesn't fix the issue, throw |
| 54 | + it away rather than stacking a workaround on top of it. |
| 55 | +4. If the bump is more than a patch, or widens scope/risk, check with me before |
| 56 | + committing to it. |
| 57 | +5. If no fixed version is reachable, a workaround is fine — but comment it with |
| 58 | + the exact condition that makes it removable (e.g. "remove once dep ships |
| 59 | + fmt ≥ 12.1"), and if you write that condition, verify it isn't already met. |
| 60 | + |
| 61 | +## Critical Build Dependencies |
| 62 | + |
| 63 | +- **Custom Hermes**: Currently depends on a patched Hermes with Node-API support (see [facebook/hermes#1377](https://github.com/facebook/hermes/pull/1377)) |
| 64 | +- **Prebuilt Binary Spec**: All tools must output to the exact naming scheme: |
| 65 | + - Android: `*.android.node/` with jniLibs structure + `react-native-node-api-module` marker file |
| 66 | + - iOS: `*.apple.node` (XCFramework renamed) + marker file |
| 67 | + |
| 68 | +## Essential Workflows |
| 69 | + |
| 70 | +### Package Development |
| 71 | + |
| 72 | +- **TypeScript project references**: Use `tsc --build` for incremental compilation |
| 73 | +- **Workspace scripts**: Most build/test commands use pnpm workspaces (`--filter` flag), run in topological (dependency) order and fail fast |
| 74 | +- **Focus on Node.js packages**: AI development primarily targets the Node.js tooling packages rather than native mobile code |
| 75 | +- **No TypeScript type asserts**: You have to ask explicitly and justify if you want to add `as` type assertions. |
| 76 | + |
| 77 | +## Key Patterns |
| 78 | + |
| 79 | +### Babel Transformation |
| 80 | + |
| 81 | +The core magic happens in `packages/host/src/node/babel-plugin/plugin.ts`: |
| 82 | + |
| 83 | +```js |
| 84 | +// Input: require("./addon.node") |
| 85 | +// Output: require("react-native-node-api").requireNodeAddon("pkg-name--addon") |
| 86 | +``` |
| 87 | + |
| 88 | +### CMake Integration |
| 89 | + |
| 90 | +For linking against Node-API in CMakeLists.txt: |
| 91 | + |
| 92 | +```cmake |
| 93 | +include(${WEAK_NODE_API_CONFIG}) |
| 94 | +target_link_libraries(addon PRIVATE weak-node-api) |
| 95 | +``` |
| 96 | + |
| 97 | +### Cross-Platform Naming |
| 98 | + |
| 99 | +Library names use double-dash separation: `package-name--path-component--addon-name` |
| 100 | + |
| 101 | +### Testing |
| 102 | + |
| 103 | +- **Individual packages**: Some packages have VS Code test tasks and others have their own `test` scripts for focused iteration (e.g., `pnpm --filter cmake-rn run test`). Use the latter only if the former is missing. |
| 104 | +- **Cross-package**: Use root-level `pnpm test` for cross-package testing once individual package tests pass |
| 105 | +- **Mobile integration**: Available but not the primary AI development focus - ask the developer to run those tests as needed |
| 106 | + |
| 107 | +**Documentation**: Integration details, platform setup, and toolchain configuration are covered in existing repo documentation files. |
0 commit comments