sunsetr logo

Introduction

Sunsetr is an automatic blue-light filter for Wayland compositors. It automates smooth color-temperature transitions from neutral to warmer tones, designed to reduce eye strain and improve sleep. Sunsetr automatically adjusts your displays based on your geolocation or manual time settings. It can also be used to persist the same color-temperature and gamma indefinitely, and can alternate between various user-defined presets. The controller can integrate with and automate changes in your shell or UI applications via IPC.

Getting Started

To get started, continue to the Installation guide, then follow the Quick Start guide to set up sunsetr with your compositor.

Installation

Sunsetr can be installed through several methods depending on your distribution and preferences.

Dependencies

Optional for Hyprland Users

  • Hyprland >= 0.49.0
  • hyprsunset >= v0.2.0 (only if using the hyprsunset backend)

For Other Wayland Compositors

  • Any Wayland compositor supporting wlr-gamma-control-unstable-v1 protocol
  • No external dependencies - uses native Wayland protocols

Build from Source

Installing

First, clone the repository:

git clone https://github.com/psi4j/sunsetr.git &&
cd sunsetr

Then install using cargo-make:

# Install cargo-make if you don't have it already
cargo install cargo-make

# Then install system-wide (requires sudo)
cargo make install
# Or install to ~/.local (no sudo)
cargo make install-local

Or install manually:

# Build with cargo
cargo build --release

# Then install manually
sudo cp target/release/sunsetr /usr/local/bin/

Uninstalling

If you used cargo make install:

cargo make uninstall

If you manually copied the binary:

sudo rm /usr/local/bin/sunsetr

Arch Linux (AUR)

sunsetr, sunsetr-git, and sunsetr-bin are available in the AUR:

sunsetr (Latest Version)

paru -S sunsetr

sunsetr-git (Development Version)

paru -S sunsetr-git

sunsetr-bin (Pre-compiled Binary)

paru -S sunsetr-bin

Recommendation: Use sunsetr for stability, or sunsetr-git if you want to help test the latest features.

NixOS

sunsetr is available in nixpkgs unstable.

NixOS Configuration

Add to your configuration.nix:

environment.systemPackages = with pkgs; [
  sunsetr
];

Then rebuild your system:

sudo nixos-rebuild switch

Imperative Installation

For non-NixOS systems or user-level installation:

nix-env -iA nixpkgs.sunsetr

Install using nix-shell

Test sunsetr without permanently installing it:

nix-shell -p sunsetr

Using Flakes

A flake is available for those wanting to use the latest version from main without waiting for it to be added to nixpkgs.

Add sunsetr to your flake inputs:

{
  inputs.sunsetr.url = "github:psi4j/sunsetr";
}

Then use it in your configuration:

{ inputs, pkgs, ... }:
{
  # Install as a system package
  environment.systemPackages = [
    inputs.sunsetr.packages.${pkgs.system}.sunsetr
  ];

  # OR with home-manager
  home.packages = [
    inputs.sunsetr.packages.${pkgs.system}.sunsetr
  ];
}

Other Distributions

Fedora / RHEL (Copr)

Coming soon! Copr repository support is planned.

Debian / Ubuntu

Coming soon! .deb packages are planned for Debian-based distributions.

Manual Installation (Any Distribution)

If your distribution isn't listed above, you can build from source:

  1. Install Rust and Cargo (if not already installed):

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    
  2. Follow the Build from Source instructions above.


Verifying Installation

After installation, verify sunsetr is available:

sunsetr --version

You should see output with the current version number.

Next Steps

Now that sunsetr is installed, you can follow the Quick Start guide to continue setting things up.

Quick Start

This guide will help you get sunsetr running on your system in just a few minutes.

Once you've completed these steps, you can customize sunsetr with the Configuration options, set your precise Geographic location, or create Presets for different scenarios.

First Run

On the first run, sunsetr will automatically create a default configuration file at ~/.config/sunsetr/sunsetr.toml. The defaults are carefully tuned to provide an excellent experience out of the box:

sunsetr

You should see output like:

┣ Automatic location detection
┃   Detecting coordinates from system timezone...
┃   Detected timezone: America/Chicago
┃   Timezone mapping: Chicago, United States
┃   Coordinates: 41.8500°N, 87.6501°W
┃   Auto-detected location for new config: Chicago
┃
┣ Loaded default configuration
┃   Backend: Auto (Wayland)
┃   Mode: Time-based (geo)
┃   Location: 41.850°N, 87.650°W
┃   Night: 3300K @ 90% gamma
┃   Day: 6500K @ 100% gamma
┃   Update interval: 60 seconds

This will use your detected timezone to automatically populate coordinates for geolocation-based sunset and sunrise transitions. I recommend most users run the geo command to select more precise coordinates when using the geo transition mode.

Compositor Setup

Sunsetr works best when started automatically via the compositor. Here's how to set it up for different compositors.

Hyprland

Add this line near the beginning of your ~/.config/hyprland/hyprland.conf:

exec-once = sunsetr

Starting sunsetr early during compositor initialization ensures seamless color temperature management from the moment your desktop loads.

⚠️ WARNING:

If selecting the Hyprland or Hyprsunset backend:

  • Do not use with hyprsunset's native config: I recommend removing hyprsunset.conf entirely or backing it up. (sunsetr will need full control for smooth transition times)
  • Make sure hyprsunset isn't already running if you want to use the Hyprland or Hyprsunset backends. You can check that a hyprsunset process isn't already running using btop or an alternative method.
  • I recommend you disable hyprsunset's systemd service using systemctl --user disable hyprsunset.service and make sure to stop the process before running sunsetr.

Niri

Add this line near the beginning of your ~/.config/niri/config.kdl:

spawn-at-startup "sunsetr"

Sway

Add this line to your ~/.config/sway/config:

exec sunsetr

River

Add this line to your ~/.config/river/init:

sunsetr &

Wayfire

Add this to your ~/.config/wayfire.ini in the [autostart] section:

[autostart]
sunsetr = sunsetr

Other Wayland Compositors

Consult your compositor's documentation for how to start background applications on startup.

Alternative Setup: Systemd Service

If you prefer systemd management over compositor-based startup:

systemctl --user enable --now sunsetr.service

Note: The systemd service file should be installed automatically with the listed Installation methods, or you can install it using cargo-make:

cargo make install-service

Running Sunsetr

Sunsetr runs in the foreground by default:

Foreground Mode (Default)

sunsetr

This is the recommended way to run sunsetr when starting it from compositor configs. The process stays attached to your compositor's lifecycle.

Background Mode

To run sunsetr as a background process:

sunsetr --background

This starts sunsetr in the background via the compositor. Useful if you're starting it manually from a terminal session and want to free up the terminal.

Debug Mode

To see detailed logging including sunrise/sunset calculations for geo mode:

sunsetr --debug

Verifying It's Working

After starting sunsetr, you can verify it's running and see its current state:

sunsetr status

You should see output showing:

 Active preset: default
Current period: Night
         State: stable
   Temperature: 3300K
         Gamma: 90.0%
   Next period: 06:29:21 (in 4h54m)

Testing Your Setup

You may want to test various temperature and gamma settings to find your ideal values for night time using the test command:

sunsetr test <TEMPERATURE> <GAMMA>

This temporarily applies temperature and gamma settings. Press ESC or Ctrl+C to restore the display and try something new.

The first value controls the color temperature (1000-20000K) and the second value (10-200%) controls the gamma of the display. Try different values to find what works best for you:

sunsetr test 4000 95   # Warm, a little dimmer
sunsetr test 3300 90   # Warmer, dimmer
sunsetr test 2333 70   # Very warm, quite dim

Once you've found your desired values (night_temp, night_gamma), you can set them in ~/.config/sunsetr/sunsetr.toml or in a custom location. You can do this by manually editing the config, or by using the set command.

