aircraft (Agent Skills)

GitHub

The A32NX & A380X Project are community driven open source projects to create free Airbus aircraft in Microsoft Flight Simulator that are as close to reality as possible.

5,398 stars TypeScript 1 Rule Files Full Docs MCP View JSON API #a320#a380#javascript#matlab

AGENTS.md

# AGENTS.md

This file applies to the entire repository. More specific `AGENTS.md` files, if added below this directory, override it for their subtree.

## Repository map

- `fbw-a32nx/`: A320neo-specific package, instruments, TypeScript systems, models, behaviors, and WASM.
- `fbw-a380x/`: A380-specific package, instruments, TypeScript systems, and WASM.
- `fbw-common/`: code shared by both aircraft, including SDK utilities, instrument components, typings, tests, and common WASM crates.
- `fbw-ingamepanels-checklist-fix/`: separate in-game panel package.
- `scripts/`: setup, build, packaging, lint, and development-container entry points.
- `tools/`: standalone project utilities.
- `large-files/`: Git submodule for large binary assets. Do not modify its contents or submodule pointer unless the task explicitly concerns those assets.
- `igniter.config.mjs`: top-level build graph. `fbw-a32nx/mach.config.js` and `fbw-a380x/mach.config.js` register instrument entry points.
- `fbw-*/out/`, `build/`, `target/`, instrument bundles, and generated localization files are build products; change their source or generator rather than generated output.

Put aircraft-independent behavior in `fbw-common` when both aircraft genuinely share the same contract. Keep aircraft geometry, configuration, simvars, and system behavior in the relevant aircraft tree. Preserve existing path aliases such as `@flybywiresim/*`, `@shared/*`, and `@instruments/*` instead of adding long relative imports.

## Generated sources

- Do not modify generated behavior XML sources in `generated` folders.
- Do not modify the generated `model/` folders in the fly-by-wire WASM modules: `fbw-a32nx/src/wasm/fbw_a320/src/model/` and `fbw-a380x/src/wasm/fbw_a380/src/model/`.

## Environment and build system

The pinned Docker development environment is the source of truth for full builds and CI-equivalent validation. Initialize the submodule before building.

```sh
git submodule update --init
./scripts/dev-env/run.sh ./scripts/setup.sh
./scripts/dev-env/run.sh ./scripts/build.sh
```

On Windows, use `scripts\dev-env\run.cmd` in place of `run.sh`. Setup runs `pnpm install`; keep `pnpm-lock.yaml` synchronized and do not introduce another package manager lockfile.

**Important:** Set `FBW_TYPECHECK=1` in the environment to enable TypeScript checks. This must be done before code is considered deliverable.

Useful scoped commands:

```sh
# Full aircraft builds (the -r expression selects Igniter tasks)
./scripts/dev-env/run.sh ./scripts/build.sh -r "a32nx"
./scripts/dev-env/run.sh ./scripts/build.sh -r "a380x"

# Instrument-only development, from the selected aircraft directory
pnpm exec mach build -f PFD
pnpm exec mach watch -f PFD

# Or from the repository root
pnpm exec mach build --config fbw-a32nx/mach.config.js --work-in-config-dir -f PFD
```

Mach/esbuild contains native binaries. If dependencies were installed inside the Linux container, host-side Mach can fail; run it in a matching environment or reinstall the host binary as described in the instrument README. Full builds also require the initialized `large-files` submodule. Avoid a full two-aircraft build when a focused instrument, crate, or test validates the change.

The Rust workspace is defined by the root `Cargo.toml`, pinned by `rust-toolchain.toml`, and targets `wasm32-wasip1`. C++/WASM code is built through the root CMake configuration and `scripts/build-cmake.sh`.

## React versus FSComponent

This repository has two unrelated JSX runtimes. A `.tsx` suffix alone does not identify which one a file uses. Before editing or moving instrument code, inspect the instrument's nearest `tsconfig.json`, its entry point, and its registration in the aircraft `mach.config.js`.

### MSFS SDK FSComponent instruments

The normal instrument tsconfig uses:

```json
"jsxFactory": "FSComponent.buildComponent",
"jsxFragmentFactory": "FSComponent.Fragment"
```

Mach registers these with `msfsAvionicsInstrument(...)`. Current examples include PFD, ND, EWD, FCU, Clock, MFD, OANC, and SDv2 (the exact lists differ by aircraft).

