Automatic display brightness daemon
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-15 10:51:15 +02:00
.forgejo/workflows Add curl 2026-07-31 13:46:23 +02:00
assets Increase wiggliness 2026-08-10 20:23:01 +02:00
debian Add post-installation instructions for Debian 2026-08-14 14:15:19 +02:00
src Dump curve points and config at INFO level 2026-08-01 11:55:24 +02:00
Cargo.toml Bump version 2026-08-14 14:17:20 +02:00
config.example.toml Improve logging 2026-08-01 11:08:29 +02:00
luxd.service Use more realistic paths for the service 2026-08-01 12:21:19 +02:00
README.md Add AI notice 2026-08-15 10:51:15 +02:00

🔆 luxd

A utility that automatically adjusts monitor brightness based on ambient light sensor readings by using configurable shell commands.

How it works

Algorithm flowchart

  1. Polls a sensor value: It runs the get_command every interval_ms milliseconds and parses the standard output as a lux reading (e.g., cat /sys/bus/iio/devices/iio:device0/in_illuminance_raw).
  2. Maps lux to brightness: The lux reading is converted to a target brightness value using linear interpolation based on the configured curve reference points.
  3. Applies hysteresis: The set_command only executes if the target brightness differs from the last applied value by more than hysteresis. This prevents rapid flickering when the sensor reading fluctuates near a transition point.
  4. Rounds and sets: The brightness is rounded to the nearest multiple of round (e.g., 0.01 or 1) before the set_command is run, replacing {} with the calculated value.

Config

Copy config.example.toml to config.toml and edit it:

Field Description
get_command Command template whose stdout is parsed as lux (required).
set_command Command template; {} → brightness (required).
interval_ms Polling interval.
log_level Log verbosity: error, info, debug, or off.
hysteresis Dead band (in brightness units). 0 disables (not recommended).
round Brightness rounded to nearest multiple of this step. 0 disables.
curve [[curve]] points of luxbrightness, >= 2 required.

The config path defaults to config.toml; override with the LUXD_CONFIG environment variable.

Ambient light sensor

A cheap DIY USB sensor can be built using a microcontroller and a light sensor. See e.g. RP2040_USBHID_Ambient-Light-Sensor.

There are also many Zigbee or Bluetooth sensors out there which report illuminance (albeit not very reliably, especially battery-powered ones). Once connected to a smart home system, they can be usually accessed via its API. Example command for Home Assistant can be found in example config.

kscreen-doctor

To use with KDE's kscreen-doctor, use this command to find out your monitor ID:

kscreen-doctor --outputs

Then use the ID (e.g. 1 or DP-3) in the set_command template:

set_command = "kscreen-doctor output.DP-3.brightness.{}"

kscreen-doctor expects brightness values in the range 0-100.

Packages

Arch Linux users can install from the AUR:

paru -S luxd

Debian/Ubuntu packages and binaries can be downloaded from the release page.

Build & run

cargo build --release
cp config.example.toml config.toml   # then edit it
./target/release/luxd

Log levels

log_level = "info"   # in config.toml
  • error — only failures (sensor reads, set commands)
  • info — also logs each brightness change, with the lux reading on the same line
  • debug — also logs every lux read, computed target, and hysteresis decision

The RUST_LOG environment variable overrides log_level if set, e.g.:

RUST_LOG=debug ./target/release/luxd

Systemd service

To run as a userspace systemd service, copy the service file and adjust it:

cp luxd.service ~/.config/systemd/user/luxd.service
ExecStart=/path/to/luxd/luxd
WorkingDirectory=/path/to/luxd

Then enable and start the service:

systemctl --user enable --now luxd.service

To monitor the service logs:

journalctl --user -f -u luxd.service

AI

This project was developed with LLM assistance.

License

Licensed under GPL-3.0 or later.