Next Steps

Now that sunsetr is running, you might want to:

Troubleshooting

If sunsetr isn't working as expected, check the Troubleshooting guide for solutions to common issues.

Configuration

Sunsetr is highly configurable through TOML files. This section covers all configuration options and how to customize sunsetr for your needs.

Configuration Files

Sunsetr creates its configuration at ~/.config/sunsetr/sunsetr.toml on first run.

Default Configuration

Here's the complete default configuration with all available options:

#[Backend]
backend = "auto"         # Backend to use: "auto", "hyprland", "hyprsunset" or "wayland"
transition_mode = "geo"  # Select: "geo", "finish_by", "start_at", "center", "static"

#[Smoothing]
smoothing = true         # Enable smooth transitions during startup and exit
startup_duration = 0.5   # Duration of smooth startup in seconds (0.1-60 | 0 = instant)
shutdown_duration = 0.5  # Duration of smooth shutdown in seconds (0.1-60 | 0 = instant)
adaptive_interval = 1    # Adaptive interval base for smooth transitions (1-1000)ms

#[Time-based config]
night_temp = 3300        # Color temperature during night (1000-20000) Kelvin
day_temp = 6500          # Color temperature during day (1000-20000) Kelvin
night_gamma = 90         # Gamma percentage for night (10-200%)
day_gamma = 100          # Gamma percentage for day (10-200%)
update_interval = 60     # Update frequency during transitions in seconds (10-300)

#[Static config]
static_temp = 6500       # Color temperature for static mode (1000-20000) Kelvin
static_gamma = 100       # Gamma percentage for static mode (10-200%)

#[Manual transitions]
sunset = "19:00:00"      # Time for manual sunset calculations (HH:MM:SS)
sunrise = "06:00:00"     # Time for manual sunrise calculations (HH:MM:SS)
transition_duration = 45 # Transition duration in minutes (5-120)

#[Geolocation]
latitude = 30.267153     # Geographic latitude (auto-detected on first run)
longitude = -97.743057   # Geographic longitude (use 'sunsetr geo' to change)

Configuration Location

The configuration directory structure looks like this:

~/.config/sunsetr/
├── sunsetr.toml         # Main configuration file
├── geo.toml             # Optional: private geographic coordinates
└── presets/             # Optional: preset configurations
    ├── day/
    │   └── sunsetr.toml
    ├── gaming/
    │   └── sunsetr.toml
    └── ...

For more information on how to use and manage presets, please see the preset command.

Configuration Management

Sunsetr provides CLI commands for reading and modifying configuration values:

Hot Reloading

Sunsetr automatically detects and applies configuration changes without requiring a restart. Simply edit your configuration file, save it, and sunsetr will reload the new settings.

Watched files:

  • ~/.config/sunsetr/sunsetr.toml - Main configuration
  • ~/.config/sunsetr/geo.toml - Private geo coordinates (if it exists)
  • Active preset configuration files

See Hot Reloading in Advanced Features for more details.

Next Steps

Backend Selection

Sunsetr supports multiple backends for different compositors. The backend determines how color temperature is applied to your display.

Available Backends

backend = "auto"

Automatically detects your compositor and selects the best backend:

  1. Hyprland detected → Uses native Hyprland CTM backend
  2. Other Wayland compositor → Uses generic Wayland backend
  3. Detection fails → Returns error with suggestions

Recommendation: Use auto unless you have a specific reason to override. This ensures optimal backend selection and makes your config portable across different compositors.

hyprland (Hyprland CTM Manager)

backend = "hyprland"

Uses Hyprland's native Color Transformation Matrix protocol (hyprland-ctm-control-v1).

Pros:

  • Most efficient for Hyprland
  • Syncs CTM animations to display's refresh rate
  • No external dependencies
  • Direct protocol communication

Cons:

  • Only works on Hyprland
  • Hyprland's built-in CTM animations are not adjustable like sunsetr's smoothing using the wayland backend

Notes:

  • Hyprland's CTM animations override sunsetr's smooth transitions. To use sunsetr's smooth transitions, use backend = "wayland" instead
  • To disable Hyprland's CTM animations for instant temperature and gamma updates, set this in hyprland.conf:
    render {
        ctm_animation = 0
    }
    

hyprsunset (Hypsunset Controller)

backend = "hyprsunset"

Controls color temperature through Hyprland's hyprsunset CTM manager.

Pros:

  • Works as Hyprland's team intends it to
  • May integrate better with their other tools and ecosystem

Cons:

  • Requires an additional dependency
  • Less efficient than using the native CTM backend
  • Process management overhead

wayland (WLR Gamma Control)

backend = "wayland"

Uses the standard Wayland wlr-gamma-control-unstable-v1 protocol.

Pros:

  • Works on any Wayland compositor supporting the protocol
  • Smooth transitions fully supported
  • No external dependencies

Cons:

  • Does not sync to dispay's refresh rate

Supported compositors: Hyprland, Niri, Sway, River, Wayfire, and most Wayland compositors.

Backend Selection Guide

Use CaseRecommended Backend
Hyprland with smooth transitionswayland
Hyprland with CTM animationsauto (uses native CTM)
Niri, Sway, River, other Waylandauto (uses wayland)
Force Hyprland CTM for presethyprland
Force WLR gamma control for presetwayland
Integrate with Hyprland ecosystemhyprsunset
Portable config across compositorsauto

Transition Modes

Transition modes determine when and how sunsetr adjusts color temperature. There are 4 time-based modes and a static mode. Time-based modes use these settings since they gradually transition from day to night values and back regularly at their specified times:

#[Time-based config]
night_temp = 3300        # Color temperature during night (1000-20000) Kelvin
day_temp = 6500          # Color temperature during day (1000-20000) Kelvin
night_gamma = 90         # Gamma percentage for night (10-200%)
day_gamma = 100          # Gamma percentage for day (10-200%)
update_interval = 60     # Update frequency during transitions in seconds (10-300)
transition_mode = "geo"

Automatically calculates sunrise and sunset windows based on your geographic location. This provides the most natural transitions that change throughout the year as seasons shift.

How it works:

  • Uses your latitude and longitude to calculate solar elevation angles
  • Determines precise sunrise and sunset times for your location
  • Transitions windows match the calculated solar timing closely
  • Automatically recalculates daily after midnight

Configuration:

transition_mode = "geo"
latitude = 40.7128      # Your latitude
longitude = -74.0060    # Your longitude

Note: When using geo mode, the sunset, sunrise, and transition_duration settings are ignored. These values are calculated automatically from your coordinates.

See Geographic Setup for detailed location configuration.

Manual Transitions:

For finish_by, start_at, and center modes, configure these settings:

sunset = "19:00:00"           # HH:MM:SS format
sunrise = "06:00:00"          # HH:MM:SS format
transition_duration = 45      # Minutes (5-120)

2. finish_by (Complete By Time)

transition_mode = "finish_by"

Ensures transitions complete exactly at the configured sunset and sunrise times.

Behavior:

  • Transition begins transition_duration minutes before the configured time
  • Reaches target temperature/gamma at the configured time

Example:

transition_mode = "finish_by"
sunset = "19:00:00"
transition_duration = 45

# Transition starts: 18:15:00
# Transition ends:   19:00:00 ← Configured time

When to use: You want night mode fully active at a specific time.

3. start_at (Begin At Time)

transition_mode = "start_at"

Transitions begin exactly at the configured sunset and sunrise times.

Behavior:

  • Transition begins at the configured time
  • Reaches target temperature/gamma transition_duration minutes after

Example:

transition_mode = "start_at"
sunset = "19:00:00"
transition_duration = 45

# Transition starts: 19:00:00 ← Configured time
# Transition ends:   19:45:00

