Skip to content

hypridle

hypridle is Hyprland’s idle management daemon.

Configuration

Configuration is done via the config file at ~/.config/hypr/hypridle.conf. A config file is required; hypridle won’t run without one.

To run hypridle at startup, add hypridle to your autostart commands in your Hyprland config.

General

Variables in the general category:

VariableDescriptionTypeDefault
lock_cmdcommand to run when receiving a D-Bus lock event (e.g., loginctl lock-session)string[[Empty]]
unlock_cmdcommand to run when receiving a D-Bus unlock event (e.g., loginctl unlock-session)string[[Empty]]
on_lock_cmdcommand to run when the session gets locked by a lock screen appstring[[Empty]]
on_unlock_cmdcommand to run when the session gets unlocked by a lock screen appstring[[Empty]]
before_sleep_cmdcommand to run when receiving a D-Bus prepare_sleep eventstring[[Empty]]
after_sleep_cmdcommand to run when receiving a D-Bus post prepare_sleep eventstring[[Empty]]
ignore_dbus_inhibitwhether to ignore D-Bus idle inhibit events (e.g., from firefox)boolfalse
ignore_systemd_inhibitwhether to ignore systemd-inhibit --what=idle inhibitorsboolfalse
ignore_wayland_inhibitwhether to ignore Wayland protocol idle inhibitorsboolfalse
inhibit_sleepsleep inhibition mode:
0: disable
1: normal
2: auto
3: lock notify
int2

Note

The general:inhibit_sleep option is used to make sure hypridle can perform certain tasks before the system goes to sleep.

Options:

  • 0 disables sleep inhibition.
  • 1 makes the system wait until hypridle launched general:before_sleep_cmd.
  • 2 (auto) selects either 3 or 1 depending on whether hypridle detects if you want to launch hyprlock before sleep.
  • 3 makes your system wait until the session gets locked by a lock screen app. This works with all Wayland session-lock apps.

Listeners

Hypridle uses listeners to define actions on idleness.

Every listener has a timeout (in seconds). After idling for timeout seconds, on-timeout will fire. When action is resumed after idle, on-resume will fire.

You can define as many listeners as you want.

Example listener
listener {
    timeout = 500                            # in seconds.
    on-timeout = notify-send "You are idle!" # command to run when timeout has passed.
    on-resume = notify-send "Welcome back!"  # command to run when activity is detected after timeout has fired.
}

Variables in the listener category:

VariableDescriptionTypeDefault
timeoutIdle time in secondsintnone, value must be specified
on-timeoutCommand to run when timeout has passedstring[[Empty]]
on-resumeCommand to run when activity is detected after timeout has firedstring[[Empty]]
ignore_inhibitIgnore idle inhibitors (of all types) for this ruleboolfalse
condition_cmdCommand run when the timeout is reached, before on-timeout. Run via /bin/sh -c; exit code 0 lets on-timeout fire, non-zero defers itstring[[Empty]]
condition_retryWhen condition_cmd defers, re-run it every N seconds while the user stays idle, firing on-timeout as soon as it succeeds. 0 disables retrying (the deferred on-timeout is skipped for this idle cycle)int0

Conditional timeouts

A listener can gate its on-timeout on external state with condition_cmd. When the timeout is reached, hypridle runs condition_cmd first; on-timeout fires only if it exits 0. A non-zero exit defers on-timeout.

Set condition_retry to keep re-checking while the user stays idle: hypridle re-runs condition_cmd every condition_retry seconds and fires on-timeout the moment it succeeds. With condition_retry = 0 (the default), a deferred on-timeout is simply skipped until the next idle cycle. Any user activity resets the listener and cancels a pending retry.

Note

condition_cmd runs synchronously on hypridle’s event loop, so keep it fast — a script that blocks holds up idle handling. Retry timing is checked on hypridle’s ~5s event-loop tick, so very small condition_retry values are effectively rounded up to that granularity.

Examples

Don’t suspend while an SSH session is connected:

listener {
    timeout = 900                                          # 15min.
    on-timeout = systemctl suspend                         # suspend pc.
    condition_cmd = ~/.config/hypr/scripts/can-suspend.sh  # exit 0 = suspend, non-zero = stay awake.
    condition_retry = 30                                   # re-check every 30s while still idle.
}
~/.config/hypr/scripts/can-suspend.sh
#!/bin/sh
ss -tn state established '( sport = :ssh )' | grep -q . && exit 1
exit 0

Full hypridle example with hyprlock:

~/.config/hypr/hypridle.conf
general {
    lock_cmd = pidof hyprlock || hyprlock                                    # avoid starting multiple hyprlock instances.
    before_sleep_cmd = loginctl lock-session                                 # lock before suspend.
    after_sleep_cmd = hyprctl dispatch 'hl.dsp.dpms({ action = "enable" })'  # to avoid having to press a key twice to turn on the display.
}

