π°π· νκ΅μ΄ μ¬μ©μμ΄μ κ°μ? β νκ΅μ΄ README 보기
English | νκ΅μ΄
π A menu bar app for Mac users β when you use a Windows remote desktop or a virtual machine on your Mac, your keyboard layout switches automatically the moment you click the window.
Traditional remapping tools make you pick a profile by hand every time you move between your Mac and a remote session. KeySwitcher takes that chore away: it detects the app you're working in β remote desktop or VM β and applies the keyboard layout you want, automatically.
Click into a Windows remote/VM app (Windows App, VMware Fusion, Parallels Desktop) and command β option are swapped automatically; click back into a Mac app and your original Mac layout is restored. No more fiddling with settings every time you enter a remote session.
- 100% native: pure Swift + built-in macOS APIs only
- No drivers: no kernel extensions, no virtual keyboard drivers
- No permissions: does not ask for Accessibility or Input Monitoring
- Built-in language profiles: Korean (ν/μ key), Japanese (θ±ζ°/γγͺ), and US layouts, switchable in one click
- Multilingual UI: Korean, Japanese, and English β follows your system language (changeable in Settings)
- Mac users working over remote desktop / VDI β connecting to a corporate Windows box via Windows App (RDP), Citrix, or other remote tools. Especially solves the IME toggle-key problem on Korean/Japanese Windows
- Developers running VMs in Parallels Β· VMware Β· UTM β Windows/Linux shortcuts inside the VM window, Mac shortcuts outside, switched just by clicking
- CrossOver/Wine users β add the app's bundle ID and the same swap applies
- Game streaming (Moonlight, Steam Link, β¦) β keep the remote gaming PC's Alt/Ctrl positions under your fingers
- Mac users with Windows-layout mechanical keyboards β independent of remoting, a per-device rule can keep "always swap βββ₯ on this keyboard only"
Switch in one click from the menu bar β "Windows Profile" (also available in Settings β "Key Mappings" tab β "Load Language Preset"):
| Profile | Mappings | Notes |
|---|---|---|
| Korean Windows | swap βββ₯, right β β right β₯ |
On Korean Windows, right Alt = Hangul/English, right Ctrl = Hanja |
| Japanese Windows (JIS) | swap βββ₯, θ±ζ°βη‘ε€ζ, γγͺβε€ζ |
Use the θ±ζ°/γγͺ keys of a Mac JIS keyboard to drive Windows MS-IME. Assign IME off/on to η‘ε€ζ/ε€ζ in Windows 11 IME settings for a Mac-like feel |
| Standard (US/Global) | swap βββ₯ only |
For layouts that need no IME keys |
Feel free to edit individual mappings after loading a preset β presets are just starting points.
- Detects the frontmost app changing (= your click) via
NSWorkspace.didActivateApplicationNotification. No special permissions needed. - Remapping is applied at the system level with macOS's built-in
hidutil(IOHIDFamilyUserKeyMapping), so it takes effect instantly for every app and every input. - Global mappings are applied first, then per-device (VendorID/ProductID) mappings override them.
./build.sh
open build/KeySwitcher.appA π (Mac mode) / η° (Windows mode) icon appears in the menu bar. The app is ad-hoc signed, so if Gatekeeper blocks the first launch of a copied build, right-click β Open.
System Settings β General β Login Items β add KeySwitcher.app.
Remapping tools that grab keyboard devices exclusively through a virtual driver can prevent this app's system remappings from applying, or cause them to apply twice. If you use such a tool, disable its device modification (or quit it) while using KeySwitcher.
Everything is editable in a GUI via menu bar β "Settingsβ¦" (no rebuild needed):
- Target Apps: the list of apps that trigger Windows mode. Pick from running apps, choose an app in /Applications, or type a bundle ID. Defaults: Windows App, VMware Fusion, Parallels Desktop
- Key Mappings: from β to mappings applied to all keyboards in Windows mode (keys picked from dropdowns)
- Device Rules: Mac/Windows-mode mappings for specific keyboards (VID/PID). "Add from Connected Keyboards" fills in the IDs automatically.
- General: UI language (Follow System / νκ΅μ΄ / ζ₯ζ¬θͺ / English) and menu bar icons (SF Symbol names or emoji)
Click "Save & Apply" and changes take effect immediately.
Settings are stored in ~/Library/Application Support/KeySwitcher/config.json;
you can also edit the file directly and use menu bar β "Reload Config".
| App | Bundle ID |
|---|---|
| Windows App (formerly Microsoft Remote Desktop) | com.microsoft.rdc.macos |
| VMware Fusion | com.vmware.fusion |
| Parallels Desktop | com.parallels.desktop.console |
To add another remote/VM app, pick it from running apps in the "Target Apps" tab, or find its bundle ID with:
mdls -name kMDItemCFBundleIdentifier "/Applications/AppName.app"Config file format (advanced β for editing config.json directly)
- Icons: an SF Symbol name renders in the same monochrome style as system menu bar
icons. Windows-mode candidates:
square.grid.2x2.fill(Windows-logo-like, default),pc,desktopcomputer,display,macwindow. Mac-mode candidates:applelogo, or any emoji (π, π», π₯οΈ, β¦). Browse all symbols in Apple's "SF Symbols" app. - Find an app's bundle ID:
mdls -name kMDItemCFBundleIdentifier /Applications/AppName.app - Find keyboard VendorID/ProductID:
hidutil list - Available key names:
left_command,left_option,left_control,left_shift,right_command,right_option,right_control,right_shift,caps_lock,escape,tab,grave_accent_and_tilde,insert,home,end,page_up,page_down,delete_forward,lang1(Hangul/English Β· γγͺ),lang2(θ±ζ°),international2(γ«γΏγ«γ/γ²γγγͺ),international4(ε€ζ),international5(η‘ε€ζ) β to add more, put the HID usage code into thehidUsagestable inSources/main.swift.
The defaults include only the global Windows-mode swap (LββLβ₯, RββRβ₯) and no
device rules. Add device rules in Settings if a specific keyboard needs different
mappings.
Remappings are removed automatically on normal quit (signal handlers included), but a force kill (kill -9) or crash can leave them in place. In that case:
# clear global mappings
hidutil property --set '{"UserKeyMapping":[]}'
# if you used device rules, clear those devices too (use your own VID/PID)
hidutil property --matching '{"VendorID":<VID>,"ProductID":<PID>}' --set '{"UserKeyMapping":[]}'(A reboot also clears everything.)
- It does not read your keystrokes. No event taps, no Input Monitoring API, and
no Accessibility permission. All it does is hand a key-substitution table to
macOS's built-in
hidutil; the OS performs the substitution. - No network access. Nothing is ever sent anywhere.
- No admin rights required; settings live only in
~/Library/Application Support/KeySwitcher/.

{ "language": "en", // UI language ("ko"/"ja"/"en"; omit to follow system) "macIcon": "π", // menu bar icon β SF Symbol name or emoji/text "windowsIcon": "square.grid.2x2.fill", "pausedIcon": "βΈ", "windowsApps": [ ... ], // Windows mode when one of these is frontmost "windowsGlobalMappings": [ ... ], // applied to all keyboards in Windows mode "deviceRules": [ // per-device mappings (override global) { "vendorID": 1234, "productID": 5678, "macMappings": [ ... ], // applied to this device in Mac mode "windowsMappings": [ ... ] // applied to this device in Windows mode } ] }