When to use: You want transitions to start at specific times.

4. center (Center On Time)

transition_mode = "center"

Transitions are centered around the configured sunset and sunrise times.

Behavior:

  • Transition begins transition_duration / 2 minutes before
  • Reaches target at configured time (midpoint)
  • Continues transition_duration / 2 minutes after

Example:

transition_mode = "center"
sunset = "19:00:00"
transition_duration = 60

# Transition starts: 18:30:00
# Midpoint:          19:00:00 ← Configured time
# Transition ends:   19:30:00

When to use: You want the transition midpoint to align with specific times.

5. static (Constant Values)

transition_mode = "static"

Maintains constant color temperature and gamma values without any time-based transitions.

When to use:

  • You want consistent display settings 24/7
  • You prefer manual control over automatic adjustments
  • You're creating a preset for specific lighting conditions
  • You need color accuracy (e.g., photo editing)

Configuration:

transition_mode = "static"
static_temp = 6500      # Constant temperature
static_gamma = 100      # Constant gamma

Note: When using static mode, all time-based settings (night_temp, day_temp, update_interval, etc ) are ignored.

Examples:

# Always neutral (daytime)
static_temp = 6500
static_gamma = 100

# Always warm (nighttime)
static_temp = 3300
static_gamma = 90

# Gaming/color-accurate mode
static_temp = 6500
static_gamma = 100

Temperature and Gamma Settings

Color temperature and gamma control how your display looks during different periods.

Color Temperature

Color temperature is measured in Kelvin (K) and affects the color "warmth" of your display:

  • 2000-3000K: Very warm, orange-yellow (candlelight to incandescent)
  • 3000-4000K: Warm white to neutral warm (halogen, sunrise/sunset)
  • 4000-5000K: Neutral white to cool white (fluorescent)
  • 5000-6500K: Daylight white (direct sunlight, overcast sky)
  • 6500-8000K: Cool white to blue-white (bright daylight)
  • 8000+K: Very cool, ice blue (this will wake you up)

Valid range: 1000-20000K

Gamma

Gamma controls the overall brightness and contrast of your display:

  • 10-80%: Very dim, reduced contrast
  • 80-90%: Dim, comfortable for night
  • 90-100%: Normal brightness
  • 100-150%: Bright, increased contrast
  • 150-200%: Very bright, high contrast

Valid range: 10-200%

Note: Gamma values above 100% increase brightness but may wash out colors. Values below 80% may make the display difficult to read.

Day and Night Configuration

Configure separate temperature and gamma values for day and night periods:

# Daytime values (during day period)
day_temp = 6500          # Neutral, natural light
day_gamma = 100          # Full brightness

# Nighttime values (during night period)
night_temp = 3300        # Warm, reduced blue light
night_gamma = 90         # Slightly dimmed

Update Interval

Controls how frequently sunsetr updates color temperature during transitions:

update_interval = 60     # Seconds (10-300)
  • Lower values (10-30s): More frequent updates for maintaining smoothness with a shorter transition_duration (5-20min)
  • Higher values (60-120s): Less frequent updates for longer a transition_duration (30-120min)
  • Default (60s): Good balance for most durations

Note: This only affects updates during sunset/sunrise transitions. Day and night periods are stable and don't update continuously.

Testing Values

Use the test command to temporarily try different temperature and gamma values:

# Test typical night-time settings
sunsetr test 3300 90

# Try different warmth levels
sunsetr test 4000 95   # Slightly cooler, brighter
sunsetr test 3000 85   # Warmer, dimmer
sunsetr test 2333 70   # Very warm, quite dim

Press ESC or Ctrl+C to restore previous settings.

Smooth Transitions

Smooth transitions provide gradual fade effects when sunsetr starts up, reloads, switches presets, and shuts down.

Backend Compatibility

⚠️ Important: Smooth transitions are only supported on the Wayland backend. To use smoothing on Hyprland, set backend = "wayland".

Configuration

smoothing = true             # Enable/disable smooth transitions
startup_duration = 0.5       # Seconds (0.1-60, 0 = instant)
shutdown_duration = 0.5      # Seconds (0.1-60, 0 = instant)
adaptive_interval = 1        # Base interval in milliseconds (1-1000)

How Smoothing Works

  1. startup_duration determines the duration of the smoothing animation at startup, for preset switching, and configuration reloading.
  2. shutdown_duration determines the duration of the smoothing animation at shutdown
  3. adaptive_interval controls the minimum granularity of the update interval that affects the perceived smoothness of the animation

Duration Settings

The duration determines how long transitions take:

# Fast (default)
startup_duration = 0.5       # Half second
shutdown_duration = 0.5

# Moderate
startup_duration = 5.0       # 5 seconds
shutdown_duration = 5.0

Adaptive Interval

The adaptive interval controls the base update interval during transitions:

adaptive_interval = 1

The adaptive interval uses an algorithm designed to adapt to your particular machine's capabilities. The default 1ms maximizes the granularity of the update interval automatically, allowing for the smoothest possible subsecond animations from current to target values. The current wlr-gamma-control-unstable-v1 protocol used by the Wayland backend relies on each compositor's implementation for gamma control updates. Each compositor will have their own performance characteristics for each type of CPU/GPU for this protocol.

Currently, niri and Hyprland handle the default settings quite well when used with Intel CPUs, and NVIDIA and AMD GPUs are noticeably less smooth. The performance characteristics of the smooth transitions are a result of the interaction between the compositor, the Linux kernel, and the GPU. Refining this further is out of the scope of this application, therefore, I've opened up the adaptive_interval as a configuration point to the user in case they'd like to attempt to refine things further to their taste.

When to adjust:

If you find that your mouse is lagging when the smoothing animation is occurring, you could try adjusting the base update interval a bit higher to reduce the granularity of the updates, but you will have to accompany this with a longer startup_duration and shutdown_duration if you want this to be a bit smoother. It's important to note that it is not necessarily the number or frequency of the updates causing the lag, but rather the way the compositor has to batch updates for rendering when sent to the kernel to then be processed by the GPU. Testing the smooth transitions on an old Intel CPU shows how smoothing works quite well when the process is streamlined between the compositor, kernel, and processor.

You may find success in further smoothing the animation with your compositor and processor by using settings similar to these:

#[Smoothing]
smoothing = true         # Enable smooth transitions during startup and exit
startup_duration = 5     # Duration of smooth startup in seconds (0.1-60 | 0 = instant)
shutdown_duration = 5    # Duration of smooth shutdown in seconds (0.1-60 | 0 = instant)
adaptive_interval = 144  # Adaptive interval base for smooth transitions (1-1000)ms

Instant updates

If the smoothing animations don't meet your expectations or you want to decrease startup time, you can always disable smoothing to achieve the same results as something like wlsunset by setting:

smoothing = false

Correspondingly, if you want to disable Hyprland's native CTM animations, you can set this in hyprland.conf:

render {
    ctm_animation = 0
}

Geographic Setup

When using transition_mode = "geo", sunsetr automatically calculates sunrise and sunset times based on your geographic location. This provides the most natural transitions that adjust throughout the year as seasons change.

Interactive City Selection

The easiest way to configure your location is using the interactive city selector. This launches a fuzzy search interface where you can search a local database of 10,000+ cities worldwide by country or city name to populate your coordinates.

Example Usage

$ sunsetr geo

You'll see this interface:

┣ Select the nearest city for more accurate transition times
┃   Type to search, use ↑/↓ to navigate, Enter to select, Esc to cancel
┃
┃ Search: _
┃ ▶ A Coruna, Spain
┃   Aabenraa, Denmark
┃   Aachen, Germany
┃   Aalborg, Denmark
┃   Aalst, Belgium
┃ 100 of 10592 cities