listener {
    timeout = 150                         # 2.5min.
    on-timeout = brightnessctl -s set 10  # set monitor backlight to minimum, avoid 0 on OLED monitor.
    on-resume = brightnessctl -r          # monitor backlight restore.
}

# turn off keyboard backlight, comment out this section if you dont have a keyboard backlight.
listener {
    timeout = 150                                           # 2.5min.
    on-timeout = brightnessctl -sd rgb:kbd_backlight set 0  # turn off keyboard backlight.
    on-resume = brightnessctl -rd rgb:kbd_backlight         # turn on keyboard backlight.
}

listener {
    timeout = 300                       # 5min
    on-timeout = loginctl lock-session  # lock screen when timeout has passed
}

listener {
    timeout = 330                                                                          # 5.5min
    on-timeout = hyprctl dispatch 'hl.dsp.dpms({ action = "disable" })'                    # screen off when timeout has passed
    on-resume = hyprctl dispatch 'hl.dsp.dpms({ action = "enable" })' && brightnessctl -r  # screen on when activity is detected after timeout has fired.
}

listener {
    timeout = 1800                  # 30min
    on-timeout = systemctl suspend  # suspend pc
}

Fading the keyboard backlight

brightnessctl sets brightness instantly, so a plain on-timeout/on-resume pair turns the keyboard backlight off and on abruptly. hypr-kbd-backlight-fade is a small script that steps through intermediate brightness values instead, fading in fast and out slowly, with a lock file so overlapping in/out calls (e.g., quick touch-then-idle cycles) don’t race each other.

Note that video players and browsers commonly hold a Wayland idle-inhibit lock during video playback (not just fullscreen), which pauses every listener, not just screen lock/suspend. If you want the keyboard backlight to keep responding to real input while a video plays, set ignore_inhibit = true on that listener specifically, rather than on general:ignore_wayland_inhibit which would disable inhibit-awareness for every listener.

Locking on suspend and hibernate

The session is locked before going to sleep, not after resuming. Every route into sleep goes through logind’s PrepareForSleep signal — systemctl suspend, systemctl hibernate, systemctl suspend-then-hibernate, a listener with on-timeout = systemctl suspend, or closing the laptop lid with logind’s HandleLidSwitch. general:before_sleep_cmd therefore fires for all of them, including sleeps that hypridle did not initiate itself.

~/.config/hypr/hypridle.conf
general {
    lock_cmd = pidof hyprlock || hyprlock     # run when the session is asked to lock.
    before_sleep_cmd = loginctl lock-session  # ask for the lock before sleeping.
}

before_sleep_cmd does not start the locker itself. loginctl lock-session only emits logind’s Lock signal for the session; hypridle picks it up and runs general:lock_cmd. Keeping the two apart means the locker is named in exactly one place, and a manual loginctl lock-session — from a keybind, for example — takes the same path as sleeping does.

Lid handling belongs to logind, not to Hyprland; see the warning about HandleLidSwitch. No extra bind is needed to lock on lid close: logind emits PrepareForSleep for that path too.

hypridle does not choose between suspend and hibernate, it only runs the command you give it. systemctl hibernate needs a working resume device, and systemctl suspend-then-hibernate suspends first and hibernates after HibernateDelaySec, set in /etc/systemd/sleep.conf.d/.

Waiting for the lock to be drawn

loginctl lock-session returns as soon as the signal has been sent, long before the locker has drawn anything. Without inhibition the system can freeze in that gap, and the frame that shows up on resume is the unlocked desktop, until the locker finally appears on top of it.

general:inhibit_sleep exists for this: hypridle takes a delay sleep inhibitor from logind and releases it once its before-sleep handling is done. What “done” means differs per mode:

  • 1 releases the inhibitor as soon as before_sleep_cmd has been spawned, which is not enough for loginctl lock-session.
  • 3 releases it only once the session is really locked, as reported over the hyprland-lock-notify-v1 protocol.
  • 2 (the default) picks 3 only when it recognizes hyprlock, that is when before_sleep_cmd contains hyprlock, or when lock_cmd contains hyprlock and before_sleep_cmd contains lock-session. It falls back to 1 otherwise.

With any other lock screen app, set inhibit_sleep = 3 explicitly. Prefer that over padding before_sleep_cmd with a sleep: the inhibitor waits for the lock event itself instead of for a guess. Which mode was picked is printed at startup, as Sleep inhibition enabled - inhibiting until the wayland session gets locked.

Note

The session counts as locked once the lock surface is up, which can be before the locker has finished fading in. If a translucent lock screen still shows through on resume, disable the fade-in as well (hypridle#146). With hyprlock, start it as hyprlock --no-fade-in, or turn off its animations entirely.

Last updated on