CLI reference
niri-computer-use serve | status | stop | resume | recover | engine | guard <server-pid> | paste-keeper | --versionIt takes exactly one subcommand, or --version, and no other options. Anything else prints that usage line to stderr and exits 1. Every subcommand works on the niri instance in NIRI_SOCKET, or, without it, the one running niri of yours the server finds. A niri bind passes NIRI_SOCKET on.
niri-computer-use serveSpeaks MCP over stdin and stdout until the client closes stdin. Your MCP client runs it; see Client setup. Stdout carries only MCP messages. It reads its environment once at startup (see Configuration) and, unless it hands the client to the shared engine, starts the crash guardian before anything else.
status
Section titled “status”niri-computer-use statusPrints the readiness report as JSON and exits 0, whatever the report says. It is the same report as the status tool, except that niri.event_stream is null, because the subcommand opens no event stream, and lease.held_by_me is false. The fields are described under status.
It asks niri for its version and outputs, logind for the lock state and, when it finds noctalia, Noctalia for its status. It changes nothing.
niri-computer-use stopSets the stop flag for this niri instance, prints nothing and exits 0. A running action is cancelled: it ends with stopped, or uncertain once what it sent may have taken effect (see Safety). The lease holder gives the lease up, and acquire_desktop and every action refuse with stopped until resume. Bind it to a key: see First session.
It never connects to niri, so it works while niri hangs. Without NIRI_SOCKET, it takes the one socket in the runtime directory that niri names, owned by you, whose PID is a running niri, without checking that this niri still listens on it. It fails, exiting 1, when there is no such socket or several, when niri’s socket doesn’t resolve to a socket of yours, with no hard link, in a directory only you can use, or when the flag can’t be written.
resume
Section titled “resume”niri-computer-use resumeClears the stop flag, prints nothing and exits 0, also when no flag was set. It finds niri’s socket the way stop does. It refuses while the input-dirty marker exists, and doesn’t clear it; recover does.
recover
Section titled “recover”niri-computer-use recoverClears the input-dirty marker that blocks every action with recovery_required. It takes the lease while it works, so it fails while a server holds it:
niri-computer-use: a server holds the lease: PID … (…); end that agent or its server firstWithout a marker it prints No input-dirty marker: nothing to recover. and exits 0. With one, it prints the marker, then, depending on what the marker names:
- held pointer buttons: sends their release from a fresh virtual pointer, or, if it can’t, asks you to press and release each of them
- native keys: sends their release and zero modifiers from a fresh virtual keyboard, which also makes niri send the compositor’s keymap again. The modifiers go out in the layout niri has active; if niri doesn’t say which that is, they go out in the layout the call started in, and
recoversays the focused application may show another layout until the next key - none of these, or a marker it can’t read, such as one an older version wrote: nothing to release, so only the check below
Then it asks you to check by hand:
Check that no input is held: press and release Shift, Ctrl, Alt and Super, click once in an empty area, and check the application the input went to.Is all input released? Type yes to confirm:Only yes clears the marker, and it prints:
Marker cleared. `niri-computer-use resume` clears the stop flag if it is set.Any other answer exits 1 with not confirmed; the marker stays.
--version
Section titled “--version”niri-computer-use --versionPrints niri-computer-use and the version, such as niri-computer-use 0.1.0, and exits 0. It reads nothing from the session.
Internal subcommands
Section titled “Internal subcommands”You don’t run these yourself.
engineis the shared engineservestarts in shared mode when its niri instance has none. It serves every shared-mode client of the instance overengine.sockin the runtime directory, writes its errors toengine.logthere, and exits two seconds after its last connection, lease and pending input cleanup have ended. A bridge passes it--unscoped <reason>when it couldn’t start the engine in a scope of its own, and--runtime-dir-discoveredwhen it foundXDG_RUNTIME_DIRitself; both only change whatstatusreports.guard <server-pid>is the crash guardian a standaloneserveor the shared engine starts. It waits for that server to end, and if the server’s marker names native keys or pointer buttons it still held, releases them at once. As it starts, it does the same for a marker a dead server left that nothing released.paste-keeperis the clipboard keeper a paste throughtype_textstarts. It holds the pasted text on the clipboard, then puts the saved clipboard back.
Exit status and errors
Section titled “Exit status and errors”Every subcommand exits 0 on success and 1 on failure, printing niri-computer-use: <message> to stderr.