After Selection

Once you select a city, sunsetr will:

  1. Show calculated times for today:
┣ Sun times for A Coruna, Spain (43.3713°N, 8.3960°W)
┃   Today's sunset: 18:09 (transition from 17:18 to 18:19)
┃   Tomorrow's sunrise: 08:27 (transition from 08:16 to 09:18)
┃   Sunset transition duration: 61 minutes
┃   Sunrise transition duration: 61 minutes
  1. Save coordinates to your configuration
  2. Change config to transition_mode="geo"
  3. Reload automatically with the new location

The coordinates are saved to the active configuration (default or an active preset):

  • ~/.config/sunsetr/sunsetr.toml (default)

Testing other cities' coordinates

I realize we might want to test other cities' sunset/sunrise times and transition durations. Maybe we have to fly to another timezone for a special event and we want to get ahead of the jet lag and fix our sleeping schedule to their timezone.

Just run sunsetr geo. If you run this with --debug, you'll see an additional set of times in brackets [] to the right of the primary set of times. These times are in your autodetected local timezone. The primary set of times correspond to the selected city's coordinates' sunset/sunrise transition times. Ex:

┣[DEBUG] Solar calculation details for 2025-11-06:
┃           Raw coordinates: 35.6895°, 139.6917°
┃               Sunrise UTC: 21:07
┃                Sunset UTC: 07:41
┃       Coordinate Timezone: Asia/Tokyo (+09:00)
┃            Local timezone: America/Chicago (-06:00)
┃     Current time (Coords): 10:39:17
┃      Current time (Local): 19:39:17
┃           Time difference: +15 hours
┃   --- Sunrise (ascending) ---
┃          Civil dawn (-6°): 05:41:07 [14:41:07]
┃    Transition start (-2°): 05:58:53 [14:58:53]
┃              Sunrise (0°): 06:07:46 [15:07:46]
┃     Golden hour end (+6°): 06:34:25 [15:34:25]
┃     Transition end (+10°): 06:52:11 [15:52:11]
┃          Sunrise duration: 53 minutes
┃              Day duration: 9 hours 5 minutes (11-06)
┃   --- Sunset (descending) ---
┃   Transition start (+10°): 15:57:30 [00:57:30]
┃   Golden hour start (+6°): 16:15:16 [01:15:16]
┃               Sunset (0°): 16:41:55 [01:41:55]
┃      Transition end (-2°): 16:50:48 [01:50:48]
┃          Civil dusk (-6°): 17:08:34 [02:08:34]
┃           Sunset duration: 53 minutes
┃            Night duration: 13 hours 8 minutes (11-06 → 11-07)
┃
┣[DEBUG] Next transition will begin at: 15:57:30 [00:57:30] Day 󰖨  → Sunset 󰖛

Using Arbitrary Coordinates

If the city selector (sunsetr geo) is not as precise as you'd like, you're welcome manually add coordinates to sunsetr.toml. I recommend using https://www.geonames.org/ or Google Earth to find your coordinates. North is positive, South is negative. East is positive, West is negative.

#[Geolocation]
latitude = 29.424122   # just switch these up
longitude = -98.493629 # `sunsetr --debug` to see the times/duration

Privacy-Focused Geographic Configuration

If you version control your configuration files (e.g., in a dotfiles repository), you may not want to expose your geographic location. sunsetr supports storing coordinates in a separate geo.toml file that you can keep private:

  1. Create the geo.toml file in the same directory as your sunsetr.toml:

    touch ~/.config/sunsetr/geo.toml
    
  2. Add geo.toml to your .gitignore:

    echo "geo.toml" >> ~/.gitignore
    
  3. Run sunsetr geo to populate it (or enter manual coordinates)

  4. Delete or spoof coordinates in sunsetr.toml

Once geo.toml exists, it will:

  • Override any coordinates in your main sunsetr.toml
  • Receive all coordinate updates when you run sunsetr geo
  • Keep your location private while allowing you to version control all other settings

Example geo.toml:

#[Private geo coordinates]
latitude = 40.7128
longitude = -74.0060

This separation allows you to share your sunsetr configuration publicly without accidentally doxxing yourself. geo.toml can also serve as a temporary place to store your coordinates when travelling.

Note: Your debug output will still print your coordinates on startup for debugging purposes, so be extremely careful when sharing your debug output online.

┣ Loaded default configuration
┃   Loaded coordinates from geo.toml
┃   Backend: Auto (Wayland)
┃   Mode: Time-based (geo)
┃   Location: 41.850°N, 87.650°W <--- ⭐ Careful!
┃   Night: 3300K @ 90% gamma
┃   Day: 6500K @ 100% gamma
┃   Update interval: 60 seconds

Next Steps

Hot Reloading

Sunsetr automatically detects and applies configuration changes without requiring a restart.

How It Works

Sunsetr watches these files for changes:

  • Main configuration: ~/.config/sunsetr/sunsetr.toml
  • Geographic coordinates: ~/.config/sunsetr/geo.toml (if it exists)
  • Active preset configuration: ~/.config/sunsetr/presets/<active>/sunsetr.toml
  • Active preset coordinates: ~/.config/sunsetr/presets/<active>/geo.toml (if it exists)

When any watched file changes:

  1. Detects change
  2. Validates new configuration before applying
  3. Applies smooth transition to new values (if configured)
  4. Logs reload in debug output

Using Hot Reload

Simply edit your configuration and save:

# Start sunsetr
sunsetr

# In another terminal, edit config
vim ~/.config/sunsetr/sunsetr.toml

# Changes apply automatically on save!

What Gets Hot-Reloaded

Applies immediately:

  • Temperature values (night_temp, day_temp, static_temp)
  • Gamma values (night_gamma, day_gamma, static_gamma)
  • Update interval (update_interval)
  • Transition mode changes (transition_mode)
  • Coordinates (latitude, longitude)
  • Timing values (sunset, sunrise, transition_duration)
  • Smoothing settings (smoothing, startup_duration, shutdown_duration)

Requires restart:

  • Backend changes (backend)

Hot Reload with Custom Config

Hot reload works with custom configuration directories:

# Start with custom config
sunsetr --config ~/dotfiles/sunsetr/

# Edit custom config
vim ~/dotfiles/sunsetr/sunsetr.toml

# Changes apply automatically

Debugging Hot Reload

Use debug mode to see reload events:

sunsetr --debug

When configuration changes, you'll see:

┣[DEBUG] Reload state change detection:
┃   State: Day → Night
┃   Temperature: 6500 → 3300K
┃   Gamma: 100% → 90%
┃   Smooth transition: enabled

Limitations

  • Backend changes require sunsetr restart
  • Invalid configurations are rejected (keeps current config)
  • Very rapid changes may be debounced (1-2 second window)

Preset System

The preset system allows quick switching between different configuration profiles for different activities, times of day, days of the week, or locations.

Preset Management

The preset system can be used via the CLI, added to keybinds, or bash scripts:

# Show currently active preset
sunsetr preset active

# List all available presets
sunsetr preset list

# Switch to a specific preset
sunsetr preset day
sunsetr preset gaming

# Return to default configuration
sunsetr preset default

# Or call the same preset twice to toggle back to default
sunsetr preset day
sunsetr preset day # returns to default

Set up keyboard shortcuts for instant toggling:

Hyprland (hyprland.conf)

bind = $mod, W, exec, sunsetr preset day # toggle between day preset and default config

Niri (config.kdl)

Mod+W { spawn "sh" "-c" "sunsetr p day"; }

Creating Presets

Create preset files in ~/.config/sunsetr/presets/:

