Macros
A macro is a piece of text — or a short sequence of keys — stored on the keyboard and typed back when you press one key. An email address, a login, a shell command, a phrase you write ten times a day.
Every keyboard with macros has this. What is different here is that the keycap tells you which
one it is. A macro key shows a short label along its bottom edge, so the row reads push,
work mail, sign off rather than M0, M1, M2.
Where they already are
Section titled “Where they already are”You do not have to place a macro before you can press one. The Utility layer’s top row
is the macro row: twelve keys, M0 to M11 from left to right across the two halves.
To reach it, hold Fn and tap the top-left key: that switches to Utility for a single keypress, so the very next key you press fires its macro. To stay on the layer instead — for several macros in a row — hold Fn and tap the top-right key.
The last four macros share the same twelve keys: hold Shift and the first four become M12
to M15. The other eight go blank while Shift is down, which is the keycap telling you where the
second bank stops.

Writing one
Section titled “Writing one”Macros live in the Keymap Editor — open the tray menu and choose Configure Keymap, then the Macros tab beside Layers & Mods.
- Pick a macro from the list on the left.
- Type the label — what the keycap will say.
- Type what it types in the field below.
- Save macro.
That is enough to use it — macro 0 is already on the first key of the Utility row. Step 5 is
only if you want it somewhere else:
- Click the key you want it on in the keyboard picture, then Use on selected key.
The label field shows the keycap exactly as it will look, next to a meter of how much of the 72-pixel-wide display the label uses. Both update as you type.
Putting one behind a modifier
Section titled “Putting one behind a modifier”A macro takes a whole key — it cannot be folded into a modifier the way Ctrl+C or a
tap-hold key is. That is a QMK limit rather than a choice: MT(), LT() and Ctrl+key
all carry the key they wrap in a single byte, and a macro keycode does not fit in one.
Use a layer instead, which is how the keyboard expresses “modifier + key” for anything that is not a plain keystroke:
- In the Keymap Editor, switch to a layer above the base one —
Fn,NumpadorUtility. - Assign the macro to a key there, exactly as on the base layer.
- Hold that layer’s key and press it — Fn + E, say.
The keycap shows the macro’s label while the layer is held, so the assignment is visible on the board rather than something you have to remember.
Chords, pauses and held keys
Section titled “Chords, pauses and held keys”A macro is really a list of steps, and plain text is the common case rather than the
only one. Press Steps… beside the Types: field to open the step editor:
| Action | What it does |
|---|---|
| Tap | press and release one key |
| Hold | press a key and leave it down |
| Release | let a held key back up |
| Wait | pause, in milliseconds |
| Type | one character, as the text field produces |
Each row is an action and its Value — a key for Tap, Hold and Release, a duration for Wait — in a single column, so a row only ever offers the one editor its action can use.
A chord is a Hold, the key, then a Release — Ctrl+Shift+P is Hold Ctrl, Hold
Shift, Tap P, Release Shift, Release Ctrl. The line under the table names what the
macro does in ordinary terms as you build it, so you can check it without reading the
rows back.
Recording
Section titled “Recording”Rather than adding those five rows by hand, press Record and then press the keys.
Every press and release is captured in order; press Stop (or Esc) when you are
done. The rows are ordinary steps afterwards, so anything captured wrongly can be
edited or deleted.
Two things worth knowing:
- Pauses are not recorded by default. Most macros should run as fast as the keyboard
can send, and a
Waitbetween every keystroke is both noise in the list and bytes out of the shared store. Switch the box beside Record to with timing if the rhythm matters — for an application that drops input sent too quickly, say. - Recording reads the character a key produces, not its position. On a layout where
the key in the QWERTY
Yposition typesz, that key records asKC_Z— the keycode that typeszon your machine, which is what you meant by pressing it. It is only the wrong answer if the macro will be replayed on a machine set to a different layout, and every step names the keycode it stored, so you can see and change it.
Leaving a modifier held at the end of a macro is allowed — the summary says so
(hold Ctrl) rather than quietly dropping it.
Writing it as text
Section titled “Writing it as text”The step editor has two tabs. Table is the one above; Script is the same macro as a line of text.
{+KC_LCTL}{KC_A}{-KC_LCTL}{50}done| Written | Means |
|---|---|
done |
type the characters |
{KC_A} |
tap |
{+KC_LSFT} |
hold |
{-KC_LSFT} |
release |
{250} |
wait, in milliseconds |
\{ |
a literal { |
Switching tabs converts the macro rather than replacing it, so use whichever suits the moment — build a chord by recording it, then switch to Script to change one keycode. If the script does not parse, the switch is refused and your text is left alone with the problem named underneath.
Record works on either tab: it appends to whichever one you are looking at. The row buttons — add, remove, reorder — belong to the Table tab, since that is what they act on.
What a macro can type
Section titled “What a macro can type”Printable ASCII, tab and newline. That is what a keyboard can actually send: it types keystrokes, not characters, so anything your keyboard layout cannot produce with a keypress — an accented letter, an emoji, a character from another script — is not something a macro can type.
If you need those, the keyboard has better tools for it: the language layer for accented letters and other scripts, and the emoji layer for emoji.
What the keycap shows
Section titled “What the keycap shows”A macro takes a whole key, so the key is free to be more than a legend. Four layouts, chosen per macro from the Keycap dropdown in the editor:
| Layout | What it draws |
|---|---|
| Icon above the label | A symbol you pick, over the label. What a fresh keyboard uses. |
| Number above the label | M3 over the label — the plain fallback, and the only one that needs nothing else. |
| Label only, as large as it fits | No mark at all — the label gets the whole key, at the largest face it fits on. |
| Icon only, filling the key | The icon alone, at full size across the whole key. The label is kept but not drawn, so switching back does not lose it. |
The label sits along the bottom edge, in the largest of two faces that fits it whole — short labels are noticeably bigger than long ones, and a label too wide for the larger face keeps all its characters at the smaller one rather than losing any to stay large. A macro with no label shows just the mark, centred — so an unlabelled macro is still identifiable, it just does not say what it does.
Before you write one
Section titled “Before you write one”A macro you have never touched is not blank. Each of the sixteen starts with the Mayan numeral
for its own number over the caption Macro — a shell for zero, then dots and bars up to
fifteen.
They are numerals rather than pictures on purpose: a slot nobody has written yet has no purpose, so a gear or an envelope would be a wrong label rather than a neutral one. The numeral carries the number so the caption does not have to, and unlike a row of identical keys it tells you at a glance which one your finger is on.
Anything you set replaces it and is kept — the stock look only ever fills a slot that has no macro and no look of its own. Clearing a macro hands its keycap the numeral back.
Labels are ASCII only. The small face has no accented letters, so anything outside the basic alphabet, digits and punctuation is dropped as you type rather than appearing on the keycap as a blank.
Choosing an icon
Section titled “Choosing an icon”Choose icon… opens a picker of the symbols and emoji the keyboard can draw — they come from
the font packs already on it, so what you see in the picker is what the key can show. It opens on
Emoji and symbols; Show: Every bundle widens it to everything on the keyboard, language
scripts included. Filter by typing a character or a codepoint (1F4E7, U+2699). Clear goes
back to no icon.
A chosen icon is drawn at half size when the label leaves it no room at full size, which is most of the time: the icons are drawn at nearly the full height of the key, and a label takes about a quarter of it. That is why an icon looks smaller beside a label than it does under Icon only, filling the key — or on a key with no label at all — where it gets the whole face.
Interrupting one
Section titled “Interrupting one”Press any key. A macro that is part-way through typing stops immediately, and the key you pressed does what it normally does.
That matters more than it sounds: a macro can contain a deliberate pause, and the keyboard keeps working normally while one runs — it does not lock up and finish before responding to you.
From the command line
Section titled “From the command line”Everything above is scriptable:
polyctl macro list # every macro, its label and sizepolyctl macro set 0 --text "git push" --label "push"polyctl macro set 0 --style icon --icon 1F4E7 # the keycap layout, and its symbolpolyctl macro set 0 --style icononly --icon 1F4E7 # …the symbol alone, filling the keypolyctl macro get 0polyctl macro clear 0polyctl macro list also prints how much of the shared store is in use.
--text writes plain characters. For chords and pauses use --script, the same
syntax as the editor’s Script view:
polyctl macro set 0 --script "{+KC_LCTL}{KC_A}{-KC_LCTL}{50}done" --label "sel all"polyctl macro get prints the script form beside the steps, so a macro built in the
editor can be copied straight back out. A script with a typo is refused before anything
is written, naming the token it could not read.
How much fits
Section titled “How much fits”All the macros share one pool of about 2.2 KB on the keyboard, across 16 slots. That is a lot of text — an email address is around 25 bytes — but it is shared, so one very long macro leaves less for the others. The editor shows the total at the bottom, and the keyboard refuses a save that would not fit rather than truncating it.