v1.12.3 — Design specification for the Ferris Sweep Colemak-DH layout. All claims verified against configuration/Cadence-FerrisSweep_v1_12_3.vil. Version history lives in CHANGELOG.md; this document describes the current state only.
Cadence is a 34-key Colemak-DH keyboard layout for the Ferris Sweep. Three things distinguish it from a generic Sweep adaptation of Colemak-DH:
tap = Space, hold = Navigation, tap + hold = Mouse. This solved a v1.9 bug where bilateral mouse triggers blocked Ctrl on the active hand.`, ', ", ^, ~), all three German umlauts (ä, ö, ü, with Shift+AltGr macros for capitals), plus ß and €, all reachable from a single layer triggered by Tab-hold.Cadence descends from Cadenza v1.0.0, the 36-key Corne version of the same design. Adapting to the Sweep's four-thumb form removed the dedicated Esc, Del, and L6-trigger thumb keys and forced their relocation into layers. The result is structurally tighter than Cadenza but feature-equivalent.
Cadence's daily-driver status means stability matters more than experimentation. The current ROADMAP focuses on stabilisation (verifying tipping terms in real use, validating bilateral-trigger ergonomics) and small completeness additions, not redesigns.
Cadence keeps Miryoku's core insight — layers via thumb holds, Home Row Mods on the home row — and replaces the parts that do not serve the use case.
| Dimension | Miryoku | Cadence |
|---|---|---|
| HRM implementation | MT() with one global tipping term |
Tap Dance with per-key tipping terms (200 / 250 ms by finger strength) |
| Symbol layer | Shifted-numpad mnemonic — !@#$% below 12345 |
Frequency × finger-strength ranking — = on the strongest finger, etc. |
| Bracket access | Scattered fixed positions on SYM | Dedicated L9 layer with tap-open / hold-close Tap Dance pairs, bilateral mirror |
| Code & CLI workflow | Not addressed — operators come from SYM | Dedicated L7 with shell macros, path TD, comparison TD, expansion TD |
| German / international support | Not addressed — relies on OS layout switching | L1 Dead Key Hub: direct umlauts, all five US-Intl dead keys, ß, € |
| Tiling WM integration | None | L8 with workspaces 1–10, focus, window-move, Kill / Float / Fullscreen |
| Inner column | G/M used for layer content | G/M never used for layer content (rule holds without exception in v1.12.3) |
| Layer count (reachable) | ~6 | 11 |
The trade-off is honest: Cadence has higher learning load and depends on a custom Vial-QMK build with TAP_DANCE_ENTRIES = 64. The bet is that the additional structure pays off for daily writers of German + English + code + shell.
Five rules that hold across every layer in v1.12.3. Individual layer sections reference these but do not repeat them.
The inner column (G and M positions in Colemak-DH) requires a lateral inward index movement and is the weakest column ergonomically. G and M carry only their plain letter values — no hold action, no layer content. The rule holds without exception in v1.12.3. The App/Menu hold on G/M that existed v1.5–v1.11.0 was relocated to L9 Brackets thumbs because it was never invoked in daily use.
Every layer access key requires a straight vertical finger movement from the home position. Pinky bottom (Z, /) → L8. Ring bottom (X, .) → L9. Ring top (W, Y) → L7. Middle top (F, U) → L6. The thumb-cluster triggers (Tab, Spc, Ent, Bsp) are vertical by definition. Q-top and '-top long-holds (500 ms) are the deliberate exception — the discomfort gates firmware-control access.
Index > middle > ring > pinky. Across layers: = (rank-1 symbol in code) sits on T (left index home, L2 Symbols Tab-thumb). $ (rank-5) sits on P. AltGr and Meta on the weaker fingers. Pipe Tap Dance on T (left index, L7). Path Tap Dance on N (right index, L7). The principle is enforced layer-by-layer.
The N-E-I-O home row positions hold ←/↓/↑/→ on L4 Navigation, L5 Mouse pointer, L8 focus (with ⌘ prefix), and L8 window-move (with ⌘⇧ prefix). One mental model for "directional movement" reused four ways. The Ctrl+arrow word-skip cluster on L4 right top mirrors the same NEIO layout one row up.
Layers used while typing with both hands have bilateral triggers (F+U, W+Y, Z+/, X+.) — whichever hand is freer activates. Layers used with one hand (Numbers on right via Ent-hold, Symbols on left via Bsp-hold) anchor the typing hand and use the other for the layer's content. Navigation (Spc-hold) anchors the right hand because right-hand arrows + page-nav dominate.
Eleven reachable layers, ordered by access frequency. Each section gives the layer's purpose, design rationale, the Tap Dances and Macros it uses, and any known limitations or open questions. L10 (Clipboard) is in firmware without a trigger by user choice and is not described here. L12 is empty (Vial format placeholder).
The base layer carries the Colemak-DH alpha grid plus the eight Tap Dance Home Row Mods, the four thumb triggers, and the eight letter-position layer-trigger Tap Dances. Every other layer is reached from here.
Colemak-DH alphas. Inherited from Cadenza, ultimately from the Colemak-DH community. Maximises home-row use for English; works acceptably for German.
HRM via Tap Dance, not MT(). Tap Dance permits per-key tipping terms — 250 ms on A and O (pinky/ring, slower fingers), 200 ms on R, S, T, N, E, I (index/middle, faster). One global term cannot serve both finger groups well.
Bilateral letter-pair triggers. F+U (middle top), W+Y (ring top), Z+/ (pinky bottom), X+. (ring bottom). Whichever hand is freer activates; the other types. Letters chosen for low DE+EN frequency to avoid hold-trigger interference.
Triple-action Spc-thumb. Tap = Space. Hold = Navigation (L4). Tap + hold = Mouse (L5). The third action is reached by tapping Spc once, then immediately pressing it again and holding — a distinct gesture from a normal tap or a normal hold.
Two-action Tab-thumb. Tap = Tab. Hold = International (L1). Tab remains a normal character available on the strongest thumb position.
Pinky-top long-holds (500 ms) for firmware control. Q and ' both trigger L11 only on a deliberately uncomfortable long-hold. The ergonomic cost is the safety gate.
| Pos | ID | Tap | Hold | Term | Why |
|---|---|---|---|---|---|
| A | TD(0) | A | ⌘ (LGui) | 250 ms | HRM. Slowest finger gets longer term. |
| R | TD(1) | R | ⌥ (LAlt) | 200 ms | HRM. |
| S | TD(2) | S | ⌃ (LCtrl) | 200 ms | HRM. |
| T | TD(3) | T | ⇧ (LShift) | 200 ms | HRM. Strongest left finger holds the most-used modifier. |
| N | TD(6) | N | ⇧ (RShift) | 200 ms | HRM mirror. |
| E | TD(7) | E | ⌃ (RCtrl) | 200 ms | HRM. |
| I | TD(8) | I | AltGr (RAlt) | 200 ms | HRM. AltGr on right ring — used during umlaut typing in combination with L1 dead keys. |
| O | TD(9) | O | ⌘ (RGui) | 250 ms | HRM. Right pinky, slow finger gets longer term. |
| F | TD(11) | F | MO(6) | 200 ms | L6 Fn+Media bilateral trigger (left half). |
| U | TD(22) | U | MO(6) | 200 ms | L6 bilateral trigger (right half). |
| W | TD(14) | W | MO(7) | 200 ms | L7 Code & CLI bilateral trigger. |
| Y | TD(23) | Y | MO(7) | 200 ms | L7 bilateral trigger. |
| Z | TD(12) | Z | MO(8) | 200 ms | L8 Tiling WM bilateral trigger. |
| / | TD(13) | / | MO(8) | 200 ms | L8 bilateral trigger. |
| X | TD(15) | X | MO(9) | 200 ms | L9 Brackets bilateral trigger. |
| . | TD(20) | . | MO(9) | 200 ms | L9 bilateral trigger. |
| Q | TD(46) | Q | MO(11) | 500 ms | L11 Firmware Control. Long-hold gates accidental access. |
| ' | TD(47) | ' | MO(11) | 500 ms | L11 mirror. Same safety design. |
| Spc-thumb | TD(21) | Space | MO(4) | 200 ms | Plus tap+hold = MO(5). Three-way Tap Dance. |
| Tab-thumb | TD(10) | Tab | MO(1) | 200 ms | L1 Dead Key Hub access. |
LT3(KC_ENTER): tap = Enter, hold = L3 Numbers.LT2(KC_BSPACE): tap = Backspace, hold = L2 Symbols.L1 is the central layer for everything the US base layout does not cover natively. All five US-International dead keys are reachable here in one mental model. Direct German umlaut Tap Dances bypass the dead-key workflow for the three high-frequency cases (ä, ö, ü). ß, €, and an extra Esc round out the layer. Q and X reappear in the centre of the right hand for muscle-memory continuity with Sonata, the 28-key sister project that lacks an inner column.
One layer, all dead keys. US-International has five dead keys: `, ', ", ^, ~. Before v1.12.0 they were scattered across multiple layers. v1.12.0 made L1 the canonical home: ` on P and L (bilateral, both mid-positions), " on T and N (the strongest mirror pair, where dead-quote use is highest in prose), ' on D and H (one row down), ^ on the dot position, ~ on the comma position. The mental model is "all dead keys live on Tab-hold."
Direct umlauts on mnemonic positions. ä on A (mnemonic: A → ä), ü on U (U → ü), ö on O (O → ö). Tap = lowercase via AltGr+letter; hold = capital via a Shift+AltGr macro. Direct access is faster than the dead-key workflow (" + a → ä) for the most-frequent German letters.
ß and € on the left home. ß on S (RAlt+S, the US-International standard). € on R (RAlt+5, also US-International standard). Both on the left home where the umlaut TDs already cluster — German typing happens in a tight area.
Esc on Bsp-thumb. When L1 is active, the right thumb's Bsp position becomes Esc. The Sweep lost the dedicated Esc thumb key from Cadenza; placing Esc on the held-into layers (L1 here, L7 too) preserves access via thumb position.
Q and X overflow on E and I. Sonata, the 28-key sister project, has no inner-column or pinky-top positions for Q and X. To preserve cross-layout muscle memory, Cadence places Q and X also on L1 R-home positions E and I, where Sonata reaches them. A Cadence user transitioning to Sonata will find Q and X exactly where the muscle memory expects.
| Pos | ID | Tap | Hold | Why |
|---|---|---|---|---|
| A | TD(48) | ä (RAlt+Q) | Ä (M16) | Direct umlaut, mnemonic A→ä. |
| U | TD(49) | ü (RAlt+Y) | Ü (M17) | Direct umlaut, mnemonic U→ü. |
| O | TD(50) | ö (RAlt+P) | Ö (M18) | Direct umlaut, mnemonic O→ö. |
| T, N | TD(33) | " | M4 (" + Space) | Double-quote dead key. Strongest mirror pair. Hold-variant commits the literal " when needed. |
| D, H | TD(34) | ' | M2 (' + Space) | Single-quote dead key. One row down from ". Hold = literal '. (Previous tap-hold action removed in v1.12.3 — see CHANGELOG.) |
RAlt+5 → € (US-Intl Euro)RAlt+S → ß (US-Intl sharp-s)` (grave dead key, bilateral)~ (Shift+grave, tilde dead key)^ (Shift+6, circumflex dead key)Capital umlaut macros M16 (Ä), M17 (Ü), M18 (Ö) are invoked from the umlaut Tap Dance hold actions. Each macro holds Shift + AltGr, taps the corresponding base letter (Q, Y, P), then releases the modifiers. Macros are used because Vial Tap Dance hold-slots cannot encode two simultaneous modifiers + a letter as a single keycode.
Macros M2 (apostrophe + space) and M4 (double-quote + space) provide explicit dead-key commit when the hold-variant is invoked.
L2 is the symbol layer for prose, code, and Markdown. Every ASCII symbol that does not require AltGr is reachable here. The layer is also shared as a specification with Sonata v3.x — the position assignments and Tap Dance encodings are identical, so muscle memory transfers between the two layouts.
Frequency × ergonomic strength = position. The most-typed operators land on the strongest fingers. = on Tab-thumb (the strongest left position), - on Spc-thumb. % on A, + on R, !/& Tap Dance on S, */@ Tap Dance on T (the strongest left finger gets the operator-pair with the highest combined frequency). The ranking is informed by code-corpus statistics, not aesthetic preference.
Right-thumb access asymmetry. Bsp (right thumb) triggers L2; the right thumb is therefore anchored. Symbol content is loaded onto the freer left hand and the upper rows of the right hand. The right bottom row is intentionally transparent — it would conflict with right-thumb anchoring during Bsp-hold.
Bracket pairs as Tap Dance on right top. (/) on L, [/] on U, </> on Y, {/} on '. Tap = open, Hold = close. The right-top row is reachable while the right thumb anchors at Bsp. This duplicates the L9 Brackets layer's content — the duplication is deliberate, because brackets appear during symbol-typing flows (e.g. after a math operator) and the layer-switch cost would interrupt the flow.
Right-home prose punctuation, with paren pair as a bonus. ,/( on N, ./) on E, '/^ on I, ; on O. Tap actions are punctuation marks for prose; hold actions on N and E together produce the (/) pair on right home, so parentheses can be typed without bridging through L9 Brackets. Useful for prose-context parens (smileys like :-), footnotes, inline asides) where layer-switching would interrupt the writing flow. Hold on I (^) and O (no hold) preserve apostrophe-caret and semicolon for code annotation.
Tap Dance pairs by semantic kinship. !/& together because both are common shell/code single-char operators. */@ together because both serve as "annotation" symbols (multiplication, decoration). //\ together because both are filesystem-path separators. The pairings are mnemonic: tap and hold of the same key are conceptually related.
Symbol-layer specification shared with Sonata. Sonata is a 28-key sister layout without an inner column and with different access keys, but its symbol layer uses the identical position-to-symbol mapping (TD(52)–TD(57) included). A user fluent in Cadence's L2 carries muscle memory into Sonata's symbol layer.
| Pos | ID | Tap | Hold | Why |
|---|---|---|---|---|
| S | TD(56) | ! | & | Both common shell/code single-char operators. Middle finger left home, strong position. |
| T | TD(52) | * | @ | "Annotation" symbols. Strongest left finger. |
| D | TD(55) | / | \ | Filesystem-path separators. Index bottom. |
| L | TD(25) | ( | ) | Bracket pair, also on L9. Right top. |
| U | TD(26) | [ | ] | Bracket pair, also on L9. |
| Y | TD(27) | < | > | Bracket pair, also on L9. |
| ' | TD(28) | { | } | Bracket pair, also on L9. |
| N | TD(53) | , | ( | Comma + redundant open-paren on right index home — combines prose-punctuation tap with operator-flow hold. |
| E | TD(54) | . | ) | Period + close-paren. Pairs with TD(53) on N (hold = () to put parentheses on right home — type (...) directly without an L9 bridge, useful for prose-context parens (smileys like :-), footnotes, inline asides). Curly-close on E was the v1.12.2 placement; } remains reachable via L9 O-position and L2 right-top '. |
| I | TD(57) | ' | ^ | Apostrophe + caret. Right ring home. |
~ (Q), ? (W), # (F), $ (P)% (A), + (R) — the rest are TDs: (X), _ (C); D is the slash/backslash TD- (Spc-thumb), = (Tab-thumb) — the most-frequent operators on the strongest positions; (O); the rest are TDsL3 is the calculator layer. Numpad on the left, ASCII operators on the right, brackets on the pinky verticals, Tab on the right thumb for spreadsheet cell navigation. (2 + 3) * 4 can be typed without leaving L3 — every character of a typical arithmetic or spreadsheet-formula expression is reachable.
Numpad-spatial digit layout. 7-8-9 on top, 4-5-6 on home, 1-2-3 on bottom (W-F-P / R-S-T / X-C-D positions). The visual layout matches a standard numeric keypad, exploiting whatever numpad muscle memory the user already has. 0 on Spc-thumb (the largest physical key, mirrors the bottom-row 0 on a numpad).
Brackets on Q and Z (pinky-top and pinky-bottom). Q = (, Z = ). Vertical pinky pair lets the same finger type both halves of a parenthesised expression without re-anchoring. Mnemonic: "pinky open, pinky close."
ASCII operators (not Numpad keycodes) on the right. +, -, *, =, ,, ., / emit the regular ASCII characters, not KC_KP_PLUS etc. v1.12.2 made this change explicit because Numpad keycodes interact poorly with locale settings (the German Numpad emits , instead of . as decimal separator) and require Num-Lock to be on. ASCII keycodes are universal.
Modifier mirror on right home. RShift, RCtrl, RAlt, RGui on N, E, I, O. While L3 is held with the right thumb (Ent), the right hand is normally typing digits or operators. The right-home modifier mirror exists for the rarer case of digit-with-modifier (e.g. Ctrl+1 to switch tabs in a browser while typing numerically). The L3 trigger is a hold, so left HRMs on A/R/S/T are not available; the right-home mirror compensates.
Esc on A position. A on L3 = Esc. The position is otherwise unused on a number layer (A would be a left-pinky-home keypress during numeric input — unlikely). Provides a backup Esc reachable from L3 in addition to the L1 Bsp-thumb Esc.
Tab on Tab-thumb (instead of typical 0). v1.12.2 placed Tab on the L3 Tab-thumb because Excel-style spreadsheet cell navigation is the dominant use case for L3-with-Tab. 0 lives on Spc-thumb instead. Cells navigate with Tab; numbers type into cells; flow is uninterrupted.
None. L3 uses only direct keycodes. Numpad-style digit input does not benefit from Tap Dance behaviour.
None.
{} and square brackets [] are not on L3; for those, switch to L2 or L9. Acceptable because numeric expressions rarely use curly or square brackets.L4 is the cursor-and-document-navigation layer. Arrows, word-skip, page navigation, line begin / end, and the PC keyboard utility keys (CapsLock, Insert, Delete, ScrollLock, Pause). Modifier mirror on left home for shift-arrow selection.
Arrows on NEIO. Right home row: ← (N), ↓ (E), ↑ (I), → (O). NEIO is the canonical "directional" home-row pattern, also reused on L5 Mouse pointer, L8 focus, and L8 window-move. One mental model serves four directional layers.
Word-skip on the row above. Ctrl+arrow for word-jump on right top — Ctrl+← on L, Ctrl+↓ on U, Ctrl+↑ on Y, Ctrl+→ on '. Same NEIO ordering one row up. The user does not need a separate Ctrl HRM — the keys already encode Ctrl+arrow as a single press.
Page navigation on the row below. Home / PgDn / PgUp / End on right bottom (H, ',', '.', '/'). Vertical layout with the most-used (PgDn for scrolling down through a document) on the strongest finger of the row.
Modifier mirror on left home. LGui, LAlt, LCtrl, LShift on A, R, S, T. While the right hand navigates with arrows, the left hand can apply modifiers — Shift+arrow for selection, Ctrl+arrow combined with the right-top word-skip for explicit Ctrl-Shift selection. The L4 trigger is a hold (Spc), so left-hand HRMs on A/R/S/T are unavailable; the L4 mirror replicates them.
PC utility keys on left. CapsLock on P, Insert on C, Delete on D, ScrollLock on Q, Pause/Break on X. These keys are rare but must exist for "complete keyboard" parity. Q and X were chosen because they are unused on L4 navigation and stay out of the way.
Tab on Ent-thumb. When L4 is active, the right Ent-thumb becomes Tab. Repeated Tab sequences (form navigation, autocomplete) work without leaving the layer.
None. L4 uses only direct keycodes and standard modifier keycodes.
None.
L5 lets the user move the mouse pointer, scroll, and click without leaving the home row. Reachable two ways: a momentary tap+hold on Spc (for quick clicks), or a persistent toggle via DF(5) on the L4 F-position (for sustained mouse work). Exit persistent via DF(0) on the Spc-thumb of L5.
Triple-action Spc solves the v1.9 HRM-blocking problem. v1.9 used bilateral F+U for Mouse — but holding F or U blocks Ctrl on the active hand (S or E HRM unavailable). For multi-select (Ctrl+click) and range-select (Shift+click) the user could not modify mouse buttons. v1.11.0 redesigned: Spc tap+hold triggers Mouse, leaving both hands free to use HRMs.
NEIO pointer movement. Right home row: ← / ↓ / ↑ / → for the pointer (KC_MS_L/D/U/R). Same NEIO pattern as L4, L8 — one directional model.
Wheel scroll on the row below. Wheel-left / down / up / right on right bottom (H, ',', '.', '/'). Mirrors the L4 page-navigation row positionally — page-scroll and wheel-scroll are conceptually similar.
Mouse buttons on right thumbs. BTN1 (left click) on Bsp-thumb, BTN2 (right click) on Ent-thumb. Most clicks come from BTN1 on the dominant Bsp position. BTN3 (middle click) on U — rare enough for a slightly off position.
Modifier mirror on left home. LGui, LAlt, LCtrl, LShift on A, R, S, T. Shift+click for range-select, Ctrl+click for multi-select. Same rationale as L4 modifier mirror.
DF(5) for persistent mode. The momentary Spc tap+hold is great for quick clicks but tiring for sustained pointer work (selecting several things, dragging windows). Persistent toggle via DF(5) on L4 F-position lets the user "enter mouse mode" until manually exiting via DF(0) on L5 Spc-thumb. Persistent mode requires entering L4 first (Hold Spc → tap F-pos), then releasing Spc — counter-intuitive but unambiguous.
None.
None.
settings section as numeric IDs that are not self-documenting. Semantic mapping is on the v2.0 ROADMAP.L6 carries F1–F12 in a numpad-spatial arrangement on the left hand, plus media controls (Prev / Vol- / Vol+ / Next, screen brightness, Mute, Play/Stop) on the right. PrintScreen on Spc-thumb because PrintScreen is a media-output-style function (capture screen → buffer).
Bilateral F-key trigger via F + U. Middle-top fingers, both hands. Letters chosen for moderate frequency in DE+EN — not the rarest possible, but acceptable for hold-detection. F-keys are the most-used "non-alpha" content after symbols and numbers, deserving a strong access pair.
F-keys numpad-spatial on left. F7-F8-F9 on top, F4-F5-F6 on home, F1-F2-F3 on bottom (W-F-P / R-S-T / X-C-D positions). Matches the L3 Numbers numpad layout — F-keys "are" numbers conceptually, indexed by the IDE / system. F10, F11, F12 fill the leftmost column (Q-A-Z positions) since they are less-frequently-used than F1–F9.
Media controls on right home. Prev / Vol- / Vol+ / Next on N, E, I, O. NEIO again — but here as "directional" through media (back/forward, down/up volume).
Screen brightness on right bottom. Bri- on the comma position, Bri+ on the period position. Less-frequent than volume, takes the row below.
Mute and Play/Stop on right thumbs. Mute on Ent-thumb (instant access during a meeting), Play/Stop Tap Dance on Bsp-thumb (TD(24): tap = Play, hold = Stop).
PrintScreen on left Spc-thumb. v1.12.0 addition. PrintScreen is conceptually a screen-output capture, grouping it with media-output controls. The left thumb is unanchored during F+U bilateral hold (whichever right-hand finger triggered, the left thumb is free).
| Pos | ID | Tap | Hold | Why |
|---|---|---|---|---|
| Bsp-thumb | TD(24) | Play (KC_MPLY) | Stop (KC_MSTP) | Play and Stop are conceptually paired; Tap Dance combines them on one key. |
None.
L7 is the layer for shell sessions, scripting, and code editing. It carries the operators and patterns that programmers and shell users hit dozens of times per hour — pipes, redirects, logical operators, path navigation, comparisons, expansions — placed so they type without leaving the layer or escaping to L2 Symbols.
Layer access is bilateral via Hold W or Hold Y (ring fingers, top row). Both letters are low-frequency in DE+EN, which gives clean hold-detection without per-key tipping-term tuning. The bilateral trigger means whichever hand is freer in the moment activates the layer; the other hand types.
Strongest fingers get the most-frequent operators. The strongest left index position (T) holds | as a pipe Tap Dance: tap emits |, hold emits | with surrounding spaces (the formatting habit when piping in scripts). The mirror right index position (N) holds the path Tap Dance: tap=/, hold=~/, double=../ — three semantic variants of "navigate the filesystem" on a single key.
Operators cluster by domain. Left home is shell territory (|| on A, 2>&1 on R, && on S, pipe on T). Right home is expression territory (path on N, $()/${} on E, !=/== on I, =>/-> on O). The split mirrors how operators tend to group in practice: a redirect on the left, an expansion on the right.
Bottom rows carry literals — except C, which earned a Tap Dance. Backtick Tap Dance on C (TD(58), see table), backslash on D, tilde on the comma position, exit-status ($?) on H. The C-position backtick became a TD in v1.12.3 because a single key now delivers three semantic variants for code typing: a dead-key tap (composes with the next vowel if any), a committed-literal hold (forces the backtick out as a literal regardless of what follows), and a Markdown code-fence opener on double-tap. The other bottom-row entries appear less often than the operator pairs above and remain second-tier positions.
Thumbs are the quote cluster. Single quote on Spc-thumb, double quote on Tab-thumb, backtick on Bsp-thumb, Tab on Ent-thumb. Mnemonic: thumbs = quoting while in Code & CLI. Tab on Ent-thumb specifically supports shell-autocomplete sequences without leaving the layer. The Bsp-thumb backtick is the simple dead-key access path; the C-position holds the richer TD(58) for explicit-commit and code-fence flows.
OS dead-key interaction. In US-International OS mode, the characters ' " ` ~ ^ are dead keys. During code typing this rarely interferes: code identifiers usually start with consonants, which the OS treats as non-combining and emits as two literal characters. The thumb-quote cluster therefore feels literal in practice, even though OS-level dead-key behaviour is technically active.
| Pos | ID | Tap | Hold | Double | Why |
|---|---|---|---|---|---|
| T | TD(45) | | | | (spaced) | — | Most-frequent shell operator on the strongest left finger; hold-variant is the formatting habit. |
| C | TD(58) | ` | ` + Spc (M19) | ``` + Spc (M3) | Backtick TD added in v1.12.3 — three semantic variants for code typing on one key. Tap = dead-key backtick (composes with following vowel for ̀ accents). Hold = backtick committed by trailing space (use before another backtick or a vowel where dead-key composition is unwanted). Double = Markdown code-fence opener (three commit-pairs). |
| N | TD(29) | / | ~/ | ../ | Path navigation. Three semantic variants on the strongest right finger. |
| E | TD(30) | $() | ${} | — | Shell expansion pair. Cursor lands inside the parens for both. |
| I | TD(31) | != | == | — | Comparison pair. |
| O | TD(32) | => | -> | — | Arrow operators. Tap = JS/Python fat arrow; hold = C-family / shell pointer. |
| Pos | ID | Output | Why |
|---|---|---|---|
| A | M11 | || | Shell logical-OR and JS short-circuit. |
| R | M7 | 2>&1 | Stderr-to-stdout redirect. Distinct domain from the adjacent &&. |
| S | M10 | && | Shell logical-AND. |
| H | M0 | $? | Bash last-exit-status. |
\ (backslash, escape character)~ (tilde, also home-dir reference distinct from N's ~/ Tap Dance hold)' (single quote)" (double quote)` (backtick — simple dead-key access; TD(58) on C carries the richer variants)set -e, set -o pipefail) if they prove worth a shortcut.. and / are open candidates.L8 is the tiling-window-manager layer. Workspaces 1–10 on the left (numpad-spatial), focus and window-move arrows on the right (NEIO again, with ⌘ and ⌘⇧ prefixes), Kill / Float / Fullscreen on the thumbs. Designed for i3, Sway, AwesomeWM, hyprland, or any WM that uses ⌘+digit (Super+digit) for workspace switching.
Bilateral pinky-bottom trigger. Z and / are the lowest-frequency letters in both DE and EN. Hold-detection on these positions has the cleanest behaviour of all bilateral trigger pairs. Compensates for L8 being a "high-cost" layer (window operations are deliberate, not flow operations).
Workspaces in numpad-spatial layout, matching L3 Numbers. WS7-WS8-WS9 on top (W, F, P), WS4-WS5-WS6 on home (R, S, T), WS1-WS2-WS3 on bottom (X, C, D), WS10 on Spc-thumb. The user holds one numpad-spatial layout for both digits and workspaces — dual-purpose muscle memory.
Tap = go-to-workspace, Hold = move-window-to-workspace. TD(35)–TD(44): tap emits ⌘+N, hold emits ⌘⇧+N. Both operations are paired in any tiling WM workflow ("send window to workspace 3, follow it" = move + go), and Tap Dance combines them on one key per workspace.
NEIO focus on right home. ⌘+←, ⌘+↓, ⌘+↑, ⌘+→ on N, E, I, O. Same directional pattern as L4/L5; here the modifier elevates "move cursor" to "move window focus."
NEIO window-move on right bottom. ⌘⇧+←, ⌘⇧+↓, ⌘⇧+↑, ⌘⇧+→ on H, ',', '.', '/'. One row below focus, with Shift added to the Cmd modifier — "elevated focus" = window-move. Mnemonic kinship with L4 page-nav row.
Window operations on thumbs. Kill (⌘⇧+Q) on Tab-thumb, Float (⌘+Space) on Ent-thumb, Fullscreen (⌘+F) on Bsp-thumb. Three high-impact actions on the easily-reachable thumb cluster.
| Pos | ID | Tap | Hold | Why |
|---|---|---|---|---|
| X | TD(35) | ⌘+1 | ⌘⇧+1 | WS1 go / move. |
| C | TD(36) | ⌘+2 | ⌘⇧+2 | WS2 go / move. |
| D | TD(37) | ⌘+3 | ⌘⇧+3 | WS3 go / move. |
| R | TD(38) | ⌘+4 | ⌘⇧+4 | WS4 go / move. |
| S | TD(39) | ⌘+5 | ⌘⇧+5 | WS5 go / move. |
| T | TD(40) | ⌘+6 | ⌘⇧+6 | WS6 go / move. |
| W | TD(41) | ⌘+7 | ⌘⇧+7 | WS7 go / move. |
| F | TD(42) | ⌘+8 | ⌘⇧+8 | WS8 go / move. |
| P | TD(43) | ⌘+9 | ⌘⇧+9 | WS9 go / move. |
| Spc-thumb | TD(44) | ⌘+0 | ⌘⇧+0 | WS10 go / move. |
⌘⇧+Q (Kill window)⌘+Space (Float toggle)⌘+F (Fullscreen toggle)⌘+←/↓/↑/→ (focus arrows)⌘⇧+←/↓/↑/→ (window-move arrows)None.
⌘⇧+Q, ⌘+Space, ⌘+F are common defaults but not universal. On the v1.11.x ROADMAP.L9 is the dedicated bracket layer. All four bracket pairs ((), [], <>, {}) on the home rows of both hands as Tap Dance pairs (tap-open / hold-close). Backslash on right-bottom slash position. App/Menu key on both Spc-thumb and Bsp-thumb.
Bilateral ring-bottom trigger. X and . — second-rarest bilateral pair after Z+/. Cleaner hold-detection than the v1.9 D+H pair (which carried HRM-blocking issues). The trigger move from D+H to X+. happened in v1.11.0.
Tap-open / hold-close on every bracket. Across all four bracket types: tap = open, hold = close, double = close. The dual encoding lets the user type a bracket pair as tap-hold without rolling — useful for quickly adding both open and close around a cursor position. Mnemonic: "press once to open, longer to close."
Bilateral mirror — same brackets, same fingers, both hands. Left home: { on A, < on R, [ on S, ( on T. Right home: ( on N, [ on E, < on I, { on O. The pinky-to-index gradient runs {-<-[-( on both hands, so the strongest finger gets the most-used bracket type (round parens are the most common in code, square less common, angle and curly rarer).
App/Menu on both unallocated thumbs. Inherited from Cadenza's left-thumb App/Menu, relocated to L9 in v1.11.1 because the original G/M-hold App/Menu was never invoked in daily use. Placed on both Spc-thumb and Bsp-thumb of L9 for either-hand reachability — App/Menu is unfrequent enough that finger choice does not matter.
Backslash on the right bottom slash position. When L9 is active, the slash key emits backslash. Useful for Windows path manipulation in code editors. Distinct from L7's D-position backslash, which is for shell escape sequences.
| Pos (L) | Pos (R) | ID | Tap | Hold | Why |
|---|---|---|---|---|---|
| T | N | TD(25) | ( | ) | Round parens — most common bracket type in most languages, on the strongest finger. |
| S | E | TD(26) | [ | ] | Square brackets — second-most common (arrays, indexing). |
| R | I | TD(27) | < | > | Angle brackets — less frequent (HTML, generics, comparison). |
| A | O | TD(28) | { | } | Curly braces — least-frequent of the four (block delimiters), pinky position. |
\ (backslash)None.
0xFF hex literals, . for property access). Real-world false-trigger rate during heavy code editing is on the v1.11.x ROADMAP.L11 holds the two firmware-control commands: QK_BOOT (jump to bootloader for re-flashing) and QK_REBOOT (soft reboot). The layer exists to keep these commands reachable without an external tool, but its access design ensures they cannot be triggered accidentally during normal typing.
Deliberately uncomfortable access. The trigger is a 500 ms long-hold on Q (left pinky top, TD(46)) or ' (right pinky top, TD(47)). Pinky-top is the worst position on the board ergonomically; 500 ms is more than double the standard 200 ms tipping term. Together they make accidental activation effectively impossible — but the user can still reach the layer when needed by deliberately holding.
Symmetric placement of the two commands. QK_BOOT on left S-position and right E-position (Ctrl HRM mirrors). QK_REBOOT on left T-position and right R-position. Symmetry across hands lets either-hand activation reach either command. The placement deliberately keeps the commands on home-row middle columns (away from pinky-top, where accidental presses while still holding the trigger could cascade).
Two separate distinct presses required. The user must (1) long-hold Q or ', then (2) press a separate home-row key. A single accidental long-hold does not trigger anything destructive — there is no command on the trigger key itself.
The only intentional pinky-top hold in the layout. Every other layer trigger uses a stronger finger or a thumb. L11 breaks the rule because the trigger discomfort is the safety gate.
None — L11 contains only direct keycodes for firmware commands.
None.
QK_BOOT (jump to bootloader)QK_REBOOT (soft reboot)All 52 used Tap Dance slots in v1.12.3, sorted by ID. Use this as the authoritative numerical lookup; the per-layer tables above are the conceptual view. Cleared slot TD(51) is shown for completeness.
| ID | Tap | Hold | Double | Tap-Hold | Term | Used in |
|---|---|---|---|---|---|---|
| TD(0) | A | ⌘ (LGui) | — | — | 250 ms | L0 HRM |
| TD(1) | R | ⌥ (LAlt) | — | — | 200 ms | L0 HRM |
| TD(2) | S | ⌃ (LCtrl) | — | — | 200 ms | L0 HRM |
| TD(3) | T | ⇧ (LShift) | — | — | 200 ms | L0 HRM |
| TD(6) | N | ⇧ (RShift) | — | — | 200 ms | L0 HRM |
| TD(7) | E | ⌃ (RCtrl) | — | — | 200 ms | L0 HRM |
| TD(8) | I | AltGr (RAlt) | — | — | 200 ms | L0 HRM |
| TD(9) | O | ⌘ (RGui) | — | — | 250 ms | L0 HRM |
| TD(10) | Tab | MO(1) | — | — | 200 ms | L0 Tab-thumb |
| TD(11) | F | MO(6) | — | — | 200 ms | L0 (L6 trigger left) |
| TD(12) | Z | MO(8) | — | — | 200 ms | L0 (L8 trigger left) |
| TD(13) | / | MO(8) | — | — | 200 ms | L0 (L8 trigger right) |
| TD(14) | W | MO(7) | — | — | 200 ms | L0 (L7 trigger left) |
| TD(15) | X | MO(9) | — | — | 200 ms | L0 (L9 trigger left) |
| TD(20) | . | MO(9) | — | — | 200 ms | L0 (L9 trigger right) |
| TD(21) | Space | MO(4) | — | MO(5) | 200 ms | L0 Spc-thumb (triple-action) |
| TD(22) | U | MO(6) | — | — | 200 ms | L0 (L6 trigger right) |
| TD(23) | Y | MO(7) | — | — | 200 ms | L0 (L7 trigger right) |
| TD(24) | Mute | Play/Stop | — | — | 200 ms | L6 Bsp-thumb |
| TD(25) | ( | ) | ) | — | 200 ms | L9 (T,N), L2 (L) |
| TD(26) | [ | ] | ] | — | 200 ms | L9 (S,E), L2 (U) |
| TD(27) | < | > | > | — | 200 ms | L9 (R,I), L2 (Y) |
| TD(28) | { | } | } | — | 200 ms | L9 (A,O), L2 (') |
| TD(29) | / | ~/ | ../ | — | 200 ms | L7 N (path TD) |
| TD(30) | $() | ${} | — | — | 200 ms | L7 E (expansion) |
| TD(31) | != | == | — | — | 200 ms | L7 I (comparison) |
| TD(32) | => | -> | — | — | 200 ms | L7 O (arrows) |
| TD(33) | " | M4 (" + Spc) | — | — | 200 ms | L1 T, N (" dead key) |
| TD(34) | ' | M2 (' + Spc) | — | — | 200 ms | L1 D, H (' dead key) |
| TD(35)–TD(43) | ⌘+1 to ⌘+9 | ⌘⇧+1 to ⌘⇧+9 | — | — | 200 ms | L8 WS1–9 |
| TD(44) | ⌘+0 | ⌘⇧+0 | — | — | 200 ms | L8 WS10 (Spc-thumb) |
| TD(45) | | | M5 ( | spaced) | — | — | 200 ms | L7 T (pipe) |
| TD(46) | Q | MO(11) | — | — | 500 ms | L0 (L11 trigger left, safety) |
| TD(47) | ' | MO(11) | — | — | 500 ms | L0 (L11 trigger right, safety) |
| TD(48) | ä (RAlt+Q) | M16 (Ä) | — | — | 200 ms | L1 A |
| TD(49) | ü (RAlt+Y) | M17 (Ü) | — | — | 200 ms | L1 U |
| TD(50) | ö (RAlt+P) | M18 (Ö) | — | — | 200 ms | L1 O |
| TD(51) | — | — | — | — | — | cleared in v1.12.0 |
| TD(52) | * | @ | — | — | 200 ms | L2 T |
| TD(53) | , | ( | — | — | 200 ms | L2 N |
| TD(54) | . | ) | — | — | 200 ms | L2 E |
| TD(55) | / | \ | — | — | 200 ms | L2 D |
| TD(56) | ! | & | — | — | 200 ms | L2 S |
| TD(57) | ' | ^ | — | — | 200 ms | L2 I |
| TD(58) | ` | M19 (` + Spc) | M3 (```` ` ` ` ```) | — | 200 ms | L7 C (backtick TD) |
Slots TD(4), TD(5), TD(16)–TD(19), TD(51) are unused (cleared or reserved). The next available IDs for new TDs are TD(59)–TD(63).
All 20 used macro slots in v1.12.3.
| Macro | Output | Used in |
|---|---|---|
| M0 | $? | L7 H (last exit status) |
| M1 | ~/ | L7 (TD(29) hold component) |
| M5 | | (with surrounding spaces) | L7 (TD(45) hold component) |
| M6 | ../ | L7 (TD(29) double-tap component) |
| M7 | 2>&1 | L7 R (stderr→stdout) |
| M8 | $() (cursor inside) | L7 (TD(30) tap component) |
| M9 | ${} (cursor inside) | L7 (TD(30) hold component) |
| M10 | && | L7 S (logical AND) |
| M11 | || | L7 A (logical OR) |
| Macro | Output | Used in |
|---|---|---|
| M12 | != | L7 (TD(31) tap component) |
| M13 | == | L7 (TD(31) hold component) |
| M14 | => | L7 (TD(32) tap component) |
| M15 | -> | L7 (TD(32) hold component) |
| Macro | Output | Action sequence | Used in |
|---|---|---|---|
| M16 | Ä | Hold ⇧ + AltGr → Tap Q → Release | L1 (TD(48) hold) |
| M17 | Ü | Hold ⇧ + AltGr → Tap Y → Release | L1 (TD(49) hold) |
| M18 | Ö | Hold ⇧ + AltGr → Tap P → Release | L1 (TD(50) hold) |
Why macro and not S(RALT(KC_X)) keycode? Vial Tap Dance hold-slots accept a single Vial keycode, but the capital umlaut needs two simultaneous modifiers (⇧+AltGr) plus a letter. Macros encode this cleanly and produce identical USB HID output.
| Macro | Output | Used in |
|---|---|---|
| M2 | ' (apostrophe + space) | L1 (TD(34) hold component) |
| M4 | " (double-quote + space) | L1 (TD(33) hold component) |
| M19 | ` (backtick + space) | L7 (TD(58) hold component) — added in v1.12.3 |
On dead-key OS layouts, pressing ', ", or ` alone produces no output until the next keystroke. These macros explicitly type the character followed by Space to commit it as a literal.
| Macro | Output | Used in |
|---|---|---|
| M3 | ` ` ` (three commit-pairs) | L7 (TD(58) double-tap component) — Markdown code-fence opener |
M3 was repurposed in v1.12.3. It previously emitted three apostrophe+space pairs as a Markdown italic dance from L1's TD(34); the new sequence emits three backtick+space pairs as a code-fence opener from L7's TD(58). The slot is the same, the semantic is different.
v1.12.3 uses 52 of 64 Tap Dance slots. The standard Vial-Sweep firmware ships with 48 entries — a custom build is required because TD(58) is occupied.
In keyboards/ferris/sweep/keymaps/vial/config.h:
#define TAP_DANCE_ENTRIES 64
The Vial settings section contains tuned QMK mouse and scroll values stored as numeric Vial setting IDs. The IDs are firmware-version-dependent and not self-documenting in the .vil format. Producing a semantic mapping is on the v2.0 ROADMAP.
Set the OS keyboard layout to US International with dead keys. Cadence's L1 Dead Key Hub assumes US-International behaviour at the OS level. On a US-no-deadkeys layout, the dead-key positions emit literal characters and accent composition fails.
The `firmware/keyboards/ferris/sweep/keymaps/vial/` directory in this repo carries a minimal Vial keymap.c reference. The active layout is loaded into the firmware as a Vial-EEPROM configuration via the `.vil` file rather than compiled directly into the firmware binary. This makes iteration fast (no recompile per change) but means the layout depends on Vial's runtime state. The v2.0 ROADMAP includes migrating to a compiled `keymap.c` for git-history and reproducibility.
configuration/Cadence-FerrisSweep_v1_12_3.vil — the authoritative layout file