~/.config/sunsetr/
├── sunsetr.toml         # Main/default config
├── geo.toml             # Optional: private coordinates
└── presets/
    ├── day/
    │   └── sunsetr.toml # Static day values
    ├── gaming/
    │   └── sunsetr.toml # Gaming-optimized settings
    ├── weekend/
    │   └── sunsetr.toml # Weekend schedule
    └── london/
        ├── sunsetr.toml # London timezone
        └── geo.toml     # London coordinates

Each preset can have:

  • Its own sunsetr.toml with complete or partial configuration
  • Optional geo.toml for location-specific presets
  • Any valid sunsetr configuration options

Example preset for static day mode (~/.config/sunsetr/presets/day/sunsetr.toml):

#[Backend]
backend = "auto"           # Backend to use: "auto", "hyprland" or "wayland"
transition_mode = "static" # Select: "geo", "finish_by", "start_at", "center", "static"

#[Smoothing]
smoothing = true           # Enable smooth transitions during startup and exit
startup_duration = 0.5     # Duration of smooth startup in seconds (0.1-60 | 0 = instant)
shutdown_duration = 0.5    # Duration of smooth shutdown in seconds (0.1-60 | 0 = instant)
adaptive_interval = 1      # Adaptive interval base for smooth transition (1-1000)ms

#[Static configuration]
static_temp = 6500         # Color temperature for static mode (1000-20000) Kelvin
static_gamma = 100         # Gamma percentage for static mode (10-200%)

Advanced Preset Usage

Day-of-Week Preset Switching:

Start sunsetr with different presets based on the day of week:

#!/bin/bash
# Start sunsetr with preset based on day of week

day=$(date +%u)  # 1=Monday, 7=Sunday

if [ $day -ge 1 ] && [ $day -le 5 ]; then
    # Weekdays: work schedule with earlier transitions
    sunsetr preset weekday
else
    # Weekends: relaxed schedule, sleep in
    sunsetr preset weekend
fi

Then use this script in your compositor startup:

Hyprland:

exec-once = ~/.config/hypr/scripts/start-sunsetr.sh

Niri:

spawn-at-startup "~/.config/niri/scripts/start-sunsetr.sh"

Next Steps

Preset Examples

Ready-to-use preset configurations for common scenarios.

Static Day Mode

Perfect for daytime work or when you want consistent, neutral lighting.

~/.config/sunsetr/presets/day/sunsetr.toml:

#[Backend]
backend = "auto"
transition_mode = "static" # No time-based transitions

#[Smoothing]
smoothing = true
startup_duration = 0.5     # Quick fade-in
shutdown_duration = 0.5    # Instant shutdown
adaptive_interval = 1

#[Static configuration]
static_temp = 6500         # Neutral daylight
static_gamma = 100         # Full brightness

Usage:

sunsetr preset day         # Enable day mode
sunsetr preset day         # Toggle back to default

Gaming Mode

Optimized for color accuracy and maximum brightness.

~/.config/sunsetr/presets/gaming/sunsetr.toml:

#[Backend]
backend = "auto"
transition_mode = "static"

#[Smoothing]
smoothing = true
startup_duration = 0.5
shutdown_duration = 0.5
adaptive_interval = 1

#[Static configuration]
static_temp = 6500           # Accurate colors
static_gamma = 115           # Slightly boosted brightness

Usage:

sunsetr preset gaming        # Enable gaming mode

Weekend Schedule

Different sunrise/sunset schedule for weekends.

~/.config/sunsetr/presets/weekend/sunsetr.toml:

#[Backend]
backend = "auto"
transition_mode = "finish_by"

#[Smoothing]
smoothing = true
startup_duration = 0.5
shutdown_duration = 0.5
adaptive_interval = 1

#[Time-based config]
night_temp = 2800            # Warmer for late nights
day_temp = 6500
night_gamma = 85             # Dimmer for comfort
day_gamma = 100
update_interval = 60

#[Manual transitions]
sunset = "22:00:00"          # Stay up later
sunrise = "09:00:00"         # Sleep in
transition_duration = 90     # Longer transitions

Usage:

# Friday night
sunsetr preset weekend

# Monday morning
sunsetr preset default

Location-Based Preset (Travel)

Separate coordinates for different locations.

~/.config/sunsetr/presets/london/sunsetr.toml:

#[Backend]
backend = "auto"
transition_mode = "geo"      # Use London coordinates

#[Smoothing]
smoothing = true
startup_duration = 0.5
shutdown_duration = 0.5
adaptive_interval = 1

#[Time-based config]
night_temp = 3300
day_temp = 6500
night_gamma = 90
day_gamma = 100
update_interval = 60

#[Geolocation]
latitude = 51.508415
longitude = -0.125533

Usage:

# When traveling to London
sunsetr preset london

# After returning home
sunsetr preset default

Reading Mode

Extra warm, dimmed for late-night reading.

~/.config/sunsetr/presets/reading/sunsetr.toml:

#[Backend]
backend = "auto"
transition_mode = "static"

#[Smoothing]
smoothing = true
startup_duration = 0.5       # Slow transition
shutdown_duration = 0.5
adaptive_interval = 1

#[Static configuration]
static_temp = 2333           # Very warm
static_gamma = 75            # Quite dim

Usage:

sunsetr preset reading       # Late-night reading mode

Minimal Blue Light

Maximum blue light reduction for sensitive users.

~/.config/sunsetr/presets/no-blue/sunsetr.toml:

#[Backend]
backend = "auto"
transition_mode = "static"

#[Smoothing]
smoothing = true
startup_duration = 0.5
shutdown_duration = 0.5
adaptive_interval = 1

#[Static configuration]
static_temp = 1000           # Extreme warmth
static_gamma = 70            # Reduced brightness

Usage:

sunsetr preset no-blue       # Extreme blue light reduction

Command Reference

This section provides a complete reference for all sunsetr commands and global flags.

Command Cheat Sheet

CommandPurposeExample
sunsetrStart sunsetrsunsetr
sunsetr --backgroundStart in backgroundsunsetr --background
sunsetr --debugStart with debug outputsunsetr --debug
sunsetr test <TEMP> <GAMMA>Test temperature/gammasunsetr test 3300 90
sunsetr geoSelect citysunsetr geo
sunsetr preset <NAME>Switch presetsunsetr preset day
sunsetr preset activeShow active presetsunsetr preset active
sunsetr preset listList presetssunsetr preset list
sunsetr statusShow current statesunsetr status
sunsetr status --jsonJSON outputsunsetr status --json
sunsetr status --followStream updatessunsetr status --follow
sunsetr get <FIELD>Read config valuesunsetr get night_temp
sunsetr set <FIELD>=<VALUE>Write config valuesunsetr set night_temp=3500
sunsetr restartRestart sunsetrsunsetr restart --instant
sunsetr stopStop sunsetrsunsetr stop
sunsetr --simulate ...Simulate time windowsunsetr --simulate "..." "..." 60

Built-in Help

Sunsetr includes comprehensive built-in help:

# General help
sunsetr help            # Show all available commands
sunsetr --help          # Show detailed usage information

# Command-specific help
sunsetr help <COMMAND>

Commands

  • test - Test color temperature and gamma values temporarily
  • geo - Configure geographic location interactively
  • preset - Switch between configuration presets
  • status - Monitor current runtime state
  • get & set - Read and modify configuration values
  • restart & stop - Process management commands
  • Global Flags - Flags available on main command

Next Steps

test

Test color temperature and gamma values temporarily without modifying your configuration.

Usage

sunsetr test <TEMPERATURE> <GAMMA>

Arguments

  • TEMPERATURE: Color temperature in Kelvin (1000-20000)
  • GAMMA: Gamma percentage (10-200)

Examples

# Test typical night-time settings
sunsetr test 3300 90

# Try different warmth levels
sunsetr test 4000 95   # Slightly cooler, brighter
sunsetr test 3000 85   # Warmer, dimmer
sunsetr test 2500 80   # Very warm, quite dim

