{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://abyss.keyboard-hub.com/schemas/keybindings/v1.json",
  "title": "Keybindings",
  "description": "KeyboardHub reusable keybinding definitions.",
  "oneOf": [
    { "$ref": "#/definitions/KeyBinding" },
    { "$ref": "#/definitions/ModTapBinding" },
    { "$ref": "#/definitions/LayerTapBinding" },
    { "$ref": "#/definitions/MoBinding" },
    { "$ref": "#/definitions/TogBinding" },
    { "$ref": "#/definitions/ToBinding" },
    { "$ref": "#/definitions/SlBinding" },
    { "$ref": "#/definitions/MouseButtonBinding" },
    { "$ref": "#/definitions/MouseMoveBinding" },
    { "$ref": "#/definitions/MouseScrollBinding" },
    { "$ref": "#/definitions/BluetoothBinding" },
    { "$ref": "#/definitions/OutputBinding" },
    { "$ref": "#/definitions/CapsWordBinding" },
    { "$ref": "#/definitions/KeyRepeatBinding" },
    { "$ref": "#/definitions/KeyToggleBinding" },
    { "$ref": "#/definitions/StickyKeyBinding" },
    { "$ref": "#/definitions/GraveEscapeBinding" },
    { "$ref": "#/definitions/BootloaderBinding" },
    { "$ref": "#/definitions/ResetBinding" },
    { "$ref": "#/definitions/TransBinding" },
    { "$ref": "#/definitions/NoneBinding" },
    { "$ref": "#/definitions/RawBinding" },
    { "$ref": "#/definitions/MacroBinding" }
  ],
  "definitions": {
    "MacroStepBinding": {
      "oneOf": [
        { "$ref": "#/definitions/MacroDownBinding" },
        { "$ref": "#/definitions/MacroUpBinding" },
        { "$ref": "#/definitions/MacroTapBinding" },
        { "$ref": "#/definitions/MacroDelayBinding" }
      ]
    },
    "MacroStepKeyBinding": {
      "oneOf": [
        { "$ref": "#/definitions/KeyBinding" },
        { "$ref": "#/definitions/ModTapBinding" },
        { "$ref": "#/definitions/LayerTapBinding" },
        { "$ref": "#/definitions/MoBinding" },
        { "$ref": "#/definitions/TogBinding" },
        { "$ref": "#/definitions/ToBinding" },
        { "$ref": "#/definitions/SlBinding" },
        { "$ref": "#/definitions/MouseButtonBinding" },
        { "$ref": "#/definitions/MouseMoveBinding" },
        { "$ref": "#/definitions/MouseScrollBinding" },
        { "$ref": "#/definitions/BluetoothBinding" },
        { "$ref": "#/definitions/OutputBinding" },
        { "$ref": "#/definitions/CapsWordBinding" },
        { "$ref": "#/definitions/KeyRepeatBinding" },
        { "$ref": "#/definitions/KeyToggleBinding" },
        { "$ref": "#/definitions/StickyKeyBinding" },
        { "$ref": "#/definitions/GraveEscapeBinding" },
        { "$ref": "#/definitions/BootloaderBinding" },
        { "$ref": "#/definitions/ResetBinding" },
        { "$ref": "#/definitions/TransBinding" },
        { "$ref": "#/definitions/NoneBinding" },
        { "$ref": "#/definitions/RawBinding" }
      ]
    },
    "MacroDownBinding": {
      "type": "object",
      "description": "Macro step that presses and holds a binding until a later up step.",
      "required": ["action", "binding"],
      "additionalProperties": false,
      "properties": {
        "action": { "const": "down" },
        "binding": { "$ref": "#/definitions/MacroStepKeyBinding" }
      }
    },
    "MacroUpBinding": {
      "type": "object",
      "description": "Macro step that releases a previously held binding.",
      "required": ["action", "binding"],
      "additionalProperties": false,
      "properties": {
        "action": { "const": "up" },
        "binding": { "$ref": "#/definitions/MacroStepKeyBinding" }
      }
    },
    "MacroTapBinding": {
      "type": "object",
      "description": "Macro step that taps a binding, optionally with firmware-specific tap timing.",
      "required": ["action", "binding"],
      "additionalProperties": false,
      "properties": {
        "action": { "const": "tap" },
        "binding": { "$ref": "#/definitions/MacroStepKeyBinding" },
        "tapTime": {
          "type": "integer",
          "minimum": 0,
          "description": "Optional tap duration in milliseconds when a firmware format can preserve it."
        }
      }
    },
    "MacroDelayBinding": {
      "type": "object",
      "description": "Macro step that waits before continuing.",
      "required": ["action", "delayTime"],
      "additionalProperties": false,
      "properties": {
        "action": { "const": "delay" },
        "delayTime": {
          "type": "integer",
          "minimum": 0,
          "description": "Delay duration in milliseconds."
        }
      }
    },
    "KeyBinding": {
      "type": "object",
      "description": "Press a HID usage, optionally with modifiers held. ZMK: &kp [mods+]KEY. QMK: [MOD()]KC_KEY.",
      "required": ["type", "usage"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "key" },
        "usage": {
          "type": "integer",
          "minimum": 0,
          "description": "HID usage ID from the selected usagePage. Keyboard page examples: A=0x04, Enter=0x28, Escape=0x29, Space=0x2c."
        },
        "usagePage": {
          "type": "string",
          "enum": ["keyboard", "consumer"],
          "default": "keyboard",
          "description": "HID usage page. Omit for the Keyboard/Keypad page; use consumer for media/system controls."
        },
        "mods": {
          "type": "array",
          "description": "Modifiers held while pressing the usage (e.g. ['LSHIFT'] with usage 0x1e to produce '!').",
          "items": { "$ref": "#/definitions/ModifierCode" },
          "uniqueItems": true,
          "maxItems": 4
        }
      }
    },
    "ModTapBinding": {
      "type": "object",
      "description": "Mod-tap - hold for a modifier, tap for a HID usage. ZMK: &mt MOD KEY. QMK: MT(MOD_*, KC_KEY).",
      "required": ["type", "mod", "usage"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "mt" },
        "mod": { "$ref": "#/definitions/ModifierCode" },
        "usage": {
          "type": "integer",
          "minimum": 0,
          "description": "HID usage ID emitted when tapped."
        },
        "usagePage": {
          "type": "string",
          "enum": ["keyboard", "consumer"],
          "default": "keyboard"
        }
      }
    },
    "LayerTapBinding": {
      "type": "object",
      "description": "Layer-tap - hold for a momentary layer, tap for a HID usage. ZMK: &lt N KEY. QMK: LT(N, KC_KEY).",
      "required": ["type", "layer", "usage"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "lt" },
        "layer": { "type": "integer", "minimum": 0, "maximum": 31 },
        "usage": {
          "type": "integer",
          "minimum": 0,
          "description": "HID usage ID emitted when tapped."
        },
        "usagePage": {
          "type": "string",
          "enum": ["keyboard", "consumer"],
          "default": "keyboard"
        }
      }
    },
    "MoBinding": {
      "type": "object",
      "description": "Momentary layer - active while held. ZMK: &mo N. QMK: MO(N).",
      "required": ["type", "layer"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "mo" },
        "layer": { "type": "integer", "minimum": 0, "maximum": 31 }
      }
    },
    "TogBinding": {
      "type": "object",
      "description": "Toggle layer on/off. ZMK: &tog N. QMK: TG(N).",
      "required": ["type", "layer"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "tog" },
        "layer": { "type": "integer", "minimum": 0, "maximum": 31 }
      }
    },
    "ToBinding": {
      "type": "object",
      "description": "Switch to layer exclusively (deactivates all others). ZMK: &to N. QMK: TO(N).",
      "required": ["type", "layer"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "to" },
        "layer": { "type": "integer", "minimum": 0, "maximum": 31 }
      }
    },
    "SlBinding": {
      "type": "object",
      "description": "One-shot layer - activates for next keypress only. ZMK: &sl N. QMK: OSL(N).",
      "required": ["type", "layer"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "sl" },
        "layer": { "type": "integer", "minimum": 0, "maximum": 31 }
      }
    },
    "MouseButtonBinding": {
      "type": "object",
      "description": "Mouse button press. ZMK: &mkp MB1..MB5. QMK: MS_BTN1..MS_BTN5.",
      "required": ["type", "button"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "mouse_button" },
        "button": { "type": "integer", "minimum": 1, "maximum": 5 }
      }
    },
    "MouseMoveBinding": {
      "type": "object",
      "description": "Mouse cursor movement. ZMK: &mmv MOVE_* or encoded axis speed. QMK: MS_UP/MS_DOWN/MS_LEFT/MS_RGHT.",
      "required": ["type", "direction"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "mouse_move" },
        "direction": {
          "type": "string",
          "enum": ["up", "down", "left", "right"]
        },
        "speed": {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 32767,
          "description": "Optional movement speed. ZMK preserves this as the absolute axis value; QMK basic mouse keycodes do not carry speed."
        }
      }
    },
    "MouseScrollBinding": {
      "type": "object",
      "description": "Mouse wheel scrolling. ZMK: &msc SCRL_* or encoded wheel speed. QMK: MS_WHLU/MS_WHLD/MS_WHLL/MS_WHLR.",
      "required": ["type", "direction"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "mouse_scroll" },
        "direction": {
          "type": "string",
          "enum": ["up", "down", "left", "right"]
        },
        "speed": {
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 32767,
          "description": "Optional scroll speed. ZMK preserves this as the absolute axis value; QMK basic mouse keycodes do not carry speed."
        }
      }
    },
    "BluetoothBinding": {
      "type": "object",
      "description": "Bluetooth profile control. ZMK: &bt BT_NXT/BT_PRV/BT_SEL/BT_CLR/BT_CLR_ALL/BT_DISC. QMK exporters use BT_* labels when available.",
      "required": ["type", "action"],
      "additionalProperties": false,
      "allOf": [
        {
          "if": {
            "properties": {
              "action": { "enum": ["next", "previous", "clear_all"] }
            },
            "required": ["action"]
          },
          "then": { "properties": { "profile": false } }
        }
      ],
      "properties": {
        "type": { "const": "bluetooth" },
        "action": {
          "type": "string",
          "enum": [
            "clear",
            "next",
            "previous",
            "select",
            "clear_all",
            "disconnect"
          ]
        },
        "profile": {
          "type": "integer",
          "minimum": 0,
          "maximum": 9,
          "description": "Optional profile index for select, clear, or disconnect actions."
        }
      }
    },
    "OutputBinding": {
      "type": "object",
      "description": "Output selection. ZMK: &out OUT_USB/OUT_BLE/OUT_TOG/OUT_NONE. QMK: OU_USB/OU_BT/OU_AUTO/OU_NEXT/OU_PREV/OU_NONE/OU_2P4G.",
      "required": ["type", "action"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "output" },
        "action": {
          "type": "string",
          "enum": [
            "auto",
            "next",
            "previous",
            "none",
            "usb",
            "bluetooth",
            "2p4ghz",
            "toggle"
          ]
        }
      }
    },
    "CapsWordBinding": {
      "type": "object",
      "description": "Caps Word toggle. ZMK: &caps_word. QMK: QK_CAPS_WORD_TOGGLE / CW_TOGG.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": { "type": { "const": "caps_word" } }
    },
    "KeyRepeatBinding": {
      "type": "object",
      "description": "Repeat the last pressed key. ZMK: &key_repeat. QMK: QK_REPEAT_KEY / QK_REP.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": { "type": { "const": "key_repeat" } }
    },
    "KeyToggleBinding": {
      "type": "object",
      "description": "Toggle a held key. ZMK: &kt KEY. QMK/VIA: QK_LOCK represents key-lock for the next pressed key and omits usage.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "key_toggle" },
        "usage": {
          "type": "integer",
          "minimum": 0,
          "description": "Optional HID usage ID for the key to toggle. Omitted for QMK/VIA key-lock."
        },
        "usagePage": {
          "type": "string",
          "enum": ["keyboard", "consumer"],
          "default": "keyboard"
        },
        "mods": {
          "type": "array",
          "items": { "$ref": "#/definitions/ModifierCode" },
          "uniqueItems": true,
          "maxItems": 4
        }
      }
    },
    "StickyKeyBinding": {
      "type": "object",
      "description": "Sticky/one-shot key. ZMK: &sk KEY. QMK/VIA: OSM(mod) for modifier usages.",
      "required": ["type", "usage"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "sticky_key" },
        "usage": {
          "type": "integer",
          "minimum": 0,
          "description": "HID usage ID for the sticky key."
        },
        "usagePage": {
          "type": "string",
          "enum": ["keyboard", "consumer"],
          "default": "keyboard"
        },
        "mods": {
          "type": "array",
          "items": { "$ref": "#/definitions/ModifierCode" },
          "uniqueItems": true,
          "maxItems": 4
        }
      }
    },
    "GraveEscapeBinding": {
      "type": "object",
      "description": "Grave Escape. ZMK: &gresc. QMK: QK_GRAVE_ESCAPE / QK_GESC.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": { "type": { "const": "grave_escape" } }
    },
    "BootloaderBinding": {
      "type": "object",
      "description": "Firmware bootloader jump. ZMK: &bootloader. QMK: QK_BOOT.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": { "type": { "const": "bootloader" } }
    },
    "ResetBinding": {
      "type": "object",
      "description": "Firmware reset. ZMK: &sys_reset. QMK: QK_REBOOT.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": { "type": { "const": "reset" } }
    },
    "TransBinding": {
      "type": "object",
      "description": "Transparent - pass through to next active lower layer. ZMK: &trans. QMK: KC_TRNS.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": { "type": { "const": "trans" } }
    },
    "NoneBinding": {
      "type": "object",
      "description": "No-op - key does nothing. ZMK: &none. QMK: KC_NO.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": { "type": { "const": "none" } }
    },
    "RawBinding": {
      "type": "object",
      "description": "Firmware-specific escape hatch for bindings not expressible as HID usages or typed module mappings. At least one of zmk or qmk must be provided.",
      "required": ["type"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "raw" },
        "zmk": {
          "type": "string",
          "minLength": 1,
          "description": "Full ZMK binding expression, e.g. '&kp SOME_KEY' or '&custom_behavior PARAM'."
        },
        "qmk": {
          "type": "string",
          "minLength": 1,
          "description": "QMK keycode expression, e.g. 'CUSTOM_KEYCODE' or 'MY_MACRO'."
        },
        "label": {
          "type": "string",
          "description": "Human-readable label for UI display and KLE export.",
          "maxLength": 120
        }
      },
      "anyOf": [
        { "required": ["zmk"], "properties": { "zmk": { "type": "string" } } },
        { "required": ["qmk"], "properties": { "qmk": { "type": "string" } } }
      ]
    },
    "MacroBinding": {
      "type": "object",
      "description": "Trigger a named macro defined in the containing KeyboardHubKeymap document.",
      "required": ["type", "macro"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "macro" },
        "macro": {
          "type": "string",
          "minLength": 1,
          "description": "Name of an entry in top-level macros[]."
        }
      }
    },
    "ModifierCode": {
      "type": "string",
      "description": "Modifier keys used in KeyBinding.mods[].",
      "enum": [
        "LSHIFT",
        "RSHIFT",
        "LCTRL",
        "RCTRL",
        "LALT",
        "RALT",
        "LGUI",
        "RGUI"
      ]
    }
  }
}
