Repository navigation
Modes and Routines
Your desktop, set up for what you're doing — and put back when you're done. Modes are named setups (Work, Gaming, Theater, Sleep…) that apply a bundle of settings while they're on and revert them when they end. Routines are small if-this-then-that automations that watch for a condition and act on it. Both come from the same idea Samsung ships as Modes and Routines, rebuilt for the shell: one manager, one engine, and conditions drawn from everything the shell already knows about your machine.
Press Super + Y to open the manager. Nothing is automatic until you say so: the built-in modes ship with automatic start off, and every routine has its own enable switch.
- Open the manager with Super + Y (or the Modes quick toggle in the right sidebar, or the bar pill once a mode is on).
- Pick a mode on the left — the presets are already there — and look at the right pane: If is what starts it, Then is what it does.
- Start it with the big button in the header. Your settings change; a brief banner says so. Start a different mode and the first one ends first: modes are exclusive.
- Turn it off from the same button, the bar pill (right-click), or the sidebar toggle. Everything it touched goes back to how it was.
- Want it automatic? Flip the switch on the If section and add a condition — a schedule, an app, a game, the battery, a Wi-Fi network, a monitor, a Bluetooth device, the phone, the weather… The mode starts when the condition holds and ends when it stops holding.
- Routines live in the second tab. Start from a template (preview it first, then Add to my routines) or build one from scratch.
A mode is a name, an icon, a colour, a set of conditions (optional) and a set of actions.
Grouped the way the Add condition menu groups them:
| Group | Condition | Holds when… |
|---|---|---|
| Time | Schedule | The clock is inside a time window, on the chosen weekdays. Either end can be sunrise or sunset (from the weather service) instead of a fixed time |
| Time | Calendar event | An event is on right now, optionally one whose title matches |
| Time | Pomodoro | A Pomodoro is running — in focus, on a break, or either |
| Windows | App | A window of the given class — or whose title contains a text — is running, or focused |
| Windows | Game | A game is running, or focused (see Game detection below) |
| Windows | Fullscreen window | The focused window is fullscreen |
| Windows | Workspace | A named or numbered workspace — or a special one — is focused |
| You | Away from the keyboard | No input for N seconds (optionally ignoring idle inhibitors) |
| You | Screen locked | The lock screen is up (or down) |
| You | Mic, camera or screen in use | Something is recording the microphone, the camera, or sharing the screen |
| You | Discord voice | A Discord voice call is going on |
| You | Media playing | Something is playing, optionally a given player |
| System | Battery | Below / above a level, plugged in, or on battery |
| System | Monitors | A named monitor is connected, or at least N are |
| System | Lid | The laptop lid is closed (or open) |
| System | CPU, GPU, memory or disk | A resource is above or below a level (with a little hysteresis) |
| System | Keyboard layout | The active layout has the given code |
| System | Updates | At least N package updates are pending |
| Connectivity | Wi-Fi | Connected (optionally to specific networks), or wired |
| Connectivity | Bluetooth | A device (or specific devices) is connected |
| Connectivity | VPN or Tailscale | The tunnel is up (or down) |
| Connectivity | Audio device | The default output or input matches a name — "headphone", say |
| Connectivity | Phone | The KDE Connect phone is reachable (or out of reach), optionally under a battery level |
| Outside | Weather | The current weather is of a kind (rain, snow, clear…), or the temperature is above / below a value |
| Automation | Mode active | A given mode (or any mode) is on — routines only |
A mode can require any or all of its conditions. Every condition unfolds to two switches:
- Invert — "when Zoom is not running" is one flip away.
- For at least — the condition only counts once it has held without a break for that long: "idle for 10 minutes", "in a game for 5 minutes", "Work on for 50 minutes". The row shows Counting while the clock runs.
Grouped the way the Add action menu groups them:
- Notifications — Do Not Disturb, auto-DND while fullscreen
- Display — Night Light and its warmth, dark/light mode, brightness (focused monitor or all), screen shader, keyboard backlight, wallpaper, OLED saver (black out all or the focused monitor), hide the desktop widgets
- Sound — volume and mute, microphone mute, output and input device, one app's volume or mute, the media player's volume, play/pause, skip track, mono audio, EasyEffects, earbuds noise control (normal / transparency / noise cancelling), system sounds, play a sound file
- Power — keep awake, power profile
- Session — lock the screen, screens off, suspend
- Hyprland — window-rule presets and raw options, Game Mode, bar auto-hide and dock visibility, go to a workspace (optionally back at the end) or move the focused window there
- Input — keyboard layout, touch gestures
- Apps — launch an app or command (optionally closing it when the mode ends), close apps by class, open a URL, apply a Workspace Profile
- Tools — start or stop the Pomodoro
- Connectivity — Wi-Fi, Bluetooth, VPN, Tailscale, encrypted DNS, ping or ring the phone (KDE Connect)
- Timing — a Wait step (see below)
- Advanced — a shell command (with a separate one for the end)
Actions that set something remember what was there and put it back at the end. A few are one-shots (launching something, a shell command, a ping) and either have their own "when it ends" counterpart or simply nothing to undo. The output/input device and app-volume actions look their target up again when they run, so a headset that was re-plugged in the meantime is still found; if it isn't there, the action is skipped and says so in Activity.
Actions run top to bottom — drag a row by its handle to reorder. Two things slow the list down on purpose:
- Delay (in each action's unfolded row) — the action runs that long after the step above it, and everything below waits with it.
- Wait (an action of its own, under Timing) — a plain pause between two steps.
"Sleep: Night Light now, screens off after 10 minutes" is Night Light → Wait 10 min → Screens off. A pending step survives a shell reload and is dropped if the mode or routine ends first; the Then header sums the whole sequence up ("5 settings applied, in this order, over 10 min").
-
By hand — the header button, the list row, the bar pill, the sidebar toggle, a touch gesture, or
qs -c ii ipc call modes toggleMode <id>. - Automatically — when the mode's conditions hold and its automatic switch is on. Modes are listed in priority order (drag to reorder): when two want to start at once, the higher one wins.
- Ending automatically — once the conditions stop holding for a grace period (20 s by default) so an alt-tab doesn't flap it. A mode you stopped by hand while its conditions still hold stays off until they reset.
- Reverting — by default a setting you changed yourself while the mode was on is left alone at the end; Strict restore reverts those too.
Sleep, Work, Focus, Gaming, Theater, Presentation and Relax are added on first run. They're ordinary modes afterwards — rename, recolour, gut or delete them. Settings → Modes & Routines → Restore missing presets brings back any you deleted without touching the rest.
Where a mode is a state you're in, a routine is a reaction. Same If / Then editor, two extra choices:
- Type — While conditions hold (applies its actions, then puts them back when the conditions stop — a tiny mode that can run alongside a real one) or When conditions become true (fires once, leaves things as they are, optionally with a cooldown).
-
Moments — a When conditions become true routine can also fire on an event rather than a state: a notification arrives (optionally from a given app or containing a text), an alarm rings, a Pomodoro lap ends (focus, break or either), or a shortcut is pressed — a Hyprland global shortcut named
quickshell:modes-<name>, bound withhl.bind("SUPER + SHIFT + R", hl.dsp.global("quickshell:modes-<name>")). These sit in the Moments group of the menu and are greyed out for while routines and modes, which need a state to hold. - Options — whether to show a banner, and for while routines whether to put settings back at all; each action can opt out of the put-back with its own Undo at end switch.
Routines get three actions modes don't: notify (a desktop notification), mode (start or stop a mode) and routine (run or stop another routine). The editor hides targets that would loop back to the routine being edited, and a stored loop shows a red Loops back pill with the chain.
Routines aren't exclusive — any number can run at once. Running ones show up in the bar pill's popup and the sidebar dialog with a stop button each.
Under the routine list, collapsed by default. Click one to preview it in the right pane exactly as it would look in the editor, then Add to my routines. Adding makes a copy you can edit; the template stays.
| Template | Does |
|---|---|
| Battery saver below 20 % | Power-saver profile and 40 % brightness while under 20 % on battery; put back when charging |
| Focus when headphones connect | Starts the Focus mode when the output switches to headphones |
| Pause media on lock | Pauses whatever is playing the moment the screen locks |
| Mute mic when Zoom closes | Mutes the microphone once the last Zoom window is gone |
| Performance profile while a game runs | Performance power profile for as long as a game is running |
| Quiet while the mic is in use | Do Not Disturb and paused media for as long as something records the microphone |
| Lock when the phone is out of reach | Locks the screen once the KDE Connect phone has been unreachable for 2 minutes |
| Break reminder after 50 min of Work | A notification once the Work mode has been on for 50 minutes |
| Suspend when locked for 30 min on battery | Suspends after half an hour on the lock screen while unplugged |
The third tab. Every start, end and run, grouped by day, with why — "Started by schedule", "Ended: conditions no longer hold", "Replaced by Gaming", "Stopped by hand". Entries whose actions couldn't all be applied carry a skipped pill that unfolds to one line per action with the reason. Filters for modes, routines and skipped actions; Clear forgets the lot. The newest 200 entries are kept.
- Bar — a pill with the mode's icon and name in its colour. Takes no room while nothing is on. Hover for details and the running routines; left-click opens the manager, right-click ends the mode. It's a normal bar widget (Mode indicator) — existing layouts get it added hidden, so turn it on in the bar layout editor or from the Modes & Routines settings page.
- Banner — a brief "Work on · by schedule" when a mode starts or ends: in the Dynamic Island when a notch is on, otherwise a small top-centre pill. Can be turned off.
- Lock screen — a read-only pill in the toolbar.
- Sidebar — the Modes quick toggle (Android and classic panels): click toggles the last-used mode, the menu side opens a picker with every mode and the running routines.
The Game condition (and the Gaming preset) rely on the shell recognising a game. Four signals, all on by default, all in Settings → Modes & Routines → Game detection:
- Windows launched by Steam, Heroic, Lutris, Bottles, Prism Launcher, and fullscreen Windows executables
- Apps whose desktop entry is in the Game category
- Your own always-a-game list of window classes (pick from the windows open right now)
- A fullscreen window keeping the GPU busy — above a threshold for a hold time (45 % for 20 s by default). This also catches a fullscreen GPU-decoded video; raise the threshold if that bites.
The settings page shows what's detected right now and why.
Settings → Modes & Routines (under Tools) holds the options around the definitions: automatic starts on/off, whether the manager overlay is loaded, presets, the bar and lock-screen pills, the banner, the grace period, game detection, and clearing the activity log. It also warns if Hyprland has no binding for the manager.
The definitions themselves are saved in config.json under modes (modes.modes and modes.routines), so a config backup carries them. What's running and the activity log are runtime state in states.json, restored after a restart — a mode survives a shell reload.
modes.enable automatic starts and ends (manual use always works)
modes.overlayEnabled load the manager window
modes.flash "auto" banner, or "off"
modes.lockPill pill on the lock screen
modes.graceSec seconds conditions must stay false before an automatic end
modes.game.* detection signals, GPU threshold and hold time, extraClasses
qs -c ii ipc call modes status # what's on, since when, why
qs -c ii ipc call modes list # modes with their ids
qs -c ii ipc call modes toggleMode work
qs -c ii ipc call modes activate gaming
qs -c ii ipc call modes deactivate
qs -c ii ipc call modes triggers work # each condition and whether it holds (and "for" timers)
qs -c ii ipc call modes actions # every action type, its group and whether it is available here
qs -c ii ipc call modes routines
qs -c ii ipc call modes runRoutine <id>
qs -c ii ipc call modes history
qs -c ii ipc call modes toggle # the manager window| Piece | Role |
|---|---|
services/Modes.qml |
The engine: definitions, watchers, start/end, revert snapshots, history, IPC |
services/modes/ModeSchema.js |
Normalisation, presets, templates, loop detection |
services/modes/ModeActions.qml |
The action registry — read, apply, revert for every action |
services/modes/ModeWatcher.qml, conditions/
|
One watcher per mode/routine, one condition type per file |
services/GameDetector.qml |
The four game signals |
modules/ii/modes/ |
The manager: tabs, lists, editors, templates, activity |
modules/ii/modeFlashPopup/, dynamicIsland/widgets/FloatingNotchMode.qml
|
The start/end banner |
bar/widgets/indicators/ModeIndicator.qml |
The bar pill |
sidebarDashboard/modes/ + the quick toggles |
The sidebar side |
settings/configs/ModesConfig.qml |
The settings page |
Things the engine routes around on purpose: a Hyprland config write triggers a burst of reloads, so Hyprland options are batched and never re-applied on reload; Bluetooth is rfkill-unblocked before being powered on; definitions are written 300 ms after the last edit so the config's own reload can't clobber a fast second change.
- Sidebar Dashboard — the quick toggle and dialog
- Bar & Dynamic Island — the pill and the banner
- System Integration — the services the actions drive
- Keybinds — Super + Y