| Ferris Sweep | Urchin | Forager |
|---|---|---|
![]() |
![]() |
![]() |
This repo contains my personal ZMK layout for three different 34-key boards. All three share the same logical keymap, while build.yaml handles the board-specific firmware targets.
The goal is not to build the most exotic layout possible. It is a pragmatic 34-key setup that stays close to normal QWERTY, keeps programming symbols easy to reach, and smooths over the annoying differences between Linux and macOS.
- Familiarity first: I want standard QWERTY muscle memory to transfer well.
- Small-board practicality: thumbs and layers do the heavy lifting instead of stretching for distant keys.
- Programming comfort: common symbols and editing actions are close to home row.
- Cross-device consistency: the same layout works across Sweep, Urchin, and Forager.
- Cross-OS consistency: shortcuts and navigation adapt between Linux and macOS.
If you want to understand the repo quickly, read the files in this order:
config/includes/base.dtsifor the shared layers, hold-taps, macros, and the main keymap.config/includes/oskey.dtsifor the Linux/macOS-aware modifiers and navigation helpers.config/includes/combos.dtsifor combos.config/includes/mouse.dtsifor mouse tuning.build.yamlfor the actual flash targets.
Notes:
- The Sweep uses the
cradio_*shield names internally, so some files and generated artifacts still usecradio. - The shared keymap logic lives in
config/includes/, so changes there apply to all three boards.
This config uses a few external ZMK modules in addition to upstream ZMK itself.
| Module | Small description | Why I use it here |
|---|---|---|
zmk-case-mode |
Case-mode behavior for typing identifiers with normal spaces. | I use it for snake_case, camelCase, and kebab-case combos on the base layer so coding-style names are easier on a 34-key board. |
oskey |
OS-aware key behavior for Linux/macOS shortcut differences. | I use it for swapped Ctrl/Cmd home-row mods, word movement, line movement, and delete-word behavior without maintaining separate keymaps. |
zmk-rgbled-widget |
RGB LED status indicator module. | I use it for battery and connection indicators on builds that support an RGB LED. |
BASE: QWERTY, home-row mods, thumb-layer access, and the main daily typing layer.SYM: symbols and punctuation placed in familiar QWERTY-style positions.NAV: numbers on the top row, text navigation and editing on the home row, and global shortcuts on the bottom row.FNC: function keys, media controls, mouse toggle, and long-press system controls, plus the utility layer where I trigger status and OS-selection combos.MSE: mouse movement, scrolling, clicks, and drag helpers.MSE_FAST: a faster temporary mouse/scroll layer.
FNC is a tri-layer that appears when both SYM and NAV are active.
System controls are intentionally hidden behind 3-second holds on function keys, so normal taps still send function keys while Bluetooth, reset, output, and Studio actions remain hard to trigger accidentally. Hold F1–F4 for Bluetooth profiles 0–3, F5 for BLE output, F6 for USB output, F7 for ZMK Studio unlock, F10 to clear the current Bluetooth profile, F11 to reset, and F12 for the bootloader.
- The alpha layout stays intentionally close to standard QWERTY.
- Numbers stay on the top row instead of moving to a more abstract arrangement, and also double as indexed navigation keys.
- Symbols try to preserve familiar positions where possible.
- Vim-style directional movement is kept on the navigation layer, with the bottom row reserved for non-text shortcuts I use often.
- Home-row mods are tuned with custom hold-tap settings for cleaner tap vs hold behavior.
- The thumbs carry most of the layout:
SYM/SPACE,NAV/BSPC,TAB, andENTER. - This keeps the main typing area simple while still fitting a full daily-driver workflow into 34 keys.
Combos are used for actions that are frequent enough to deserve a shortcut but not important enough to consume a dedicated key.
Current combos include:
- editing:
Delete,Cut,Copy,Paste - control:
Escape,Enter,Caps Word, sticky shift - casing:
snake_case,kebab-case,camelCase - navigation aid: fast scroll combos
- utility:
Soft Off, battery indicator, and connection indicator - OS switching: dedicated macOS and Linux combos on
FNC
Each keyboard supports two connection modes.
<keyboard>_dongle: flash to the dongle<keyboard>_left_peripheral: flash to the left half<keyboard>_right: flash to the right half
<keyboard>_left_central: flash to the left half acting as central<keyboard>_right: flash to the right half
GitHub Actions builds the full matrix from build.yaml, including all boards and both dongle and dongleless profiles.
Use local Docker when iterating on one board.
make build KEYBOARD=<sweep|urchin|forager>builds a single board in dongleless modemake build KEYBOARD=<sweep|urchin|forager> DONGLE=1builds the dongle profile setmake draw KEYBOARD=<sweep|urchin|forager>regenerates the keymap drawing- Docker must be running first
make help
make build KEYBOARD=sweep
make build KEYBOARD=urchin
make build KEYBOARD=urchin DONGLE=1
make build KEYBOARD=forager
make draw KEYBOARD=sweep
make draw KEYBOARD=urchin
make draw KEYBOARD=foragerBuild notes:
- Local firmware builds read
build.yamldirectly, so local and CI targets stay aligned. - Firmware outputs are written to
build/local/. - Keymap-drawer outputs are written to
tools/keymap-drawer/. - The first keymap draw builds a pinned local Docker image for keymap-drawer.
- urob/zmk-config for home-row mod philosophy and layout ideas
- caksoylar/zmk-config for layout structure and keymap-drawer integration


