Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .claude/hooks/session-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
#
# SessionStart hook: bootstraps the repo so a fresh Claude Code worker can build,
# lint and test the Node.js tooling packages out of the box.
#
# It ensures the Node.js version pinned in .nvmrc (which matches CI), installs
# the npm workspace dependencies and builds the TypeScript project references.
#
# Native iOS/Android artifacts are intentionally NOT built here: they require the
# Android NDK / Apple toolchains which are not present on a generic Linux worker.
# See CLAUDE.md for how to build those when you actually need them.
set -euo pipefail

# Only bootstrap in remote (Claude Code on the web) workers. Local machines
# usually already have their own Node setup, so we don't want to interfere.
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
exit 0
fi

cd "${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel)}"

# --- Ensure the Node.js version from .nvmrc via nvm ---------------------------
# .nvmrc pins the Node version (matching CI). package.json's devEngines requires
# Node ^24 / npm ^11, and npm refuses to install with an older runtime. nvm ships
# on the remote workers, so use it to install and select the pinned version.
NVM_DIR="${NVM_DIR:-/opt/nvm}"
if [ ! -s "$NVM_DIR/nvm.sh" ] && [ -s "$HOME/.nvm/nvm.sh" ]; then
NVM_DIR="$HOME/.nvm"
fi

if [ -s "$NVM_DIR/nvm.sh" ]; then
export NVM_DIR
# nvm.sh dereferences unset variables, so relax `set -u` while it is active.
set +u
# shellcheck disable=SC1091
. "$NVM_DIR/nvm.sh"
# No version argument: nvm reads .nvmrc from the current directory.
nvm install >/dev/null
nvm use >/dev/null
NODE_BIN="$(dirname "$(nvm which current)")"
set -u

export PATH="$NODE_BIN:$PATH"

# Persist the resolved Node toolchain on PATH for the rest of the session.
if [ -n "${CLAUDE_ENV_FILE:-}" ]; then
echo "export PATH=\"$NODE_BIN:\$PATH\"" >> "$CLAUDE_ENV_FILE"
fi
else
echo "warning: nvm not found; using system Node $(node -v). package.json requires Node ^24." >&2
fi

echo "Using Node $(node -v) / npm $(npm -v)"

# --- Install dependencies and build the TypeScript packages -------------------
# `npm install` (not `ci`) so the resolved node_modules can be cached between
# sessions; it stays deterministic thanks to the committed package-lock.json.
npm install
npm run build

echo "Bootstrap complete: dependencies installed and TypeScript packages built."
14 changes: 14 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh"
}
]
}
]
}
}
79 changes: 5 additions & 74 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,8 @@
# Copilot Instructions for React Native Node-API

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.
The shared, tool-agnostic agent instructions for this repository now live in the
top-level [`AGENTS.md`](../AGENTS.md). Please read that file.

## Package-Specific Instructions

**IMPORTANT**: Before working on any package, always check for and read package-specific `copilot-instructions.md` files in the package directory. These contain critical preferences and patterns for that specific package.

## Architecture Overview

**Core Flow**: JS `require("./addon.node")` → Babel transform → `requireNodeAddon()` TurboModule call → native library loading → Node-API module initialization

### Package Architecture

