chkb turns a regular keyboard intro a fully programmable keyboard.
So you basically get a cheap programmable keyboard.
It has been inspired by QMK firmware and kmonad.
This applies to the current preview version, this will change in the future but I will try to keep this info updated.
ATTENTION: if you manage to block your keyboard, hold ESC and the application will quit. This is a safe guard and cannot be disabled and is handled before any key event.
create a keys.yaml
with at least a base layer keyMap.
layers:
base:
keyMap:
find the input file from your keyboard. This files are located at /dev/input/by-id/
. The id should be enough to tell which one is your keyboard. if not, you can sudo cat /dev/input/by-id/file
and see if you can see data when you type on your keyboard.
To avoid sudo, you can add your user to the input group.
sudo usermod -a -G input $USER
chkb needs access to /dev/uinput
in order to generate key events. You can create a rule for this. so you don't need sudo.
Extracted from here: https://github.com/bendahl/uinput
echo KERNEL==\"uinput\", GROUP=\"$USER\", MODE:=\"0660\" | sudo tee /etc/udev/rules.d/99-$USER.rules
sudo udevadm trigger
Run chkb
from the directory containing this file providing as first parameter the path to your device. If everything works, you should see a message push layer base
which means that everything is running. You can start typing to see some captured events.
./chkb -i /dev/input/by-id/usb-Logitech_USB_Receiver-if01-event-kbd
# TIP add -v flag for debug info
This example remaps the CAPSLOCK to LEFTMETA. This means that pressing caps will behave as if you've pressed leftmeta.
layers:
base:
keyMap:
KEY_CAPSLOCK:
Map:
- keyCode: KEY_LEFTMETA
A layer modifies how your keys behave. Base layer is pushed at startup and cannot be removed but it can be changed. Just make sure that you always have a way to move between layers or you will be stuck.
layers:
base:
keyMap:
KEY_CAPSLOCK:
Tap:
## Change base layer for control layer
- action: ChangeLayer
layerName: control
control:
keyMap:
KEY_CAPSLOCK:
Tap:
## Go back to base
- action: ChangeLayer
layerName: base
You can push other layers to extend the functionality of the base layer. The layers are push into a stack and read from top to down. Once the event is handled by a layer, the next layers do not receive it. Most users will be fine using only ChangeLayer. but this is still an interesting feature to modify only parts of your keyboard.
This example shows how to create a layer that temporally swaps keys AB
layers:
base:
keyMap:
KEY_CAPSLOCK:
# Tap means to press and release in less than 200ms
Tap:
# PushLayer requires the layer name to push that must match with yaml key
- action: PushLayer
layerName: swapAB
# definition of swapAB layer
swapAB:
keyMap:
# swap A
KEY_A:
- keyCode: KEY_B
# swap B
KEY_B:
- keyCode: KEY_A
# remove the layer if caps is tapped again,
# as this event is handled by swapAB layer,
# base layer wont trigger the Tap action
KEY_CAPSLOCK:
Tap:
- action: PopLayer
layerName: swapAB
You can capture special events like tap/hold and perform custom actions
This will tap CAPSLOCK if you hold LEFTSHIFT
layers:
base:
keyMap:
KEY_LEFTSHIFT:
Hold:
- action: Tap
keyCode: KEY_CAPSLOCK
There are cases where you want to do multiple actions with a single input event. You may have noticed that the Keyboard events are a list, This means you can use as many as you need.
This example shows how to enable a control layer that allows you to jump to another layer
layers:
base:
keyMap:
KEY_CAPSLOCK:
Tap:
- action: PushLayer
layerName: control
Map:
- keyCode: KEY_LEFTMETA
## Intermediate layer
control:
keyMap:
KEY_CAPSLOCK:
## Go back to base
Tap:
- action: PopLayer
layerName: control
## Ensure key still works as a meta key
Map:
- keyCode: KEY_LEFTMETA
KEY_A:
# If tap A, pop this layer and push arrows layer
Tap:
- action: PopLayer
layerName: control
- action: PushLayer
layerName: arrows
# Block a key so it doesn't type anything
Map:
- action: Nil
arrows:
keyMap:
KEY_CAPSLOCK:
## Go back to base by poping arrows layer
Tap:
- action: PopLayer
layerName: arrows
## Ensure key still works as a meta key
Map:
- keyCode: KEY_LEFTMETA
## Put arrows on hjkl vim style
KEY_J:
Map:
- keyCode: "KEY_DOWN"
KEY_K:
Map:
- keyCode: "KEY_UP"
KEY_H:
Map:
- keyCode: "KEY_LEFT"
KEY_L:
Map:
- keyCode: "KEY_RIGHT"
onMiss event is triggered on keydown if a key contains no mapping in the current layer. It is useful to automatically leave a layer if you press something that it is not mapped. By default, the keydown event stops on the current layer, if you want to propagate it, you have to add the Map action to the onMiss action list
layers:
base:
keyMap:
KEY_CAPSLOCK:
Tap:
- action: ChangeLayer
layerName: control
control:
onMiss:
## If you press a non mapped key...
Tap:
## Go back to base
- action: ChangeLayer
layerName: base
## And forward the down even to base layer
- action: Map
keyMap:
## (keymaps...)
key events are used to capture events from your keyboard and map them into other keyboard events.
layers:
base:
keyMap:
KEY_LEFTSHIFT:
Hold: <--- This is the key event
- action: Tap
layerName: KEY_CAPSLOCK
- Map: Forwards the up/down events to a different key
- Down: On key down
- Up: On key up
- Tap: press and release in less than 200ms, no other keys are pressed in between
- DoubleTap: tap twice!
- Hold: keep the key down for more than 200ms or press another key while it is down.
These events are the ones generated by the keyMaps.
layers:
base:
keyMap:
KEY_LEFTSHIFT:
Hold:
- action: Tap <--- This is a Keyboard Event
layerName: KEY_CAPSLOCK
- Nil: does nothing
- Map: Forwards the up/down events to a different key // Default behaviour
- keyCode: Key used
- Down: Simulate key up
- keyCode: Key used
- Up: Simulate key down
- keyCode: Key used
- Tap: press and release in less than 200ms
- keyCode: Key used
- DoubleTap: tap twice!
- keyCode: Key used
- Hold: press until the keyboard repeats the event
- keyCode: Key used
- PushLayer: push a layer into the stack
- layerName: name of the layer
- PopLayer: removes a layer from the stack
- layerName: name of the layer
- ChangeLayer: The base layer will be replaced
- layerName: name of the layer
If you tap a key, you will see the code printed in the chkb log. This way you can find the name of any key from your keyboard.
To find extra keys, you can read ./pkg/chkb/ecodes.go and use anything starting with KEY_
. This keys are just standard keycodes and you can also find them in linux source code /usr/include/linux/input-event-codes.h
- integrate with cobra cli
- allow to specify the location of the config file
- Allow to disable layerFile functionality
- extract tapDelay to configuration
- implement testing run mode. just to see keypresses and final maps
- easy autoshift functionality for layers
- examples
- Implement RESETKEY to start-stop the app in the background
- add initialLayer as a configuration parameter