Introduction

If you spend late nights at the terminal (and let's be honest, who on this blog doesn't), you've probably leaned on KDE Plasma's Night Light feature to keep the blue light from frying your eyes at 2 AM. The GUI slider works fine — but what if you want to script your color temperature, tie it to a cron job, or just toggle it faster than clicking through System Settings? Turns out KDE doesn't give you an official CLI for that. So I built one.

This is a smaller, more focused project than some of the infrastructure builds I've covered here, but it scratches the same itch: understanding what's actually happening under the hood instead of settling for "it just works." Here's how you can build your own settemp utility in about ten minutes.


Core Concept

The obvious approach doesn't work

Your first instinct is probably to write directly to the config file with kwriteconfig6:

kwriteconfig6 --file kwinrc --group NightColor --key NightTemperature 3000

This looks like it should work, but it doesn't do anything visible. The value gets written to ~/.config/kwinrc, but KWin's Night Light manager never notices. That's because KWin caches its config at startup and only re-reads it when it receives a KConfigBase::Notify D-Bus signal. kwriteconfig6 writes the file but skips sending that signal, so your change just sits there ignored until the next login.

The actual fix: talk to KConfig directly

The real solution is to bypass the CLI tool entirely and use KDE's KConfig API with the Notify flag baked in. That flag is what triggers the D-Bus signal KWin is listening for, so the temperature change applies instantly — no restart, no relogin.

Building the utility

You need two files: a CMakeLists.txt and a small C++ source file.

Install dependencies first.
On Debian/Ubuntu:

sudo apt install cmake g++ extra-cmake-modules \
    libkf6config-dev qt6-base-dev


Arch users:

sudo pacman -S cmake gcc extra-cmake-modules \
    kconfig qt6-base


Fedora users:

sudo dnf install cmake gcc-c++ extra-cmake-modules \
    kf6-kconfig-devel qt6-base-devel

CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
project(settemp)

find_package(Qt6 REQUIRED COMPONENTS Core)
find_package(KF6Config REQUIRED)

add_executable(settemp settemp.cpp)
target_link_libraries(settemp Qt6::Core KF6::ConfigCore)

settemp.cpp:

#include <KConfig>
#include <KConfigGroup>
#include <QCoreApplication>
#include <cstdio>
#include <cstdlib>

int main(int argc, char* argv[]) {
    QCoreApplication app(argc, argv);
    if (argc < 2) {
        printf("Usage: settemp <temperature>\n");
        return 1;
    }
    int temp = atoi(argv[1]);
    if (temp < 1000 || temp > 6500) {
        printf("Temperature must be 1000-6500\n");
        return 1;
    }

    KConfig config("kwinrc");
    KConfigGroup group(&config, "NightColor");
    group.writeEntry("Active", true, KConfigBase::Notify);
    group.writeEntry("Mode", "Constant", KConfigBase::Notify);
    group.writeEntry("NightTemperature", temp, KConfigBase::Notify);
    config.sync();
    printf("Set to %dK\n", temp);
    return 0;
}

The key line is this one:

group.writeEntry("NightTemperature", temp, KConfigBase::Notify);

That third argument is doing all the work — it's the difference between a value that sits in a file and a value that actually changes what's on your screen.

Build and install:

mkdir build && cd build
cmake ..
make
sudo cp settemp /usr/local/bin/settemp
sudo chmod +x /usr/local/bin/settemp

Using it

settemp 3000    # Warm, anti-blue
settemp 4500    # Slightly warm
settemp 6500    # Neutral daylight

Quick reference if you're not sure where to start:

Temperature Description
6500K Neutral daylight (default)
4500K Slightly warm
4000K Warm
3500K Warm, noticeable blue light reduction
3000K Very warm (like incandescent bulb)
2700K Standard anti-blue
2300K Strong anti-blue (like candlelight)
1900K Maximum anti-blue (like firelight)

Wire it into your shell

Add a few aliases to ~/.zshrc or ~/.bashrc so you can flip modes without remembering exact Kelvin values:

# Anti-blue light modes
alias anti-blue-mild="settemp 3000"
alias anti-blue="settemp 2700"
alias anti-blue-strong="settemp 2300"
alias anti-blue-max="settemp 1900"

# Day mode (disable Night Light)
alias day-mode="kwriteconfig6 --file kwinrc --group NightColor --key Active false && qdbus6 org.kde.KWin /KWin reconfigure"

Now anti-blue-strong is one command away instead of three clicks deep in System Settings.

What's actually happening under the hood

The utility writes to ~/.config/kwinrc under the [NightColor] group:

[NightColor]
Active=true
Mode=Constant
NightTemperature=3000

KWin also exposes Night Light over D-Bus, so you can check the live temperature without opening any settings panel:

qdbus6 org.kde.KWin.NightLight /org/kde/KWin/NightLight \
    org.freedesktop.DBus.Properties.Get org.kde.KWin.NightLight currentTemperature

That's a handy one-liner to keep around if you ever want to confirm a change actually landed.


Best Practices

  • Verify Night Light is enabled first. If nothing changes after running settemp, double-check System Settings > Display > Night Light is turned on — the utility sets Active=true, but it's worth confirming on a fresh install.
  • Check compiler and library versions before building. This depends on KDE Frameworks 6 and Qt6; if cmake fails, it's almost always a missing dev package rather than a code issue.
  • Use the D-Bus query to debug, not guesswork. If a temperature change doesn't seem to apply, querying currentTemperature over D-Bus tells you definitively whether KWin picked it up.
  • Keep Mode=Constant. If Mode is left on Automatic (KDE's default sunrise/sunset schedule), your manual temperature calls will get overridden the next time the schedule ticks over.
  • Respect the 1000–6500K range. The utility enforces this, but it mirrors KWin's own accepted range — going outside it won't do anything useful even if you hack around the check.

Final Thoughts

This was a fun, self-contained little build — a good reminder that sometimes the "no CLI available" wall in a GUI-first desktop environment is really just a missing wrapper around an API that's been there the whole time. If you want to take this further, the natural next step is wrapping settemp in a systemd timer or cron job to automate warm/cool transitions on a schedule, instead of relying on aliases you have to remember to run.

Credit where it's due: this build is based on the set_KDE_nightlight_temperature utility by Will Avudim, available at codeberg.org/Will_Avudim/set_KDE_nightlight_temperature.