[drop_cap]L[/drop_cap]ast year I bought an ASUS Zenbook 14 OLED (UM3406HA) with the sole purpose of running Linux on it. Everything just worked out of the box, except for one minor annoyance: the keyboard backlight. You can turn it on and off just fine. But if you want it to automatically dim after some idle time, like other laptops do out of the box, you’re in tough luck. There’s simply no such setting, so the glow stays on forever unless you remember to turn it off yourself.
And this isn’t even a Linux issue per se. This model, like many others, simply doesn’t have auto-backlight-dimming integrated into its firmware. It’s purely software controlled. On Windows that’s why you need MyASUS bloatware.
On Linux you can just access the brightness controls directly via:
#turning it on (brightness level):
brightnessctl -d 'asus::kbd_backlight' set 1
#turning it off:
brightnessctl -d 'asus::kbd_backlight' set 0
So far so good. Now all you need is some basic timer to turn that on and off, right? Well, yes and no. Because to replicate hardware-controlled auto-dimming, it’s not just about the lights. You also need to detect when the user is active (typing or trackpad) and then dynamically flip the brightness off and on again.
My first attempt at that last year was some unholy Python/bash monstrosity (I’ve mercifully blocked out the details) that hooked straight into raw user input. It technically worked, but I hated it: reading every keystroke off /dev/input just to decide whether to dim a light made me feel like I was keylogging myself. So I retreated to hypridle with a simple config:
listener {
timeout = 15
on-timeout = brightnessctl -d 'asus::kbd_backlight' set 0
on-resume = brightnessctl -d 'asus::kbd_backlight' set 1
}
That worked better than my homemade contraption ever did, but it also has the annoying side-effect that your keyboard backlight is now tied to a global “idle” state as defined by hypridle.
For example, when you watch a movie, hypridle accurately doesn’t track this as “idle”, because you want your screen to stay on, don’t show screensaver etc. And that means your keyboard backlight will just constantly stay on, unless you write specific exceptions, but it gets messy fast.
This week I’d finally had enough. I chucked hypridle and built my own minimalist daemon in Rust: asus-backlight-idle. It literally has one job: dim the keyboard.
It doesn’t care about systemd inhibit or any other global idle states. After a set amount of seconds it turns the backlight off. On interaction with trackpad/keyboard it brings it back.
And here’s the twist: watching input directly turned out to be the simple part. My first attempt had just been doing it badly. The new daemon blocks in a single poll(2) on the evdev device nodes, and the kernel only wakes it when something actually happens. No polling loop, no timers. Zero CPU while you’re idle. And unlike that first monster, it doesn’t just read all input. Instead each event is asked exactly one question: “Did activity just happen?”, and the payload (which keys, which motion) is discarded immediately. Nothing is read, stored, or logged.
It also fixes another wart of my hypridle config above, which blindly reset the backlight to level 1 every time: instead, it restores whatever brightness level you last chose, and if you change it manually mid-session (Fn+F7 or brightnessctl), it quietly adopts your new preference.
It turned out pretty well. Minimal and effective. One ./install.sh sets it up as a per-user systemd service, no root daemon required. And yes, sure, this could be a Python script too, but a small Rust binary just made it tidier: one stripped static file, no runtime deps.
Note: in its current state the tool will only work with ASUS laptops that expose asus::kbd_backlight under /sys/class/leds/ (check with ls /sys/class/leds | grep kbd_backlight), but it should be easy to extend to other software-only backlights by different vendors. PRs welcome.
Want to try it on your machine?
git clone https://github.com/burninc0de/asusbacklight
cd asusbacklight && ./install.sh
github.com/burninc0de/asusbacklight