{"id":13579408,"url":"https://github.com/ItayGarin/ktrl","last_synced_at":"2025-04-05T20:34:07.397Z","repository":{"id":62441740,"uuid":"264729447","full_name":"ItayGarin/ktrl","owner":"ItayGarin","description":"A Supercharged Keyboard Programming Daemon ⌨️","archived":false,"fork":false,"pushed_at":"2023-03-11T20:49:21.000Z","size":310,"stargazers_count":327,"open_issues_count":18,"forks_count":12,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-05-11T18:53:24.197Z","etag":null,"topics":["daemon","keyboard","linux","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ItayGarin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-05-17T18:19:10.000Z","updated_at":"2024-05-08T08:55:02.000Z","dependencies_parsed_at":"2024-01-14T07:04:49.289Z","dependency_job_id":"dad6203f-1eaf-4e44-ba63-5d002ab17f1a","html_url":"https://github.com/ItayGarin/ktrl","commit_stats":{"total_commits":157,"total_committers":9,"mean_commits":"17.444444444444443","dds":"0.10828025477707004","last_synced_commit":"5af7288ad345e3a448917789f33f9b51094f45ff"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItayGarin%2Fktrl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItayGarin%2Fktrl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItayGarin%2Fktrl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ItayGarin%2Fktrl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ItayGarin","download_url":"https://codeload.github.com/ItayGarin/ktrl/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246741122,"owners_count":20826067,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["daemon","keyboard","linux","rust"],"created_at":"2024-08-01T15:01:39.119Z","updated_at":"2025-04-05T20:34:02.384Z","avatar_url":"https://github.com/ItayGarin.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# ktrl\n\n\u003cp\u003e\n  \u003ca href=\"https://crates.io/crates/ktrl\"\u003e\n    \u003cimg alt=\"Crates.io\" src=\"https://img.shields.io/badge/crates.io-0.1.8-orange\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n**TL;DR**\n\n**ktrl** is a **Linux keyboard programming daemon**.\nIt aims to aid you in the never-ending quest of achieving the ultimate keybinding setup.\n\nYou can dip your toes by remapping a few modifier keys (e.g `CapLock` to `Ctrl`).\nOr you can go all-in by creating a sophisticated layering setup with dual-function keys, tap-dancing, etc...\n\nktrl is heavily inspired by the amazing open-source keyboard firmware project [QMK](https://docs.qmk.fm/#/).\nYou can think of ktrl as an attempt to re-implement QMK as a Linux daemon.\n\nThis is an **alpha** state project.\nIf you find any bugs or quirks please reach out to me.\n\n\u003c!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc --\u003e\n**Table of Contents**\n\n- [ktrl](#ktrl)\n    - [Intro](#intro)\n    - [Features Overview](#features-overview)\n        - [Layers](#layers)\n        - [Tap-Hold (Dual Function Keys)](#tap-hold-dual-function-keys)\n        - [Tap-Dancing (Multi-Tap)](#tap-dancing-multi-tap)\n        - [`Meh` and `Hyper`](#meh-and-hyper)\n        - [Audible Feedback](#audible-feedback)\n    - [Installation](#installation)\n    - [Configuration](#configuration)\n        - [Primitives](#primitives)\n            - [Input Event Codes](#input-event-codes)\n            - [Actions](#actions)\n            - [Effects](#effects)\n        - [Configuration File Format](#configuration-file-format)\n    - [Examples](#examples)\n        - [Remapping `Ctrl` to `Capslock`](#remapping-ctrl-to-capslock)\n        - [Home-row Modifiers](#home-row-modifiers)\n    - [Limitations](#limitations)\n\n\u003c!-- markdown-toc end --\u003e\n\n## Intro\n\nktrl sits right in the middle of the human-interface software stack.\nIt lives in userspace, between the kernel and your display server (a.k.a X11 / Wayland).\n\nThis position allows ktrl complete control over the events your keyboard generates.\nThese events are either transparently passed-on or transformed into ktrl's \"Effects\" (more on that later).\n\n## Features Overview\n\nAside from the obvious key remapping capability,\nhere's a taste of some of the major things you can do with ktrl -\n\n### Layers\n\nAlthough \"layers\" might seem like a foreign idea, it's something you're already very familiar with.\nAfter all, you apply \"layers\" all the time by using modifier and function keys :)\n\nQMK takes this mechanism and generalizes it.\nLetting you design your own custom keyboard's layers!\n\nIf that sounds confusing, I encourage you to head over to [QMK's documentation about layers](https://beta.docs.qmk.fm/using-qmk/guides/keymap#keymap-and-layers).\n\n### Tap-Hold (Dual Function Keys)\n\nTap-Hold keys let you do one thing when the key is pressed, and another thing when it is held.\nFor example, you can make your Spacebar act as normal when tapping, but serve as Ctrl when held.\n\n### Tap-Dancing (Multi-Tap)\n\nTap-dancing is quite similar to Tap-Hold. The key will act in one way if tapped once,\nand will act differently if tapped multiple times.\n\n### `Meh` and `Hyper`\n\nAgain, both of these were shamelessly taken from QMK. `Meh` and `Hyper` are special modifiers\nfor creating keybindings that'll probably never conflict with existing ones.\nThat's possible since `Hyper` is equal to pressing `Ctrl+Alt+Shift+Win` and `Meh` is the same as pressing `Ctrl+Alt+Shift`.\n\n### Audible Feedback\n\nEver wanted to bind your favorite 8bit tunes to your key-presses? Well, now you can!\nThough, aside from making your hacking session more musical, this feature as some very practical uses as well.\n\nFor example, it can help you build new muscle-memory connections using audible feedback.\nSee the Capslock \u003c-\u003e Ctrl example below for more on that.\n\n## Installation\n\n#### Getting the Executable\n\nStart off by grabbing the main `ktrl` executable. Here's how you do that -\n\n```\nsudo cargo install --root /usr/local ktrl\n```\n\nNote: you may need to install `alsa` development bindings, `autoconf` and `libtool`. For Debian/Ubuntu distributions this can be done with\n\n```\n# apt install libalsa-ocaml-dev autoconf libtool libtool-bin\n```\n\n#### Setting up ktrl's User and Groups\n\nAlthough a bit cumbersome, this step makes sure we can run ktrl without root privileges.\nInstead of running it as root, we'll make a new user for ktrl. Then, we'll add the\nnew user to the input and audio groups. Let's get started -\n\n```\nsudo useradd -r -s /bin/false ktrl\nsudo groupadd uinput\nsudo usermod -aG input ktrl\nsudo usermod -aG uinput ktrl\n\n# If you're using the sound effects\nsudo usermod -aG audio ktrl\n```\n\nNow, let's add a new udev rule that'll allow ktrl to write to `/dev/uinput`.\n`/dev/uinput` is ktrl's output device. Your keyboard being the input device.\n\n```\ngit clone https://github.com/itaygarin/ktrl\ncd ktrl\nsudo cp ./etc/99-uinput.rules /etc/udev/rules.d/\n```\n\nNote that'll need to reboot your machine for the changes to take effect...\n\n#### Setting up ktrl's Assets and Config\n\nNow, it's time to decide where you'd like ktrl's assets and config to live.\n\nBy default, ktrl will assume you've placed these under `/opt/ktrl`.\nSpecifically, `/opt/ktrl/cfg.ron` and `/opt/ktrl/assets`.\nThough, you can override these defaults with the `--cfg` and `--assets` cli arguments.\n\nTo set-up the defaults, you can follow these steps -\n\n```\n# Asumming you've already cloned and cd`d into the ktrl project\n\nsudo mkdir /opt/ktrl\nsudo cp -r ./assets /opt/ktrl\nsudo cp examples/cfg.ron /opt/ktrl\n\nsudo chown -R ktrl:$USER /opt/ktrl\nsudo chmod -R 0770 /opt/ktrl\n```\n\n#### Locating your Keyboard's input device\n\n#### The easy and obvious way\nIf you want ktrl to process events from all input devices, just run it without arguments.\nIf you also want ktrl to watch for new devices in `/dev/input`, you can pass `--watch` as an argument.\nThis could be useful if you use bluetooth devices that connect and reconnect all the time.\n\n#### Specifying devices manually\n\nIf you want to process events only from selected devices, you have to supply it with a path to your keyboard's input device.\nInput devices reside in the `/dev/input` directory.\n\nLinux provides two convenient symlinks-filled directories to make the search process easier.\nThese directories are `/dev/input/by-id` and `/dev/input/by-path`.\n\nWithin these two directories keyboard devices usually have a `-kbd` suffix.\nFor example, in my laptop, the path is `/dev/input/by-path/platform-i8042-serio-0-event-kbd`.\n\nIf you provide both `--watch` and `--device` arguments, then ktrl will watch for file events only on those devices.\n\n##### Bluetooth keyboard location\n\nIf you are using a bluetooth keyboard, you will need to locate the associated `/dev/input/event\u003c#\u003e` as `/dev/input/by-*` only lists usb connected inputs. The best way to do this is to run `cat /proc/bus/input/devices` and search for the associated bluetooth keyboard (the `Phys` output will have the MAC address). Here is an example:\n```\nI: Bus=0005 Vendor=05ac Product=0239 Version=0050\nN: Name=\"My Keyboard\"\nP: Phys=SO:ME:MA:CA:DD:RS\nS: Sysfs=/devices/pci0000:00/0000:00:01.2/0000:02:00.0/0000:03:08.0/0000:07:00.3/usb3/3-5/3-5:1.0/bluetooth/hci0/hci0:256/0005:05AC:0239.0009/input/input40\nU: Uniq=SO:ME:MA:CA:DD:RS\nH: Handlers=sysrq kbd event25 leds\n\u003csnip\u003e\n```\nNotice in `Handlers`, it tells us the event # we need. So our path to our device is `/dev/input/event25`.\n\n#### Listening on all input devices\n\nIf you still can not figure out which device to use, or want to map events from\nseveral devices, you can pass all (or chosen) devices as an arg:\n```\n--device /dev/input/event*\n# or\n--device /dev/input/event2 /dev/input/event10\n```\n\n#### Setting up ktrl as a Service (Optional)\n\nktrl is a daemon that's designed to run as a background process.\nTherefore, you might want to set it up as a service. Feel free\nto skip this step if you just want to experiment with it.\n\nCreating a service will vary from distro to distro,\nthough, here are some basic steps that'll get you started on `systemd` based systems -\n\n```\n# Again, asumming you've cloned and cd`d into the ktrl project\n\nedit ./etc/ktrl.service # change your device path\nsudo cp ./etc/ktrl.service /etc/systemd/system\nsudo systemctl daemon-reload\nsudo systemctl start ktrl.service\n```\n\n## Configuration\n\nFinally, we get to the cool part!\nThough, let's briefly go over ktrl's config primitives before assembling our first config file\n\n### Primitives\n\n#### Input Event Codes\n\nktrl uses Linux's input-event-codes everywhere.\nThe full list can be found either in Linux's codebase [here](https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h#L75)\nor under ktrl's [KeyCode](https://github.com/ItayGarin/ktrl/blob/master/src/keys.rs) enum.\n\nSpecifically, ktrl uses a subset of the event codes that describe keyboard keys.\nE.g `KEY_A` and `KEY_LEFTCTRL` describe the 'A' and Left-Ctrl keys.\n\n#### Actions\n\nWithin a layer, we map a source key (ex: `KEY_A`) into an `Action`.\nActions describe the **physical input** movements you'll apply to the source key.\nE.g A `TapHold` describes a **tap** and a **hold**.\n\n##### Actions List\n\n- `Tap`: This is the default keyboard action. Use for simple key remappings.\n- `TapHold`: Attach different `Effect`s for a tap and hold.\n- `TapDance`: Attach different `Effect`s for a tap and multiple taps.\n\n#### Effects\n\nAn `Action` will contain one or more `Effect`s.\nThese are the **virtual output** effects that'll manifest following the action.\nE.g Playing a sound, toggling a layer, sending a key sequence, etc...\n\n##### Effects List\n\n- `NoOp`: As the name suggests. This won't do anything.\n- `Key`: This is the default effect you're \"used to\".\n- `KeySticky`: Once pressed, the key will remain active until pressed again (like Capslock).\n- `KeySeq`: Outputs multiple keys at once. E.g `Meh` and `Hyper` are `KeySeq`s\n- `Meh`: A shorthand for `KeySeq(KEY_LEFTCTRL, KEY_LEFTALT, KEY_LEFTSHIFT)`\n- `Hyper`: A shorthand for `KeySeq(KEY_LEFTCTRL, KEY_LEFTALT, KEY_LEFTSHIFT, KEY_LEFTMETA)`\n- `ActivateProfile`: Activates a user-defined profile\n- `DeactivateProfile`: Deactivates a user-defined profile\n- `DeactivateAllProfiles`: Deactivates all user-defined profiles\n- `ToggleLayerAlias`: When pressed, either turns on or off a named layer.\n- `ToggleLayer`: When pressed, either turns on or off a layer.\n- `MomentaryLayer`: While pressed, the relevant layer will remain active\n- `Sound`: Plays one of the pre-built sounds\n- `SoundEx`: Plays a custom sound provided by you.\n- `Multi`: Lets you combine all the above effects. E.g `Multi([Sound(Sticky), KeySticky(KEY_LEFTCTRL)])`\n\n### [Configuration File Format](https://github.com/ItayGarin/ktrl/blob/master/examples/cfg.ron)\n\nktrl uses the wonderful [ron](https://github.com/ron-rs/ron) (Rust Object Notation) to make serializing\nconfiguration much easier. The format should be pretty intuitive, though please refer to the supplied [cfg.ron](https://github.com/ItayGarin/ktrl/blob/master/examples/cfg.ron) for a practical example.\n\n## Examples\n\n### Remapping `Ctrl` to `Capslock`\n\nThis is probably one of the most effective yet simple changes you can make right now.\nYou're left pinky will greatly appreciate this change in the long-run.\n\nDoing this with ktrl is easy. In one of your layers, add the following -\n\n```\nKEY_CAPSLOCK:  Tap(Key(KEY_LEFTCTRL)),\nKEY_LEFTCTRL:  Tap(Key(KEY_LEFTCTRL))),\n```\n\nThough, let's make this more interesting, shall we?\n\nTo make the transition smoother, let's add an error sound effect to the left Ctrl.\nThis'll remind you you're doing something wrong -\n\n```\nKEY_CAPSLOCK:  Tap(Key(KEY_LEFTCTRL)),\nKEY_LEFTCTRL:  Tap(Multi([Key(KEY_LEFTCTRL), Sound(Error)])),\n```\n\nAh, much better!\n\nOf course, you can also go cold turkey and only leave the sound effect. Like so -\n\n```\nKEY_CAPSLOCK:  Tap(Key(KEY_LEFTCTRL)),\nKEY_LEFTCTRL:  Tap(Sound(Error)),\n```\n\n### Home-row Modifiers\n\nAnother change I've been experimenting with is mapping modifiers to home row keys\nThough, due note you'll have to calibrate the `tap_hold_wait_time` config value to\navoid false-positives.\n\nHere's an example setup -\n\n```\nKEY_A:  TapHold(Key(KEY_A), Key(KEY_LEFTCTRL)),\nKEY_S:  TapHold(Key(KEY_S), Key(KEY_LEFTSHIFT)),\nKEY_D:  TapHold(Key(KEY_D), Key(KEY_LEFTALT)),\n```\n\nThis will make `A`, `S` and `D` act as usual on taps and as modifiers when held.\n\n### Remap mouse button to control musical player\n\nIf you have a mouse with a side buttons, you can remap a button to act as a media button.\nThis example shows how to map tap to play/pause and long tap to next song:\n```\nBTN_SIDE: TapHold(Key(KEY_PLAYPAUSE), Key(KEY_NEXTSONG))\n```\n\n##  Limitations\n\n- `TapHold` and `TapDance` require calibration and tinkering. as stated above, you'll have to tweak the wait times for both\nof these to minimize false-positives.\n\n## Similar Projects\n- [alt](https://github.com/ItayGarin/alt): An Event Aggregator that connects to ktrl\n- [QMK](https://docs.qmk.fm/#/): An open source keyboard firmware (ktrl's inspiration)\n- [kmonad](https://github.com/david-janssen/kmonad): Very similar to ktrl (written in Haskell)\n- [xcape](https://github.com/alols/xcape): Implements tap-hold only for modifiers (Linux)\n- [Space2Ctrl](https://github.com/r0adrunner/Space2Ctrl): Similar to `xcape`\n- [interception tools](https://gitlab.com/interception/linux/tools): A framework for implementing tools like ktrl\n- [karabiner-elements](https://karabiner-elements.pqrs.org/): A mature keyboard customizer for Mac\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FItayGarin%2Fktrl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FItayGarin%2Fktrl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FItayGarin%2Fktrl/lists"}