The Tale of Two Keyboards: Taming Per-Device Repeat Rates in Hyprland
The Tale of Two Keyboards: Taming Per-Device Repeat Rates in Hyprland
There's a quiet kind of frustration that builds when the tools meant to empower you start to rebel. Imagine this: you have your trusty mechanical keyboard, its satisfying click-clack the rhythm of your workday. Beside it, a sleek, silent laptop keyboard sits waiting for when you're on the move. In Hyprland, you've crafted a window manager that flows like water — windows tile, resize, and move with the grace of a well-rehearsed dance.
But when you switch between these two keyboards, something feels... off. On one, keys repeat at a brisk, comfortable pace that matches your typing speed. On the other, they feel sluggish — each held key takes an eternity to start repeating — or perhaps they fire too fast, turning a gentle hold into a frantic, uncontrollable burst of characters that makes you feel like you've lost control of your own fingers.
This isn't a ghost in the machine. This is the reality of using multiple keyboards with different physical and firmware behaviors under a single, system-wide setting. For weeks, this inconsistency drove me to distraction — until I learned that Hyprland allows us to speak to each device in its own language.
The Direct Answer: Configuring Key Repeat Per Device in Hyprland
The core solution lies in Hyprland's ability to apply rules to specific input devices using their identifiers. You cannot set repeat_rate and repeat_delay directly in a device rule block in the config file (this is a known limitation), but you can create a targeted workaround using exec and the hyprctl command to set per-device rates at runtime.
Step 1: Identify Your Keyboards
Discover the precise name and address of each keyboard connected to your system.
hyprctl devices
Look for the Keyboards section. Note the exact name of each keyboard — something like Corsair CORSAIR K70 RGB MK.2 Low Profile Mechanical Gaming Keyboard or AT Translated Set 2 keyboard (the built-in laptop keyboard). You'll need these names for the next step.
Pay close attention here — the name you see in hyprctl devices is your ground truth. Don't guess, don't abbreviate, don't assume. Copy it exactly. I spent an entire afternoon debugging a script only to realize I had written "Corsair" instead of "CORSAIR" — uppercase matters when you convert it for the config.
Step 2: Create a Configuration Script
Create a shell script, e.g., ~/.config/hypr/set-keyboards.sh.
#!/bin/bash
# Sleep to ensure Hyprland is fully ready before applying settings
sleep 1
# Apply fast repeat rate to the Corsair mechanical keyboard
# Device name must be lowercased and spaces replaced with hyphens
hyprctl keyword 'device:corsair-corsair-k70-rgb-mk-2:kb-repeat-rate' 40
hyprctl keyword 'device:corsair-corsair-k70-rgb-mk-2:kb-repeat-delay' 250
# Apply slower repeat rate to the built-in laptop keyboard
hyprctl keyword 'device:at-translated-set-2-keyboard:kb-repeat-rate' 30
hyprctl keyword 'device:at-translated-set-2-keyboard:kb-repeat-delay' 400
Important: The device name in the device: rule must be lowercased and have spaces replaced with hyphens (e.g., Corsair CORSAIR K70 becomes corsair-corsair-k70). Double-check by running hyprctl devices and carefully formatting the name.
Why these specific values? The mechanical keyboard with its shorter key travel and crisp tactile feedback can handle a faster repeat rate (40 chars/sec) with a shorter delay (250ms). The laptop keyboard, with its softer membrane switches and shorter total travel, benefits from a slightly slower rate (30 chars/sec) and a longer delay (400ms) to prevent accidental repeated characters. These are starting points — your ideal values depend on your specific hardware and typing style.
Step 3: Make Executable and Autostart
chmod +x ~/.config/hypr/set-keyboards.sh
In your hyprland.conf:
exec-once = ~/.config/hypr/set-keyboards.sh
This ensures the per-device settings are applied every time Hyprland starts. The sleep 1 at the beginning of the script is crucial — without it, the commands may execute before Hyprland has fully initialized its device list, causing them to silently fail.
Step 4: The Simpler, Global Fallback
If per-device configuration proves too tricky or your keyboard names change frequently, at least ensure a consistent global rate that works reasonably well for both keyboards:
input {
kb_rate = 40 # Repeat rate in characters per second
kb_delay = 250 # Delay before repeat starts, in milliseconds
}
This won't be perfect for both keyboards, but it's better than leaving one at an unusable default. Think of it as the compromise position — not ideal, but functional.
Understanding the Problem: Why Key Repeat Goes Rogue
Key repeat is managed by multiple layers working together: the physical keyboard's controller, the OS input stack, and the compositor (Hyprland). Some keyboards — especially gaming ones with their own firmware — can report themselves differently or have internal repeat rates that interfere with the compositor's settings. This can cause one keyboard to effectively ignore the compositor's settings, defaulting to its own built-in rate.
The result is a jarring experience: your muscle memory expects a certain response when you hold a key, but the keyboard delivers something completely different. This breaks your flow, slows your typing, and creates a subtle but persistent sense of disconnection from your own machine.
Here's the deeper technical picture: when you press and hold a key, the keyboard's controller sends an initial "key down" event, then after its own internal delay, starts sending repeated "key down" events at its own rate. The compositor (Hyprland) can override this by implementing its own repeat logic — it receives the first "key down" event, waits for the configured delay, then generates repeat events at the configured rate. But some keyboards — particularly those with QMK/VIA firmware or proprietary gaming software — continue sending their own repeat events alongside the compositor's generated ones. This creates a conflict that manifests as erratic, inconsistent repeat behavior.
For Pakistani developers who frequently switch between a laptop keyboard during load-shedding (when the mechanical keyboard's USB port is powering something more important) and the full desktop setup when power is stable, this inconsistency isn't just annoying — it's a genuine productivity killer. Every time you switch, you have to mentally recalibrate your typing rhythm, and that cognitive overhead adds up over a day of coding.
A Systematic Guide to Diagnosis and Solutions
Step 1: Map Your Input Landscape
Run hyprctl devices and create a mental map of your plugged-in devices. Note which keyboard is which, their exact names, and whether any have special firmware or onboard memory. If you're using a keyboard with QMK firmware, check whether it's configured to send its own repeat events — you may need to disable that in the keyboard's own configuration before Hyprland's settings will take full effect.
Step 2: Test and Refine Your Rates
Before scripting, test global settings to find your "sweet spot" values:
input {
kb_rate = 35
kb_delay = 300
}
Try different combinations. Most people find 30–50 for rate and 200–400 for delay comfortable. The rate is how many characters per second appear when you hold a key; the delay is how long (in milliseconds) you must hold before repeating starts. A good testing method: open a text editor, hold down a single key, and count how the characters appear. Adjust until it feels natural — not too sluggish, not too explosive.
For developers who spend hours navigating code with hjkl in Vim-style keybindings, the repeat rate is especially critical. Too slow and navigating to the end of a 200-line function feels like wading through mud. Too fast and you overshoot your target by ten lines. The sweet spot is where the cursor moves at the speed of your intention.
Step 3: Implement the Per-Device Script
Use the script method described above. Verify success with:
hyprctl getoption "device:your-keyboard-name:kb-repeat-rate"
If this returns the value you set, the script is working correctly. If it returns an empty value or the default, the device identifier is wrong — go back to Step 1 and double-check.
Step 4: Advanced Solution for Keyboards Without Stable IDs
If you frequently plug and unplug a USB keyboard, its ID might change between sessions. Bind a key to re-run your script manually so you can fix the settings on the fly:
bind = $mainMod SHIFT, R, exec, ~/.config/hypr/set-keyboards.sh
Now you can press Super+Shift+R to re-apply your keyboard settings whenever needed. This is especially useful if you use a USB hub that sometimes reassigns device numbers on reconnect.
Step 5: Handling Bluetooth Keyboards
Bluetooth keyboards add another layer of complexity because they connect and disconnect as they enter and exit sleep mode. Each reconnection can potentially change the device identifier or reset the repeat settings. For Bluetooth keyboards, add a udev rule or use hyprctl in a loop that periodically checks for the device and re-applies settings:
#!/bin/bash
while true; do
hyprctl keyword 'device:your-bt-keyboard:kb-repeat-rate' 35
hyprctl keyword 'device:your-bt-keyboard:kb-repeat-delay' 300
sleep 30
done
This is a brute-force approach, but it works reliably for Bluetooth devices that keep disconnecting and reconnecting throughout the day.
Troubleshooting
- Script Doesn't Run: Ensure it's executable (
chmod +x). Check for syntax errors. Check logs:journalctl --user -u hyprland -f. - Settings Have No Effect: Double-check the device identifier. Typos and case errors are the number one cause. Run
hyprctl devicesagain and compare the exact name. The conversion rule (lowercase, spaces to hyphens) must be applied precisely. - Keyboard Ignores Settings: Check if your keyboard has onboard memory (like QMK/VIA or proprietary gaming software) that overrides OS settings. You may need to configure the keyboard's own software to match. For QMK keyboards, you can set the repeat rate in the firmware itself using the
TAP_CODE_DELAYandREPEAT_DELAYconfiguration options. - Settings Reset After Suspend: This is a known issue. Add a systemd service that re-runs your keyboard script after resume from suspend. Create
~/.config/systemd/user/hyprland-keyboards.servicewith appropriateAfter=suspend.targetdirectives.
Final Reflections: Harmony Across Devices
Taming per-keyboard repeat rates in Hyprland is an exercise in mindful computing. That moment when you switch from your laptop to your mechanical keyboard and the cursor dashes across the screen with exactly the same rhythm you expect — that's not just a technical victory. It's the feeling of your tools finally understanding you, adapting to you, rather than the other way around.
Your workflow deserves that consistency. Your muscle memory deserves that respect. When your keyboard responds exactly as you expect, every single time, you stop thinking about the tool and start focusing entirely on the work. That's the promise of a well-tuned system — and in Hyprland, that promise is achievable with just a few lines of careful configuration.
The beauty of the Linux ecosystem, and Hyprland in particular, is that it gives you the building blocks to solve problems that other operating systems would simply tell you to live with. Windows doesn't offer per-device key repeat rates. macOS doesn't either. But on Linux, with a bit of scripting and the right tools, you can make your system respond to you — not the other way around.
🇵🇸 Stand With Palestine
Never let the world forget the people of Palestine. They will be free. They have the right to live peacefully on their own land — a right that no occupation, no apartheid wall, and no bombing campaign can ever erase. For decades, the fake state of Israel has displaced families, demolished homes, and murdered innocent men, women, and children with complete impunity. Their leaders have committed atrocities and war crimes that the so-called international community refuses to hold them accountable for.
Western media will never tell you the truth. They will call resistance "terrorism" and call genocide "self-defense." But independent sources from Iran, the Global South, and brave journalists on the ground continue to expose the reality: Palestine is enduring one of the most brutal occupations in modern history. The lies of Western media cannot bury the truth forever.
May Allah help them and grant them justice. May He protect every Palestinian child, heal every wounded soul, and return every stolen home. Free Palestine — from the river to the sea.
🇸🇩 A Prayer for Sudan: May Allah ease the suffering of Sudan, protect their people, and bring them peace.
Written by Huzi