name: qmk-rgb
Explains how to control RGB lighting on QMK-compatible keyboards using qmk-rgb-tool.
When a user asks about RGB lighting, effects, colors, brightness, zones, profiles, or keyboard lighting in general — use this skill. Always delegate to the tool for live data and up-to-date help.
Any RGB-related question about QMK keyboards, effects, colors, zones, brightness, profiles, or keyboard lighting.
The tool is the single source of truth. Always start by fetching its output:
qmk-rgb-tool --help # Command structure
qmk-rgb-tool effect all # Effects per zone, one per line
qmk-rgb-tool --json effect all # The same, as JSON for parsing
qmk-rgb-tool keyboard info # Connected keyboards
qmk-rgb-tool info # Current RGB state
qmk-rgb-tool keyboard definitions # Which definition files are in use, and where each is from
Present the raw output to the user. Never duplicate documentation — the tool output is authoritative.
These are two different problems and need different commands. qmk-rgb-tool
effect all opens the keyboard, so it fails when none is connected; use
keyboard info, which does not.
If the tool is not built:
The tool is not currently built. Would you like me to build it and run
qmk-rgb-tool keyboard info?
If no keyboard is connected:
No QMK keyboard is connected.
qmk-rgb-tool keyboard infolists what is found — plug the board in, or check that it is in wired mode, and I will run it again.
backlight, rgblight, rgb_matrix, audio or
led_matrix, or the name this keyboard's definition gives it — on the Impact
80 that is logo, Backlight or side, and the name matches ignoring caselogo,side), and all means every channel the keyboard reportsall, which changes every channelqmk-rgb-tool effect rgb_matrix breathingProfiles are stored as JSON in the per-user profiles/ directory
(~/.config/qmk-rgb-tool/profiles on Linux) — the same place they are read from
and written to, so a save is a load away. A checkout's own profiles/
directory is not searched for a name; an argument ending in .json is a path, and
that file is read or written where it says, so load profiles/lava.json uses a
file in the working directory. delete is name-only, so a file in a checkout is
removed with rm rather than with this tool. save and delete both report the
file they wrote or removed. They persist RGB state across reboots.
qmk-rgb-tool list # List saved profiles
qmk-rgb-tool save name # Save the state of every channel
qmk-rgb-tool save profiles/lava.json # Save to that file instead
qmk-rgb-tool load name # Apply a profile to every channel it names
qmk-rgb-tool load name side # Apply it to one channel or a list of them only
qmk-rgb-tool load profiles/lava.json # Apply the profile in that file
qmk-rgb-tool delete name # Remove a profile, by name only, and report it
Effect names come from a VIA definition file, the same one VIA reads. If a keyboard has no names, say so and offer the two ways to supply them, in this order:
qmk-rgb-tool keyboard fetch # download the definition for the connected board
qmk-rgb-tool keyboard definitions # every definition in use, from the per-user directory and built in
fetch needs the board to be in VIA's collection. Many are not, including the
Impact 80. Then the vendor's own definition is the source: find the board's
support or driver page, download the VIA JSON it links, and put it in the
per-user definitions/ directory — ~/.config/qmk-rgb-tool/definitions on
Linux, ~/Library/Application Support/qmk-rgb-tool/definitions on macOS,
%AppData%\qmk-rgb-tool\definitions on Windows — or pass it with
--definition <path>. A file is used for its own board only; one for another
board is refused by name. This is not the repository's own definitions/, which
is read at build time and built into the binary.
Never write an effect name into this repo that no source states. Either the
vendor's file names it, or the user has looked at the board and named what they
see — in which case it is a tool name, it goes in that board's definition file
in definitions/, and the comment says it was measured. No name belongs in Go
code: there is no hand-written catalog anywhere in internal/, because a list
beside the vendor's file is two places to update one name, and that is how the
names here drifted from the ones Wobkey publishes. definitions/README.md says
which files belong in that directory; a file added there takes effect after a
rebuild.
A command that writes lighting names its target as its first argument: one
channel, several comma separated, or all for every channel the keyboard reports.
The channels are written in channel order however the names were spelled, so a
script sees one order for every way of writing the same selection. Naming no zone
is refused by the argument count before the keyboard is even opened, and a channel
the keyboard does not have is refused by name. info, effect without a name and
save only read, so a zone is optional there; load takes a profile name and at
most a zone.
An effect a named channel does not have fails rather than being skipped, all
included — so effect all with a name only one channel has is refused rather
than writing the others. load is the exception: it warns on stderr and skips,
because a whole profile is being applied.
Effect names come from a VIA definition file, read at runtime from the per-user
definitions/ directory; the Impact 80's is also built into the binary so an
installed tool has it, and that built-in copy is consulted last, so a file you
place there takes precedence. No name is hand-written. The names in the output
are the vendor's own spelling, which is not
the tool's: the Impact 80's file writes fixed wave,
breathe on logo and side, and breathing on the backlight, and the tool
reports each channel as written while accepting the tool's spellings too.
On the Impact 80 the rgblight and audio channels carry fewer effects (0–6)
than rgb_matrix (0–45, and the board takes a 46th the file does not name). Always check qmk-rgb-tool effect all to see what is
available per channel, and note that a keyboard with no catalog has no effect
names at all — effect <zone> <index> is the way to set one there. The list prints the
file the names came from as its last line.
brightness and speed accept 0–255, but the firmware rescales per channel:
rgblight and audio cap brightness at 160 and have only three reachable
speeds — 0 freezes the animation, 1 is the slowest movement, anything above 1
becomes 4 — while rgb_matrix scales brightness up to 255 and applies speed as
given.
These commands read the value back. When a zone differs, the output names what was actually applied:
$ qmk-rgb-tool brightness all 200
Brightness logo 160 backlight 255 side 160 (requested 200)
Expect this instead of "Brightness set to 200". Never report a value to the user that the tool's own output did not confirm.
off → none, but on logo and side the firmware reads effect ID 0 as
"lighting off" and leaves the mode register where it was, so the running
effect keeps running; disable is what turns a channel off, because it also
writes brightness 0breathe → breathingrainbow → varies by zone (resolves automatically)solid → varies by zone (resolves automatically)Aliases are channel-aware, and the zone comes first because it is the command's
first argument: qmk-rgb-tool effect logo rainbow and
qmk-rgb-tool effect backlight rainbow select different effects. They also
bridge a definition file's spelling: where a vendor writes breathe or
fixed wave, the tool's breathing and fixed_wave still resolve to the same
effect, and the output shows the spelling of the source in use.
The alias table covers rgblight, rgb_matrix and audio only. On a keyboard
with a backlight or led_matrix channel an alias is refused by name rather
than resolved, so do not promise one there; the Impact 80 has neither, which is
why the gap does not show up on it.
qmk-rgb-tool load <name> to reapply a profile.rgblight and audio channels have only seven effects, so every Backlight ID
above 6 is Backlight-only. Trying one on another channel is
refused with effect <name> is not supported on <channel>, and nothing is
written. The check happens after the keyboard has been opened, because which
channels a board has is only knowable by asking it.