Karabiner-Elements: signing identities and the cost of a self-built package
Karabiner-Elements is a powerful tool for customizing keyboards on macOS
At a glance
- What is it?
- Karabiner-Elements remaps keys on macOS, and its repository documents the build path in unusual detail: signing identities many builders cannot create, a Makefile that prints a URL when you run it bare, prebuilt binaries it never rebuilds, and permissions a signer change silently revokes.
- Who is it for?
- Take the official disk image or the Homebrew cask unless you need a change that has not shipped. If you do build, you own three things the repository hands you unfinished: code signing identities, a macOS restart after the signer change, and a virtual HID driver pkg you copied rather than compiled.
- Can I use it commercially?
- Yes. Unlicense is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- pqrs-org/Karabiner-Elements23,102 ★ · +531
| Repository | 2026-08-01 | 2026-11-13 |
|---|---|---|
| pqrs-org/Karabiner-Elements | 22.6k | 23.1k |
531 Stars in the last 104 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Two installers, and an OS list that stops Intel on the newest macOS
Karabiner-Elements is a macOS key remapper written in C++ and released under the Unlicense, with `main` as the default branch and its documentation hosted at karabiner-elements.pqrs.org. Two paths get it onto a Mac. The official site hands over a disk image whose payload is a pkg file, and Homebrew installs the same thing as a cask with `brew install --cask karabiner-elements`. Older builds are not linked from the repository at all; previous versions sit behind the release notes page on the documentation site.
The supported-systems list runs from macOS 13 Ventura up through macOS 27 Golden Gate, and one asymmetry decides who gets the newest system. Every entry from Ventura to macOS 26 Tahoe covers both Intel-based Macs and Apple Silicon Macs. macOS 27 Golden Gate lists Apple Silicon Macs only. An Intel owner therefore reads a support matrix that stops one release short of the top, and the newest macOS is unreachable for them no matter which installer they choose. Read that list as a build constraint too, because the same project sets a higher floor for compiling than for running, which is the subject of the prebuilt binary section below.
A bare make prints a URL and exits, and package deletes your old dmg
Running the Makefile with no target compiles nothing. Its default target `all` echoes two lines, the second of which points at the how-to-build section of the repository page, so a plain `make` is a signpost rather than a build. The target that produces something distributable is:
make packageThat target depends on `clean`, which means every packaging run first recurses into `src` and `tests` through their own clean targets, removes `pkgroot`, and deletes every `*.dmg` already sitting in the working directory. Only after that does the script run, producing a Karabiner-Elements-VERSION.dmg in the current directory, followed by a recurse into tools/clean-launch-services-database. VERSION is the first line of the `version` file, so the name on your disk follows a text file rather than a flag you pass and a version you read off the website.
A separate `build` target exists and recurses into `src` alone. Use it when you want compiled objects and expect nothing else: it never runs make-package.sh, never writes a dmg, and never reaches the launch services cleanup. One more sibling is worth naming before you experiment, because `gitclean` runs `git clean -f -x -d` in the repository root and in two vendor directories, which removes ignored files that `clean` leaves behind.
Signing identities gate the build, and the notarize target belongs to the maintainer
Karabiner-Elements runs background services, and unsigned services do not start. The identity hashes come from:
security find-identity -vThe sample output shows three kinds of identity on a single machine: a Developer ID Installer entry, a Developer ID Application entry, and an Apple Development entry. Which ones you can create decides what you can build. Without Apple Developer Program enrollment you are limited to a development identity, added under Apple Accounts in Xcode Settings and then created from Manage Certificates. Enrolled developers create Developer ID Application and Developer ID Installer certificates instead. Those hashes feed two environment variables:
# Specify the identity hash for Developer ID Application or Apple Development.
export PQRS_ORG_CODE_SIGN_IDENTITY=BD3B995B69EBA8FC153B167F063079D19CCC2834
# Specify the identity hash for Developer ID Installer or Apple Development.
export PQRS_ORG_INSTALLER_CODE_SIGN_IDENTITY=C3107C61DB3605DA2D4549054B225DAFB1D6FA2DRead the two comments literally, because each variable accepts either a Developer ID identity or an Apple Development one. Notarization is closed to outsiders by default as well. The `notarize` target submits with `--keychain-profile "pqrs.org notarization"`, a profile stored in the maintainer's own keychain, so the `notarized-dmg` chain stops there until you create a profile under that name yourself and edit the Makefile. Without enrollment or a profile, your dmg is self signed and unnotarized, and Gatekeeper treats it as such on every other Mac.
Changing the signer kills Accessibility and both background services at once
The permissions the app requests, background service startup and Accessibility access, are attached to the code signing identity that produced the package rather than to the app's name. Swap the official build for one you compiled and macOS sees a new signer, so both permissions die together. The two services carry versioned names in System Settings: Karabiner-Elements Non-Privileged Agents v3 and Karabiner-Elements Privileged Daemons v3. The complication is that System Settings may not refresh its own display after a signer change, leaving a toggle that looks granted while the daemon underneath is not running.
The recovery sequence is blunt. Install your package. In System Settings, disable both background services and remove the Accessibility permission. Restart macOS. Open Karabiner-Elements and grant the permissions again. The same trap fires when you move between two personal builds signed with different identities, so keeping one identity for every package you compile keeps the reset out of your routine. Expect to walk through this once per switch between the official installer and your own.
make package copies a DriverKit pkg it never rebuilds
Part of the shipped product is treated as an artifact that can be trusted without compiling. Pre-built binaries live in the source tree under vendor/Karabiner-DriverKit-VirtualHIDDevice/dist/, and the newest one is picked up by the glob Karabiner-DriverKit-VirtualHIDDevice-*.pkg. Swift dependencies are a separate mechanism: Xcode and SwiftPM resolve `Sparkle` for `Karabiner-Updater`, plus `AsyncAlgorithms`, `CodeEditor`, and other packages used by individual apps, straight from each upstream repository during the build.
The practical consequence is that `make package` copies a virtual HID driver payload it does not build and cannot check. You ship whatever the maintainer last committed into that dist directory, byte for byte, and if the upstream DriverKit project has moved ahead, nothing inside your build tells you. Rebuilding it means leaving this repository and following that project's own instructions. The same looseness applies to the toolchain floor, which sits above the runtime floor: building needs macOS 15 or later and Xcode 26 or later, plus the Command Line Tools for Xcode, xz, XcodeGen, and CMake. macOS 13 Ventura and macOS 14 Sonoma are supported as systems to run on yet are too old to build from, so a reader on an older Mac installs the official build happily and cannot produce one.
The usage section is a documentation link, not a configuration reference
If your question is whether Karabiner-Elements can perform the remap you have in mind, the repository will not answer it. The usage section consists of one line pointing at the documentation site, and no rule syntax, no key name, and no configuration example appears anywhere in the file. The top level offers `docs/`, `appendix/`, `DEVELOPMENT.md`, `NEWS.md`, `TASKS.md`, `SECURITY.md`, `src/`, `tests/`, `tools/`, `vendor/`, `files/`, `pkginfo/`, and `scripts/`, so the material exists somewhere, just not in the entry point you read first.
The cost lands on evaluation. You cannot tell from this repository whether a particular modifier is expressible, and you cannot tell what a misconfigured rule does to your input method, because neither the failure mode nor its recovery appears here. Anyone evaluating the tool has to read the external docs before installing anything. Translations follow the same split: edits go through the localization guide at src/apps/localization/README.md, and the Makefile's `format` target includes a `localization-format` step.
A beta dated after the tagged release is the newest thing in the feed
Three recent releases sit close together: v16.2.0 on 2026-08-30, v16.3.0 on 2026-09-06, and a beta on 2026-09-12. The beta carries the later date, so the most recent tag by timestamp is not the newest stable feature set, and picking by date alone gets you a build the maintainer labelled differently from the two versioned ones. The last push to `main` landed on 2026-11-02, so the tree behind those tags is still moving.
Two consequences follow for anyone pinning a version. First, there is no way to move back through the feed from the repository: the download section offers only the official site and the cask, and earlier builds arrive through the release notes page, which is a documentation page rather than a package index. Second, because VERSION is read from the first line of the `version` file, a build taken from a branch produces a dmg whose filename comes from that file, not from any release name. Two builders on different commits can therefore produce two differently named dmgs with the same upstream provenance, and nothing in the filename tells you which is which.
Editorial conclusion
Take the official disk image or the Homebrew cask unless you need a change that has not shipped. If you do build, you own three things the repository hands you unfinished: code signing identities, a macOS restart after the signer change, and a virtual HID driver pkg you copied rather than compiled. Pin an older build only after checking the release notes page, and test your mapping on a second machine before you depend on it.
Frequently asked questions
What are karabiner-elements on a Mac?
It is a key remapper for macOS, written in C++ and released under the Unlicense, distributed as a disk image containing a pkg file or through a Homebrew cask. It requests Accessibility access and two background services, Karabiner-Elements Non-Privileged Agents v3 and Karabiner-Elements Privileged Daemons v3.
Are karabiner-elements trustworthy?
The permissions it needs are tied to the code signing identity of the package, so a package you build yourself is not the same signer as the official one and its permissions must be granted again. Building requires code signing identities, and without Apple Developer Program enrollment you are limited to an Apple Development certificate.
Why isn't karabiner-elements working?
If you replaced the official package with your own build, the Accessibility permission and both background services became invalid, and System Settings may not update its interface. The documented fix is to disable both services, remove the Accessibility permission, restart macOS, then grant the permissions again from the app.
how to install karabiner elements
Run `brew install --cask karabiner-elements` in Homebrew, or download the disk image from the official site and install the pkg file inside it. Previous versions are downloaded from the release notes page on the documentation site.
How to get rid of karabiner-elements?
The repository does not document an uninstall procedure. What it does document is a permission reset that disables both background services and removes the Accessibility permission, which is the closest thing to a removal path described anywhere in the file.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pqrs-org-karabiner-elements)Star history chart for your README
[](https://hysenlabs.com/projects/pqrs-org-karabiner-elements)Was this useful?