# AGENTS.md ## Project Overview `xone_macos` is a user-space macOS app that speaks to the Xbox Wireless Dongle (MediaTek MT76xx chip) and exposes connected controllers as HID gamepads. It ports the Linux kernel driver `medusalix/xone` to macOS: a C++ protocol stack (USB, MT76 chip, GIP, auth) plus a Swift app layer. Current state: build system and module scaffolding are in place. The protocol ports land phase by phase; see `PLAN.md`. ## Build System - **Generator:** Ninja (the Xcode generator also works; Unix Makefiles do not support Swift) - **CMake minimum:** 3.21 - **Languages:** C++23 (protocol stack), Swift (app layer) ### Commands Configure: ```sh cmake -S . -B build -GNinja -DBUILD_TESTING=ON ``` Build: ```sh ninja -C build ``` Run: ```sh ./build/xone_app ``` Run tests (full Unity output): ```sh ninja -C build check ``` Run a single test (requires prior build): ```sh ninja -C build test_version && ninja -C build test ``` > Prefer `ninja -C build check` for everyday use; it builds and runs in > one step. The built-in `test` target only executes CTest and does not > trigger a rebuild, so the binaries must already be up to date. Configure with AddressSanitizer: ```sh cmake -S . -B build-asan -GNinja -DBUILD_TESTING=ON -DENABLE_ASAN=ON ``` ### Dependencies Dependencies are managed via custom `Find*.cmake` scripts in `deps/`. These scripts use `FetchContent` under the hood to download and build libraries automatically. To add a new dependency: 1. Add the corresponding `Find.cmake` to `deps/` 2. Add `find_package( REQUIRED)` to `CMakeLists.txt` 3. Link with `::` in `target_link_libraries()` ### Static Libraries The project is split into static libraries, layered bottom-up: - **`xone_usb`**: USB transport (IOKit / IOUSBFamily) - **`xone_auth`**: auth + crypto (ECDH, RSA, SHA transcript/PRF) - **`xone_mt76`**: MT76 chip protocol (firmware load, EFUSE, radio init, beacons, pairing, WCID key setup) - **`xone_gip`**: GIP protocol (client lifecycle, handshake, status reports) - **`xone_hid`**: virtual HID gamepad presentation - **`xone_api`**: C ABI bridge consumed by the Swift app and tests The Swift executable `xone_app` links against `xone_api`. ### CMake Module Path `deps/` is added to `CMAKE_MODULE_PATH` so `find_package()` resolves to the custom scripts instead of system-installed packages. ## Coding Conventions ### C++ (protocol stack) - **Language:** C++23 - **Trailing return type** for function signatures (e.g. `auto fn() -> void`) - **4-space indentation** - **No semicolons after closing braces** for namespaces/classes - `auto` for obvious types (e.g. `auto main(...) -> int`) - **East const** (e.g. `char const*` not `const char*`) - **Public members first** in class declarations, private members at the bottom - `<>` includes only for system headers (std, OS, etc.) - `""` includes for third-party dependencies - **Naming:** `snake_case` for variables, functions, and classes - **Naming:** `SCREAMING_SNAKE_CASE` only for macros and constants - **Header extensions:** C++ headers use `.hpp`, C headers use `.h` - Include order: 1. C++ standard library headers (``, ``, etc.) 2. *(blank line)* 3. C standard library headers (``, ``, etc.) 4. *(blank line)* 5. OS-specific headers (IOKit, CoreFoundation, POSIX, etc.) 6. *(blank line)* 7. Third-party dependencies (`"unity.h"`, etc.) 8. *(blank line)* 9. Local/project headers ### Swift (app layer) - **4-space indentation** - Types: `UpperCamelCase`; functions, properties, and parameters: `lowerCamelCase` - Prefer `let` over `var`; default to immutability - Use `guard let` for early return; no force-unwraps outside tests - Keep the app layer thin (UI + lifecycle); protocol work lives in C++ ### C bridge (`include/app/xone_api.h`) - Pure C only: no C++ syntax. The header is imported into Swift via `-import-objc-header`, so it must compile as C. - Standard C declaration style; trailing returns and east const do not apply here. - Use `stdbool.h` types so Swift sees `Bool`. ## Shell Scripts - Always use `#!/bin/sh` shebang for shell scripts - Scripts must be POSIX compliant (no bashisms) - When providing commands to users: - Windows/PowerShell: use `` ` `` for line continuation - Unix/Linux/macOS: use `\` for line continuation ## Commit Messages - Follow the 50/72 rule: - Subject line: max 50 characters - Body lines: wrapped at 72 characters - Use conventional commit prefixes (`feat:`, `fix:`, `docs:`, `chore:`, `ci:`, etc.) - Separate subject from body with a blank line - Keep messages concise: no one wants to read a novel in the log - Always include a `Co-Authored-By:` trailer listing every agent or model that contributed to the commit. Use one line per co-author: ``` Co-Authored-By: porter (anthropic/claude): scaffolded build system Co-Authored-By: luna (openai/gpt-5.6-luna): reviewed edge cases ``` Example: ``` feat: add C ABI bridge for the Swift app Expose xone_version() and xone_dongle_present() through a pure C header so the Swift app can query the protocol stack. ``` ## Versioning This project follows [Semantic Versioning](https://semver.org). The version is set in the top-level `CMakeLists.txt` (`project(xone_macos VERSION ...)`). - **Patch** (`x.y.Z`): bump on every commit that changes code. No commit is too small. - **Minor** (`x.Y.z`): bump when adding a feature or significant new capability. - **Major** (`X.y.z`): bump on breaking API changes. ## Documentation (Markdown) - Wrap normal text and lists at **max 80 columns** (for readability in terminals and editors). - **Exceptions**: Tables and code blocks (```` ``` ````) can exceed 80 columns when formatting requires it (e.g. trees, alignment). - Use standard Markdown: `**bold**`, `` `inline code` ``, `##` headings, `-` or numbered lists, fenced code blocks with language hints (```` ```cpp ````, ```` ```sh ````). - Keep examples concise, up-to-date, and self-documenting. - This file (`AGENTS.md`) follows its own rules. - Do not use em dashes (`—`). Use a colon or rewrite the sentence. ## Source Layout ```text xone_macos/ CMakeLists.txt # Build configuration src/ # Protocol stack + app layer usb/ # USB transport (IOKit / IOUSBFamily) mt76/ # MT76 chip protocol (port of transport/mt76.c) gip/ # GIP protocol (port of bus/protocol.c) auth/ # Auth + crypto (port of auth/) hid/ # Virtual HID gamepad presentation app/ # Swift entry point + C ABI bridge include/ # Headers (common, usb, mt76, gip, auth, hid, app) tests/ # Unity test suites deps/ # Custom Find*.cmake scripts (FetchContent) firmware/ # Downloaded firmware binaries (gitignored) ``` ## Upstream Reference Protocol logic is ported from the Linux kernel driver [`medusalix/xone`](https://github.com/medusalix/xone). See the "Source Files to Port" table in `PLAN.md` for the module-by-module mapping and the "Quick Reference" table in `README.md` for the Linux-to-macOS API replacements. Kernel idioms (kzalloc, spin locks, URBs, uinput) must be replaced with their user-space / IOKit equivalents when porting. ## Behavioral Guidelines Reduce common LLM coding mistakes. These guidelines bias toward caution over speed. For trivial tasks, use judgment. ### 1. Think Before Coding Don't assume. Don't hide confusion. Surface tradeoffs. Before implementing: - State your assumptions explicitly. If uncertain, ask. - If multiple interpretations exist, present them, don't pick silently. - If a simpler approach exists, say so. Push back when warranted. - If something is unclear, stop. Name what's confusing. Ask. ### 2. Simplicity First Minimum code that solves the problem. Nothing speculative. - No features beyond what was asked. - No abstractions for single-use code. - No "flexibility" or "configurability" that wasn't requested. - No error handling for impossible scenarios. - If you write 200 lines and it could be 50, rewrite it. Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify. ### 3. Surgical Changes Touch only what you must. Clean up only your own mess. When editing existing code: - Don't "improve" adjacent code, comments, or formatting. - Don't refactor things that aren't broken. - Match existing style, even if you'd do it differently. - If you notice unrelated dead code, mention it, don't delete it. When your changes create orphans: - Remove imports/variables/functions that YOUR changes made unused. - Don't remove pre-existing dead code unless asked. Every changed line should trace directly to the user's request. ### 4. Goal-Driven Execution Define success criteria. Loop until verified. Transform tasks into verifiable goals: - "Add validation" means: write tests for invalid inputs, then make them pass. - "Fix the bug" means: write a test that reproduces it, then make it pass. - "Refactor X" means: ensure tests pass before and after. For multi-step tasks, state a brief plan: ``` 1. [Step] → verify: [check] 2. [Step] → verify: [check] 3. [Step] → verify: [check] ``` Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. ## Platform Support The project targets macOS only (Intel and Apple Silicon). Platform and compiler detection lives in `deps/Platform.cmake` and `deps/Flags.cmake`. Swift is compiled by CMake, which requires the Ninja or Xcode generator.