# Test day-time neutral values
sunsetr test 6500 100

Behavior

  • Temporarily applies the specified temperature and gamma values
  • Works with running instance - Sends values to the existing sunsetr process
  • Press ESC or Ctrl+C to automatically restore previous settings
  • Does not modify your configuration file
  • Perfect for finding your preferred settings before committing them to config

geo

Configure geographic location through an interactive city selector.

Usage

sunsetr geo

Interactive Interface

The geo command launches a fuzzy search interface where you can:

  • Type to search from 10,000+ cities worldwide
  • Navigate with arrow keys (↑/↓)
  • Select with Enter
  • Cancel with Esc
  • Search by city name or country

Examples

# Launch city selector
sunsetr geo

# Run sunsetr in debug mode to see detailed solar calculations
sunsetr --debug
# Or
sunsetr restart -d

Behavior

After selecting a city, sunsetr will:

  1. Display calculated times for today (sunrise, sunset, transition durations)
  2. Save coordinates to either:
    • ~/.config/sunsetr/geo.toml (if it exists)
    • ~/.config/sunsetr/sunsetr.toml (otherwise)
  3. Change config to transition_mode="geo"
  4. Restart automatically with the new location

Notes

  • Only works with transition_mode = "geo"
  • See Geographic Setup for more details on location configuration

preset

Switch between configuration presets or view preset information.

Usage

sunsetr preset <PRESET_NAME>
sunsetr preset active
sunsetr preset list

Subcommands

preset <name> - Switch to a specific preset

sunsetr preset day      # Switch to day preset
sunsetr preset gaming   # Switch to gaming preset
sunsetr preset default  # Return to default configuration

preset active - Show which preset is currently active

sunsetr preset active

Output:

gaming

preset list - List all available presets

sunsetr preset list

Output:

day
gaming
weekend
london

Toggle Behavior

Calling the same preset twice toggles back to default:

sunsetr preset day    # Switches to day preset
sunsetr preset day    # Switches back to default

Notes

  • Presets are stored in ~/.config/sunsetr/presets/
  • Each preset is a directory containing sunsetr.toml (and optionally geo.toml)
  • See Preset System for detailed preset configuration

status

Monitor the current runtime state of sunsetr via IPC.

Usage

sunsetr status
sunsetr status --json
sunsetr status --follow
sunsetr status --json --follow

Flags

  • --json, -j: Output in JSON format for scripting
  • --follow, -f: Stream real-time state changes continuously

One-Shot Mode (Default)

Displays current state once and exits:

sunsetr status

Output:

 Active preset: default
Current period: Sunset 󰖛 (32.19%)
         State: transitioning
   Temperature: 5470K → 3300K
         Gamma: 96.8% → 90.0%
   Next period: 17:49:25 (in 31m)

Follow Mode

Stream real-time state changes:

sunsetr status --follow

Events displayed:

  • StateApplied: Temperature/gamma updates
  • PeriodChanged: Period transitions (Day → Sunset → Night → Sunrise)
  • PresetChanged: Preset switching

JSON Output

Machine-readable output for scripting:

sunsetr status --json
{
  "active_preset": "default",
  "period": "sunset",
  "state": "transitioning",
  "progress": 0.4637135,
  "current_temp": 5016,
  "current_gamma": 95.36286,
  "target_temp": 3300,
  "target_gamma": 90.0,
  "next_period": "2025-11-11T17:49:25.000679991-06:00"
}

Use Cases

  • Verify sunsetr is running correctly
  • Monitor transition progress and timing
  • Status bar integration (waybar, quickshell, etc.)
  • Automating changes in your UI or other applications

IPC Socket

The IPC can be used directly with a custom client or you can use the status command in follow and json mode (sunsetr -f -j) using something like jq. The IPC is located at:

$XDG_RUNTIME_DIR/sunsetr-events.sock
# Typically: /run/user/1000/sunsetr-events.sock

Notes

get & set

Read and modify configuration values.

Using the get command

Read configuration values from sunsetr configuration files.

Usage:

sunsetr get <FIELD>...
sunsetr get all
sunsetr get <FIELD> --json
sunsetr get <FIELD> --target <PRESET>

Arguments:

  • FIELD: One or more configuration field names
  • all: Special keyword to retrieve all configuration values

Flags:

  • --json: Output in JSON format
  • --target <PRESET>, -t <PRESET>: Read from specific preset (default: default)

Examples:

# Get specific field
sunsetr get night_temp
# Output: night_temp = 3300

# Get multiple fields
sunsetr get night_temp day_temp
# Output:
# night_temp = 3300
# day_temp = 6500

# Get all configuration
sunsetr get all

# JSON output for scripting
sunsetr get night_temp --json
# Output: {"night_temp": 3300}

# Full config as JSON
sunsetr get all --json

# Read from specific preset
sunsetr get night_temp --target gaming
sunsetr get night_temp -t day

Available Fields:

All fields from sunsetr.toml:

  • backend
  • transition_mode
  • smoothing
  • startup_duration
  • shutdown_duration
  • adaptive_interval
  • night_temp
  • day_temp
  • night_gamma
  • day_gamma
  • update_interval
  • static_temp
  • static_gamma
  • sunset
  • sunrise
  • transition_duration
  • latitude
  • longitude

Notes:

  • Does not require sunsetr to be running
  • Reads from configuration files directly
  • Useful for scripting and automation

Using the set command

Modify configuration values with validation and safety features.

Usage:

sunsetr set <FIELD>=<VALUE>... # sets values in default config
sunsetr set --target <PRESET> <FIELD>=<VALUE>...

Arguments:

  • FIELD=VALUE: One or more field-value pairs to set

Flags:

  • --target <PRESET>, -t <PRESET>: Modify specific preset configuration (default: default)

Examples:

# Set single value
sunsetr set night_temp=3500

# Set multiple values
sunsetr set night_temp=3500 day_temp=6000

# Modify specific preset
sunsetr set --target gaming static_temp=4700
sunsetr set -t day static_gamma=110

Notes:

  • Does not require sunsetr to be running
  • Changes are written to configuration files
  • If sunsetr is running, changes are applied immediately via hot reload

restart & stop

Process management commands for controlling the running sunsetr instance.

Using the restart command

Restart sunsetr with clean backend re-initialization.

Usage:

sunsetr restart
sunsetr restart --instant
sunsetr restart --background

Flags:

  • --instant: Skip smooth transitions for immediate restart
  • --background: Restart in background mode

Examples:

# Normal restart with smooth transitions
sunsetr restart

# Skip smooth transitions for faster restarts
sunsetr restart --instant

# Restart in background mode
sunsetr restart --background

Behavior:

The restart command performs a clean stop-wait-start sequence:

  1. Stops current instance gracefully
  2. Waits for shutdown to complete
  3. Starts new instance with fresh backend initialization
  4. Applies smooth transitions (unless you run with --instant)

When to Use:

  • DPMS recovery: After manual display sleep/wake cycles on Hyprland
  • Backend issues: If temperature/gamma stop working

Using the stop command

Gracefully shutdown the running sunsetr instance.

Usage:

sunsetr stop

Behavior:

  • Graceful shutdown: Applies smooth shutdown transitions if configured
  • Cleanup: Removes lock files and IPC socket
  • Restoration: Returns display to configured day values
  • Verification: Confirms process has terminated

Global Flags

These flags modify how sunsetr runs and are available on the main command.

--debug

Enable detailed debug output including solar calculations and state changes.

sunsetr --debug

Shows:

  • Configuration loading details
  • Detected/configured coordinates and timezone when using geo mode
  • Precise sunset/sunrise timing with transition boundaries
  • Real-time state changes and temperature updates

--background

