Architecture
These drawings follow the code. The full account, module by module, is docs/architecture.md in the repository.
Processes
Section titled “Processes”Your agent starts niri-computer-use serve over stdio, one per session. By default every serve on one niri relays to a single engine, and starts that engine when none is running. With shared = false or NIRI_COMPUTER_USE_SHARED=0, serve runs the engine itself. The engine holds the lease and talks to niri, the accessibility bus and Noctalia. It runs grim, notify-send and loginctl through one runner, each with a deadline. The crash guardian is the same binary watching the engine: if the engine dies while its virtual pointer or keyboard holds a button or key, the guardian sends the release.
scroll sideways for the rest →
The lease, the stop flag and the input-dirty marker are files in a directory beside niri’s socket. Every server on the same niri sees the same files, in either mode.
One action
Section titled “One action”Looking needs no lease. Every action passes the same gate first, under the action mutex, so one server’s actions run one at a time. A refusal at the gate is an error, and nothing was sent. Once the request is on its way, a stop can’t take it back: the result is uncertain, with accepted true if niri answered and null if it didn’t. Otherwise the result has accepted, observed, changes when niri saw something change, and a screenshot when the agent asked for one or the outcome is in doubt. Every call writes one line to the audit log, refusals included.
scroll sideways for the rest →
The drawing follows a niri action such as focus. Keys and text go to the server’s own virtual keyboard, clicks to a virtual pointer, and element actions to the app over the accessibility bus, all behind the same gate.
Lease, stop and recovery
Section titled “Lease, stop and recovery”scroll sideways for the rest →
acquire_desktop locks the lease file before it asks anything slow, so an agent on another server gets lease_held at once. Another session of the same engine waits until the first acquire_desktop is done, which with confirm_lease can take up to a minute, and then gets lease_held, or the lease if the first was refused. With confirm_lease on, a notification asks you to Allow or Deny before the lease is granted. niri-computer-use stop sets the stop flag: the running action is cancelled and the lease is taken back. resume clears the flag, except while the input-dirty marker says a key or button may be stuck. Then recover releases what the marker names and asks you to check before it clears the marker.
Coordinates
Section titled “Coordinates”A click names a pixel of a screenshot, by its screenshot_ref, or an element from elements. Each space is its own type in the code, so a pixel can’t be passed where a layout point is expected. Before anything moves, the server maps the final point back through niri’s own formula and refuses it if it lands more than 0.002 logical pixels away.
scroll sideways for the rest →
A screenshot ref expires after 60 seconds, when niri’s event stream reconnects, or when its output’s position, size, scale or transform changes. An element ref is checked against the app again each time it is used, and the pointer aims at one only while its window is floating and in view.