Easy GNOME display eye comfort daemon
  • Python 49.8%
  • JavaScript 46.2%
  • Shell 4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Egor Gorbunov 0a69c1520a Declare GNOME Shell 51 support
The extension's APIs (QuickMenuToggle, SystemIndicator, panel
addExternalIndicator, quickSettings._nightLight, Adw prefs widgets)
are unchanged in gnome-shell 51.1, so list "51" in shell-version
and say 50 or 51 in the README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 01:21:58 +03:00
assets Add logo, MIT license and full README 2026-10-29 19:39:26 +03:00
daemon Add Pause: stop measuring but keep the current look 2026-10-29 23:29:27 +03:00
dbus Vassago: webcam-driven eye comfort for GNOME 2026-10-29 19:32:44 +03:00
extension Declare GNOME Shell 51 support 2026-11-07 01:21:58 +03:00
systemd Vassago: webcam-driven eye comfort for GNOME 2026-10-29 19:32:44 +03:00
.gitignore Vassago: webcam-driven eye comfort for GNOME 2026-10-29 19:32:44 +03:00
install.sh install.sh: enable the extension even when the shell can't see it yet 2026-10-29 21:00:39 +03:00
LICENSE Add logo, MIT license and full README 2026-10-29 19:39:26 +03:00
README.md Declare GNOME Shell 51 support 2026-11-07 01:21:58 +03:00

Vassago

Vassago

Eye comfort for GNOME that actually looks at the room.

Your webcam becomes a light sensor; your screen follows the light.
Blackout curtains at noon? Vassago sees it, and warms and dims the screen.

GNOME 50 | 51 Wayland Python License: MIT


Vassago, third spirit of the Goetia, is said to see what is hidden and what is yet to come. This one only sees how bright your room is, but it is very good at it.

✨ What it does

  • 🌡️ Colour temperature that follows the room. Neutral 6500 K in daylight, warm in a dark room. Applied through GNOME Night Light as a hardware gamma ramp: no compositor effects and no frame cost.
  • 🔆 Real monitor brightness over DDC/CI. Each monitor gets its own range, learned from the brightness you had when you first ran it.
  • 👁️ Webcam as an ambient light sensor. A short burst of tiny frames every couple of minutes at a fixed, auto-ranged exposure. Nothing is stored or sent anywhere.
  • 🎛️ Native Quick Settings tile. The Vassago tile takes the Night Light slot, with warmth and brightness sliders, a per-monitor readout, Pause and Measure now.
  • ⚙️ libadwaita preferences with one-tap calibration for your own room.
  • 🤝 Plays nice. If a video call is using the camera, the measurement is skipped and the call is never touched.
  • ⏸️ Pause vs. off. Pause stops measuring but keeps the current colour and brightness, which is handy for a call or a film. It clears itself at the next login. Turning the tile off restores your own Night Light settings and monitor brightness.

🧭 How it works

flowchart LR
    cam["📷 Webcam<br/>(manual exposure burst)"] --> d["vassagod<br/>meter → smooth → map"]
    d -->|"Night Light temperature<br/>(GSettings)"| gsd["gnome-settings-daemon<br/>gamma ramp"]
    d -->|"VCP 0x10 brightness<br/>(ddcutil)"| mon["🖥️ Monitors"]
    d <-->|"D-Bus<br/>io.github.fureunoir.Vassago"| ext["GNOME Shell extension<br/>Quick Settings + prefs"]
  1. Metering. The camera is switched to manual exposure with zero gain, then ffmpeg grabs 8 frames at 160×120 and the camera's own settings are put back. The reading is log2(mean luminance / exposure). Exposure auto-ranges so frames are neither black nor clipped, which gives a stable figure from a pitch-dark room to a sunny one.
  2. Mapping. The reading is placed between your dark and bright calibration points to get a 0–1 room level, smoothed so a passing shadow does nothing. The level is applied only when it moves by more than 5 %.
  3. Applying. Temperature goes from warm to neutral along a gentle curve. Brightness goes from each monitor's min to max, plus your correction, and is stepped smoothly instead of jumping.

📦 Requirements