Start sunsetr in the background via the compositor. Also compatible with the restart command.

sunsetr --background
sunsetr restart --background

Note: Not needed when starting from compositor config (exec-once, spawn-at-startup)

--config

Use a custom configuration directory instead of ~/.config/sunsetr/.

sunsetr --config ~/dotfiles/sunsetr/

Use cases:

  • Portable configuration setups
  • Multiple configuration profiles
  • Custom dotfiles management

Behavior:

  • All commands respect the custom directory
  • Relative directory structure remains the same:
~/dotfiles/sunsetr/
├── sunsetr.toml
├── geo.toml
└── presets/
    └── [your presets]

Examples:

# Start with custom config
sunsetr --config ~/dotfiles/sunsetr/

Note: Once started with --config, subsequent commands during that session automatically use the custom directory.

See Custom Config Directories for more details.

--simulate

Test sunsetr's behavior across arbitrary time windows without waiting.

sunsetr --simulate "<START>" "<END>" <MULTIPLIER>
sunsetr --simulate "<START>" "<END>" --fast-forward
sunsetr --simulate "<START>" "<END>" <MULTIPLIER> --log

Arguments:

  • START: Start time in format "YYYY-MM-DD HH:MM:SS"
  • END: End time in format "YYYY-MM-DD HH:MM:SS"
  • MULTIPLIER: Time speed multiplier (0.1x to 3600x)
  • --fast-forward: Near-instant updates (maximum speed)
  • --log: Save output to timestamped log file

Examples:

# Simulate evening to morning at 60x speed
sunsetr --simulate "2025-01-15 18:00:00" "2025-01-16 08:00:00" 60

# Fast-forward through time window
sunsetr --simulate "2025-01-15 18:00:00" "2025-01-16 08:00:00" --fast-forward

# Save output to log file
sunsetr --simulate "2025-01-15 18:00:00" "2025-01-16 08:00:00" 60 --log
# Creates: sunsetr-simulation-20250115-232140.log

Behavior:

  • Simulates runtime during specified time window
  • Faithfully reproduces actual behavior including temperature/gamma updates
  • Shows all logging and state transitions
  • Respects active preset and custom config directory

Use for:

  • Testing geo calculations for specific dates
  • Verifying transition timing
  • Debugging time-dependent behavior
  • Generating logs for bug reports

Note: At higher multipliers, actual time may exceed theoretical time due to system overhead.

Advanced Features

This section covers advanced features for power users, including various IPC integrations and using custom configuration directories.

Features

Next Steps

IPC Integration

Sunsetr provides a Unix socket-based IPC (Inter-Process Communication) system for real-time state monitoring and external integrations. The easiest way to interact with IPC is through the status command.

IPC Socket Location

The IPC socket is created at:

$XDG_RUNTIME_DIR/sunsetr-events.sock

Typically this resolves to:

/run/user/1000/sunsetr-events.sock

Event Types

The IPC socket broadcasts three types of events:

1. StateApplied:

Sent when temperature/gamma values are applied to the display.

JSON format:

{
  "active_preset": "default",
  "period": "sunset",
  "state": "transitioning",
  "progress": 0.4637135,
  "current_temp": 5016,
  "current_gamma": 95.36286,
  "target_temp": 3300,
  "target_gamma": 90.0,
  "next_period": "2025-11-11T17:49:25.000679991-06:00"
}

2. PeriodChanged:

Sent when transitioning between periods (Day ↔ Sunset ↔ Night ↔ Sunrise).

Available periods:

  • day - Stable day period
  • sunset - Transitioning from day to night
  • night - Stable night period
  • sunrise - Transitioning from night to day
  • static - Static mode (no transitions)

3. PresetChanged:

Sent when switching presets.

Includes:

  • New preset name
  • Target temperature and gamma values
  • Target Period

Status Bar Integration

Waybar Example:

Add to ~/.config/waybar/config:

{
  "custom/sunsetr": {
    "exec": "sunsetr status --json --follow | jq --unbuffered --compact-output 'if .event_type == \"preset_changed\" then {text: \"\\(.target_temp)K\", alt: .target_period, tooltip: \"Preset: \\(.to_preset // \"default\")\\nTarget: \\(.target_temp)K @ \\(.target_gamma)%\"} elif .event_type == \"state_applied\" then {text: \"\\(.current_temp)K\", alt: .period, tooltip: \"Period: \\(.period)\\nTemp: \\(.current_temp)K @ \\(.current_gamma)%\"} else empty end'",
    "return-type": "json",
    "format": "{icon} {text}",
    "format-icons": {
      "day": "󰖨",
      "night": "",
      "sunset": "󰖛",
      "sunrise": "󰖜",
      "static": "󰋙"
    },
    "on-click": "sunsetr preset day"
  }
}

Note: This requires that you have a day preset set in your presets directory.

Custom IPC Clients

You can write custom clients that connect to the IPC socket directly.

Python Example

import socket
import json

def monitor_sunsetr():
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.connect("/run/user/1000/sunsetr-events.sock")

    buffer = ""
    try:
        while True:
            data = sock.recv(4096).decode('utf-8')
            buffer += data

            while '\n' in buffer:
                line, buffer = buffer.split('\n', 1)
                if line.strip():
                    event = json.loads(line)
                    event_type = event.get('event_type', 'unknown')

                    if event_type == 'state_applied':
                        period = event.get('period', 'unknown')
                        temp = event.get('current_temp', 0)
                        gamma = event.get('current_gamma', 0)
                        print(f"Period: {period}")
                        print(f"Temp: {temp}K")
                        print(f"Gamma: {gamma}%")
                    elif event_type == 'preset_changed':
                        preset = event.get('to_preset') or 'default'
                        target_period = event.get('target_period', 'unknown')
                        target_temp = event.get('target_temp', 0)
                        target_gamma = event.get('target_gamma', 0)
                        print(f"Preset changed to: {preset}")
                        print(f"Period: {target_period}")
                        print(f"Target: {target_temp}K @ {target_gamma}%")
                    elif event_type == 'period_changed':
                        to_period = event.get('to_period', event.get('period', 'unknown'))
                        from_period = event.get('from_period', 'unknown')
                        print(f"Period: {from_period} → {to_period}")
                    else:
                        # Unknown event type, print full event for debugging
                        print(f"Unknown event: {json.dumps(event, indent=2)}")

                    print("---")
    except KeyboardInterrupt:
        print("\nExiting...")
    finally:
        sock.close()

if __name__ == "__main__":
    monitor_sunsetr()

Bash Example with socat

# Stream IPC events (all events, raw JSON)
socat UNIX-CONNECT:/run/user/1000/sunsetr-events.sock -

# Parse state_applied events with jq
socat UNIX-CONNECT:/run/user/1000/sunsetr-events.sock - | \
    while read -r line; do
        echo "$line" | jq -r 'select(.event_type == "state_applied") | "Period: \(.period) | Temp: \(.current_temp)K"'
    done

Custom Config Directories

Use custom configuration directories for portable setups, testing, or multiple profiles.

Basic Usage

sunsetr --config ~/dotfiles/sunsetr/

Directory Structure

The custom directory must maintain the same structure:

~/dotfiles/sunsetr/
├── sunsetr.toml         # Main configuration
├── geo.toml             # Optional: geographic coordinates
└── presets/             # Optional: presets
    ├── day/
    │   └── sunsetr.toml
    └── gaming/
        └── sunsetr.toml

All Commands Respect Custom Directory

Once started with --config, all subsequent commands use the custom directory:

# Start with custom config
sunsetr --config ~/dotfiles/sunsetr/

# All commands use custom directory
sunsetr preset gaming
sunsetr geo
sunsetr set night_temp=3500
sunsetr status

Note: You don't need to specify --config for subsequent commands during the same session.

Use Cases

