Stasis

Integration

Live Events

stasis watch prints the current state immediately, then writes another JSON object only when the state, pause status, or active profile changes. Any program that can keep a process open and read lines can use it instead of polling stasis info.

stasis watch
# {"state":"waiting","paused":false,"manually_paused":false,"profile":"default"}
# {"state":"manual","paused":true,"manually_paused":true,"profile":"work"}

Each line includes state, paused, manually_paused, and profile. The state is one of waiting, active, inhibited, locked, or manual.

Blame

stasis blame explains why an idle action is held. It names active manual and system pauses, matched applications and media, suspend-only blockers, live D-Bus inhibit cookies or portal request handles, and login1 idle holds. Use stasis blame --json for a versioned snapshot that scripts can parse.

stasis blame
stasis blame --json

The JSON form uses schema_version 1. Categories include app_inhibitors, media_inhibitors, suspend_app_inhibitors, and suspend_media_inhibitors. Live D-Bus and login1 holds are listed separately.

{
  "schema_version": 1,
  "generated_at_ms": 1750000000000,
  "progression_blocked": true,
  "manual_pause": false,
  "system_pause": false,
  "browser_source_capture": false,
  "app_inhibitors": { "active": false, "count": 0, "sources": [] },
  "media_inhibitors": { "active": false, "count": 0, "sources": [] },
  "suspend_app_inhibitors": { "active": false, "count": 0, "sources": [] },
  "suspend_media_inhibitors": { "active": false, "count": 0, "sources": [] },
  "dbus_holds": [],
  "login1_idle_holds": [
    {
      "status": "live",
      "what": "idle",
      "who": "codex",
      "why": "Codex is running an active turn",
      "mode": "block",
      "uid": 1000,
      "pid": 42,
      "process": "codex",
      "started_at_ms": 1749999996500,
      "age_ms": 3500
    }
  ]
}

Status JSON

stasis info --json is the stable status-bar contract. The text field uses short labels: waiting, active, inhibited, locked, and manual.

The alt and class fields are intended for icon mapping and CSS styling. Tooltips include the active profile, plan source, state, manual pause status, app/media inhibitor counts, D-Bus inhibit state, login1 idle inhibitors that are blocking suspend, and the next pending action when available. When one or more login1 idle holds are present, stasis info --json also includes a login1_idle_inhibitors array.

{
  "text": "active",
  "alt": "idle_active",
  "class": "idle_active",
  "tooltip": "Profile: default\nPlan Source: Desktop\nState: active",
  "profile": "default"
}

Waybar

Example Custom Module

To use Stasis with Waybar, define a custom module that polls stasis info --json.

Icon-based Display

"custom/stasis": {
  "exec": "stasis info --json",
  "format": "{icon}",
  "format-icons": {
    "idle_active": "",
    "idle_waiting": "",
    "idle_inhibited": "",
    "manually_inhibited": "",
    "locked": "",
    "not_running": "󰒲"
  },
  "tooltip": true,
  "on-click": "stasis toggle-inhibit",
  "interval": 2,
  "restart-interval": 2,
  "return-type": "json"
}

Text-based Display

Or display text instead of icons:

"custom/stasis": {
  "exec": "stasis info --json",
  "format": "{text}",
  "tooltip": true,
  "on-click": "stasis toggle-inhibit",
  "interval": 2,
  "restart-interval": 2,
  "return-type": "json"
}

System Tray

stasis tray runs the optional StatusNotifier tray frontend. It is separate from the headless daemon and does not replace stasis info --json, so Waybar and other status bars can keep polling the JSON output directly.

The tray tooltip shows the current Stasis state. Its menu provides actions to toggle manual inhibition, pause, resume, reload the config, and quit only the tray process. Only one tray instance is allowed per desktop session; additional launches exit cleanly. The shell title is Stasis. The menu includes a disabled status row so hosts such as Waybar still show the current state, including Stasis paused (manually).

Tray host required

Start a StatusNotifier tray host first, such as Waybar's tray module, KDE Plasma, or another panel with tray support. The daemon remains headless and does not launch the tray automatically.

Run Manually

stasis tray

Systemd User Service

Run the daemon and tray as separate user services. Packages may already install this optional service file as stasis-tray.service.

[Unit]
Description=Stasis System Tray Frontend
PartOf=graphical-session.target
After=graphical-session.target stasis.service
ConditionPathExists=%t

[Service]
Type=simple
ExecStart=/usr/bin/stasis tray
Restart=on-failure
RestartSec=2

[Install]
WantedBy=graphical-session.target

NixOS and Home Manager users can enable the tray through the module option services.stasis.tray.enable.