A free, robust keyboard key remapping tool for Windows 11 (also works on Windows 10).
Easily customize and remap keys with dual purpose key-press separated by delayed release:

Block keys to prevent unintentional keypress:

Complete Co-Pilot Key Remapping & Customization (Or disable forever):

Option to auto-start at launch for uninterruped remapping and key blocking:

Easily visualize all available mapping options:

Ignore keyboard layout to map special characters to modifier keys:

Version 2.6 | Built by Li Fan, 2026
📥 Download: Grab KeyRemapper.exe from the
latest release — a single file, no
Python needed. Windows will show a SmartScreen warning the first time.
Runs as a normal user. Administrator rights are only needed if you want it to affect windows that themselves run elevated (some games, Task Manager, etc.).
Created out of frustration at being unable to disable or remap keys within a particular game.
- Numpad stays a numpad while Shift is held — with NumLock on, Windows turns Shift+Numpad into arrow keys and briefly releases Shift, which breaks numpad bindings and drops a held sprint or crouch. A new Settings → Gaming option stops both. Off by default. See Numpad + Shift in games
- Start works for every kind of setup — the remapper used to refuse to start unless at least one mapping or block existed, which locked out Copilot-key-only setups; it now starts whenever there is anything for it to do
- Nothing replaces your setup without a backup — Reset and Load now save a timestamped
copy of your current setup first (the last 10 are kept in
%APPDATA%\KeyRemapper\backups) - Save Config makes a real copy — it suggests your Documents folder and refuses to save over the live settings file, which Reset and every change overwrite. Previously its default was that file, so a "backup" made with the defaults could be wiped by the next Reset
- Load Config sticks — a loaded setup now becomes the live one and is still there after a restart, and the Settings tab updates to match (before, the next Apply could quietly put the old settings back). Files that aren't a Key Remapper setup are refused without touching anything
- Closing the window can be cancelled — the "keep running in the tray?" prompt now has a Cancel button, and its X works; before, the X was greyed out and there was no way back
- 166 unit tests, up from 135, plus a live check against real Windows input
- A proper key reference — 📋 Show Keys now opens every key name grouped by category (letters, modifiers, navigation, punctuation, numpad, media, browser, mouse…) with a plain-English description, the alternative names each key accepts, and a search box
- ⌨ beside every key field in Add Mapping and Block Key opens the same list, and
clicking keys fills the field for you: click
ctrl, thens, and the field readsctrl+s. Remove last and Clear undo mistakes; mouse buttons are greyed out where they can't be used
- Type text that ignores your keyboard layout — a new Type text action sends
characters instead of keys, so switching between, say, English and Russian no longer
changes what a remapped key types. Map Right Ctrl to
.and Shift+Right Ctrl to,and you have a dedicated period/comma key in every layout. See Type text - Basic text expansion for free — the same action types whole strings: an email address, a signature, a snippet
- A switch to pause it all — Settings → Typing text turns every text rule off and on again at once; the rules are kept and show as (off) while paused
- Clearer buttons — whichever of Start/Stop is inactive keeps readable text on a darker fill, and gray buttons now light up blue on hover instead of a barely different gray
- 127 unit tests, up from 104
- A key can now launch an app — set a mapping's action to Launch a program or
app and pick Calculator, File Explorer, Terminal and friends from a list, browse
for any
.exe, or paste ashell:AppsFolder\…link for a Store app. Open a website does the same for URLs. See Launch an app from a key - A picker for volume, media and function keys — Mute, Volume Up/Down, Play/Pause, F1–F24, Copy/Paste and the browser keys are two clicks away instead of a name you had to know
- Keys with no name are mappable — 🎯 Detect writes
vk0x5Dfor anything exotic your keyboard sends instead of giving up. This is what makes most Fn combinations usable, since Fn itself is invisible — see The Fn key - Detect shows the raw hardware code (
vk 0x7B · scan 0x58), which is the only way to tell two keys that share a virtual key code apart - Only one copy runs at a time — launching the app while it sits in the tray reopens that window instead of installing a second keyboard hook
- It says when it hides — minimising to the tray shows a notification once per run, so a hidden app never looks like it crashed
- 104 unit tests, up from 58
- Scrollbars only appear when there is something to scroll — every panel hides its scrollbar while the content fits
- Reset everything to defaults — one button in Settings clears all rules, the Copilot action and every setting, and removes the logon entry
- Nothing is blocked out of the box. A stale development config meant
/could arrive pre-blocked; a fresh install now starts completely empty - Rewritten Help/About — leads with what the app does, with the project link and a ☕ Donate button at the end
- Give the Copilot key back its old job: one click turns it into Right Alt, Windows, Menu ▤ or Right Ctrl — whichever key your laptop sacrificed for it
- Per-app profiles: scope any mapping or block to a single executable, so
F1can mean one thing in your game and nothing anywhere else - Tap vs hold (dual-role keys): CapsLock can send Escape when tapped and act as Ctrl when held
- Pause hotkey: suspend every mapping without stopping the remapper, from a hotkey or the tray
- Mouse side buttons (
mouse3/mouse4/mouse5) usable as sources - Run at logon and start hidden in the tray, with a new Settings tab
- Edit mappings in place (double-click a row) with conflict warnings before you overwrite
- 🎯 Detect now uses the low-level hook, so Win, F13-F24 and Copilot combinations are detectable instead of "type it manually"
- 58 unit tests covering the rule engine, including the Copilot chord and the mouse hook
- Copilot Key tab: detect what your laptop's Copilot key actually sends, then disable it, send different keys, or launch any program, file or website — see Copilot Key
- Modifier combinations now work:
ctrl+/shift+/alt+/win+combos are matched by modifier family, so the left/right key the hardware reports no longer matters. (Previously any combination involving a modifier silently never fired.) - Config and log moved to
%APPDATA%\KeyRemapper\so settings survive updates and work from a one-file.exe. An existingkey_remap_config.jsonnext to the app is migrated once. - Hook runs on its own thread: a busy or blocked UI can no longer stall your keyboard, and the text-mode menu works properly.
- Media & browser keys available as remap targets (
playpause,mute,calculator, …). - Real logging again — every action goes to
%APPDATA%\KeyRemapper\key_remapper.log.
- Extended Function Keys (F13-F24): Full support for extended function keys including F13-F24
- Interactive Key Detection: 🎯 Detect buttons to capture key presses in real-time
- Auto-Save: All changes are automatically saved - no need to manually save config
- Improved Key Capture: Better handling of modifier keys and combinations
- Modern GUI: Clean, dark-themed interface built with customtkinter
- Gaming Compatible: Uses low-level Windows hooks (
SetWindowsHookEx) that work with most games and applications - Key Combinations: Remap single keys to key combinations (e.g.,
F1→Ctrl+S,F2→Ctrl+Shift+S) - Launch Apps and Websites: Point a key at Calculator, any
.exe, a Store app or a URL - Layout-Independent Text: Type characters or whole strings that come out the same in every keyboard layout
- Multimedia Keys: Mute, volume, play/pause, track skip and the browser keys, from a picker
- Key Blocking: Completely disable specific keys to prevent accidental presses during gaming (e.g., block
/key) - Copilot Key Control: Detect and repurpose the dedicated Copilot key found on 2024+ laptops
- Per-App Profiles: Limit any rule to a single executable
- Dual-Role Keys: One key that taps one thing and holds another
- Pause Hotkey: Suspend everything without stopping the remapper
- Mouse Side Buttons:
mouse3/mouse4/mouse5as remap sources - Single Instance: a second launch reopens the existing window instead of double-hooking
- Interactive Key Detection: Click 🎯 Detect buttons to capture key presses automatically
- System Tray: Minimize to system tray while remapper runs in the background
- Standalone Executable: Build a single
.exefile - no Python installation required - Auto-Save Configuration: Changes are saved automatically to JSON file
- Toggle Mappings: Enable/disable individual mappings or blocked keys without removing them
- Logging: All actions logged to
%APPDATA%\KeyRemapper\key_remapper.logfor troubleshooting
- Windows 10 or Windows 11
- Python 3.8 or higher
- Windows 10 or Windows 11
Administrator privileges are optional. Elevate only if you need the remapper to reach windows that run elevated themselves.
- Download
KeyRemapper.exefrom the latest release - Double-click it. See the SmartScreen note below for the first-run warning.
- Clone or download this repository
- Install dependencies:
pip install -r requirements.txt - Run the GUI:
python key_remapper_gui.py
- Install dependencies:
pip install -r requirements.txt - Run the build script:
python build.py
- Find the executable at
dist/KeyRemapper.exe - Double-click to run
The first time you run the downloaded .exe, Windows shows a blue box:
Windows protected your PC Microsoft Defender SmartScreen prevented an unrecognised app from starting.
To run it anyway: click "More info", then "Run anyway".
The executable is not code-signed. A signing certificate costs money per year, and this is a free hobby project. SmartScreen flags every unsigned executable that it hasn't seen downloaded many times before — it is a statement about the certificate and download count, not about whether anything is wrong with the file. The warning fades for everyone as more people download a given release.
Some browsers also block the download itself for the same reason. In Edge or Chrome, choose Keep → Keep anyway in the downloads bar.
Fair. You have three options, in order of paranoia:
-
Verify the checksum — confirm your download is byte-for-byte the file published here:
Get-FileHash .\KeyRemapper.exe -Algorithm SHA256
Release SHA-256 v2.6.0 e0daa4a3baf758e2f374a8922347d546557b2b4046cd4d0e361f9a94f5f577eav2.5.1 32f4f100586954ee5db25c2165b7d7b380eb7a9ce799d9f1f89061524287bf1ev2.5.0 e8f3a50413c93744e3cc36e0f9957dc637adb942d1a468cdd1b1044ad94b2f55v2.4.0 2cb3995c8c40374c681e4a76bd0914e9841721cf86af7ca76ddf64d450a0342bv2.3.0 883f407b5b61655076cc8e57d2bb50c1d2f74ba9e837bf16b2dfc09e34e4eff9v2.2.0 44e158dd07c9a9b9d6c1ca109fbe19b2d546778de95515fb5bf35c52805b48a0This proves the file wasn't tampered with in transit. It does not prove the code is trustworthy — for that, see below.
-
Read the source — it's all in this repository, about 2,000 lines of Python, and the
.exeis justbuild.pyrunning PyInstaller over it. -
Build it yourself — Option 3 above. Then no download, no warning, no trust required.
A key remapper is, by construction, indistinguishable from a keylogger to a scanner: it installs
a global WH_KEYBOARD_LL hook and therefore sees every keystroke you type. That is the whole
mechanism — there is no way to remap keys without it. So here is exactly what it does with them:
- Your typing is never recorded. Keystrokes are matched against your rules in memory and
then forgotten. There is no logging in the key-handling path
(
_handle_key_event) apart from an error handler. - One exception, and it's one you trigger: when you press 🎯 Detect, the key code you
deliberately capture is written to the log so the feature can be debugged — e.g.
Chord captured: ('shift', 'win') + 0x86. Nothing else you type ever reaches the log. - The log otherwise records actions only — "added mapping", "remapper started" — plus the rules you configure, which you wrote yourself.
- No network connections. No telemetry, no update check, no sockets anywhere in the source. The only outbound action is opening a URL or launching a program you assigned to the Copilot key, which hands off to your normal browser or shell.
- It writes to two places:
%APPDATA%\KeyRemapper\(config + log), and — only if you tick "Launch when I sign in" — oneKeyRemappervalue underHKCU\Software\Microsoft\Windows\CurrentVersion\Run. Unticking it removes the value.
Every one of these is checkable in key_remapper.py; grep for logger.,
winreg, and webbrowser and you'll find the lot.
python key_remapper_gui.pyIf a specific game ignores your remaps, that game is probably running elevated — start the remapper as administrator in that case.
The Copilot key on modern Windows laptops is not a new scan code. The keyboard firmware
emits a hidden chord — on virtually every OEM that chord is Left Shift + Left Win + F23.
That is why simply "blocking F23" does nothing useful, and why releasing the key can pop the
Start menu.
Open the Copilot Key tab and:
| Step | What it does |
|---|---|
| 🎯 Detect | Swallows all input until you press the Copilot key, then records the exact chord your machine sends (handles the rare win+c / bare-F23 keyboards) |
| Do nothing | Kills the key entirely, including the Start-menu side effect |
| Send other key(s) | Turn it into any key or combination — ctrl+shift+p, playpause, f13, … |
| Launch a program or file | Point it at an .exe, document, folder or shell command |
| Open a website | Any URL, opened in your default browser |
| Pass through | Leave the key alone |
Most laptops made room for the Copilot key by dropping a key you were already using. One click puts it back:
| Button | Result |
|---|---|
| Right Alt | The Copilot key behaves as ralt (AltGr on international layouts) |
| Windows | Acts as a Windows key |
| Menu ▤ | The context-menu key that most Copilot keyboards replaced |
| Right Ctrl | Acts as rctrl |
Modifier targets are held for as long as the firmware holds the chord, so Copilot+another key
works on keyboards that keep the chord down. Most send a single burst, which lands as a tap —
exactly what you want for Menu and Windows.
Other quick presets: Disable it, Screenshot (win+shift+s), Play/Pause, File Explorer.
Apply saves immediately; the remapper must be started (▶ Start) for the key to take effect.
Windows 11 24H2 can also remap this key from Settings, but only to signed, MSIX-packaged apps. This tab works with anything on your machine.
Under the hood, when the chord fires the remapper injects an unassigned virtual key so that
releasing the still-held Windows key does not open the Start menu, virtually releases the
held modifiers, and only then performs your action — so Shift/Win never leak into the
keys it sends.
A mapping does not have to send keys. In Add Mapping, What should it do? offers:
| Action | What you fill in |
|---|---|
| Send other key(s) | A key or combination — with a picker for volume, media, function and browser keys |
| Type text | Characters to type, whatever the keyboard layout — see Type text |
| Launch a program or app | Pick from the common apps list, 📂 Browse for an .exe, or type anything the shell can open |
| Open a website | Any URL — it opens in your default browser |
▶ Test runs the action once without pressing the key, so you can check a path before committing to it.
Anything these accept:
| You type | What happens |
|---|---|
calc.exe |
An executable on PATH — this one opens the Windows Calculator |
C:\Tools\thing.exe --flag |
A full path, arguments included |
D:\notes\todo.md |
Any document or folder, opened with its default program |
ms-settings: |
A Windows Settings page (ms-settings:bluetooth, …) |
shell:AppsFolder\<app-id> |
A Microsoft Store / packaged app |
To find a Store app's id: run
explorer shell:AppsFolder, right-click the app → Create shortcut, then read the target off the shortcut on your desktop.
So the classic setup — Fn+F12 opens the calculator — is: Add Mapping → 🎯 Detect → press Fn+F12 → Launch a program or app → Calculator → Add.
Launching happens on a worker thread, never inside the keyboard hook: a low-level hook
that takes longer than LowLevelHooksTimeout is silently removed by Windows.
Why it exists. Send other key(s) sends a virtual key — a position on the keyboard.
The app receiving it turns that into a character using whatever layout is active. So a
rule sending period types . in English but ю in Russian: the remap follows the layout.
That is how every virtual-key remapper behaves, PowerToys included.
Type text sends the characters themselves (SendInput with KEYEVENTF_UNICODE),
which no layout can reinterpret.
| Source | Type text | Result |
|---|---|---|
rctrl |
. |
Right Ctrl is a period key in every layout |
shift+rctrl |
, |
…and Shift+Right Ctrl a comma |
ctrl+alt+m |
me@example.com |
Text expansion |
f13 |
— |
A character your layout has no key for |
▶ Test in the dialog types the text into a box right there, so you can see exactly
what comes out. Whitespace is kept — , (comma space) and a lone space are valid.
Things to know:
- Shift does not change typed text — it is a literal character, not a key. Give the
shifted character its own rule, as with
shift+rctrlabove. - Holding the key repeats the text, the same as holding a normal key.
- Games that read raw keyboard input won't see it. Typed characters arrive as text
(
WM_CHAR), not as key presses. This is a typing feature, not a gaming one — use Send other key(s) for games. - Settings → Typing text pauses every text rule at once. The keys go back to normal, the rules are kept, and the list marks them (off) until you switch it back on.
Fn is not supported as a modifier, and it is worth explaining why.
On the overwhelming majority of keyboards, the Fn key never reaches Windows at all. It is
handled inside the keyboard's own controller, which simply emits a different key for the
combination. Pressing Fn+F12 does not produce "Fn plus F12" — it produces volumeup, or
plain f12, or a code with no name, depending on the hardware. No application can observe
a key the hardware never sends, and a low-level hook is no exception.
So there is no fn you can type in a rule, and 🎯 Detect cannot record Fn on its own.
Fn key mapping is limited to what follows.
What does work — map what the combination actually sends:
- Add Mapping → 🎯 Detect on the source
- Hold Fn and tap F12 — press the whole combination
- The dialog records exactly what arrived —
VOLUMEUP,F12,vk0x97, … — and shows the raw code underneath (vk 0x7B · scan 0x58) - Give it a target or an app, and click Add
That covers the common case completely: if Fn+F12 sends volumeup, then mapping volumeup
to the Calculator gives you exactly "Fn+F12 opens the Calculator".
The one case it cannot cover: if Fn+F12 and a plain F12 arrive as byte-for-byte the same event, nothing can distinguish them — not this app, not any other. The Detect dialog shows the raw code precisely so you can check: press each one and compare. Different codes mean you are fine.
Keyboards send codes this app has no friendly name for, especially under Fn. 🎯 Detect
writes those as vk0x5D (or vk93 — decimal works too) and they can be used anywhere a
key name can. Nothing your keyboard sends is off-limits.
The problem. With NumLock on, Windows turns Shift+Numpad into navigation keys — Numpad 8 becomes Up, Numpad 7 becomes Home, and so on. To do it, Windows fakes a Shift release, sends the arrow key, then fakes the Shift press again. Recorded from a live hook:
down LSHIFT scan 0x02A you press Shift
up LSHIFT scan 0x22A <- Windows fakes a release
down UP scan 0x048 <- Numpad 8 arrives as the Up arrow
up UP scan 0x048
down LSHIFT scan 0x02A <- Windows presses Shift again
In a game, the numpad binding never fires, and anything bound to holding Shift (sprint, crouch, walk) drops for an instant on every numpad press.
The fix. Settings → Gaming → Keep numpad keys as numbers while Shift is held.
The fake Shift events carry scan code 0x22A (left) or 0x236 (right), which a real
Shift key never sends, so they are swallowed; the arrow key that follows is replaced by
the numpad digit it came from. The game receives:
down LSHIFT down NUMPAD8 up NUMPAD8 up LSHIFT
It is exact rather than a guess:
- Real arrow keys are never touched — the arrow cluster sends the extended flag and the numpad never does, and Windows fakes nothing for real arrow keys anyway.
- NumLock off is left alone — Windows only fakes the Shift release with NumLock on, so Shift+numpad arrows still select text when you want navigation.
- Your rules see the real digit: a rule on
shift+num8fires as you would expect. - Off by default, because outside games Windows' behaviour is what people expect.
⚠️ Admin rights and anti-cheat. Most games run as administrator, and Windows only lets a program change a game's keyboard input when it runs with at least the same rights — so for most games, run Key Remapper as administrator (right-click → Run as administrator). The Settings tab shows whether it currently is. Some games and anti-cheat systems block keyboard hooks altogether; there, this option cannot work.
Leave Only in this app empty and a rule applies everywhere. Fill in an executable name
(game.exe — a full path is fine, it gets reduced to the file name) and the rule only fires
while that window has focus. An app-specific rule beats a global one for the same key, so you
can have a global default and a per-game override.
The foreground executable is only looked up when at least one app-scoped rule exists, and the answer is cached briefly — the hook stays fast.
Fill in When held instead and a key gets two jobs:
| Source | Target | When held | Result |
|---|---|---|---|
capslock |
escape |
ctrl |
Tap for Escape, hold for Ctrl — the classic Vim setup |
space |
space |
shift |
Space bar doubles as Shift |
The hold role activates as soon as you press another key while holding it, or after the tap vs hold threshold (Settings tab, 250 ms by default). Hold roles need a single source key, not a combination.
Set one in the Settings tab (e.g. ctrl+alt+f12) to suspend every mapping without
releasing the hook — useful when a remap is fighting with an app. The status turns amber, the
tray icon turns orange, and anything currently held down is released rather than left stuck.
The tray menu has Pause / Resume too.
mouse3 (middle), mouse4 and mouse5 (the side buttons) can be used as sources for
mappings and blocks — e.g. mouse4 → ctrl+c. Left and right click are deliberately not
remappable, and mouse buttons cannot be a target. The mouse hook is only installed when a
rule actually needs it.
Key Mappings:
- Add mapping - Create a new key remap
- Remove mapping - Delete an existing remap
- List mappings - View all configured remaps
- Toggle mapping - Enable/disable a mapping
Block Keys (Gaming): 5. Block a key - Completely disable a key (useful for gaming) 6. Unblock a key - Re-enable a blocked key 7. List blocked keys - View all blocked keys 8. Toggle blocked key - Enable/disable a key block
Copilot Key: 9. Configure the Copilot key - Detect it and choose what it should do
Control:
- S - Start remapper (activate all mappings and blocks)
- X - Stop remapper (deactivate all)
- P - Pause/resume without releasing the hook
- W - Save configuration to
key_remap_config.json - L - Load configuration from config file
- K - Show available keys
- 0 - Exit
Keys can be specified as:
- Single keys:
a,f1,escape,space - Combinations:
ctrl+a,shift+f1,ctrl+shift+escape,win+shift+f23
💡 Tip: Use the 🎯 Detect buttons in the GUI to automatically capture key presses, or click ⌨ beside any key field to pick names from a searchable list.
| Category | Keys |
|---|---|
| Letters | a - z |
| Numbers | 0 - 9 |
| Function | f1 - f12 |
| Extended Function | f13 - f24 (includes Copilot key: win+shift+f23) |
| Modifiers | ctrl, lctrl, rctrl, shift, lshift, rshift, alt, lalt, ralt, win, lwin, rwin |
| Navigation | up, down, left, right, home, end, pageup, pagedown |
| Special | escape, tab, capslock, space, enter, backspace, delete, insert, apps |
| Numpad | num0 - num9, numplus, numminus, nummultiply, numdivide |
| Media | playpause, nexttrack, prevtrack, mediastop, mute, volumeup, volumedown, calculator, mail, mediaselect, launchapp1, launchapp2, sleep |
| Browser | browserback, browserforward, browserrefresh, browserhome, browsersearch, browserstop, browserfavorites |
| Raw codes | vk0x5D / vk93 — any key with no friendly name |
| Mouse (source only) | mouse3 / middleclick, mouse4, mouse5 |
| Punctuation | semicolon, comma, period, slash, backslash, quote, grave, lbracket, rbracket |
Modifiers are matched by family: a mapping written as ctrl+a fires for either Ctrl key.
Left/right distinctions still work when the modifier is the key being remapped (e.g. ralt → ctrl).
| Source | Target | Description |
|---|---|---|
capslock |
escape |
Caps Lock acts as Escape (popular for Vim users) |
ctrl+j |
down |
Ctrl+J acts as Down arrow |
f1 |
ctrl+s |
F1 saves the document |
ralt |
ctrl |
Right Alt acts as Control |
f9 |
mute |
F9 mutes the system volume |
f10 / f11 |
volumedown / volumeup |
Media keys on a keyboard that lacks them |
f12 |
launch calc.exe |
F12 opens the Windows Calculator |
volumeup |
launch calc.exe |
Whatever Fn+F12 sends on your laptop, repurposed |
mouse5 |
open https://claude.ai |
Side button opens a site |
| Key | Use Case |
|---|---|
/ |
Prevent accidentally opening chat in games |
win |
Prevent Windows key from minimizing your game |
alt+tab |
Prevent accidental window switching |
escape |
Prevent accidental pause menu in some games |
win+shift+f23 |
The raw Copilot chord — prefer the Copilot Key tab, which also suppresses the Start menu |
Everything is saved to %APPDATA%\KeyRemapper\key_remap_config.json:
{
"version": 7,
"mappings": [
{
"source": "CAPSLOCK",
"target": "ESCAPE",
"action": "keys",
"value": "",
"hold": "CTRL",
"app": "",
"enabled": true,
"description": "Caps Lock to Escape"
},
{
"source": "F12",
"target": "",
"action": "launch",
"value": "calc.exe",
"hold": "",
"app": "",
"enabled": true,
"description": "Calculator"
},
{
"source": "RCTRL",
"target": "",
"action": "text",
"value": ".",
"hold": "",
"app": "",
"enabled": true,
"description": "Period in every layout"
}
],
"blocked_keys": [
{
"key": "/",
"app": "game.exe",
"enabled": true,
"description": "Block slash key during gaming"
}
],
"copilot": {
"enabled": true,
"modifiers": ["shift", "win"],
"key": "f23",
"mode": "keys",
"value": "ralt",
"description": "Copilot key"
},
"settings": {
"toggle_hotkey": "ctrl+alt+f12",
"tap_timeout_ms": 250,
"run_at_startup": false,
"start_minimized": false,
"start_on_launch": false,
"type_text_enabled": true,
"numpad_ignores_shift": false
}
}A mapping's action is keys (send target), text (type value literally), or
launch / url (open value). type_text_enabled is the Settings switch for text rules, and numpad_ignores_shift
the Gaming option for Shift+Numpad.
Copilot mode is one of disable, keys, launch, url or passthrough.
Older config files load unchanged — missing fields and sections fall back to defaults.
python -m unittest discover -s tests166 tests drive the rule engine directly (no real hooks, no keyboard input needed), covering
remaps, blocks, per-app scoping, dual-role keys, the pause hotkey, the Copilot chord, the mouse
hook, app-launching mappings, layout-independent text (including the exact SendInput
events it produces), raw key codes, the key reference, Shift+Numpad correction (replaying event sequences
recorded from Windows), the single-instance guard and config
round-tripping — including that configs written by earlier versions still load.
Click More info → Run anyway. The executable is not code-signed, so SmartScreen flags it — see Windows SmartScreen warning for why, how to verify the download's checksum, and how to build it yourself instead.
Expect the occasional false positive: the app installs a global keyboard hook, which is the same API a keylogger uses, and PyInstaller one-file executables are themselves a common heuristic trigger. The SmartScreen section documents exactly what the app does with your keystrokes and where it writes. Building from source avoids the packed-executable heuristic entirely.
- Check Settings → Gaming is ticked, you clicked ✔ Apply, and the remapper is started (▶ Start)
- Run Key Remapper as administrator — the Settings tab says whether it is
- NumLock must be on; with NumLock off the numpad is the arrow keys, by design
- If it still fails, the game's anti-cheat is probably blocking keyboard hooks
- If the game runs elevated, run the remapper as administrator too
- Some anti-cheat systems block keyboard hooks - this is by design for security
Fn is not a modifier this app can see — your keyboard handles it internally and never tells Windows. That is normal and it is the majority case. Detect the combination rather than the Fn key: 🎯 Detect, then hold Fn and tap F12, and whatever your keyboard actually sends is recorded and mappable. Full explanation.
Before v2.6, 💾 Save Config suggested the very file Key Remapper saves to automatically. Saving
there and then using Reset everything to defaults wiped the "backup" along with everything else.
From v2.6, Reset and Load save a backup first — look in %APPDATA%\KeyRemapper\backups and load the
newest one from before your reset. If you have no backup, the log (key_remapper.log in the same
folder) lists every rule each time the app loads, so a setup can be rebuilt from it by hand.
It did not close — it minimised to the system tray, because Settings → "Start hidden in
the system tray" is ticked. Windows 11 hides new tray icons behind the ^ arrow on the
taskbar; click it, then drag the K icon onto the taskbar to keep it visible. Untick that
setting if you would rather see the window on every launch. Launching the app again while
it is hidden reopens the window rather than starting a second copy.
- Click ▶ Test in the mapping dialog — it runs the same code path and fails the same way
- A Store app usually needs
shell:AppsFolder\<app-id>rather than an.exepath - Check
%APPDATA%\KeyRemapper\key_remapper.log— every launch and every failure is logged
- Check that the remapper status shows "ACTIVE"
- Verify your mapping is enabled (not disabled)
- Check
%APPDATA%\KeyRemapper\key_remapper.logfor error messages
- Use 🎯 Detect on the Copilot Key tab — your keyboard may send a different chord
- Make sure the remapper is started, and that the tab does not say "pass through"
- Check
%APPDATA%\KeyRemapper\key_remapper.logfor error details - Ensure you're using Python 3.8 or higher
- Make sure you're on Windows (not Linux/Mac)
- Uses
SetWindowsHookExwithWH_KEYBOARD_LLfor low-level keyboard interception - The hook is installed and pumped on a dedicated thread, so UI work can never stall input
- Injects replacement keys using
SendInputAPI, as virtual keys — so the active layout decides the character, exactly as for a physical key - The Gaming numpad option swallows Windows' synthetic Shift events (scan codes
0x22A/0x236) and re-sends non-extended navigation keys as the numpad digits they came from - Type text rules instead send
KEYEVENTF_UNICODEpackets (wVk = 0, the character inwScan), which bypass the layout entirely; the whole string goes in oneSendInputcall - Marks injected events (
dwExtraInfo) to prevent infinite loops - Combinations are matched as (modifier families, main key) signatures
- Slow actions (launching apps, opening URLs) run on a worker thread — a low-level hook that
takes longer than
LowLevelHooksTimeoutis silently removed by Windows - Thread-safe design with proper locking
- Windows only (uses Windows-specific APIs)
- Some games with kernel-level anti-cheat may not work
- Left and right mouse buttons are deliberately not remappable, and mouse buttons cannot be a target
- Cannot remap keys used by Windows itself (e.g., Ctrl+Alt+Del)
- The Fn key cannot be used as a modifier. Virtually no keyboard reports it to Windows; map what the combination actually sends instead (why)
- Two keys that send an identical virtual key code and scan code cannot be told apart
Built by Li Fan, 2026. If Key Remapper saved you some frustration, you're very welcome to buy me a coffee ☕ — there's also a Donate button in the app's ℹ️ About dialog.
Bug reports and feature requests are welcome on the issue tracker.
MIT License - Feel free to use and modify as needed.