Configuration
Overview
Stasis uses a .rune configuration file. It first looks for $XDG_CONFIG_HOME/stasis/stasis.rune (typically ~/.config/stasis/stasis.rune).
For system-wide configuration, copy the example to /etc/stasis/stasis.rune.
On first run, Stasis generates a default configuration at ~/.config/stasis/stasis.rune.
The master reference config is located at /usr/share/doc/stasis/stasis.rune.
Globals (Variables)
The top level is intended for reusable values. Define timers and strings once, then reference them inside default: and profiles.
@author "Your Name"
@description "Stasis configuration"
# Top-level is intended for reusable values.
lock_after 300
screen_off_after 300
suspend_after 1800
debounce_seconds 4
notify_seconds 5Default Block
Your config must contain a default: block. Most settings live under this block.
Action blocks defined directly under default: form the desktop plan. On laptops,
the ac: and battery: sub-blocks are used instead (see AC & Battery).
default:
enable_loginctl_integration false
enable_dbus_inhibit true
pre_suspend_command None
#prepare_sleep_command "hyprlock"
#low_power_when_idle false
#low_power_when_idle_timeout 10
monitor_media true
ignore_remote_media true
# Optional: ignore these media sources (case-insensitive)
#media_blacklist ["spotify"]
debounce_seconds debounce_seconds
# Lid actions (laptop only — live here so they apply to both ac: and battery:)
lid_close_action "hyprlock"
#lid_open_action ""
notify_on_unpause true
# Global gate: per-step notifications only fire if this is true
notify_before_action true
notification_icon "stasis"
inhibit_apps [
r"steam_app_.*"
]
startup:
timeout 0
command "notify-send 'Stasis idle manager started!'"
end
lock_screen:
timeout lock_after
command "hyprlock"
resume_command "notify-send 'Welcome back $env.USER!'"
notification "Locking soon"
#notification_icon "dialog-warning"
notify_seconds_before notify_seconds
end
dpms:
timeout screen_off_after
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
suspend:
timeout suspend_after
command "systemctl suspend"
end
endStartup Action
The startup: block runs once when Stasis starts (always first):
startup:
timeout 0
command "notify-send 'Stasis idle manager started!'"
endlogin1 Sleep/Wake Integration
Set enable_loginctl_integration true to monitor login1 PrepareForSleep transitions. This enables sleep/wake handling, including prepare_sleep_command; it does not select the screen-lock tracking method.
# Enable login1 PrepareForSleep monitoring
enable_loginctl_integration trueLockedHint property through systemd-logind or eLogind. A positive hint becomes
authoritative for that lock episode until the real unlock.Foreground lockers remain compatible through process-lifetime tracking. Service-backed lockers such
as Veila work through LockedHint, so their short-lived client may exit safely after the
session is confirmed locked.
A locker that forks into the background without publishing LockedHint should be run in
the foreground. login1 Lock and Unlock signals are requests rather than
completed state, so a loginctl lock-session wrapper is not a reliable substitute.
Session D-Bus Inhibit Integration
Keep session-bus inhibit handling enabled so desktop/session requests (including portal inhibits) are honored correctly:
# Enable session-bus inhibit tracking (recommended)
enable_dbus_inhibit trueniri-session, dbus-run-session, or your compositor's recommended launcher)
so session D-Bus features are available.Pre-Suspend Command
Optionally run a command immediately before suspending — useful to ensure the screen is locked before the system sleeps:
# Run before suspending (e.g. ensure screen is locked first)
# pre_suspend_command is BLOCKING — use your locker's fork flag if it has one,
# or wrap it with the daemonize utility.
pre_suspend_command "swaylock -f" # swaylock has a built-in fork flag
#pre_suspend_command "daemonize hyprlock" # hyprlock doesn't, use daemonize
# Disable:
pre_suspend_command Nonepre_suspend_command is blocking — Stasis waits for it to exit before suspending, so if you pass a locker directly it will wait until you unlock before ever suspending. Use your locker's fork flag if it has one (e.g. swaylock -f), or wrap it with the daemonize utility. If your plan already has a lock_screen: step, you generally don't need pre_suspend_command at all.# pre_suspend_command is BLOCKING — Stasis waits for it to finish before suspending.
# Use your locker's fork flag if it has one, or wrap with daemonize:
pre_suspend_command "swaylock -f" # swaylock: built-in fork flag
#pre_suspend_command "daemonize hyprlock" # hyprlock: no fork flag, use daemonize
suspend:
timeout 1800
command "systemctl suspend"
end
# If you already lock as a plan step, prefer this instead:
#pre_suspend_command NonePrepare Sleep Command
Use prepare_sleep_command when you need a command to run as soon as logind announces
an external sleep transition. This is different from pre_suspend_command, which only runs
before Stasis's own suspend: step.
# Run immediately when logind emits PrepareForSleep(true).
# This covers external sleep events such as lid-triggered sleep or systemctl suspend.
prepare_sleep_command "hyprlock"
# Disable or clear inherited value:
prepare_sleep_command ""Low-Power Mode
Enable low_power_when_idle to apply conservative GPU power saving after the DPMS
step fires. Stasis snapshots every setting it changes and restores the original values on activity,
unlock, lid open, profile changes, reload, or shutdown.
# Enter low-power mode 10 seconds after the DPMS step
low_power_when_idle true
low_power_when_idle_timeout 10stasis report today or stasis report week to review recorded display-off, low-power, and suspend time.Media Monitoring
Media Playback
Control whether Stasis monitors media playback to prevent idle actions:
monitor_media true
ignore_remote_media truemonitor_media— active playback prevents idle timeoutsignore_remote_media— ignores remote sources (Spotify remote, KDEConnect, etc.)
Media Blacklist
Ignore specific media sources (case-insensitive):
media_blacklist ["spotify", "rhythmbox"]Inhibitors
Application Inhibitors
Specify apps/processes that prevent idle actions while running (strings or regex literals):
inhibit_apps [
"vlc"
"Spotify"
"mpv"
r".*\.exe"
r"steam_app_.*"
r"firefox.*"
]- Use raw string syntax:
r"pattern" - Escape special characters:
\.for literal dots - Use
.*for wildcards - Use
^and$for anchors
Notifications
On Unpause
Notify when resuming from an IPC pause (e.g., stasis pause for 1h):
notify_on_unpause truePre-Action
To show notifications before actions run:
- Enable the gate:
notify_before_action true - Optionally set a default:
notify_seconds_before - Set
notification "message"on the action block - Optionally override timing per-block with
notify_seconds_before
notify_before_action true
notify_seconds_before 5Notification Icons
Stasis 1.3.0 passes an icon to notify-send for generated notifications.
Packaged installs provide the default stasis icon, and you can override or clear it globally.
# Global default for Stasis-generated notifications.
# Packaged installs provide the "stasis" icon.
notification_icon "stasis"
# Use another icon name or an absolute file path:
notification_icon "dialog-warning"
# Disable the default icon entirely:
notification_icon ""Individual action blocks can override the global icon:
lock_screen:
timeout 300
command "hyprlock"
notification "Locking session in 10s"
notification_icon "dialog-warning"
notify_seconds_before 10
endLaptop Settings
Lid Actions
Configure what happens when the laptop lid closes or opens. These live directly under default: so they automatically apply to both ac: and battery: plans without duplication. Lid close/open also pause/resume the plan
timers regardless. A profile can override or clear them.
# Lives under default: so it applies to both ac: and battery: plans.
# A profile can override or clear these.
lid_close_action "hyprlock"
lid_open_action "brightnessctl set 60%"
# Clear an action entirely:
lid_open_action ""Debounce
Prevent rapid lid open/close events from triggering multiple actions:
debounce_seconds 4Idle Actions
Each action block supports:
timeout— seconds of idle time before triggering (required);0runs immediately on plan activationcommand— command to run (required; useNoneto disable)resume_command/resume-command— optional, run when activity resumesnotification— optional message shown before the action runsnotification_icon— optional icon name or path for this action's notificationnotify_seconds_before— optional per-block timing override
startuplock_screen/lock-screenearly_dpms— useful for a shorter initial screen-off before the main lockdpmsbrightnesssuspend*— custom actions can be named anything
AC & Battery
Laptop plans live as sub-blocks inside default: (or inside a profile).
When running on a laptop chassis, Stasis uses ac: or battery: depending
on current power state — the desktop plan blocks are ignored. Globals and lid actions defined
directly under default: still apply to both plans.
AC Plan
default:
# ...globals, lid actions, desktop plan...
ac:
# timeout 0 runs immediately when AC becomes active
custom_brightness_instant:
timeout 0
command "brightnessctl set 100%"
end
brightness:
timeout 120
command "brightnessctl set 30%"
end
dpms:
timeout 60
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
lock_screen:
timeout 120
command "hyprlock"
notification "Locking on AC in 10s"
notify_seconds_before 10
end
suspend:
timeout 300
command "systemctl suspend"
end
end
endBattery Plan
default:
# ...globals, lid actions, desktop plan...
battery:
custom_brightness_instant:
timeout 0
command "brightnessctl set 40%"
end
brightness:
timeout 60
command "brightnessctl set 20%"
end
dpms:
timeout 30
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
lock_screen:
timeout 120
command "hyprlock"
resume_command "notify-send 'Welcome back $env.USER!'"
end
suspend:
timeout 120
command "systemctl suspend"
end
end
end- Put
timeout 0actions first — they run immediately when the plan activates (e.g., restore brightness on plug-in). - Profiles can also define their own
ac:/battery:sub-blocks to override the laptop plan per-profile.
Full Example
Complete example covering desktop plan, laptop AC/battery plans, notification icons, sleep hooks,
and both profile modes (overlay and fresh):
# This file was auto-generated by Stasis on first run
# Feel free to customize it to your needs
# Master config reference: /usr/share/doc/stasis/stasis.rune
@author "Dustin Pilgrim"
@description "Lightweight feature packed idle manager for Wayland"
# Top-level: reusable values (recommended)
lock_after 300
screen_off_after 300
suspend_after 1800
debounce_seconds 4
notify_seconds 5
default:
enable_loginctl_integration false
enable_dbus_inhibit true
pre_suspend_command None
#prepare_sleep_command "hyprlock"
monitor_media true
ignore_remote_media true # ignore remote players (spotify/kdeconnect/etc.)
# Optional: ignore these media sources for media inhibit (case-insensitive)
#media_blacklist ["spotify"]
debounce_seconds debounce_seconds
# Lid actions (laptop only — live here so they apply to both ac: and battery:)
lid_close_action "hyprlock"
#lid_open_action ""
# Notify when resuming from IPC pause (e.g. `stasis pause 1h`)
notify_on_unpause true
# Enables per-step notifications (only if the block sets `notification`)
notify_before_action true
# Icon name/path for Stasis-generated notifications. Defaults to "stasis".
# Set to "" to disable the default icon, or override per step with
# notification_icon.
notification_icon "stasis"
inhibit_apps [
"mpv"
"vlc"
"Spotify"
r".*\.exe"
r"steam_app_.*"
r"firefox.*"
]
# ----------------------------------------------------------------
# DESKTOP PLAN (used only on desktop chassis)
# ----------------------------------------------------------------
startup:
timeout 0
command "notify-send -a Stasis 'Stasis started!'"
end
early_dpms:
timeout 300
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
lock_screen:
timeout lock_after
command "hyprlock"
resume_command "notify-send 'Welcome back $env.USER!'"
notification "Locking session in 10s"
notification_icon "dialog-warning"
notify_seconds_before 10
end
dpms:
timeout screen_off_after
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
suspend:
timeout suspend_after
command "systemctl suspend"
end
# ----------------------------------------------------------------
# LAPTOP PLANS (used only on laptop chassis — ac: or battery:)
# Desktop plan blocks above are ignored for laptops.
# ----------------------------------------------------------------
ac:
# timeout 0 runs immediately when AC becomes active
custom_brightness_instant:
timeout 0
command "brightnessctl set 100%"
end
brightness:
timeout 120
command "brightnessctl set 30%"
end
dpms:
timeout 60
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
lock_screen:
timeout 120
command "hyprlock"
notification "Locking on AC in 10s"
notify_seconds_before 10
end
suspend:
timeout 300
command "systemctl suspend"
end
end
battery:
custom_brightness_instant:
timeout 0
command "brightnessctl set 40%"
end
brightness:
timeout 60
command "brightnessctl set 20%"
end
dpms:
timeout 30
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
lock_screen:
timeout 120
command "hyprlock"
resume_command "notify-send 'Welcome back $env.USER!'"
end
suspend:
timeout 120
command "systemctl suspend"
end
end
end
# --------------------------------------------------------------------
# PROFILES
#
# mode "overlay": merges on top of the active base (default/ac/battery)
# mode "fresh": starts from nothing — define every global and action block you want
# --------------------------------------------------------------------
# gaming: overlay — only replace inhibit_apps
gaming:
mode "overlay"
inhibit_apps [
r".*\.exe"
r"steam_app_.*"
r".*\.x86_64"
]
end
# work: overlay — longer timeouts, login1 sleep/wake monitoring enabled
work:
mode "overlay"
enable_loginctl_integration true
enable_dbus_inhibit true
debounce_seconds 10
monitor_media true
ignore_remote_media true
lock_screen:
timeout 600
command "hyprlock"
resume_command "notify-send 'Welcome back, $env.USER!'"
end
dpms:
timeout 300
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
suspend:
timeout 3600
command "systemctl suspend"
end
end
# presentation: fresh — keep display on, suppress all idle actions
presentation:
mode "fresh"
pre_suspend_command None
enable_dbus_inhibit true
monitor_media false
ignore_remote_media true
debounce_seconds 0
notify_on_unpause false
notify_before_action false
inhibit_apps [ ]
lid_close_action ""
lid_open_action ""
brightness:
timeout 0
command "brightnessctl set 100%"
end
end
# Profile switching (runtime IPC):
# stasis profile gaming
# stasis profile work
# stasis profile presentation
# stasis profile default (or: stasis profile none)Profiles
Profiles are any top-level named blocks other than default. They override settings
and action blocks from the active base plan, and can define their own ac:/battery: plans.
"overlay"(default) — merges on top of the active base; only what you specify is overridden"fresh"— starts from nothing; you must define every global and action block you want
# Any top-level named block besides `default:` is a profile.
# Profiles override settings/steps from the active base and can
# have their own `ac:` / `battery:` plans.
gaming:
mode "overlay" # merges on top of active base
# Replace the inherited inhibit_apps list:
inhibit_apps [
r".*\.exe"
r"steam_app_.*"
r".*\.x86_64"
]
end
work:
mode "overlay"
enable_loginctl_integration true
debounce_seconds 10
monitor_media true
ignore_remote_media true
lock_screen:
timeout 600
command "hyprlock"
resume_command "notify-send 'Welcome back, $env.USER!'"
end
dpms:
timeout 300
command "hyprctl dispatch dpms off"
resume_command "hyprctl dispatch dpms on"
end
suspend:
timeout 3600
command "systemctl suspend"
end
end
presentation:
mode "fresh" # starts from NOTHING — define every global and step you want
pre_suspend_command None
monitor_media false
ignore_remote_media true
debounce_seconds 0
notify_on_unpause false
notify_before_action false
inhibit_apps [ ]
# Clear lid actions so they don't fire during a presentation
lid_close_action ""
lid_open_action ""
# Keep display on; no lock/dpms/suspend unless you add them
brightness:
timeout 0
command "brightnessctl set 100%"
end
endProfiles are switched at runtime via IPC:
# Switch profiles at runtime via IPC:
stasis profile gaming
stasis profile work
stasis profile presentation
# Return to default (no profile):
stasis profile default
# (alias)
stasis profile none