- Use `DisplayComponent`, `FSComponent`, `VNode`, `Subject`/`MappedSubject`, event-bus publishers and subscribers, and SDK lifecycle methods.
- Keep `FSComponent` imported when JSX needs the configured factory; ESLint intentionally exempts that name from unused-variable reporting.
- Use FSComponent JSX conventions, notably `class`, subscribable attributes, and SDK refs. Do not mechanically convert them to React's `className` or React refs.
- Create subscriptions in the appropriate lifecycle phase (usually `onAfterRender`). Retain subscriptions/resources and destroy them in `destroy()`, then call `super.destroy()`.
- Mount with `FSComponent.render(...)` from the base instrument's `connectedCallback`; drive publishers/backplanes from the instrument update lifecycle.
- Do not use React hooks, React context, `ReactDOM`, or React-only libraries in an FSComponent tree.

### React instruments

React instruments extend `tsconfig.react.json`, whose JSX factory is `React.createElement`, and Mach registers them with `reactInstrument(...)`. Examples include EFB and BAT plus legacy or aircraft-specific instruments such as A32NX SD and A380X SD/RTPI.

- Use React 17 conventions: `className`, React refs, hooks, context/providers, and the existing React render helper.
- Use `@flybywiresim/fbw-sdk-react` hooks where established. Clean up timers, listeners, and subscriptions in the `useEffect` cleanup function.
- Follow the Rules of Hooks even though the root ESLint configuration cannot yet enforce every React rule.
- Do not pass React elements or hooks into an FSComponent subtree. Share framework-neutral data/model code when logic is needed by both runtimes.
- New instruments should use FSComponent; the instrument README explicitly says to avoid React for new instruments unless the development team agrees otherwise.

When adding an instrument, update the appropriate `mach.config.js`, choose the correct helper, add the matching local tsconfig inheritance, and follow a neighboring instrument's base-instrument registration and package layout.

## TypeScript and JavaScript conventions

- TypeScript is preferred in `src/systems`; JavaScript is mainly for build/config scripts and legacy exceptions.
- The simulator runtime targets ES2017/Coherent GT. Do not assume Node.js APIs or modern browser APIs are available in shipped instrument code.
- Use 2 spaces, single quotes, trailing commas where Prettier emits them, and a 120-column print width. Let repository ESLint/Prettier rules decide formatting.
- The TypeScript strictness plugin is incremental. Do not add `// @ts-strict-ignore` to new files or broaden an existing exemption merely to silence errors; keep new and modified code strictly typed where practical.
- Prefix intentionally unused parameters or locals with `_`. Do not add blanket ESLint disables when a narrow line-level exception is sufficient.
- Preserve the copyright/SPDX header style used by neighboring files. When modifying a file with a copyright header, extend its ending year to the current calendar year; retain existing holders and SPDX identifiers.
- Keep simulator reads/writes, event-bus topics, ARINC validity handling, units, and update frequency explicit. Avoid polling faster than the source data requires.
- Follow local naming and file organization. Instrument folders contain domain-specific conventions that are more authoritative than distant examples.

## Rust and C++ conventions

- Format Rust with `cargo fmt`; keep Clippy warning-free under the flags in `scripts/lint-rust.sh`.
- Add Rust unit tests close to the module under test. Use package-scoped commands during iteration, then workspace validation when warranted.
- Follow the root `.clang-format` (Chromium base, two-space indentation, 140-column limit) or a closer subtree override for C/C++.
- Preserve physical units and simulation update semantics. Prefer the existing typed-unit and simulation-element abstractions over raw numeric values.

## Tests and validation

Run the smallest relevant checks first, followed by the broader checks justified by the change.

```sh
# TypeScript/JavaScript
pnpm lint
pnpm test
pnpm exec vitest run path/to/file.spec.ts

# Rust (CI-equivalent scripts)
./scripts/dev-env/run.sh scripts/lint-rust.sh
./scripts/dev-env/run.sh scripts/test-rust.sh

# Faster scoped Rust iteration
cargo test -p <package>
cargo clippy -p <package> --all-targets --all-features -- -D warnings -A clippy::too_many_arguments -A deprecated
```

TypeScript tests are colocated as `*.spec.ts`/`*.spec.tsx`; Vitest uses `jsdom` and `fbw-common/src/jest/setupJestMock.ts`. Add regression tests for pure logic and system behavior where feasible. UI or simulator-coupled changes should also receive a focused Mach build and an in-simulator check when behavior cannot be covered outside MSFS. Report which checks ran and which could not run.

Before handing off a change:

1. Review `git diff` and do not include build products, secrets, `.env` changes, or unrelated user modifications.
2. Run lint/tests for touched languages and a focused build for affected instruments or aircraft.
3. Keep `pnpm-lock.yaml` and `Cargo.lock` changes intentional.
4. For contributions, follow `.github/Contributing.md`: realism changes need supporting documentation, commits/PR titles use Conventional Commits, and user-visible changes require an entry in `.github/CHANGELOG.md`.