# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Custom QMK firmware for a System76 Launch 3 keyboard (RP2040, 84-key). The custom keymap adds OS-aware shortcut translation (Linux/Mac/Windows) with automatic OS detection. ## Build Commands ```bash # Development (uses symlink to custom keymap) nix develop qmk compile -kb system76/launch_3 -km custom # Production build (sandboxed, outputs result/system76_launch_3_custom.uf2) nix build ``` New files in `keymaps/custom/` must be `git add`ed before `nix build` — flakes only see git-tracked files. ## Architecture ### Repository Layout - `qmk_firmware/` — System76's QMK fork (git submodule, do not modify) - `keymaps/custom/` — Custom keymap, kept separate from the submodule - `flake.nix` — Dev shell and sandboxed firmware build; uses `self.submodules = true` ### Custom Keymap Files (`keymaps/custom/`) - `keymap.c` — Keymaps, layer override, modifier rewriting, process_record_user - `os_detect.c` — OS auto-detection polling, os_mode/os_mode_manual definitions, RGB flash - `os_mode.h` — Shared `os_mode_t` enum and extern declarations - `rules.mk` — Enables OS_DETECTION and adds `SRC += os_detect.c` ### Key Constraints **keymap_introspection.c textually `#include`s keymap.c** — this means: - Headers in `keymaps/custom/` can't be `#include`d from `keymap.c` (the compiler resolves includes relative to `quantum/keymap_introspection.c`, not the included file) - Variables shared between `keymap.c` and other files must be non-static with `extern` declarations - Guard OS-specific code with `#ifdef OS_DETECTION_ENABLE` if it uses types from guarded headers, or put it in a separate `.c` file (preferred) **keyboard_post_init_user is taken** by `launch_3.c` — use `matrix_init_user` instead. **DYNAMIC_KEYMAP_ENABLE** causes EEPROM to override PROGMEM keymaps — `dynamic_keymap_reset()` in `matrix_init_user` forces PROGMEM back. ### Modifier Rewriting System `mod_rewrite_t` structs define from→to modifier translations. `normalize_mods()` collapses left/right modifier variants into a single nibble for comparison. `mods_match()` does exact mod matching and skips rewrites when FN layer is active. ### OS Mode `os_mode_t` enum (NONE/LINUX/MAC/WINDOWS). Auto-detected via USB enumeration polling after 2s. Manual cycling via FN+Del (`CK_OSMODE`). Once manually set, `os_mode_manual` prevents auto-detection override. RGB indicator: red=none, green=linux, yellow=mac, blue=windows. OS detection on System76's QMK fork often misidentifies Linux as Windows — both currently map to `OS_MODE_LINUX`. ### Nix Build The flake copies `keymaps/custom/` into the QMK tree during `postUnpack`. `patchShebangs` is needed for `uf2conv.py` in the sandbox. `python3` and `python3Packages.appdirs` are required nativeBuildInputs.