#unicode-characters #keyboard-firmware #keymap #mechanical-keyboard #keyboard-macro

bin+lib infinikey

Tool that allows programmable keyboards to send arbitrary Unicode characters

8 releases (breaking)

Uses new Rust 2024

0.7.0 Jul 14, 2026
0.6.0 Jun 12, 2026
0.5.1 Jun 8, 2026
0.4.0 May 26, 2026
0.1.0 May 14, 2026

#133 in Accessibility

GPL-3.0-or-later

105KB
2.5K SLoC

InfiniKey

Tool that allows programmable keyboards to send arbitrary Unicode characters. For example, you can use it for things like:

  • Emoji 🌈 ✅ ✨
  • Non-latin scripts א ߒ ش
  • Special characters € » «
  • Other symbols ⯅ × ∞

Key Features

  • Independent of your operating system's keymap
  • Cross-platform: Windows & Linux (Wayland only)
  • Written in Rust to be fast, reliable and secure
  • 100% human made. No AI was used to generate, transform or augment any code or documentation written for InfiniKey. To the best of my knowledge, the same is true for those parts of the InfiniKey code which were copied from Espanso.

Details

InfiniKey listens for keyboard events, specifically keypresses of F13 to F24. When the end of a sequence is detected, InfiniKey converts it into Unicode codepoints and sends it to the OS.

Comparison

A similar thing could be achieved with Espanso or AutoHotkey's "hotstring" feature: When those tools detect a specific phrases such as :date, they send simulated backspace key presses to remove the trigger phrase and then send the replacement text, for example December 7, 2024.

Compared to that approach, InfiniKey offers several advantages:

  • Relying on function keys which are otherwise unused means that the original key events are harmless and there is no need to undo them. This avoids problems that occur in Chrome or Electron-based applications where sometimes, parts of the replacement text get lost or the text caret ends up in the wrong position.
  • InfiniKey does not need to be configured for specific sequences, you only need to configure your keyboard to send the sequence for the characters you want.

Various design choices result in these potential disadvantages:

  • InfiniKey cannot be used with non-programmable keyboards.
  • It does not offer dynamic expansion such as the date example above. It also cannot invoke scripts or third-party tools.

Security and Privacy

  • InfiniKey operates 100% locally. There are no network calls whatsoever.
  • To avoid accidentally logging sensitive data, or being misused as a keylogger, InfiniKey entirely ignores letter and number keys.
  • The privileges required on Linux systems to access the input device are only acquired briefly at startup and then dropped irreversibly. To limit its attack surface, InfiniKey does not support being run as root or as a user within the input group.
  • Before injection, Enter and Tab codepoints are removed from the received sequence.

Known shortcut collisions & solutions

  • Linux
    • General
      • Several function keys in the F13-F24 range have special mappings by default. Here is how to neutralize them:
        • KDE Plasma
          • Open System Settings, select "Keyboard" and then click the Key Bindings button in the top right corner. Check "Configure keyboard options", then enter "F13" in the search bar. Check "Use F13-F24 as usual function keys". Click Apply.
        • Other desktop environments
    • Firefox: F14 (Undo) and F18 (Paste)
      • No workaround known. InfiniKey's default configuration avoids these keys.
  • Windows
    • Microsoft OneNote: F16 (Backspace)
      • No workaround known. InfiniKey's default configuration avoids this key.

Installation

Linux

  • Prerequisites:
    • cargo and rustc, v1.89 or above
      • Install via rustup (recommended) or as a system package (may be outdated)
    • System packages: C compiler & libudev
      • Fedora: sudo dnf install cc libudev-devel
      • Ubuntu: sudo apt install gcc
  1. Build and install
    cargo install infinikey
    
  2. Enable permissions
    sudo setcap cap_dac_override=p $(which ik-daemon)
    
  3. Set up systemd service on user level
    infinikey service register
    
  4. Start InfiniKey
    systemctl --user start infinikey
    

Windows

  • Prerequisites:
    • cargo and rustc, v1.89 or above
  1. Build and install
    cargo install infinikey
    
  2. Set up autostart shortcut
    infinikey service register
    
  3. Start InfiniKey
    ik-daemon background
    

Basic usage

  1. Decide on the characters or character sequences you want to type, for example 🌐 on one key and (◕‿◕) on another.
  2. Use the InfiniKey CLI to encode them.
    • By default, each mapping is printed as a list of function keys:
      infinikey encode -m "🌐:globe" "(◕‿◕):face"
      
      🌐      globe   F19, F22, F13, F20, F23, F23, F13, F22, F17, F17, F13, F24
      
      (◕‿◕)   face    F17, F20, F19, F20, F17, F20, F21, F23, F15, F17, F23, F20, F17, F20, F13, F15, F19, F23, F23, F20, F17, F20, F21, F23, F15, F17, F20, F21, F15, F24
      
    • Passing the --zmk option generates a ready-to-use snippet for ZMK keyboards:
      infinikey encode -m "🌐:globe" "(◕‿◕):face" --zmk
      
      #define IK_12(name, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12) \
                      name: name { \
                          label = #name; \
                          compatible = "zmk,behavior-macro"; \
                          #binding-cells = <0>; \
                          wait-ms = <0>; \
                          tap-ms = <2>; \
                          bindings \
                              = <&macro_tap &kp k1 &kp k2 &kp k3 &kp k4 &kp k5 &kp k6 &kp k7 &kp k8 &kp k9 &kp k10 &kp k11 &kp k12> \
                              ; \
                      };
      #define IK_30(name, k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k30) \
                      name: name { \
                          label = #name; \
                          compatible = "zmk,behavior-macro"; \
                          #binding-cells = <0>; \
                          wait-ms = <0>; \
                          tap-ms = <2>; \
                          bindings \
                              = <&macro_tap &kp k1 &kp k2 &kp k3 &kp k4 &kp k5 &kp k6 &kp k7 &kp k8 &kp k9 &kp k10 &kp k11 &kp k12 &kp k13 &kp k14 &kp k15 &kp k16 &kp k17 &kp k18 &kp k19 &kp k20 &kp k21 &kp k22 &kp k23 &kp k24 &kp k25 &kp k26 &kp k27 &kp k28 &kp k29 &kp k30> \
                              ; \
                      };
      
      // 🌐
      IK_12(globe, F19, F22, F13, F20, F23, F23, F13, F22, F17, F17, F13, F24)
      
      // (◕‿◕)
      IK_30(face, F17, F20, F19, F20, F17, F20, F21, F23, F15, F17, F23, F20, F17, F20, F13, F15, F19, F23, F23, F20, F17, F20, F21, F23, F15, F17, F20, F21, F15, F24)
      
  3. Configure your keyboard to send the respective function key sequence for the desired keys.
    • For non-ZMK keyboards, see the manual or firmware documentation for instructions. Have the keyboard send the sequence as regular keypresses with short wait/tap times. Usually, about 2 milliseconds should be sufficient.
    • For ZMK-based keyboards, you can paste the generated snippet into a macros { } block in the keymap / device tree. Then, map the desired keys to the new behaviors. In the example above, you would use &globe and &face instead of built-in behaviors such as &kp.

Acknowledgements

InfiniKey's low-level event detection and text injection capabilities are based on Espanso. Without their great work, InfiniKey would not have been possible.

License

InfiniKey as a whole is licensed under the GPL 3.0 or later. Some parts are licensed under the CC BY 3.0 license.

All files state their individual copyright and license following the REUSE specification.

Dependencies

~4–20MB
~261K SLoC