Note: CLAUDE.md is a symlink to AGENTS.md. Edit AGENTS.md directly.
keymaps/
├── firmware/ # Canonical keyboard definitions (synced to $QMK_HOME via sync tasks)
│ └── lazydesigners/
│ └── apricot/ # keyboard.json, apricot.h, apricot.c
├── keyboards/ # Keymaps for keyboards
│ └── lazydesigners/
│ └── apricot/
│ └── keymaps/
│ └── patcoll/
├── users/ # User-specific keymap code (shared across keyboards)
│ └── patcoll/
├── working_area/ # $QMK_HOME lives here (external, not in repo)
│ └── qmk_firmware/
└── qmk.json # QMK external userspace config
Key directories:
firmware/- Custom keyboard definitions. Synced to QMK_HOME viamise run sync.keyboards/- Keymaps that reference keyboards (either from firmware/ or upstream QMK).users/- Shared user code (macros, combos, tap behaviors, etc.). This repo is configured as a QMK external userspace.working_area/qmk_firmware/- Working copy of QMK firmware (cloned viamise run setup).
Key files:
keymaps- Canonical list of keyboards we care about. Used by build system.
To get the list of keyboards with custom firmware (keyboards in keymaps that have firmware in firmware/):
mise run firmware:listThis project uses uv for Python dependency management and mise for task automation. It also uses QMK's external userspace feature.
-
Install dependencies:
uv sync
-
Clone QMK firmware and install its dependencies:
mise run setup
-
Sync keyboards and keymaps:
mise run sync-all
The setup task will:
- Clone the QMK firmware repository to
working_area/qmk_firmware/ - Install QMK firmware Python dependencies into the uv-managed virtual environment
The sync-all task will:
- Rsync custom firmware from
firmware/to QMK_HOME - Symlink keymaps from
keyboards/into QMK_HOME
QMK_HOME: Points toworking_area/qmk_firmware(defined inmise.toml)QMK_USERSPACE: Points to this repo root (enables external userspace forusers/directory)
Use mise run <task> to execute:
mise run setup- Clone QMK firmware and install dependencies (run after teardown)mise run teardown- Remove QMK firmware directory (requires setup to rebuild)mise run sync <keyboard>- Sync firmware and keymaps for one keyboard to QMK_HOMEmise run sync-all- Sync all keyboards listed inkeymapsfilemise run reset <keyboard>- Remove and re-sync a keyboard (only for keyboards with custom firmware)mise run remove <keyboard>- Remove a keyboard's firmware from QMK_HOMEmise run clean- Runqmk clean -ato clean build artifactsmise run test- Build all keymaps to verify they compilemise run qmk <command>- Run any QMK CLI command in $QMK_HOME
# Compile firmware
mise run qmk compile -kb lazydesigners/apricot -km patcoll
# Flash firmware to keyboard
mise run qmk flash -kb lazydesigners/apricot -km patcoll
# List available keyboards
mise run qmk list-keyboards
# Get keyboard info
mise run qmk info -kb lazydesigners/apricot# Compile your keymap
mise run qmk compile -kb <keyboard> -km <keymap>
# Flash to keyboard
mise run qmk flash -kb <keyboard> -km <keymap>CRITICAL: After mise run teardown, you must run both mise run setup and mise run sync-all before builds will work.
# Correct workflow after teardown
mise run teardown
mise run setup # Clone QMK firmware
mise run sync-all # Sync keyboards and keymaps
mise run qmk compile -kb <keyboard> -km <keymap>
# Incorrect - will fail
mise run teardown
mise run qmk compile -kb <keyboard> -km <keymap> # ERROR: no QMK firmware
# Also incorrect - keyboard not synced
mise run teardown
mise run setup
mise run qmk compile -kb <keyboard> -km <keymap> # ERROR: keyboard not foundThis keyboard has been migrated from legacy format to modern keyboard.json format for QMK 0.31.9+ compatibility.
Modern format (in firmware/lazydesigners/apricot/):
keyboard.json- All hardware configuration (USB IDs, matrix pins, features, layout)apricot.h- Header only, no LAYOUT macro (auto-generated from keyboard.json)apricot.c- Keyboard code
Removed legacy files:
info.json- Replaced by keyboard.jsonconfig.h- Merged into keyboard.jsonrules.mk- Merged into keyboard.json
How it works: The firmware/ directory is the canonical source. Running mise run sync <keyboard> rsyncs these files to $QMK_HOME/keyboards/, overriding any upstream QMK files. Keymaps from keyboards/ are symlinked into QMK_HOME. QMK auto-generates the LAYOUT macro from keyboard.json at compile time.
How to convert old QMK firmware (info.json + config.h + rules.mk) to modern keyboard.json format.
Combine these legacy files into one keyboard.json:
| Legacy File | keyboard.json Section |
|---|---|
info.json |
keyboard_name, manufacturer, url, maintainer, layouts |
config.h |
usb, matrix_pins, diode_direction, ws2812, rgblight |
rules.mk |
processor, bootloader, features |
Layout format change: Old info.json uses labels, new format uses matrix positions:
// OLD: {"label": "K000", "x": 0, "y": 0}
// NEW: {"matrix": [0, 0], "x": 0, "y": 0}Matrix gaps (KC_NO in old LAYOUT macro) are simply omitted from the layout array.
Remove the LAYOUT macro from <keyboard>.h - QMK auto-generates it from keyboard.json.
Keep only:
#pragma once
#include "quantum.h"Remove: info.json, config.h, rules.mk
Keep: keyboard.json, <keyboard>.h, <keyboard>.c
QMK 0.31.9 renamed many keycodes:
Mouse movement:
| Old | New |
|---|---|
KC_MS_L |
MS_LEFT |
KC_MS_R |
MS_RGHT |
KC_MS_U |
MS_UP |
KC_MS_D |
MS_DOWN |
Mouse buttons:
| Old | New |
|---|---|
KC_BTN1 |
MS_BTN1 |
KC_BTN2 |
MS_BTN2 |
KC_BTN3 |
MS_BTN3 |
Mouse wheel:
| Old | New |
|---|---|
KC_WH_L |
MS_WHLL |
KC_WH_R |
MS_WHLR |
KC_WH_U |
MS_WHLU |
KC_WH_D |
MS_WHLD |
RGB underglow:
| Old | New |
|---|---|
RGB_TOG |
UG_TOGG |
RGB_MOD |
UG_NEXT |
RGB_HUI |
UG_HUEU |
RGB_SAI |
UG_SATU |
RGB_VAI |
UG_VALU |
Remove redundant defines that are now in keyboard.json:
RGBLIGHT_LED_COUNT(nowrgblight.led_countin keyboard.json)- Any
#definethat duplicates keyboard.json settings
# Check JSON syntax
python3 -m json.tool firmware/<keyboard>/keyboard.json
# Verify keyboard is recognized
mise run qmk list-keyboards | grep <keyboard>
# Check configuration
mise run qmk info -kb <keyboard>
# Test compile
mise run qmk compile -kb <keyboard> -km <keymap>- Both info.json and keyboard.json exist - QMK gets confused. Delete info.json.
- LAYOUT macro still in .h file - Causes "Layout macro should not be defined within .h files" warning. Remove it.
- Old keycodes in keymaps - Compilation errors like "'KC_BTN1' undeclared". Update to new names.
- Redundant defines in keymap config.h - Warnings about redefinition. Remove duplicates.
To switch QMK firmware versions:
- Edit
mise-tasks/setupand change theqmk clone -b <version>line - Run:
mise run teardown mise run setup mise run sync-all
This will re-clone the firmware at the new version and re-sync all keyboards.
The GitHub Actions workflow (.github/workflows/keymaps.yml) uses awalsh128/cache-apt-pkgs-action to pre-cache apt packages for faster builds. The qmk_install.sh step still runs to ensure all dependencies are properly installed, but the cached packages make it faster.