⚠️ STASYS - STABLE FORK This is Stasys - a stable fork of Stasis v0.7.0, maintained to preserve brightness restoration and stable media detection. Why this fork exists: Upstream v0.8+ removed automatic brightness restoration and introduced media detection instability. Goal: Keep v0.7.0 stability with selective bug fixes from later versions.
A modern Wayland idle manager that knows when to step back.
Stable Fork of Stasis v0.7.0 • Preserving brightness restoration and stable media detection
Features • Installation • Quick Start • Compositor Support • Configuration • Profiles
Stasys doesn't just lock your screen after a timer—it understands context. Watching a video? Reading a document? Playing music? Stasys detects these scenarios and intelligently manages idle behavior.
- 🧠 Smart idle detection with configurable timeouts
- 🎵 Media-aware idle handling – automatically detects media playback
- 🚫 Application-specific inhibitors – prevent idle when specific apps are running
- ⏸️ Idle inhibitor respect – honors Wayland idle inhibitor protocols
- 🛌 Lid events via DBus – detect laptop lid open/close events
- ⚙️ Flexible action system – supports named action blocks and custom commands
- 🔍 Regex pattern matching – powerful app filtering with regular expressions
- 📝 Clean configuration – uses the intuitive RUNE configuration language
- ⚡ Live reload – update configuration without restarting the daemon
- 💡 Automatic brightness restoration – captures and restores brightness on resume
- Download the appropriate archive from Releases
- Extract
stasysbinary somewhere in your $PATH (ex. .local/bin) - Adjust systemd service accordingly or add
stasysto your DE’s startup menu
Build and install manually:
# Clone and build
git clone https://github.com/Alanon202/stasys
cd stasys
cargo build --release --locked
# Install system-wide
sudo install -Dm755 target/release/stasys /usr/local/bin/stasys
# Or install to user directory
install -Dm755 target/release/stasys ~/.local/bin/stasysA systemd user service file is provided in systemd/stasys.service. Copy it to your systemd user directory:
mkdir -p ~/.config/systemd/user
cp systemd/stasys.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now stasys.serviceEdit the service file if you installed stasys to a different location than /usr/local/bin/stasys.
Stasys requires access to input devices and brightness controls:
sudo usermod -aG input,video $USERLog out and back in for group changes to take effect.
On first run, Stasys automatically generates a default configuration at ~/.config/stasys/stasys.rune. You can also create it manually:
mkdir -p ~/.config/stasys
cp examples/stasys.rune ~/.config/stasys/stasys.runeEdit the configuration to your needs.
# Start the daemon
stasys daemon
# Or use systemd (recommended)
systemctl --user start stasysstasys infoStasys integrates with each compositor's native IPC protocol for optimal app detection and inhibition.
| Compositor | Support Status | Notes |
|---|---|---|
| Niri | ✅ Full Support | Tested and working perfectly |
| Hyprland | ✅ Full Support | Native IPC integration |
| labwc | Process-based fallback | |
| River | Process-based fallback |
Both River and labwc have IPC protocol limitations:
- Limited window enumeration – Can't get complete window lists via IPC
- Fallback mode – Uses process-based detection (sysinfo) for app inhibition
- Pattern adjustments – Executable names may differ from app IDs
💡 Tip: When using River or labwc, include both exact executable names and flexible regex patterns in your
inhibit_appsconfiguration.
Stasys uses RUNE—a purpose-built configuration language.
- User config:
~/.config/stasys/stasys.rune - System config:
/etc/stasys/stasys.rune - Logs:
~/.cache/stasys/stasys.log
stasis:
pre_suspend_command "hyprlock"
monitor_media true
ignore_remote_media true
respect_idle_inhibitors true
# Laptop lid events
lid_close_action "lock-screen"
lid_open_action "wake"
# Desktop idle actions
lock_screen:
timeout 300 # 5 minutes
command "loginctl lock-session"
resume-command "notify-send 'Welcome Back!'"
lock-command "swaylock"
end
dpms:
timeout 60 # 1 minute
command "niri msg action power-off-monitors"
resume-command "niri msg action power-on-monitors"
end
suspend:
timeout 1800 # 30 minutes
command "systemctl suspend"
end
end
# Show current state
stasys info
# Trigger action manually
stasys trigger lock-screen
# Pause idle detection
stasys pause for 1h
stasys resume
# Toggle idle inhibition (Waybar-friendly)
stasys toggle-inhibit
# Reload config
stasys reload
# View recent logs
stasys dump 50
# Stop daemon
stasys stopProfiles let you switch between different configurations for different scenarios (work, gaming, presentations, etc.).
- Each profile is a standalone config file in
~/.config/stasys/profiles/ - Switching profiles completely replaces your current config
- Actions not defined in a profile are disabled during that profile, unless your system provides fallbacks
- Profile state persists across restarts
- Create a profiles directory in
~/.config/stasys/profiles - Create a profile (e.g., work.rune) manually or use one of the examples in the repo
# List available profiles
stasys profile list
# Switch to a profile
stasys profile work
# Return to base config
stasys profile none
# Check current profile
stasys infoThree example profiles are included in examples/profiles/:
| Profile | Purpose | Key Changes |
|---|---|---|
| work.rune | Office work | Longer timeouts, video call apps inhibited |
| gaming.rune | Gaming | Gaming apps inhibited, no brightness auto-dim |
| presentation.rune | Presentations | No idle, max brightness, inhibitors disabled |
Add profile switching to your Waybar module:
"custom/stasys": {
"exec": "stasys info --json",
"format": "{icon}",
"format-icons": {
"idle_active": "",
"idle_inhibited": "",
"manually_inhibited": "",
"not_running": ""
},
"tooltip": true,
"on-click": "stasys toggle-inhibit",
"on-click-right": "stasys profile cycle",
"on-click-middle": "stasys info",
"interval": 2,
"return-type": "json"
}Profile cycling: Right-click cycles through: none → work → gaming → presentation → none...
Alternatively, you can simply use one fallback profile and invoke it directly, i.e. "stasys profile work"
Create a script for custom profile cycling:
#!/bin/bash
# ~/.local/bin/stasys-profile-cycle
PROFILES=("none" "work" "gaming" "presentation")
CURRENT=$(cat ~/.config/stasys/active_profile 2>/dev/null || echo "none")
# Find current index
for i in "${!PROFILES[@]}"; do
if [[ "${PROFILES[$i]}" == "$CURRENT" ]]; then
NEXT="${PROFILES[$(( (i + 1) % ${#PROFILES[@]} ))]}"
stasys profile "$NEXT"
notify-send "Stasys Profile" "Switched to: $NEXT"
exit 0
fi
done
# Fallback
stasys profile noneMake it executable and update Waybar:
chmod +x ~/.local/bin/stasys-profile-cycle"custom/stasys": {
"on-click-right": "~/.local/bin/stasys-profile-cycle"
}Contributions are welcome! Here's how you can help:
- 🐛 Report bugs – Open an issue with reproduction steps
- 💡 Suggest features – Share your use cases and ideas
- 🔧 Submit PRs – Fix bugs, add features, or improve code
- 📖 Improve docs – Better explanations, examples, and guides
Released under the MIT License – free to use, modify, and distribute.
Built with ❤️ for the Wayland community
Keeping your session in perfect balance between active and idle
