Keyhac 2
Python-scriptable keyboard customization for Windows and macOS.
Keyhac installs a system-wide keyboard hook and lets you script what your keys do in
Python. You write one file, ~/.keyhac/config.py, and it runs unchanged on both OSes —
remapping keys, binding keys to Python functions, and driving windows, applications and
the clipboard from the keyboard.
Keyhac 2 is the successor to both Keyhac for Windows and Keyhac for macOS, rebuilt as one shared codebase. Its UI is built on PuiKit.
Features
- Key remapping: key → key, key → key sequence, key → Python function.
- Per-application key tables: match by app name, window title, Win32 window class, or the full accessibility focus path (AX on macOS, UI Automation on Windows) — down to "only in this app's text editor pane".
- User modifiers: turn any key into a modifier of your own (User0–User3), invisible to applications.
- One-shot modifiers: tap a modifier alone for one action, hold it to modify.
- Multi-stroke key tables: Emacs-style prefix keys, with a balloon showing the armed prefix.
- Clipboard history: persistent history in a popup chooser — type to filter, Enter pastes into the app you came from. Plus fixed snippets and scriptable clipboard-transform tools.
- Window control: move, snap/tile, minimize, activate and launch applications, multi-monitor aware.
- Keyboard macros: record and replay keys.
- Mouse output: send clicks, wheel scrolls and pointer moves from key bindings.
- Console window: live log, last-key and focus-path inspector — see exactly what to bind. Runs from the system tray (Windows) / menu-bar extra (macOS).
Screenshots
| Console (macOS) | Console (Windows) |
|---|---|
| Menu-bar extra (macOS) | Task tray (Windows) |
|---|---|
Install
Download from Releases:
- macOS 15+ —
Keyhac-<version>-macos.dmg: drag Keyhac.app into Applications and launch it. Grant the Accessibility permission when prompted (required for the keyboard hook). - Windows 10/11 (x64) —
Keyhac-<version>-win64.zip: unzip anywhere and runKeyhac.exe.
Details, data locations and privacy notes: doc/installation.md.
Quick start
On first run Keyhac creates ~/.keyhac/config.py from a fully commented template.
Open it from the tray / menu-bar icon ("Edit Config"), edit, then "Reload Config".
A config defines one function:
from keyhac import *
def configure(keymap):
kt = keymap.define_keytable(focus_path_pattern="*") # active everywhere
kt["Fn-J"] = "Left" # key -> key
kt["Fn-A"] = "Home", "Shift-End" # key -> sequence
def hello(): # key -> Python function
print("Hello from config.py")
kt["Fn-H"] = hello
kt["Fn-V"] = ShowClipboardHistory() # clipboard history popup
kt_browser = keymap.define_keytable(app="chrome|Safari") # per-app table
kt_browser["Fn-R"] = "Cmd-R"
The full reference is doc/configuration.md; the shipped template (keyhac/_config.py) is a working tour of every feature.
Documentation
- Installation — install, permissions, data files, privacy.
- Configuration — the complete config.py reference.
- Migrating from Keyhac for macOS — mostly drop-in.
- Migrating from Keyhac for Windows — API renamed; translation table.
- Developer documentation — architecture, platform layer, packaging, testing. Project guide for coding agents: CLAUDE.md.
Running from source
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest # engine + unit tests, no permissions needed
.venv/bin/python -m keyhac # run (macOS: needs Accessibility permission)
python -m keyhac -d enables debug logging, --no-ui runs headless (hook + engine
only), --config PATH uses an alternate config file (its data files live beside it).
License
MIT — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file keyhac-2.0.0.tar.gz.
File metadata
- Download URL: keyhac-2.0.0.tar.gz
- Upload date:
- Size: 175.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97a6db48ec14caea291ed1c951cf34de756187021c7c23448da61d78c462e533
|
|
| MD5 |
834ae0cee658d3e8e1c1636e47c2e217
|
|
| BLAKE2b-256 |
cf6ad213ffe43c0608f2bfb86c0f125de076fd860bc861975ae6a257996db6c8
|
File details
Details for the file keyhac-2.0.0-py3-none-any.whl.
File metadata
- Download URL: keyhac-2.0.0-py3-none-any.whl
- Upload date:
- Size: 188.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af6fc3c52114ed8078e552f61a6de2ef19c7475e5b45abc3e2a9108cf33ea1d1
|
|
| MD5 |
8e5afd488f0071bee5796516208c8b8c
|
|
| BLAKE2b-256 |
0256d9155ee95f901b96fa25158a22e6c8ee200738b2c18f9e80943eaedb8efb
|