An advanced, easy-to-use key remapper for Linux written in Rust, inspired by QMK.
Note
This project is currently in its early stages of development. More comprehensive documentation will be available soon.
Tip
Click on the feature to expand the example configuration.
Easy-to-use: designed to be used as a systemd service, configured using simple YAML with IDE support (see schema).
# yaml-language-server: $schema=https://raw.githubusercontent.com/luckasRanarison/okey/refs/heads/master/schema/okey.json
keyboards:
- name: "My keyboard"
keys:
KEY_X: KEY_Y
combos:
- keys: [KEY_D, KEY_F]
action: KEY_LEFTCTRL
tap_dances:
KEY_CAPSLOCK:
tap: KEY_TAB
hold: KEY_MOMLAYER
layers:
momentary:
modifier: KEY_MOMLAYER
keys:
KEY_O: KEY_KKey remapping: change the default global key actions.
keyboards:
- name: My keyboard
keys:
KEY_CAPSLOCK: KEY_TAB
KEY_TAB: CUSTOM_KEYCODE # can be used to activate a layer or to trigger other actionsMacros: execute arbitrary key sequences with a single key stroke.
keyboards:
- name: My keyboard
keys:
KEY_F1: [KEY_H, KEY_E, KEY_L, KEY_L, KEY_O] # executes simple key sequences (press + release)
KEY_F2: { string: "Hi, you!" } # inserts an ASCII string
KEY_F3: { env: FOO } # inserts the value of the environment variable
KEY_F4: { unicode: 🙂👍 } # inserts unicode characters using CTRL + SHIFT + U + <code> + ENTER
KEY_F5: { shell: "echo 'foo'", trim: true } # inserts shell script output
KEY_F6: [
{ press: KEY_O },
{ hold: KEY_O },
{ delay: 1000 },
{ release: KEY_O },
KEY_K, # press + release
] # executes detailed key sequences
KEY_F7: [{ env: USERNAME }, { string: "@gmail.com" }] # all types of macro are composableCombos: trigger an action when two or more keys are pressed simultaneously.
keyboards:
- name: My keyboard
combos:
- keys: [KEY_D, KEY_F]
action: LEFT_CTRLTap dance: overload keys by binding different actions to a key whether it is tapped or held.
keyboards:
- name: My keyboard
tap_dances:
tap: KEY_S
hold: KEY_LEFTSHIFT
timeout: 250 # (default: 200ms)Virtual layers: create custom layers, similar to holding Shift. It supports momentary, toggle and oneshoot layers.
keyboards:
- name: "My keyboard"
keys:
KEY_TAB: KEY_ONELAYER # a custom keycode to activate the layer below
tap_dances:
KEY_CAPSLOCK:
tap: KEY_TAB
hold: KEY_MOMLAYER
layers:
momentary:
modifier: KEY_MOMLAYER # type is momentary by default, active on hold
keys:
KEY_X: KEY_Y
one:
modifier:
key: KEY_ONELAYER
type: oneshoot # active for one keypress
keys:
KEY_O: KEY_K
toggle:
modifier:
key: KEY_F12
type: toggle # active until switched off
keys:
KEY_K: KEY_ONote
The features are composable. For example, you can use a combo to trigger a tap dance.
Important
The Rust toolchain is required to build the project.
There are currently no packaged binaries for specific distros, but you can download okey from the releases or install it with cargo:
cargo install okey-cliYou can also build the project from source using the following commands:
git clone --depth 1 https://github.com/luckasRanarison/okey/
cd okey && cargo install --path .okey is designed to be used as a systemd service. It expects a configuration file at ~/.config/okey/config.yaml when installed at the user level, or at /etc/okey/config.yaml when installed with root privileges (see the schema).
For simple testing, you can use the start command to activate keymaps.
okey start # using ~/.config/okey/config.yaml
okey start --config ./path/to/config/okey.yaml
okey start --config ./path/to/config/okey.yaml --daemon # to run as a daemon in the backgroundTo use okey as systemd a service at the user level, you can use the following commands:
okey.service (expand)
[Unit]
Description=Okey Service
[Service]
ExecStart=/usr/bin/okey start --systemd
Restart=on-failure
StandardOutput=journal
StandardError=journal
Nice=-20
[Install]
WantedBy=multi-user.targetokey service install # creates the okey.service file at ~/.config/systemd/
okey service start # shorthand for systemctl --user enable okey && systemctl --user start okey
okey service stop # shorthand for systemctl --user stop okey && systemctl --user disable okey
okey service restart # shorthand for systemctl --user restart okey
okey service status # shorthand for systemctl --user status okey
okey service uninstall # disables the service and remove the okey.service fileBut to get access to higher priority settings and capabilities, it is recommended to install okey at the root level.
okey.service (expand)
[Unit]
Description=Okey Service
[Service]
ExecStart=/usr/bin/okey start --systemd
Restart=on-failure
StandardOutput=journal
StandardError=journal
Nice=-20
CPUSchedulingPolicy=rr
CPUSchedulingPriority=99
IOSchedulingClass=realtime
IOSchedulingPriority=0
[Install]
WantedBy=multi-user.targetsudo okey service install # creates the okey.service file at /etc/systemd/system/
sudo okey service start # shorthand for systemctl enable okey && systemctl start okeyUse okey --help to see all the available commands.
The configuration for okey is written in YAML, it defines how okey remaps keys and sets up advanced behaviors. Check out the examples folder for practical use cases.
Tip
If you are using yaml-language-server, you can get autocompletion and IDE support by adding the following at the top of your file:
# yaml-language-server: $schema=https://raw.githubusercontent.com/luckasRanarison/okey/refs/heads/master/schema/okey.jsonHere's a breakdown of the schema:
Shared global settings, fields:
-
deferred_key_delay: Delay for keys following non-acknowledged special keys.Type:
numberDefault:
0(ms) -
unicode_input_delay: Delay for inserting unicode code points with macro. (flushing)Type:
numberDefault:
50(ms) -
event_poll_timeout: Controls the main event loop interval.Type:
numberDefault:
1(ms)
-
default_timeout: Fallback tap dance timeout.Type:
numberDefault:
200(ms)
-
default_threshold: Window for acknowledging combos.Type:
numberDefault:
10(ms)
Per keyboard configuration.
Type aliases:
KeyCode (expand)
Shifted keycodes (expand)
KEY_EXCLAMATIONKEY_ATKEY_HASHKEY_DOLLARSIGNKEY_PERCENTKEY_CARETKEY_AMPERSANDKEY_STARKEY_LEFTPARENKEY_RIGHTPARENKEY_UNDERSCOREKEY_PLUSKEY_LEFTCURLYKEY_RIGHTCURLYKEY_COLONKEY_DOUBLEQUOTEKEY_LESSKEY_GREATERKEY_QUESTIONKEY_TILDEKEY_PIPE
A custom string or one of:
KEY_RESERVEDKEY_ESCKEY_1KEY_2KEY_3KEY_4KEY_5KEY_6KEY_7KEY_8KEY_9KEY_0KEY_MINUSKEY_EQUALKEY_BACKSPACEKEY_TABKEY_QKEY_WKEY_EKEY_RKEY_TKEY_YKEY_UKEY_IKEY_OKEY_PKEY_LEFTBRACEKEY_RIGHTBRACEKEY_ENTERKEY_LEFTCTRLKEY_AKEY_SKEY_DKEY_FKEY_GKEY_HKEY_JKEY_KKEY_LKEY_SEMICOLONKEY_APOSTROPHEKEY_GRAVEKEY_LEFTSHIFTKEY_BACKSLASHKEY_ZKEY_XKEY_CKEY_VKEY_BKEY_NKEY_MKEY_COMMAKEY_DOTKEY_SLASHKEY_RIGHTSHIFTKEY_KPASTERISKKEY_LEFTALTKEY_SPACEKEY_CAPSLOCKKEY_F1KEY_F2KEY_F3KEY_F4KEY_F5KEY_F6KEY_F7KEY_F8KEY_F9KEY_F10KEY_NUMLOCKKEY_SCROLLLOCKKEY_KP7KEY_KP8KEY_KP9KEY_KPMINUSKEY_KP4KEY_KP5KEY_KP6KEY_KPPLUSKEY_KP1KEY_KP2KEY_KP3KEY_KP0KEY_KPDOTKEY_ZENKAKUHANKAKUKEY_102NDKEY_F11KEY_F12KEY_ROKEY_KATAKANAKEY_HIRAGANAKEY_HENKANKEY_KATAKANAHIRAGANAKEY_MUHENKANKEY_KPJPCOMMAKEY_KPENTERKEY_RIGHTCTRLKEY_KPSLASHKEY_SYSRQKEY_RIGHTALTKEY_LINEFEEDKEY_HOMEKEY_UPKEY_PAGEUPKEY_LEFTKEY_RIGHTKEY_ENDKEY_DOWNKEY_PAGEDOWNKEY_INSERTKEY_DELETEKEY_MACROKEY_MUTEKEY_VOLUMEDOWNKEY_VOLUMEUPKEY_POWERKEY_KPEQUALKEY_KPPLUSMINUSKEY_PAUSEKEY_SCALEKEY_KPCOMMAKEY_HANGEULKEY_HANJAKEY_YENKEY_LEFTMETAKEY_RIGHTMETAKEY_COMPOSEKEY_STOPKEY_AGAINKEY_PROPSKEY_UNDOKEY_FRONTKEY_COPYKEY_OPENKEY_PASTEKEY_FINDKEY_CUTKEY_HELPKEY_MENUKEY_CALCKEY_SETUPKEY_SLEEPKEY_WAKEUPKEY_FILEKEY_SENDFILEKEY_DELETEFILEKEY_XFERKEY_PROG1KEY_PROG2KEY_WWWKEY_MSDOSKEY_COFFEEKEY_DIRECTIONKEY_ROTATE_DISPLAYKEY_CYCLEWINDOWSKEY_MAILKEY_BOOKMARKSKEY_COMPUTERKEY_BACKKEY_FORWARDKEY_CLOSECDKEY_EJECTCDKEY_EJECTCLOSECDKEY_NEXTSONGKEY_PLAYPAUSEKEY_PREVIOUSSONGKEY_STOPCDKEY_RECORDKEY_REWINDKEY_PHONEKEY_ISOKEY_CONFIGKEY_HOMEPAGEKEY_REFRESHKEY_EXITKEY_MOVEKEY_EDITKEY_SCROLLUPKEY_SCROLLDOWNKEY_KPLEFTPARENKEY_KPRIGHTPARENKEY_NEWKEY_REDOKEY_F13KEY_F14KEY_F15KEY_F16KEY_F17KEY_F18KEY_F19KEY_F20KEY_F21KEY_F22KEY_F23KEY_F24KEY_PLAYCDKEY_PAUSECDKEY_PROG3KEY_PROG4KEY_DASHBOARDKEY_SUSPENDKEY_CLOSEKEY_PLAYKEY_FASTFORWARDKEY_BASSBOOSTKEY_PRINTKEY_HPKEY_CAMERAKEY_SOUNDKEY_QUESTIONKEY_EMAILKEY_CHATKEY_SEARCHKEY_CONNECTKEY_FINANCEKEY_SPORTKEY_SHOPKEY_ALTERASEKEY_CANCELKEY_BRIGHTNESSDOWNKEY_BRIGHTNESSUPKEY_MEDIAKEY_SWITCHVIDEOMODEKEY_KBDILLUMTOGGLEKEY_KBDILLUMDOWNKEY_KBDILLUMUPKEY_SENDKEY_REPLYKEY_FORWARDMAILKEY_SAVEKEY_DOCUMENTSKEY_BATTERYKEY_BLUETOOTHKEY_WLANKEY_UWBKEY_UNKNOWNKEY_VIDEO_NEXTKEY_VIDEO_PREVKEY_BRIGHTNESS_CYCLEKEY_BRIGHTNESS_AUTOKEY_DISPLAY_OFFKEY_WWANKEY_RFKILLKEY_MICMUTEBTN_0BTN_1BTN_2BTN_3BTN_4BTN_5BTN_6BTN_7BTN_8BTN_9BTN_LEFTBTN_RIGHTBTN_MIDDLEBTN_SIDEBTN_EXTRABTN_FORWARDBTN_BACKBTN_TASKBTN_TRIGGERBTN_THUMBBTN_THUMB2BTN_TOPBTN_TOP2BTN_PINKIEBTN_BASEBTN_BASE2BTN_BASE3BTN_BASE4BTN_BASE5BTN_BASE6BTN_DEADBTN_SOUTHBTN_EASTBTN_CBTN_NORTHBTN_WESTBTN_ZBTN_TLBTN_TRBTN_TL2BTN_TR2BTN_SELECTBTN_STARTBTN_MODEBTN_THUMBLBTN_THUMBRBTN_TOOL_PENBTN_TOOL_RUBBERBTN_TOOL_BRUSHBTN_TOOL_PENCILBTN_TOOL_AIRBRUSHBTN_TOOL_FINGERBTN_TOOL_MOUSEBTN_TOOL_LENSBTN_TOOL_QUINTTAPBTN_TOUCHBTN_STYLUSBTN_STYLUS2BTN_TOOL_DOUBLETAPBTN_TOOL_TRIPLETAPBTN_TOOL_QUADTAPBTN_GEAR_DOWNBTN_GEAR_UPKEY_OKKEY_SELECTKEY_GOTOKEY_CLEARKEY_POWER2KEY_OPTIONKEY_INFOKEY_TIMEKEY_VENDORKEY_ARCHIVEKEY_PROGRAMKEY_CHANNELKEY_FAVORITESKEY_EPGKEY_PVRKEY_MHPKEY_LANGUAGEKEY_TITLEKEY_SUBTITLEKEY_ANGLEKEY_ZOOMKEY_FULL_SCREENKEY_MODEKEY_KEYBOARDKEY_SCREENKEY_PCKEY_TVKEY_TV2KEY_VCRKEY_VCR2KEY_SATKEY_SAT2KEY_CDKEY_TAPEKEY_RADIOKEY_TUNERKEY_PLAYERKEY_TEXTKEY_DVDKEY_AUXKEY_MP3KEY_AUDIOKEY_VIDEOKEY_DIRECTORYKEY_LISTKEY_MEMOKEY_CALENDARKEY_REDKEY_GREENKEY_YELLOWKEY_BLUEKEY_CHANNELUPKEY_CHANNELDOWNKEY_FIRSTKEY_LASTKEY_ABKEY_NEXTKEY_RESTARTKEY_SLOWKEY_SHUFFLEKEY_BREAKKEY_PREVIOUSKEY_DIGITSKEY_TEENKEY_TWENKEY_VIDEOPHONEKEY_GAMESKEY_ZOOMINKEY_ZOOMOUTKEY_ZOOMRESETKEY_WORDPROCESSORKEY_EDITORKEY_SPREADSHEETKEY_GRAPHICSEDITORKEY_PRESENTATIONKEY_DATABASEKEY_NEWSKEY_VOICEMAILKEY_ADDRESSBOOKKEY_MESSENGERKEY_DISPLAYTOGGLEKEY_SPELLCHECKKEY_LOGOFFKEY_DOLLARKEY_EUROKEY_FRAMEBACKKEY_FRAMEFORWARDKEY_CONTEXT_MENUKEY_MEDIA_REPEATKEY_10CHANNELSUPKEY_10CHANNELSDOWNKEY_IMAGESKEY_PICKUP_PHONEKEY_HANGUP_PHONEKEY_DEL_EOLKEY_DEL_EOSKEY_INS_LINEKEY_DEL_LINEKEY_FNKEY_FN_ESCKEY_FN_F1KEY_FN_F2KEY_FN_F3KEY_FN_F4KEY_FN_F5KEY_FN_F6KEY_FN_F7KEY_FN_F8KEY_FN_F9KEY_FN_F10KEY_FN_F11KEY_FN_F12KEY_FN_1KEY_FN_2KEY_FN_DKEY_FN_EKEY_FN_FKEY_FN_SKEY_FN_BKEY_BRL_DOT1KEY_BRL_DOT2KEY_BRL_DOT3KEY_BRL_DOT4KEY_BRL_DOT5KEY_BRL_DOT6KEY_BRL_DOT7KEY_BRL_DOT8KEY_BRL_DOT9KEY_BRL_DOT10KEY_NUMERIC_0KEY_NUMERIC_1KEY_NUMERIC_2KEY_NUMERIC_3KEY_NUMERIC_4KEY_NUMERIC_5KEY_NUMERIC_6KEY_NUMERIC_7KEY_NUMERIC_8KEY_NUMERIC_9KEY_NUMERIC_STARKEY_NUMERIC_POUNDKEY_NUMERIC_AKEY_NUMERIC_BKEY_NUMERIC_CKEY_NUMERIC_DKEY_CAMERA_FOCUSKEY_WPS_BUTTONKEY_TOUCHPAD_TOGGLEKEY_TOUCHPAD_ONKEY_TOUCHPAD_OFFKEY_CAMERA_ZOOMINKEY_CAMERA_ZOOMOUTKEY_CAMERA_UPKEY_CAMERA_DOWNKEY_CAMERA_LEFTKEY_CAMERA_RIGHTKEY_ATTENDANT_ONKEY_ATTENDANT_OFFKEY_ATTENDANT_TOGGLEKEY_LIGHTS_TOGGLEBTN_DPAD_UPBTN_DPAD_DOWNBTN_DPAD_LEFTBTN_DPAD_RIGHTKEY_ALS_TOGGLEKEY_BUTTONCONFIGKEY_TASKMANAGERKEY_JOURNALKEY_CONTROLPANELKEY_APPSELECTKEY_SCREENSAVERKEY_VOICECOMMANDKEY_ASSISTANTKEY_KBD_LAYOUT_NEXTKEY_BRIGHTNESS_MINKEY_BRIGHTNESS_MAXKEY_KBDINPUTASSIST_PREVKEY_KBDINPUTASSIST_NEXTKEY_KBDINPUTASSIST_PREVGROUPKEY_KBDINPUTASSIST_NEXTGROUPKEY_KBDINPUTASSIST_ACCEPTKEY_KBDINPUTASSIST_CANCELKEY_RIGHT_UPKEY_RIGHT_DOWNKEY_LEFT_UPKEY_LEFT_DOWNKEY_ROOT_MENUKEY_MEDIA_TOP_MENUKEY_NUMERIC_11KEY_NUMERIC_12KEY_AUDIO_DESCKEY_3D_MODEKEY_NEXT_FAVORITEKEY_STOP_RECORDKEY_PAUSE_RECORDKEY_VODKEY_UNMUTEKEY_FASTREVERSEKEY_SLOWREVERSEKEY_DATAKEY_ONSCREEN_KEYBOARDKEY_PRIVACY_SCREEN_TOGGLEKEY_SELECTIVE_SCREENSHOTBTN_TRIGGER_HAPPY1BTN_TRIGGER_HAPPY2BTN_TRIGGER_HAPPY3BTN_TRIGGER_HAPPY4BTN_TRIGGER_HAPPY5BTN_TRIGGER_HAPPY6BTN_TRIGGER_HAPPY7BTN_TRIGGER_HAPPY8BTN_TRIGGER_HAPPY9BTN_TRIGGER_HAPPY10BTN_TRIGGER_HAPPY11BTN_TRIGGER_HAPPY12BTN_TRIGGER_HAPPY13BTN_TRIGGER_HAPPY14BTN_TRIGGER_HAPPY15BTN_TRIGGER_HAPPY16BTN_TRIGGER_HAPPY17BTN_TRIGGER_HAPPY18BTN_TRIGGER_HAPPY19BTN_TRIGGER_HAPPY20BTN_TRIGGER_HAPPY21BTN_TRIGGER_HAPPY22BTN_TRIGGER_HAPPY23BTN_TRIGGER_HAPPY24BTN_TRIGGER_HAPPY25BTN_TRIGGER_HAPPY26BTN_TRIGGER_HAPPY27BTN_TRIGGER_HAPPY28BTN_TRIGGER_HAPPY29BTN_TRIGGER_HAPPY30BTN_TRIGGER_HAPPY31BTN_TRIGGER_HAPPY32BTN_TRIGGER_HAPPY33BTN_TRIGGER_HAPPY34BTN_TRIGGER_HAPPY35BTN_TRIGGER_HAPPY36BTN_TRIGGER_HAPPY37BTN_TRIGGER_HAPPY38BTN_TRIGGER_HAPPY39BTN_TRIGGER_HAPPY40
KeyAction (expand)
A single keycode or a sequence of key events (macro).
Type: KeyCode | KeyEvent[]
Example: KEY_C, [KEY_H, { press: KEY_I }, { release: KEY_I }]
To hold a key, a press event musy be preceding hold.
Type:
{ press: KeyCode }{ hold: KeyCode }{ release: KeyCode }{ delay: number }: Input delay in milliseconds.{ string: string }: ASCII string.{ env: string }: Environment variable key.{ unicode: string }: Unicode string.{ shell: string }: Bash shell command.KeyCode: Press + Release.
TapDance (expand)
Tap dance entry configuration.
-
tap: Action on tap, on release below timeout.Type:
KeyAction -
hold: Action on hold, exceeded timeout.Type:
KeyAction -
timeout: When to consider as a hold.Type:
numberDefault:
250(ms)
Combo (expand)
Combo entry cobfiguration.
-
keys: Set of keys to activate the combo.Type:
KeyCode[] -
action: Action when keys are pressed/held at the same time.Type:
KeyAction
Layer (expand)
Layer entry configuration.
-
modifier: Layer activation key and behavior.Type:
KeyCode|{ key: KeyCode; type?: "momentary" | "toggle" | "oneshoot" } -
keys: Key mappings for the layer.Type:
Record<KeyCode, KeyAction>
Fields:
Name of the keyboard as an input device, you can use okey device list --keyboard to find the name of a keyboard.
Type: string
Key mappings for the main layer.
Type: Record<KeyCode, KeyAction>
Dual function keys on tap/hold.
Type: Record<KeyCode, TapDance>
List of combo mappings.
Type: Combo[]
Virtual layers (shift-like).
Type: Record<string, Layer>
MIT