Desktop GNOME Shell 50 or 51 (Wayland or X11)
Packages python3-gobject, ffmpeg, ddcutil
Camera any UVC webcam with manual exposure (tested: Logitech C922)
Monitors DDC/CI enabled in the OSD (optional: without it you get colour only)
Kernel i2c-dev loaded, with user access to the GPU's I²C buses

On Fedora:

sudo dnf install python3-gobject ffmpeg ddcutil
echo i2c-dev | sudo tee /etc/modules-load.d/i2c-dev.conf
sudo modprobe i2c-dev
ddcutil detect        # your monitors should show up here

Warning

OpenRGB users: openrgb-udev-rules gives your user access to every I²C bus, including the motherboard SMBus. On some boards, probing that bus hangs the machine. ddcutil only needs the GPU buses, so you can drop OpenRGB's I²C rule (USB lighting keeps working):

sed 's/^KERNEL=="i2c-\[0-99\]\*", TAG+="uaccess"/# &/' \
    /usr/lib/udev/rules.d/60-openrgb.rules | sudo tee /etc/udev/rules.d/60-openrgb.rules

🚀 Install

git clone https://git.wiseless.net/fureunoir/Vassago.git
cd Vassago
./install.sh

Everything is installed for your user only, with no root:

What Where
daemon ~/.local/bin/vassagod
extension ~/.local/share/gnome-shell/extensions/vassago@fureunoir/
systemd user unit ~/.config/systemd/user/vassagod.service
D-Bus activation ~/.local/share/dbus-1/services/io.github.fureunoir.Vassago.service

On Wayland, log out and back in once so GNOME Shell loads the new extension.

🎯 Calibrate (2 minutes, once)

Open Quick Settings → Vassago → Vassago Settings → Calibration:

  1. Make the room as dark as it usually gets (curtains closed, lamps off). Press Measure, then Save as dark.
  2. Make it as bright as it usually gets. Press Measure, then Save as bright.

Then set how warm the screen gets in the dark, and each monitor's brightness range under Brightness.

🔧 Configuration

All settings live in GSettings (org.gnome.shell.extensions.vassago) and apply live:

Key Default Meaning
enabled true master switch (the Quick Settings toggle)
paused false stop measuring, keep current values; cleared at daemon start
interval 120 seconds between camera readings
camera-device /dev/video0 which webcam to use
temperature-neutral 6500 K in a bright room
temperature-warm 4500 K in a dark room
brightness-enabled true drive monitor brightness over DDC/CI
brightness-offset 0 correction in percentage points, −50…+50
ambient-dark / ambient-bright 4.0 / 10.0 calibration points
monitor-limits learned per-monitor (min, max) brightness

From a terminal:

export GSETTINGS_SCHEMA_DIR=~/.local/share/gnome-shell/extensions/vassago@fureunoir/schemas
gsettings set org.gnome.shell.extensions.vassago temperature-warm 4000

🛰️ D-Bus API

io.github.fureunoir.Vassago at /io/github/fureunoir/Vassago:

Member
State (property, s) JSON: status, last reading, room level, temperature, monitors
MeasureNow() take a reading right away
Calibrate(s point) store the last reading as "dark" or "bright"
busctl --user get-property io.github.fureunoir.Vassago \
    /io/github/fureunoir/Vassago io.github.fureunoir.Vassago State

🩺 Troubleshooting

Symptom Try
Tile says Daemon not running journalctl --user -u vassagod -f
No monitors in the tile ddcutil detect; turn on DDC/CI in the monitor's OSD
Camera LED blinks too often raise interval, or Pause for a while
Screen too yellow in the dark raise Warmth in the dark toward 6500 K
Dims too much in a dim room the camera also sees the screen's own glow; save a new dark point with the screen at the brightness you like

🧹 Uninstall

Turn the tile off first: that restores your Night Light settings and monitor brightness. Then:

systemctl --user disable --now vassagod.service
gnome-extensions disable vassago@fureunoir
rm -r ~/.local/share/gnome-shell/extensions/vassago@fureunoir \
      ~/.local/bin/vassagod \
      ~/.config/systemd/user/vassagod.service \
      ~/.local/share/dbus-1/services/io.github.fureunoir.Vassago.service

📜 License

MIT © 2026 Egor Gorbunov