Setup Guide
Install Keyboard Helper, grant the permissions it needs, then configure layouts and synchronization from the app menu.
1. Download
Grab the latest release for your platform from the GitHub releases page. Builds are available for macOS Apple Silicon, macOS Intel, Windows, and Linux.
- Download the appropriate archive for your OS. On macOS choose
macos-apple-siliconfor an M-series Mac ormacos-intelfor an Intel Mac. - On macOS, download the neighboring
.sha256file, open the.dmg, and drag Keyboard Helper.app to Applications. - On Windows, run the
.msiinstaller. - On Linux, extract the archive and run the binary.
Verify a macOS download with both files in the same directory:
shasum -a 256 -c Keyboard-Helper_*.dmg.sha256 ~/.keyri.json settings remain compatible.Android Companion
API 31+ · arm64 previewAndroid is a separate foreground companion with its own installation, connection, Browse, compatible read-only Live, custom-layout, and recovery flow. The signed preview is distributed through GitHub Releases rather than Google Play.
Open the complete Android Companion guide →
2. First launch
- On macOS, try to launch the installed app once.
- If Gatekeeper blocks it, open System Settings -> Privacy & Security, scroll to Security, choose Open Anyway for Keyboard Helper, then confirm Open.
- Grant Input Monitoring when requested so global key highlighting can work.
- Start typing in any app. The transparent overlay should show the default QWERTY layout and highlight pressed keys.
If highlighting stops after an update, quit Keyboard Helper, remove stale Keyboard Helper or Keyboard Layout entries from System Settings -> Privacy & Security -> Input Monitoring, add /Applications/Keyboard Helper.app, and relaunch it.
Closing the window hides it to the system tray. Restore it from the tray icon menu, the configured hotkey, or the CLI toggle.
3. Use the application menu
The top-right application menu is the main control surface. On macOS, the native menu bar exposes matching commands for common actions.
4. Configuration
Open the application menu and choose Settings. You can enable built-in layouts, choose the startup layout, record a show/hide shortcut, and add a custom layout with the native file picker. Review your changes, then choose Save changes; the running overlay refreshes automatically.
Advanced JSON configuration
To manage the file directly, edit ~/.keyri.json. The legacy ~/keyri.json location is still read, while saves from Settings use the primary path. Without either file the app enables every built-in layout and starts with QWERTY.
Select a default layout
{
"defaultLayout": "corne",
"layouts": {
"corne": true,
"qwerty": true
}
} Load a custom layout file
{
"defaultLayout": "my-layout",
"layouts": {
"my-layout": "/home/you/keyboards/my-layout.json"
}
} Usually, choose Add layout file... in Settings. Layout files are JSON. Copy one of the built-in layouts from the repo, such as src/layout_corne.json, as a starting point.
Global toggle hotkey
Use Record shortcut in Settings to configure a system-wide hotkey to show or hide the app. Press it once to restore, press it again to hide.
{
"toggleHotkey": "Shift+Meta+K"
} Supported modifiers: Shift, Meta / Cmd, Ctrl, Alt / Option. Single letters are accepted, such as K becoming KeyK. For other keys use the rdev key name directly, such as F1.
5. Mini Mode
Desktop appChoose Mini Mode from the overlay menu when screen space is limited. On macOS you can also choose View -> Enter Mini Mode. The compact window keeps showing the active keyboard layer and live key highlights, but hides menus and status chrome.
Drag Mini Mode from the empty padding around the keyboard. Use the arrow button labelled Restore full size to return to the previous full window size and position. Mini Mode is temporary, so a fresh launch always starts full size.
6. Guided keyboard self-test
Desktop appExpand Keyboard in the overlay menu and choose Keyboard Self-test. Select a configured layout and one layer; the base layer is selected initially. Activate the chosen layer on your keyboard yourself, release all keys, then start the guided test and press and release each highlighted physical position.
- Passed means the configured HID code completed the expected press-and-release cycle.
- Unexpected records a different received code after you choose to continue.
- Skipped means you explicitly continued because no usable event arrived.
- Not testable covers empty, unsupported, or multi-step layout behaviors.
Use Retest problems to repeat unexpected and skipped positions, or Test another layer to return to selection. Results are discarded when the window closes.
Modifier descriptors such as Shift+KeyQ are checked as complete HID chords. The required modifiers must match exactly when the trigger is pressed, and the position passes only after the trigger and every contributing modifier have been released; either release order is accepted.
7. ZMK BLE layer sync
BLE-dependentA layout can include bleLayerSource metadata so Keyboard Helper listens to a compatible keyboard's active ZMK layer and updates the overlay from firmware state instead of only local modifier handling.
When the active layout has BLE metadata, the Connection flyout shows connecting, connected, not configured, or error state. Use Reconnect BLE after waking the keyboard, changing Bluetooth permission, or editing layout metadata.
8. Synchronize a ZMK language layer on macOS
macOS + BLEAn external layout can map installed macOS input-source IDs to ZMK language families. When the metadata is valid, the overlay shows a Language flyout. Choosing a language selects that exact macOS source first; the app then corrects a stable mismatched ZMK base layer through the layout's existing writable BLE characteristic. Changes made by another keyboard or the macOS input menu are observed too.
{
"inputSourceSync": {
"macos": {
"settleMs": 1000,
"sources": [
{
"id": "de",
"label": "Deutsch",
"inputSourceId": "com.apple.keylayout.German",
"baseLayer": 4,
"layers": [4, 5, 6, 16]
},
{
"id": "ru",
"label": "Русский",
"inputSourceId": "com.apple.keylayout.Russian",
"baseLayer": 9,
"layers": [9, 10, 12, 17]
}
],
"neutralLayers": [13, 18]
}
}
} Run defaults read ~/Library/Preferences/com.apple.HIToolbox.plist AppleEnabledInputSources to inspect enabled sources. The configured value must be the exact Text Input Source Services kTISPropertyInputSourceID. An unavailable configured source is disabled instead of being guessed.
Every family layer and neutral layer must be a valid, non-overlapping keyLayers index, and each baseLayer must belong to its family. Optional settleMs controls how long the app waits before correcting a stable mismatch; it defaults to 1000 and accepts integer milliseconds from 0 through 60000.
bleLayerSource to point to a characteristic supporting encrypted Write with response and Notify. Transient Shift/AltGr/Character layers and configured neutral Functional/Mouse layers are preserved until a stable base layer returns.9. Shift-Space Invaders
Practice modeChoose Shift-Space Invaders from the application menu to open a separate typing arcade window. It uses focused window input for gameplay, so overlay global key events can keep highlighting without advancing the game twice.
10. CLI toggle flag
You can also toggle the app by launching it with the --toggle flag. If the app is already running, this shows or hides the window rather than opening a second instance.
/Applications/Keyboard\ Helper.app/Contents/MacOS/keyboard-app --toggle Useful for binding to external hotkey managers like Raycast, BetterTouchTool, or Shortcuts.app.
11. Build from source
Prerequisites: Node.js LTS, Rust toolchain, and Tauri v2 platform deps.
git clone https://github.com/maxistar/keyboard_helper.git
cd keyboard_helper
npm install
npm run tauri dev # dev window
npm run tauri build # release bundle Need a short fix instead of the full guide? The FAQ covers common setup, permission, BLE, and feature questions.