Cross-platform ground control station for drones (Android, iOS, Mac OS, Linux, Windows)
# AGENTS.md
Instructions for AI coding agents (Codex, Claude Code, etc.) working on QGroundControl.
## Quick References
- [CODING_STYLE.md](CODING_STYLE.md) โ Naming, formatting, C++20 features, QML style, logging
- [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) โ Architecture patterns (Fact System, Multi-Vehicle, FirmwarePlugin)
- [tools/README.md](tools/README.md) โ Development scripts and tooling
- [test/README.md](test/README.md) โ Test framework, base classes, CTest labels, MultiSignalSpy, coverage
- [.github/ci-overview.md](.github/ci-overview.md) โ CI workflow/action/script layout and conventions
- [.pre-commit-config.yaml](.pre-commit-config.yaml) โ All enforced linters (clang-format, clang-tidy, ruff, pyright, shellcheck, actionlint, zizmor, qmllint, clazy, vehicle-null-check, check-no-qassert, check-no-qtest-ignore-message)
## Required Preflight
Before modifying any repository file:
1. Read [CODING_STYLE.md](CODING_STYLE.md) completely.
2. Read the task-specific references listed in this file.
3. Do not begin editing until those reads are complete.
4. Before the first edit, state in a progress update which instruction files were read.
## Golden Rules (enforced โ violations fail CI)
These are the non-negotiables. The first four are QGC's core architecture patterns; the rest are
enforced by pre-commit hooks, so ignoring them wastes a build cycle. Full list with code examples:
[.github/CONTRIBUTING.md#architecture-patterns](.github/CONTRIBUTING.md#architecture-patterns) and
[CODING_STYLE.md#common-pitfalls](CODING_STYLE.md#common-pitfalls).
- **Fact System** โ ALL vehicle parameters flow through Facts; never create custom parameter storage.
- **Multi-Vehicle** โ ALWAYS null-check `activeVehicle()` / `Vehicle*` before dereferencing (`vehicle-null-check`).
- **Firmware Plugin** โ use `vehicle->firmwarePlugin()` for firmware-specific behavior, not `if (px4)` branches.
- **QML Integration** โ register types with `QML_ELEMENT`/`QML_SINGLETON`/`QML_UNCREATABLE`; expose state via `Q_PROPERTY`.
- **No `Q_ASSERT` in production code** โ use defensive checks with early returns (`check-no-qassert`).
- **No `QTest::ignoreMessage`** in tests โ use `expectLogMessage`/`ignoreLogMessage` (`check-no-qtest-ignore-message`).
- **No fixed-delay `QTest::qWait(<n>)`** โ use `QTRY_*_WITH_TIMEOUT` or `QSignalSpy::wait` (`check-no-fixed-qwait`).
- **Comments** โ prefer self-documenting code; comment only non-obvious intent, constraints, or workarounds.
## Critical Files (Read First!)
1. `src/FactSystem/Fact.h` โ Parameter system foundation
2. `src/Vehicle/Vehicle.h` โ Core vehicle model
3. `src/FirmwarePlugin/FirmwarePlugin.h` โ Firmware abstraction
## Code Structure
Key modules (full tree under `src/` โ ~33 subdirectories):
```text
src/
โโโ Vehicle/ # Vehicle state/comms
โโโ Comms/ # Link layer (serial, UDP, TCP, Bluetooth)
โโโ FactSystem/ # Parameter management
โโโ FirmwarePlugin/ # PX4/ArduPilot abstraction
โโโ AutoPilotPlugins/ # Vehicle setup UI
โโโ MissionManager/ # Mission planning
โโโ MAVLink/ # Protocol handling
โโโ VideoManager/ # Video pipeline (GStreamer)
โโโ FlyView/ # In-flight UI
โโโ PlanView/ # Mission planning UI
โโโ QmlControls/ # Reusable QML components
โโโ Settings/ # Persistent settings
```
## Build & Test Commands
The `just` recipes are the canonical workflow โ see [tools/README.md](tools/README.md) for the full list.
[.github/ci-overview.md](.github/ci-overview.md) documents how CI invokes builds and tests; match CI, don't guess.
```bash
just configure # CMake configure (pulls submodules first)
just build # incremental build; uses all cores (override with JOBS=N)
just test # ctest, LABELS="Unit|Integration" EXCLUDE="Flaky|Network"
just lint # fast pre-commit gate (clang-format, ruff, qmllint, ...)
just check # lint + test (run before declaring done)
just format-fix # apply clang-format / ruff-format
just info # print resolved versions (Qt, CMake, GStreamer)
```
- **Build incrementally** โ rebuild every few file edits during multi-file C++/Qt work, not just at the end; fix build errors before continuing.
- **Tight test loops** โ iterate one test with `ctest -R <name>` (or `--gtest_filter`); only run the full label on the final pass. CI runs `ctest --output-on-failure -L Unit`.
- **Match CI** โ before running tests/lint locally, use the same command CI runs ([.github/ci-overview.md](.github/ci-overview.md)), not a local guess.
## Definition of Done
Before considering a change complete:
1. `just build` succeeds.
2. `just lint` (or `pre-commit run --all-files` for the full sweep) passes.
3. Relevant tests pass (`ctest -R <name>` for the touched area; full `-L Unit` on the final pass).
4. Commit message follows Conventional Commits (below).
## Commit & Review Conventions
Commit messages follow **Conventional Commits** โ the type drives release automation
(`.releaserc.json` โ semantic-release). Use: `feat`, `fix`, `perf`, `revert` (release-triggering);
`docs`, `style`, `chore`, `refactor`, `test`, `build`, `ci` (no release). Example: `fix(Vehicle): guard null activeVehicle in telemetry handler`.
Keep pull request history intentional and easy to review. Organize related work into coherent commits and
combine fixups or closely related incremental changes before publication. Avoid a trail of tiny work-in-progress,
cleanup, or review-fix commits. Each commit should represent a clear, reviewable change without mixing unrelated work.
Your output will be reviewed by another AI agent before being accepted. Keep changes focused and
minimal, use clear naming, and leave explanatory commit messages. Avoid unrelated changes,
commented-out code, or ambiguous TODOs.
---
**Key Principle**: Match the style of code you're editing. See [CODING_STYLE.md](CODING_STYLE.md) for conventions and [CODING_STYLE.md#examples](CODING_STYLE.md#examples) for canonical Vehicle/Fact/QML snippets.