See the [README.md](../README.md#packages) for detailed descriptions of each package and their roles in the system. Key packages include:

- `packages/host` - Core Node-API runtime and Babel plugin
- `packages/cmake-rn` - CMake wrapper for native builds
- `packages/cmake-file-api` - TypeScript wrapper for CMake File API with Zod validation
- `packages/ferric` - Rust/Cargo wrapper with napi-rs integration
- `packages/gyp-to-cmake` - Legacy binding.gyp compatibility
- `apps/test-app` - Integration testing harness

## Critical Build Dependencies

- **Custom Hermes**: Currently depends on a patched Hermes with Node-API support (see [facebook/hermes#1377](https://github.com/facebook/hermes/pull/1377))
- **Prebuilt Binary Spec**: All tools must output to the exact naming scheme:
- Android: `*.android.node/` with jniLibs structure + `react-native-node-api-module` marker file
- iOS: `*.apple.node` (XCFramework renamed) + marker file

## Essential Workflows

### Development Setup

```bash
npm ci && npm run build # Install deps and build all packages
npm run bootstrap # Build native components (weak-node-api, examples)
```

### Package Development

- **TypeScript project references**: Use `tsc --build` for incremental compilation
- **Workspace scripts**: Most build/test commands use npm workspaces (`--workspace` flag)
- **Focus on Node.js packages**: AI development primarily targets the Node.js tooling packages rather than native mobile code
- **No TypeScript type asserts**: You have to ask explicitly and justify if you want to add `as` type assertions.

## Key Patterns

### Babel Transformation

The core magic happens in `packages/host/src/node/babel-plugin/plugin.ts`:

```js
// Input: require("./addon.node")
// Output: require("react-native-node-api").requireNodeAddon("pkg-name--addon")
```

### CMake Integration

For linking against Node-API in CMakeLists.txt:

```cmake
include(${WEAK_NODE_API_CONFIG})
target_link_libraries(addon PRIVATE weak-node-api)
```

### Cross-Platform Naming

Library names use double-dash separation: `package-name--path-component--addon-name`

### Testing

- **Individual packages**: Some packages have VS Code test tasks and others have their own `npm test` scripts for focused iteration (e.g., `npm test --workspace cmake-rn`). Use the latter only if the former is missing.
- **Cross-package**: Use root-level `npm test` for cross-package testing once individual package tests pass
- **Mobile integration**: Available but not the primary AI development focus - ask the developer to run those tests as needed

**Documentation**: Integration details, platform setup, and toolchain configuration are covered in existing repo documentation files.
**IMPORTANT**: Before working on any package, also check for and read
package-specific instruction files (`AGENTS.md` or `copilot-instructions.md`) in
the package directory.
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lts/krypton
85 changes: 85 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# AGENTS.md

Instructions for AI coding agents working in the React Native Node-API repo.

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.

## Package-Specific Instructions

**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.

## Architecture Overview

**Core Flow**: JS `require("./addon.node")` → Babel transform → `requireNodeAddon()` TurboModule call → native library loading → Node-API module initialization

### Package Architecture

See the [README.md](README.md#packages) for detailed descriptions of each package and their roles in the system. Key packages include:

- `packages/host` - Core Node-API runtime and Babel plugin
- `packages/cmake-rn` - CMake wrapper for native builds
- `packages/cmake-file-api` - TypeScript wrapper for CMake File API with Zod validation
- `packages/ferric` - Rust/Cargo wrapper with napi-rs integration
- `packages/gyp-to-cmake` - Legacy binding.gyp compatibility
- `apps/test-app` - Integration testing harness

## Environment & Bootstrap

- **Node.js 24 is required** — pinned in `.nvmrc` as `lts/krypton` (matching CI); `package.json`'s `devEngines` requires Node `^24` and npm `^11`, and npm refuses to install with an older runtime. With nvm: `nvm install && nvm use`.
- Standard setup for the Node.js tooling packages:

```bash
npm install # Install workspace dependencies
npm run build # Incremental TypeScript build (tsc --build)
```

- On Claude Code on the web, `.claude/hooks/session-start.sh` performs the above automatically (selecting the `.nvmrc` version via nvm) at session start.
- **Native (iOS/Android) builds are not part of the default bootstrap.** `npm 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. `npx ferric --apple`) only when the corresponding SDK is installed.

## Critical Build Dependencies

- **Custom Hermes**: Currently depends on a patched Hermes with Node-API support (see [facebook/hermes#1377](https://github.com/facebook/hermes/pull/1377))
- **Prebuilt Binary Spec**: All tools must output to the exact naming scheme:
- Android: `*.android.node/` with jniLibs structure + `react-native-node-api-module` marker file
- iOS: `*.apple.node` (XCFramework renamed) + marker file

## Essential Workflows

### Package Development

- **TypeScript project references**: Use `tsc --build` for incremental compilation
- **Workspace scripts**: Most build/test commands use npm workspaces (`--workspace` flag)
- **Focus on Node.js packages**: AI development primarily targets the Node.js tooling packages rather than native mobile code
- **No TypeScript type asserts**: You have to ask explicitly and justify if you want to add `as` type assertions.

## Key Patterns

### Babel Transformation

The core magic happens in `packages/host/src/node/babel-plugin/plugin.ts`:

```js
// Input: require("./addon.node")
// Output: require("react-native-node-api").requireNodeAddon("pkg-name--addon")
```

### CMake Integration

For linking against Node-API in CMakeLists.txt:

```cmake
include(${WEAK_NODE_API_CONFIG})
target_link_libraries(addon PRIVATE weak-node-api)
```

### Cross-Platform Naming

Library names use double-dash separation: `package-name--path-component--addon-name`

### Testing

- **Individual packages**: Some packages have VS Code test tasks and others have their own `npm test` scripts for focused iteration (e.g., `npm test --workspace cmake-rn`). Use the latter only if the former is missing.
- **Cross-package**: Use root-level `npm test` for cross-package testing once individual package tests pass
- **Mobile integration**: Available but not the primary AI development focus - ask the developer to run those tests as needed

**Documentation**: Integration details, platform setup, and toolchain configuration are covered in existing repo documentation files.
21 changes: 21 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# CLAUDE.md

Guidance for Claude Code working in this repository.

The architecture overview, package layout, coding patterns, and
environment/bootstrap notes are shared with other AI tools and live in the
top-level, tool-agnostic instructions file — prefer editing that over
duplicating content here:

@AGENTS.md

## Claude Code on the web

A `SessionStart` hook (`.claude/hooks/session-start.sh`) bootstraps remote
workers automatically: it selects the Node.js version pinned in `.nvmrc` via
`nvm` (Node 24, as required by `package.json`'s `devEngines`), then runs
`npm install` and `npm run build`, so a fresh session is ready to build, lint,
and test the Node.js tooling packages.

See the "Environment & Bootstrap" section of `AGENTS.md` for the manual steps and
for why native iOS/Android builds are not part of the default bootstrap.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copilot Instructions for cmake-file-api Package
# AGENTS.md — cmake-file-api Package

This package provides a TypeScript wrapper around the CMake File API using Zod schemas for validation.

Expand Down
Loading