A key remapping daemon for Linux.
Note
https://github.com/keyd-project/keyd-fork is a temporary, friendly fork of the original keyd project (upstream). This fork was created on 2024-12-06 with the following goals:
- Help reduce the backlog of pull requests in the original project by merging them here and creating releases that users can test.
- Provide a well-maintained distribution tarball to make it easier for downstream packagers to maintain keyd packages.
- Recruit potential maintainers. (If you are interested, please speak up at rvaiya/keyd#887 or contact @rhansen directly.)
Once the original project acquires a vibrant group of maintainers, this fork
will be archived. If the original project is abandoned, this fork will be
made permanent by dropping the -fork
suffix.
See rvaiya/keyd#887 for discussion.
This fork's branch plan: Commits intended to be reintegrated with the upstream
project will be put on a reintegrate-vN
branch where N
is a version
number. If new commits are pushed to the upstream project, and the new
commits cause the current reintegrate-vN
branch to no longer be
fast-forwardable from the upstream's default branch:
- A new
reintegrate-vM
branch (whereM = N+1
) is created pointing to the same commit asreintegrate-vN
, but not pushed yet. reintegrate-vM
is rebased onto the upstream project's default branch, preserving merges.reintegrate-vM
is merged intomain
.reintegrate-vN
is deleted.
This is a bit painful, but the goal is to make it as easy as possible to
reintegrate with the upstream project without force-pushing this fork's main
branch.
Feel free to open issues or pull requests in this fork. Pull requests
containing commits intended for reintegration into the upstream project should
be merged into the current reintegrate-vN
branch, not main
. After the
pull request is merged, reintegrate-vN
is merged into main
.
Linux lacks a good key remapping solution. In order to achieve satisfactory results a medley of tools need to be employed (e.g xcape, xmodmap) with the end result often being tethered to a specified environment (X11). keyd attempts to solve this problem by providing a flexible system wide daemon which remaps keys using kernel level input primitives (evdev, uinput).
The config format has undergone several iterations since the first release. For those migrating their configs from v1 it is best to reread the man page.
See also: changelog.
- Speed (a hand tuned input loop written in C that takes <<1ms)
- Simplicity (a config format that is intuitive)
- Consistency (modifiers that play nicely with layers by default)
- Modularity (a UNIXy core extensible through the use of an IPC mechanism)
keyd has several unique features many of which are traditionally only found in custom keyboard firmware like QMK as well as some which are unique to keyd.
Some of the more interesting ones include:
- Layers (with support for hybrid modifiers).
- Key overloading (different behaviour on tap/hold).
- Keyboard specific configuration.
- Instantaneous remapping (no more flashing :)).
- A client-server model that facilitates scripting and display server agnostic application remapping. (Currently ships with support for X, sway, and gnome (wayland)).
- System wide config (works in a VT).
- First class support for modifier overloading.
- Unicode support.
- Would like to experiment with custom layers (i.e custom shift keys) and oneshot modifiers.
- Want to have multiple keyboards with different layouts on the same machine.
- Want to be able to remap
C-1
without breaking modifier semantics. - Want a keyboard config format which is easy to grok.
- Like tiny daemons that adhere to the Unix philosophy.
- Want to put the control and escape keys where God intended.
- Wish to be able to switch to a VT to debug something without breaking their keymap.
- A tool for programming individual key up/down events.
- Your favourite C11 compiler
- POSIX-compatible
make
(e.g., GNU Make) - Linux kernel headers (already present on most systems)
- Python 3.8 or newer
- scdoc
- bash (for the
usb-gadget
virtual keyboard driver) - Python 3.8 or newer (for application specific remapping)
- python-xlib (only for X support)
- dbus-python (only for KDE support)
- systemd (for system services)
Binary packages for some distributions exist. These are kindly maintained by community members; the keyd developers do not take responsibility for them. If you wish to add yours below, please open a PR.
keyd package maintained by @jirutka.
Arch Linux package maintained by Arch packagers.
Experimental keyd
and keyd-application-mapper
packages can be found in the
CI build artifacts of the work-in-progress Debian package
repository:
Any Debian Developer who is willing to review the debianization effort and sponsor its upload is encouraged to contact @rhansen (also see the Debian ITP bug).
COPR package maintained by @alternateved.
opensuse package maintained by @bubbleguuum.
Easy install with sudo zypper in keyd
.
Experimental keyd
and keyd-application-mapper
packages can be found in the
ppa:keyd-team/ppa
archive.
If you wish to help maintain this PPA, please contact @rhansen.
Note
The default branch (main
) is the development branch; it contains the latest
work-in-progress code. Things may occasionally break between releases.
Stable releases are tagged
and announced on the releases
page; these versions are
known to work.
-
Download the desired tarball:
- Releases can be found on the releases page.
- The current revision of the
main
branch (work-in-progress development version) can be found at https://nightly.link/keyd-project/keyd-fork/workflows/ci/main/distribution-tarball. Note that the distribution tarball is inside a zip file due to an unfortunate GitHub limitation.
-
Extract the tarball and
cd
to the source code directory:tar xvfa /path/to/keyd-*.tar.gz cd keyd-*
-
Ensure that all required build dependencies have been installed.
-
Build and install keyd:
./configure make sudo make install
-
Install Git, GNU Autoconf, and GNU Automake.
-
Get the source code:
git clone https://github.com/keyd-project/keyd-fork cd keyd-fork
-
Optionally switch to a released revision, if desired:
git checkout v2.5.0
-
Generate the
configure
script:./autogen
-
Follow steps 3 and later from installation from a source code distribution tarball.
-
Install and start keyd (e.g
sudo systemctl enable keyd --now
) -
Put the following in
/etc/keyd/default.conf
:
[ids]
*
[main]
# Maps capslock to escape when pressed and control when held.
capslock = overload(control, esc)
# Remaps the escape key to capslock
esc = capslock
Key names can be obtained by using the keyd monitor
command. Note that while keyd is running, the output of this
command will correspond to keyd's output. The original input events can be seen by first stopping keyd and then
running the command. See the man page for more details.
-
Run
sudo keyd reload
to reload the config set. -
See the man page (
man keyd
) for a more comprehensive description.
Config errors will appear in the log output and can be accessed in the usual
way using your system's service manager (e.g sudo journalctl -eu keyd
).
Note: It is possible to render your machine unusable with a bad config file.
Should you find yourself in this position, the special key sequence
backspace+escape+enter
should cause keyd to terminate.
Some mice (e.g the Logitech MX Master) are capable of emitting keys and are consequently matched by the wildcard id. It may be necessary to explicitly blacklist these.
-
Add yourself to the keyd group:
usermod -aG keyd <user>
-
Populate
~/.config/keyd/app.conf
:
E.G
[alacritty]
alt.] = macro(C-g n)
alt.[ = macro(C-g p)
[chromium]
alt.[ = C-S-tab
alt.] = macro(C-tab)
-
Run:
keyd-application-mapper
You will probably want to put keyd-application-mapper -d
somewhere in your
display server initialization logic (e.g ~/.xinitrc) unless you are running Gnome.
See the man page for more details.
Experimental support for single board computers (SBCs) via usb-gadget has been added courtesy of Giorgi Chavchanidze.
See usb-gadget.md for details.
[ids]
*
[main]
leftshift = oneshot(shift)
capslock = overload(symbols, esc)
[symbols]
d = ~
f = /
...
Many users will probably not be interested in taking full advantage of keyd. For those who seek simple quality of life improvements I can recommend the following config:
[ids]
*
[main]
shift = oneshot(shift)
meta = oneshot(meta)
control = oneshot(control)
leftalt = oneshot(alt)
rightalt = oneshot(altgr)
capslock = overload(control, esc)
insert = S-insert
This overloads the capslock key to function as both escape (when tapped) and control (when held) and remaps all modifiers to 'oneshot' keys. Thus to produce the letter A you can now simply tap shift and then a instead of having to hold it. Finally it remaps insert to S-insert (paste on X11).
xmodmap and friends are display server level tools with limited functionality. keyd is a system level solution which implements advanced features like layering and oneshot modifiers. While some X tools offer similar functionality I am not aware of anything that is as flexible as keyd.
What about kmonad?
keyd was written several years ago to allow me to easily experiment with different layouts on my growing keyboard collection. At the time kmonad did not exist and custom keyboard firmware like QMK (which inspired keyd) was the only way to get comparable features. I became aware of kmonad after having published keyd. While kmonad is a fine project with similar goals, it takes a different approach and has a different design philosophy.
Notably keyd was written entirely in C with performance and simplicitly in mind and will likely never be as configurable as kmonad (which is extensible in Haskell). Having said that, it supplies (in the author's opinion) the most valuable features in less than 2000 lines of C while providing a simple language agnostic config format.
If you feel something is missing or find a bug you are welcome to file an issue on github. keyd has a minimalist (but sane) design philosophy which intentionally omits certain features (e.g execing arbitrary executables as root). Things which already exist in custom keyboard firmware like QMK are good candidates for inclusion.
See CONTRIBUTING. IRC Channel: #keyd on oftc