Status: v1.1.0-windows.2 - Fully functional on Windows, Linux support in progress
Switch your keyboard layout automatically based on which keyboard you plug in.
You have multiple keyboards (Corne, Lily58, laptop keyboard...) and each one uses a different layout? Polykeys detects which keyboard you just connected and switches to the right layout automatically.
Current features:
- Automatic layout switching on device connection/disconnection
- Interactive device detection with
polykeys add --detect - System default fallback when no device is connected
- Real-time device monitoring
- Lua-based configuration
# Clone the repository
git clone https://github.com/0xJohnnyboy/polykeys.git
cd polykeys
# Build for your platform
make build
# Or build for all platforms
make build-all
# Install to system
make installgo install github.com/0xJohnnyboy/polykeys/cmd/polykeysd@latest
go install github.com/0xJohnnyboy/polykeys/cmd/polykeys@latestCreate a config file with device-to-layout mappings:
-- Format: { "alias", "deviceID", "layout" }
mappings = {
{ "Corne", "4653:0004", "US International" },
{ "Lily58", "1209:bb58", "US" },
{ "Logitech K380", "046d:c52b", "US" },
-- Fallback when no device matches
{ "System Default", "system_default", "French AZERTY" },
}Device ID format: VID:PID (Vendor ID:Product ID in hex, lowercase)
Tip: Use polykeys add --detect to automatically detect and add keyboards
⚠️ Important: Keyboard layouts must be installed on your system before Polykeys can switch to them. On Windows, go to Settings → Time & Language → Language & Region → Add a keyboard. On macOS, go to System Settings → Keyboard → Input Sources. On Linux, layouts are typically pre-installed.
Linux/macOS:
$XDG_CONFIG_HOME/polykeys/polykeys.lua(preferred)~/.config/polykeys/polykeys.lua$XDG_CONFIG_HOME/polykeys.lua~/polykeys/polykeys.lua~/polykeys.lua
Windows:
%APPDATA%\polykeys\polykeys.lua(preferred)%USERPROFILE%\.config\polykeys\polykeys.lua%LOCALAPPDATA%\polykeys\polykeys.lua%USERPROFILE%\polykeys\polykeys.lua%USERPROFILE%\polykeys.lua
Start the daemon:
polykeysd
# use the --debug flag for more verbose outputpolykeys-app is the recommended day-to-day launcher. It runs in your user session,
adds a notification-area/menu-bar icon, and starts the existing device monitor. Its menu
shows the state and last applied layout, reloads the Lua configuration, opens logs with the
system default application or $EDITOR, and quits cleanly.
After installing on Windows, Polykeys starts automatically. To configure a keyboard:
- Connect the keyboard.
- Open the Polykeys icon in the notification area.
- Open Devices, then choose a layout for the keyboard.
The selected mapping is saved and reloaded immediately. Selecting the checked layout removes that mapping. The System default keyboard entry controls the fallback layout used when no specific keyboard mapping applies. Devices are rescanned automatically; no manual refresh is needed.
Use Open configuration to edit polykeys.lua directly. If your Lua configuration contains
custom comments or logic, tray changes are added as commented suggestions and the editor opens for
your review instead of overwriting the file.
Enable automatic startup after sign-in:
polykeys-app --install
# or: make install-backgroundDisable it without deleting your configuration or logs:
polykeys-app --uninstall
# or: make uninstall-backgroundThis is deliberately a per-user background application, not a Windows system service or a
macOS LaunchDaemon: keyboard layout APIs and the tray/menu bar belong to the signed-in user.
On Windows it registers under the current user's startup settings; on macOS it writes a current-user
LaunchAgent.
Logs are stored under the platform user cache directory in polykeys/logs/polykeys.log.
Until the project has an Apple Developer signing identity, macOS release artifacts are unsigned and not notarized. Gatekeeper may block their first launch. Open the app explicitly from Finder (or allow it in Privacy & Security) only after verifying where the artifact came from. Do not disable Gatekeeper globally.
For Windows releases, prefer Polykeys-Setup-<version>.exe. It installs Polykeys for the current user
without administrator rights, enables automatic startup, creates a Start-menu shortcut and offers
to launch Polykeys at the end. The uninstaller keeps configuration and logs by default; it asks
before removing them.
The installer is currently unsigned. SmartScreen may warn on first launch: verify the installer source and checksum before choosing to continue. Do not install a self-signed certificate or disable SmartScreen globally.
To create a release, tag the commit first, then build the installer on Windows with Inno Setup:
git tag v1.2.0
make package-windows-installerThe installer name and embedded version come from git describe. A build made away from a tag
includes its commit suffix (and -dirty when the working tree has changes).
Add a new keyboard (interactive):
polykeys add --detect
# Then plug in your keyboardSee what's happening (useful for debugging):
polykeys logs -fList your mappings:
polykeys list- ✅ Windows
- ✅ macOS
- 🚧 Linux - requires further testing
Windows:
- Device detection via WMI queries
- Layout switching using Windows Keyboard Layout API, preserving language
- Polling-based detection (every 2 seconds)
- Automatic switch to default layout on device disconnection
macOS:
- Device detection via
system_profilerUSB enumeration - Layout switching using Carbon Text Input Sources API (CGO)
- Polling-based detection (every 2 seconds)
- Requires native compilation on macOS with CGO enabled
- Supports standard macOS keyboard layouts and input methods
Polykeys does not work on WSL due to limitations in device access:
- WSL does not expose
/dev/inputfor USB device monitoring - USB events are not propagated to the WSL environment
- Layout switching commands may not affect the Windows host
Workarounds:
- Run polykeys natively on Windows (use the Windows build)
- Use a native Linux installation (dual boot or VM)
- Use WSL2 with usbipd (complex setup, not recommended)
On Linux, you may need appropriate permissions to access /dev/input. If the daemon fails to start, try:
- Adding your user to the
inputgroup:sudo usermod -a -G input $USER - Running the daemon with
sudo(not recommended for production)
# Build for current platform
make build
# Build for all platforms
make build-all
# Build for specific platform
make build-linux
make build-windows
make package-windows-installer # Requires Inno Setup on Windows
make build-darwin
# Run tests
make test
# Show all available targets
make helpHaving issues? Check the troubleshooting guide for common error codes and solutions.
All errors include a code (e.g., PK_100) to help identify and resolve issues quickly.
AGPL-3.0