Portable Configuration:

# Keep config with dotfiles
~/dotfiles/
└── sunsetr/
    ├── sunsetr.toml
    └── presets/
# Use from dotfiles
sunsetr --config ~/dotfiles/sunsetr/

Testing Configuration:

# Create test config
mkdir -p ~/test-sunsetr
cp ~/.config/sunsetr/sunsetr.toml ~/test-sunsetr/

# Test without affecting main config
sunsetr --config ~/test-sunsetr/

Multiple Profiles:

# Work profile
sunsetr --config ~/configs/sunsetr-work/

# Home profile
sunsetr --config ~/configs/sunsetr-home/

# Travel profile
sunsetr --config ~/configs/sunsetr-travel/

Simulation with Custom Config:

sunsetr --config ~/test-config/ \
    --simulate "2025-01-15 18:00:00" "2025-01-16 08:00:00" 60

Configuration Precedence

When using custom directories:

  1. Custom directory files take precedence
  2. Default directory is never read
  3. All operations affect custom directory only

Lock Files and IPC

Custom directories create separate lock files and IPC sockets:

# Default instance
$XDG_RUNTIME_DIR/sunsetr/sunsetr.lock
$XDG_RUNTIME_DIR/sunsetr/ipc.sock

# Custom instance (hashed path)
$XDG_RUNTIME_DIR/sunsetr/sunsetr-<hash>.lock
$XDG_RUNTIME_DIR/sunsetr/ipc-<hash>.sock

This allows multiple instances with different config directories to run simultaneously.

Troubleshooting

This guide covers common issues and their solutions. If you encounter a problem not listed here, please open an issue on GitHub.

Sunsetr won't start hyprsunset

  • Ensure hyprsunset is installed and accessible if you're attempting to use sunsetr as a controller
  • Make sure hyprsunset is not already running
  • Be sure you're running on Hyprland
  • Try using the Hyprland backend instead and consider removing hyprsunset as a dependancy.

Smooth transitions aren't smooth

  • Ensure smoothing = true in config
  • Try different startup_duration and shutdown_duration settings for smoother transitions
  • Adjust adaptive_interval for extended durations
  • Check that no other color temperature tools are running

Display doesn't change

  • If using the Hyprsunset backend, verify hyprsunset works independently: hyprctl hyprsunset temperature 4000
  • Check configuration file syntax
  • Look for error messages in terminal output, follow their recommendations
  • Use "wayland" as your backend (even on Hyprland)

Still Having Issues?

If none of these solutions work:

  1. Search existing issues: GitHub Issues
  2. Open a new issue: Include debug output and system information

When reporting, please include:

  • Sunsetr version
  • Operating system and version
  • Compositor and version
  • Configuration file (redacted if needed)
  • Debug output
  • Steps to reproduce

Changelog

v0.11.0

  • Process Management Commands: New status, stop, and restart commands
    • status command displays current runtime state with JSON output support
    • stop command cleanly terminates running instances with verification
    • restart command recreates backend with clean stop-wait-start sequence
  • Background Operation: New --background flag for daemon-like operation
  • Extended Gamma Range: Gamma now supports 10-200% (previously 10-100%) for enhanced brightness control
  • IPC Foundation: Unix socket-based IPC for real-time state broadcasting to external applications
  • Critical Timing Fixes:
    • Eliminated period transition boundary delays (transitions now occur exactly on time)
    • Fixed time jump handling for NTP sync, sleep/resume, and manual time adjustments
    • Corrected DST boundary handling in status output and transition schedules
    • Fixed geo mode timezone mismatch causing delayed transition updates
  • Reliability Improvements:
    • Session-aware zombie process detection with automatic recovery after logout/reboot
    • Test command instance isolation to prevent concurrent instance conflicts
    • Multiple preset switching fixes and edge case improvements
  • Geographic Data Improvements:
    • Added Asia/Kolkata timezone support (Special thanks @acagastya)
    • Fixed country/coordinate data accuracy (Special thanks @acagastya)
  • Breaking Changes:
    • reload command deprecated and removed (use restart or rely on automatic hot reloading)

v0.10.0

  • Configuration Management Commands: New get and set commands for CLI-based config management
    • get command reads configuration values with JSON output support
    • set command modifies configuration fields with validation and safety features
  • Enhanced Preset System: Improved preset command with subcommands
    • preset active shows the currently active preset
    • preset list displays all available presets
  • Native Hyprland CTM Backend: Experimental Color Transformation Matrix support for Hyprland
  • Comprehensive Help System: Built-in help command with detailed documentation for all features
  • XDG Base Directory Support: Migrated state management to follow XDG specifications
  • Improved Error Handling: Consistent error severity levels and better user guidance
  • Interactive Configuration Warnings: Safer configuration editing with preset warnings
  • Enhanced Logger: Colored severity levels and cleaner output formatting
  • Bug Fixes:
    • Fixed config directory handling with --config flag
    • Resolved smooth transition issues during reload for Hyprland

v0.9.0

  • Static Mode: New transition mode for maintaining constant temperature/gamma values
  • Preset Management System: Quick switching between configuration profiles with sunsetr preset
  • Hot Configuration Reloading: Automatic detection and application of config file changes
  • Custom Config Directories: Support for portable configurations with --config flag
  • Enhanced Smooth Transitions: Configurable startup/shutdown durations with adaptive algorithm
  • Improved D-Bus Handling: Better recovery from system sleep/resume cycles
  • Configuration Refactoring: Modular config system with better organization and validation
  • CLI Architecture Improvements: Subcommand-based CLI with backward compatibility

v0.8.0

  • D-Bus Sleep/Resume Detection: Automatically resumes from sleep using systemd-recommended D-Bus approach
  • No Root Scripts: Sleep/resume detection now runs entirely in user space via D-Bus
  • Nix Flake Support: Added official flake.nix with reproducible builds and development shell (Special thanks @scottmckendry)
  • Display Hotplug Detection: Automatically detects and handles monitor connection/disconnection (Special thanks @scottmckendry)

v0.7.0

  • Runtime Simulations: New --simulate command for testing transitions and geo calculations
  • NixOS/Nix Support: Now available in nixpkgs unstable repository (Special thanks @DoctorDalek1963)
  • Enhanced Logging System: Zero-cost abstraction via macros, improved performance and cleaner output formatting
  • Progress Bar Improvements: Extracted reusable progress bar component with new EMA smoothing
  • Geo Module Refactoring: Improved transition time calculations, fixed nanosecond precision timing bugs

v0.6.0

  • Privacy-Focused Geo Configuration: New optional geo.toml file for privately storing coordinates separately from main config
  • Smoother Startup Transitions: New Bézier curve for startup transitions and new minimum of 1 second startup_transition_duration

v0.5.0

  • Geographic Location Support: Complete implementation of location-based sunrise/sunset calculations
  • Interactive City Selection: Fuzzy search interface with 10,000+ cities worldwide (sunsetr geo)
  • Automatic Location Detection: Smart timezone-based coordinate detection with 466 timezone mappings
  • Enhanced Transitions: Fine-tuned sun elevation angles and Bézier curves for more natural transitions
  • Extreme Latitude Handling: Robust polar region support with seasonal awareness
  • Comprehensive Timezone System: Multiple detection methods with intelligent fallbacks
  • Geographic Debug Mode: Detailed solar calculation information for location verification
  • Timezone Precision: Automatic timezone determination from coordinates for accurate times
  • Default Geo Mode: New installations use geographic mode by default for optimal experience
  • Live Reload Command: New reload flag to reload configuration without restarting
  • Interactive Testing: New test command for trying different temperature/gamma values
  • Signal-Based Architecture: Improved process communication for reload and test commands

Version History

For the complete version history with all minor releases and patches, see the GitHub Releases page.