Karabiner-Elements Documentation

repository·main·Indexed 30 days ago

https://github.com/pqrs-org/karabiner-elements

A low-level macOS keyboard remapper that uses a multi-process architecture to intercept, modify, and repost HID events via DriverKit. Documentation covers installation via Homebrew, building from source with Xcode, development details for core processes (daemon, agent, and user server), and using libkrbn for application history and mathematical expression evaluation.

Tokens
8.4K
Snippets
5
Records
70
Agent score
97%

What's inside Karabiner-Elements

  1. Understand Karabiner-Elements core processes

    main

    Karabiner-Elements relies on several distinct processes with different privilege levels:

    • Karabiner-Core-Service (daemon): Runs with root privileges. It seizes input devices and modifies/reposts events via Karabiner-DriverKit-VirtualHIDDevice.
    • Karabiner-Core-Service (agent): Runs with user privileges. It monitors application switches and UI element changes using the Accessibility API.
    • karabiner_console_user_server: Runs with console user privileges. It is responsible for:
      • Detecting the current console user (using CGSessionCopyCurrentDictionary).
      • Executing shell_command, software_function, and select_input_source.
      • Notifying the daemon of active application and input source information.
      • Connecting to the Unix domain socket provided by Karabiner-Core-Service to request the start of input event processing.
  2. Understand Karabiner-Elements required permissions

    main

    Karabiner-Elements requires several macOS permissions to function correctly:

    • Privileged Daemon (SMAppService.daemon): Required to run Karabiner-Core-Service with root privileges. Root access is necessary to use kIOHIDOptionsTypeSeizeDevice to seize hardware devices.
    • Input Monitoring: Required to receive events from devices via IOHIDDeviceOpen.
    • Accessibility: Required for:
      • Detecting application switches for apps that do not emit NSWorkspace.didActivateApplicationNotification (e.g., Spotlight).
      • Obtaining the focused UI element.
      • Receiving key events when the CGEventTap fallback is enabled.
  3. Build Karabiner-Elements from source

    main

    To build Karabiner-Elements, ensure your system meets the following requirements:

    Prerequisites

    • macOS 15+
    • Xcode 26+
    • Command Line Tools for Xcode (xcode-select --install)
    • xz (brew install xz)
    • XcodeGen (brew install xcodegen)
    • cmake (brew install cmake)

    Build Steps

    1. Clone the repository

    git clone --depth 1 https://github.com/pqrs-org/Karabiner-Elements.git
    cd Karabiner-Elements
    git submodule update --init --recursive --depth 1

    2. Configure Code Signing

    Code signing is required for background services. Use security find-identity -v to find your identity hashes, then export them as environment variables:

    # Use the hash for Developer ID Application or Apple Development
    export PQRS_ORG_CODE_SIGN_IDENTITY=<YOUR_IDENTITY_HASH>
    
    # Use the hash for Developer ID Installer or Apple Development
    export PQRS_ORG_INSTALLER_CODE_SIGN_IDENTITY=<YOUR_IDENTITY_HASH>

    3. Build the package

    Run the following command to generate a .dmg file containing the package:

    make package
    git clone --depth 1 https://github.com/pqrs-org/Karabiner-Elements.git
    cd Karabiner-Elements
    git submodule update --init --recursive --depth 1
    # ... set env vars ...
    make package
  4. Replace individual binaries without reinstalling the package

    main

    If you are developing and modifying the source code, you must first rebuild and install the entire package with your own code signature to ensure inter-process communication (via UNIX domain sockets) works correctly. Once the full package is installed, you can quickly replace individual binaries by navigating to their respective directories and running make install.

    Note: All official binaries are signed with G43BCU2T37. If you replace only some binaries without matching signatures, communication between processes will fail.

    ### Replace `Karabiner-Core-Service`
    
    ```shell
    cd src/core/CoreService
    make install

    Replace karabiner_console_user_server

    cd src/core/console_user_server
    make install
  5. Understand the Karabiner-Elements keybinding lifecycle

    main

    Karabiner-Elements processes keybindings through a multi-stage pipeline. Understanding this pipeline helps in debugging why a rule might not be firing or why there is perceived latency.

    The Keybinding Pipeline

    1. Input Ingestion: An input device emits a HID event, which macOS delivers to the Karabiner core.
    2. Manipulator Matching: The core evaluates the from key/button, modifiers, and conditions (e.g., frontmost app, variables, device type). If they match, the to actions are emitted as internal events.
    3. Post-event Scheduling: The emitted events are queued for dispatch.
    4. Dispatch: Events follow one of two paths:
      • Path A (Virtual HID): For key/mouse outputs (synthetic keypresses/clicks). These are posted to a virtual HID service.
      • Path B (User-context Operations): For actions like shell_command, send_user_command, select_input_source, or software functions. These are forwarded via IPC to the console_user_server to run in the logged-in user's context.

    Debugging Strategy

    When a keybinding fails, debug it in stages:

    1. Matching: Did the manipulator actually match the input? (Check modifiers, conditions, and event types like key_down vs key_up).
    2. Emission: Which internal to event type was emitted?
    3. Dispatch: Which path was used (Virtual HID vs console_user_server)?
    4. Execution: Did the chosen path complete? (e.g., Is the console_user_server running? Is the target socket available for send_user_command?)
  6. Generate Complex Modifications using JavaScript

    main
    As of version 16.0.0, you can generate JSON for Complex Modifications rules by writing JavaScript. The Complex Modifications viewer includes an "Add your own rule using JavaScript" button to facilitate this workflow.