Borrow the Contract, Not the Daemon
A review of Stasis changed Glimpse's idle design, but the useful part was its state machine and control contract, not another daemon to install.
I studied Stasis while designing idle management for Glimpse and came away wanting much of its interface but not its process model. The useful artifact was the contract: observable state, explicit actions, and a small control surface. Running a second daemon would have split ownership of the same desktop behavior.
This was a design review, not a compatibility claim. I reviewed Stasis 1.4.0 at commit a0aff93 in July 2026. Its current repository may have moved on, so the version matters.
The interface made the state machine visible
Stasis exposed a compact set of operations through its CLI. A client could watch a JSON event stream, pause or resume idle handling, switch profiles, and trigger actions. Internally, the shape was roughly event to state to action to service.
That is a much better boundary than asking every panel widget to infer what an idle daemon might be doing. A widget needs an answer to concrete questions: Is idle handling active? Which profile is selected? Is something inhibiting it? What action will occur next? It should not reconstruct those answers from timers and process lists.
The implementation also mixed event-driven and periodic inputs. Wayland activity could arrive through a file descriptor, while application inhibitors, media state, and socket availability were checked on their own intervals. That combination is ordinary in desktop software. The important part was that the polling stayed behind one state-producing service instead of leaking into every consumer.
Stasis still documents 0 and explicit control commands, which is a good example of a daemon treating observability as part of its API rather than an afterthought.
Two daemons would create ambiguous ownership
Glimpse already has a service layer that owns desktop state and publishes snapshots to its interfaces. Adding Stasis as a required runtime would leave two plausible authorities for idle configuration: the Glimpse service graph and the Stasis process.
That ambiguity appears quickly. If a user changes a Glimpse profile, does Glimpse translate it into a Stasis profile? If Stasis is restarted independently, which process restores the intended state? If both expose inhibition, which one explains why the screen stayed awake? An adapter can answer those questions, but the adapter becomes a second state machine whose job is keeping two state machines aligned.
I kept one owner and borrowed the parts that made the other system comprehensible:
- Publish a stable snapshot instead of exposing internal timers.
- Represent pause, resume, profile changes, and manual triggers as commands.
- Give clients a stream so they do not poll the daemon.
- Keep platform-specific sources behind the service boundary.
This also leaves room for an optional Stasis adapter later. Compatibility becomes a translation at the edge, not a foundational dependency.
Reading code can produce a better dependency decision
The first question in this kind of review is often, "Can we integrate it?" The better question is, "Which responsibility does it own unusually well?" Sometimes the answer is a parser, protocol, or library worth importing. Here it was a behavioral contract worth reproducing.
Every resident process in a small desktop environment adds configuration, startup ordering, failure reporting, packaging, and upgrade behavior. A mature daemon can still be the wrong dependency when the host application already owns the same state.
Glimpse did not need Stasis running beside it to learn from Stasis. It needed the clear idea underneath it: idle management is a service with observable state and explicit commands, not a collection of timers scattered through panel widgets.