hypruse

Uso de computadora para Hyprland: servidor MCP que brinda a los agentes de IA control nativo sobre tu escritorio Wayland.

Documentación

hypruse

Uso de computadora para Hyprland. Un servidor MCP que brinda a los agentes de IA control nativo sobre tu escritorio Wayland: espacios de trabajo, ventanas, mouse, teclado, capturas de pantalla.

Sin demonio ydotool. Sin root. Sin portales. Sin X11.

Claude reading the desktop over IPC, switching to btop on another workspace, and reporting back

Por qué

El uso de computadora existe en macOS y Windows, y las aplicaciones Linux de los proveedores aún se envían sin él: la documentación de Linux de Claude Desktop dice que el uso de computadora no está disponible allí, y el uso de computadora de ChatGPT solo cubre macOS y Windows. La implementación de referencia de Anthropic es un contenedor X11. Otras herramientas de Wayland dependen de ydotool y uinput, de portales solo para GNOME, o de un plugin de compositor construido para una versión exacta de Hyprland.

Mientras tanto, Hyprland ya expone todo lo que un agente necesita, mejor que cualquier puente de accesibilidad: una superficie IPC completa para el estado y la gestión de ventanas, y protocolos Wayland de primera clase para la entrada. hypruse solo los conecta a MCP:

  • Semántico primero. desktop devuelve el árbol real de ventanas/espacios de trabajo (direcciones, clases, títulos, geometría) en una sola llamada. El agente cambia de espacio de trabajo y enfoca ventanas como lo haces tú (al instante, a través de IPC), no mirando píxeles.
  • Visión cuando importa. Capturas de pantalla de un monitor, una ventana (con grim 1.5+ en Hyprland 0.54+, capturada como tal incluso en un espacio de trabajo oculto o debajo de otra ventana, aunque una aplicación oculta puede mostrar cómo se veía la última vez), o una región ampliada, con los metadatos de geometría/escala para mapear cualquier píxel a una coordenada clicable: un bucle de grueso a fino fundamentado en la investigación de agentes GUI.
  • Entrada nativa. Los clics y desplazamientos se hablan directamente a través del cable Wayland (zwlr_virtual_pointer_v1); la escritura pasa por el teclado virtual de wtype con un mapa de teclas XKB adecuado, seguro para Unicode en cualquier distribución.

Cómo funciona

agent (Claude Code, or any MCP client)
   │ stdio
   ▼
hypruse
   ├── hyprctl -j ········▶ desktop state: monitors, workspaces, windows, layers
   ├── hyprctl dispatch ··▶ focus / move / close / launch / movecursor
   ├── grim ··············▶ screenshots: monitor, window, region
   ├── busctl (AT-SPI) ···▶ accessibility tree: named controls, current
   │                        values, exact coords (ui / marks / click_ui)
   ├── wtype ·············▶ keyboard (zwp_virtual_keyboard_v1, real XKB keymap)
   └── raw Wayland wire ··▶ click & scroll (zwlr_virtual_pointer_v1)

Los binarios opcionales controlan dos herramientas más: imagemagick dibuja la superposición numerada para marks, y wl-clipboard respalda la herramienta opcional clipboard.

Decisiones de diseño:

  • Sin ydotool / uinput. Ese camino necesita un demonio, reglas de udev o root, y escribe scancodes de EE. UU. que se rompen en otras distribuciones. hypruse es solo otro cliente Wayland de tu compositor, con el mismo estatus que wlrctl.
  • Sin portales. xdg-desktop-portal-hyprland no implementa el portal RemoteDesktop (InputCapture es captura, no inyección), por lo que cualquier cosa construida sobre libei/portales se degrada silenciosamente en Hyprland. hypruse no lo intenta.
  • Posicionamiento del cursor a través del despachador de cursor del propio compositor (coordenadas lógicas globales, exactas en cualquier diseño de monitor), con solo eventos de botón/eje en el puntero virtual, evitando los errores conocidos de múltiples monitores del movimiento absoluto del puntero virtual (hyprwm/Hyprland#6749).

Herramientas

herramientaqué hace
desktopInstantánea semántica en una llamada: monitores, espacios de trabajo, ventanas (dirección/clase/título/geometría), ventana activa, cursor y superficies de capa (lanzadores, barras, ventanas emergentes de notificación) con un tipo y geometría de mejor esfuerzo. Una capa listada es una que el compositor rastrea, no una que puedas ver: las superficies transparentes e inactivas también se informan, así que captura la pantalla cuando la visibilidad importe
screenshotMonitor enfocado, una ventana por dirección (con grim 1.5+ en Hyprland 0.54+, incluso oculta o cubierta; los metadatos visible dicen si el compositor la dibuja, source si los píxeles son de la ventana o un recorte de pantalla, y una captura oculta puede estar desactualizada), o región x,y,WxH; devuelve imagen + metadatos de mapeo de coordenadas; JPEG rápido por defecto (lossless=true para PNG); stable=true espera a que el marco se asiente
zoomRecaptura a resolución nativa alrededor de un punto estimado (opcionalmente limitado a una ventana): el paso de precisión antes de hacer clic en controles pequeños, mismo contrato de metadatos
uiLee el árbol de accesibilidad de una ventana (AT-SPI, aplicaciones GTK/Qt que expongan uno) y devuelve elementos clicables por nombre con coordenadas globales exactas, sin captura de pantalla; también informa valores actuales (texto escrito, posición de control deslizante, estado de casilla); recurre a la visión cuando una aplicación no expone nada
marksCaptura de Marcas de Conjunto: la captura de pantalla de la ventana con cada control accesible dibujado como una marca numerada, más una leyenda JSON (rol, nombre, valor actual, punto de clic exacto por número); necesita ImageMagick para el dibujo, se degrada a solo la leyenda sin él
click_uiHaz clic en un control por NOMBRE accesible o por un número marks en una llamada: la coordenada proviene del árbol, el clic pasa por el puntero real (visible, mismas garantías de seguridad); un nombre ambiguo devuelve los candidatos en lugar de adivinar
pointermover / hacer clic / arrastrar / desplazar (muescas discretas de rueda) en coordenadas globales
keyboardEscribe texto literal (seguro para Unicode) o presiona combinaciones a nivel de aplicación (ctrl+shift+t, esc, F5); la dirección opcional window enfoca el objetivo primero para que las pulsaciones de teclas lleguen a la aplicación correcta. Los enlaces del compositor (super+...) pasan por use_bind, no aquí
hyprCambia de espacio de trabajo, enfoca/mueve/cierra ventanas, pantalla completa, flotante (IPC puro, milisegundos; close_window también espera hasta 1s el evento de destrucción, por lo que su resultado y la observación then= reflejan el cierre en lugar de competir con él)
launchInicia una aplicación (opcionalmente silenciosa en otro espacio de trabajo), bloquea su evento openwindow real, devuelve su dirección; detecta aplicaciones de instancia única (navegadores) cuya ventana ignora las reglas de ejecución y la mueve al espacio de trabajo solicitado
bindsLos atajos de teclado del propio usuario, decodificados (SUPER+Q, acción, descripción); el agente ejecuta uno con use_bind
use_bindEjecuta un atajo de teclado por combinación (SUPER+F), ejecutando su acción vinculada, para que el agente maneje los lanzadores y accesos directos del propietario. No disponible para enlaces en un hyprland.lua Lua: esos son cierres anónimos que Hyprland no expone forma de llamar, por lo que binds los muestra como acción lua y use_bind lo dice en lugar de fallar crípticamente
sequenceEjecuta una lista ordenada de acciones (puntero/teclado/click_ui/hypr/wait_for) en una llamada; se detiene en el momento en que el escritorio cambia de una manera que el paso actual no esperaba, por lo que una micro-secuencia de clic/escribir/entrar cuesta un viaje de ida y vuelta en lugar de varios
wait_forBloquea eventos reales del compositor (apertura/cierre de ventana, cambio de espacio de trabajo, cambio de título, aparición/cierre de superficies de capa, urgencia, uso compartido de pantalla activado/desactivado) con un filtro de coincidencia y tiempo de espera; una espera filtrada cuya condición ya se cumple (ventana ya cerrada, espacio de trabajo ya activo, capa ya mapeada) responde al instante con already: true en lugar de perder un evento que ocurrió antes de suscribirse. Reemplaza dormir-y-esperar en automatizaciones de múltiples pasos
clipboardLee o escribe el portapapeles de texto a través de wl-clipboard; opcional, existe solo con HYPRUSE_CLIPBOARD=1 en el entorno del servidor

Las herramientas de acción (pointer, keyboard, click_ui, hypr, use_bind, sequence) toman un argumento opcional then que agrega el resultado a la misma llamada, para que el agente vea el efecto sin un segundo viaje de ida y vuelta: then='desktop' agrega una instantánea semántica fresca (~20 ms, barata, mejor para cambios de ventana/enfoque), then='screenshot' una captura estable (mejor para cambios visuales), then='ui' los controles de la ventana afectada con sus valores actuales (unos pocos cientos de tokens exactos, mejor después de escribir o alternar; click_ui lee la ventana en la que hizo clic incluso si el clic dio el enfoque a un diálogo, los otros leen la ventana enfocada), then='none' nada (el valor predeterminado en todos lados excepto sequence, que por defecto es 'desktop').

Cada herramienta también es un verbo de shell (hypruse desktop, hypruse click_ui Save --window 0x...) para agentes que ejecutan comandos en lugar de MCP, con una habilidad que les enseña: ver Verbos de shell y la habilidad del agente.

Características

Las herramientas se agrupan en cinco capacidades, ordenadas de más confiable y barata primero. Un agente que las usa en este orden es más rápido y más preciso, y muchas tareas nunca necesitan una captura de pantalla.

1. Control semántico del escritorio (empieza aquí)

desktop devuelve todo el árbol de ventanas y espacios de trabajo en una llamada: la dirección, clase, título y geometría de cada ventana, la ventana activa, el cursor y cualquier superficie de capa que el compositor esté rastreando (lanzadores, barras, ventanas emergentes de notificación). hypr y launch luego actúan sobre él a través de IPC en milisegundos: cambia de espacio de trabajo, enfoca/mueve/cierra/pantalla completa/flota una ventana por dirección, o inicia una aplicación.

Úsalo bien: nunca tomes una captura de pantalla para encontrar o organizar ventanas. Lee desktop, actúa sobre la dirección que quieras. launch bloquea el evento openwindow real y devuelve la dirección de la nueva ventana, por lo que no hay nada que sondear o adivinar; también reubica aplicaciones de instancia única (navegadores) que ignoran las reglas de espacio de trabajo.

2. Haz clic en controles por nombre, sin píxeles

Cuando una aplicación expone un árbol de accesibilidad (la mayoría de las aplicaciones GTK y Qt), puedes apuntar a controles por nombre en lugar de por píxel. ui lista cada control con su coordenada global exacta e informa el valor actual de los controles que llevan uno: el texto en un campo, el porcentaje de un control deslizante, el estado de una casilla. click_ui resuelve un nombre y hace clic en él en una llamada, a través del cursor real (por lo que la baliza y cada garantía de seguridad aún se aplican). marks dibuja marcas numeradas sobre una captura de pantalla con una leyenda, para cuando quieras ver las opciones primero y luego click_ui(mark=N).

Úsalo bien: recurre a click_ui name="Save" antes de estimar cualquier píxel, ya que es exacto y no gasta imagen. Lee el estado de un formulario con ui (¿la casilla realmente se marcó?) en lugar de capturarlo. Un nombre ambiguo devuelve los candidatos en lugar de adivinar. Cuando una aplicación no expone ningún árbol (terminales, aplicaciones de lienzo, Electron/Chrome sin --force-renderer-accessibility) la herramienta lo dice, y recurres a la visión.

3. Visión cuando importa: el bucle de zoom

Para todo lo que el árbol de accesibilidad no puede nombrar, screenshot (monitor, ventana o región) y zoom (una recaptura a resolución nativa alrededor de un punto) llevan un contrato de coordenadas estricto, global = geometry + pixel / scale, que permanece exacto en cada monitor y escala fraccionaria.

Úsalo bien: no adivines un control pequeño desde una imagen de pantalla completa. Trabaja de grueso a fino: captura la ventana, estima el objetivo, zoom allí, re-estima en el recorte nítido, luego haz clic. Este bucle de dos pasos es la forma respaldada por investigación de acertar objetivos pequeños.

4. Menos viajes de ida y vuelta: la palanca de latencia

Para un agente, las llamadas del modelo dominan la latencia de la tarea, no el escritorio, por lo que las aceleraciones reales son estructurales. sequence ejecuta un micro-plan ordenado (clic, escribir, presionar enter, esperar) en una sola llamada, deteniéndose en el momento en que el escritorio cambia estructuralmente de una manera que un paso no pretendía (una ventana abriéndose, cerrándose o moviéndose, un cambio inesperado de espacio de trabajo, o un lanzador que toma asiento o un teclado en pantalla; ignora deliberadamente cambios de enfoque simples y ventanas emergentes de notificación). then='desktop' | 'screenshot' | 'ui' fusiona una vista fresca del resultado en la llamada de acción misma. wait_for bloquea eventos reales del compositor (una ventana o lanzador abriéndose, un título cambiando, un cambio de espacio de trabajo, una pista de urgencia, el uso compartido de pantalla comenzando) en lugar de dormir y esperar.

Úsalo bien: colapsa un flujo conocido de clic/escribir/entrar en un solo sequence. Después de escribir en un formulario, agrega then='ui' para leer el efecto en unos pocos cientos de tokens exactos en lugar de una captura de pantalla. Después de un lanzamiento o un acceso directo que abre algo, wait_for el evento en lugar de dormir.

5. Delegación segura: capas de confianza

hypruse le entrega a un agente tu asiento real, por lo que te da los controles para limitar lo que ese agente puede hacer. Más allá de las indicaciones de aprobación siempre activas y el faro de actividad de Waybar, las variables de entorno opcionales limitan lo que un agente puede tocar: HYPRUSE_READONLY expone solo las herramientas de observación; HYPRUSE_CONFINE restringe la entrada a las ventanas que el agente lanzó, o a una lista de permitidos de clase/espacio de trabajo; HYPRUSE_AUTH_GUARD (activada por defecto) se niega a manejar diálogos de autenticación; HYPRUSE_STRICT se niega a actuar si recuperaste el asiento; HYPRUSE_MARK etiqueta las ventanas propiedad del agente y anuncia cuando el agente abre una ventana o captura la pantalla. Dos más registran en lugar de restringir: HYPRUSE_JOURNAL escribe una línea NDJSON auditable por cada llamada de herramienta, incluidas las denegaciones, y HYPRUSE_DRYRUN ejecuta cada verificación y no entrega nada, para que puedas ver a un agente planificar el trabajo antes de que toque tu escritorio.

Úsalo bien: ejecuta en modo solo lectura durante la primera semana. Cuando confíes en un flujo de trabajo, permite sus herramientas y, si quieres alejarte, confina al agente a un ámbito para que no pueda hacer clic ni escribir en tu gestor de contraseñas en otro espacio de trabajo. Mantén un atajo de pánico a mano (hypruse stop, o pkill -f hypruse). El modelo de seguridad tiene la historia completa.

Verbos de shell y la habilidad del agente

No todos los agentes hablan MCP, y los que lo hacen prefieren cada vez más una línea de comandos: una lista de herramientas cuesta unos pocos miles de tokens por sesión antes de la primera llamada, un verbo de shell no cuesta nada hasta que se ejecuta. Así que las mismas quince herramientas son verbos, que pasan por las mismas funciones que registra el servidor MCP, con las mismas protecciones de confianza, diario y faro de actividad:

hypruse desktop                                  # one line per monitor, workspace, window, layer
hypruse launch --workspace 2 -- firefox --new-window https://example.org
hypruse ui --window 0x55a4479a1200 --name Save   # [0] push button "Save" @1204,88
hypruse click_ui Save --window 0x55a4479a1200 --then ui
hypruse screenshot --window 0x55a4479a1200       # a file path, then {"geometry":[x,y,w,h],"scale":1.0,...}
hypruse zoom 1180 840 --window 0x55a4479a1200
hypruse keyboard type "hello" --window 0x55a4479a1200
hypruse wait_for title_change --match Inbox --timeout 10
hypruse sequence '[{"op":"click_ui","name":"Search","window":"0x55a4479a1200"},{"op":"keyboard","action":"type","text":"btop"},{"op":"keyboard","action":"key","keys":"enter"}]'

El contrato está diseñado para un programa que lee la salida: los verbos son los nombres de las herramientas, el action de una herramienta es un sub-verbo posicional (pointer click 800 60, hypr workspace 3, clipboard read), la salida es texto plano compacto (una línea por dato, --json para el resultado crudo como una línea), una captura imprime su ruta de archivo y metadatos de coordenadas en lugar de bytes, y los errores son una línea en stderr con un código de salida significativo: 0 entregado, 1 error, 2 uso, 3 denegado por una capa de confianza (o por el modo solo lectura), 4 se ejecutó pero no encontró nada sobre lo que actuar (un tiempo de espera de wait_for, sin árbol de accesibilidad, un nombre ambiguo). hypruse --help lista cada verbo y hypruse <verb> --help sus banderas; --dry-run ensaya un verbo de acción. Un verbo comienza en unos pocos cientos de milisegundos: la pila MCP nunca se importa en esa ruta.

Entre procesos de un solo disparo, hypruse mantiene el pequeño estado que un verbo perdería en $XDG_RUNTIME_DIR/hypruse/cli-state.json, claveado por la instancia del compositor: la numeración de marks (para que click_ui --mark N funcione), el conjunto de confinamiento de launched y la línea base del asiento de HYPRUSE_STRICT, que es la que de otro modo fallaría abierta.

La habilidad que enseña a un agente los verbos, el flujo de trabajo centrado en el escritorio y las reglas de seguridad viene dentro del paquete. Instálala en los directorios de habilidades de los agentes de tu máquina (Claude Code, Codex, Pi, Hermes, OpenClaw, OpenCode, Gemini, Antigravity, Cursor, Copilot), o mediante la CLI de skills:

hypruse skill install                # ~/.agents/skills/hypruse, linked into each agent that is installed
hypruse skill install --agent codex  # one agent, created if absent
npx skills add IlyasKhallouki/hypruse -g

hypruse init ofrece la misma instalación. La habilidad pre-aprueba solo los verbos de observación, doctor, --help y la lectura de los archivos de captura; los verbos de acción permanecen detrás de la indicación de aprobación de tu propio agente, que es el límite en el que se apoya el modelo de seguridad.

Instalación

Requisitos: Hyprland (ambos gestores de configuración: hyprland.conf y el Lua hyprland.lua que introdujo 0.56), grim (grim 1.5+ en Hyprland 0.54+ permite que una captura de ventana capture la ventana misma, y hypruse doctor dice si la tuya puede), wtype (la mayoría de las configuraciones de Hyprland ya tienen ambos), y uv. Las herramientas de accesibilidad (ui/marks/click_ui) usan busctl, que viene con systemd. Opcional: wl-clipboard para la herramienta de portapapeles opcional, imagemagick para capturas numeradas de marks.

Arch Linux, desde el AUR:

yay -S hypruse        # or hypruse-git for main

Luego deja que se configure solo y verifica el entorno:

hypruse init     # detects your MCP clients, registers (asks first), offers the agent skill, runs doctor
hypruse doctor   # just the diagnostics

Registro manual, Claude Code:

claude mcp add -s user hypruse -- uvx hypruse

Desde un checkout de fuente:

claude mcp add -s user hypruse -- uv run --directory /path/to/hypruse hypruse

Cualquier otro cliente MCP: ejecuta uvx hypruse como servidor stdio. hypruse también está en el registro oficial de MCP como io.github.IlyasKhallouki/hypruse, por lo que los clientes que navegan por el registro pueden instalarlo desde allí.

Modo solo lectura: establece HYPRUSE_READONLY=1 en la configuración del servidor para exponer solo las herramientas de observación (desktop, screenshot, zoom, ui, marks, binds, wait_for). El agente puede ver y narrar, pero no puede hacer clic, escribir ni lanzar. Una buena primera semana.

Claude Desktop (beta de Linux)

La beta de Linux viene sin el uso de computadora de primera parte de Anthropic, pero los servidores MCP stdio funcionan en el chat, lo que convierte a hypruse en la solución. En ~/.config/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "hypruse": {
      "command": "uvx",
      "args": ["hypruse"],
      "env": { "HYPRUSE_SCREENSHOT_MODE": "image" }
    }
  }
}

Dos notas específicas de Desktop: usa el modo image (Desktop renderiza imágenes MCP en línea y no tiene herramienta de lectura de archivos), y la aplicación debe ejecutarse de forma nativa dentro de tu sesión de Hyprland para que el servidor herede WAYLAND_DISPLAY/HYPRLAND_INSTANCE_SIGNATURE; desde una VM o contenedor no puede alcanzar tu compositor. Si tu instalación de Desktop omite las indicaciones de aprobación de herramientas, trata el indicador de Waybar + atajo de pánico como obligatorio, no opcional.

Modelo de seguridad

Lee esta sección antes de instalar. hypruse le entrega a un agente tu mouse, tu teclado, el contenido de tu pantalla y un lanzador de aplicaciones. Las capas que mantienen eso cuerdo:

  1. Aprobación: los clientes MCP controlan las llamadas de herramientas. En Claude Code, permite las herramientas de solo lectura (desktop, screenshot) y deja pointer/keyboard/hypr/launch en preguntar-primero hasta que confíes en un flujo de trabajo.
  2. Visibilidad: el servidor mantiene un faro de actividad ($XDG_RUNTIME_DIR/hypruse/state.json); el módulo de Waybar incluido es invisible cuando está inactivo y muestra un indicador de robot mientras un agente tiene las manos en tu escritorio.
  3. Interrupción: haz clic en el indicador, o vincula una tecla de pánico. La forma portátil funciona para cada instalación: bind = SUPER SHIFT, BackSpace, exec, pkill -f hypruse. Si hypruse está en tu PATH (el AUR o una instalación pipx), bind = SUPER SHIFT, BackSpace, exec, hypruse stop es mejor: le indica al servidor que se apague de forma ordenada, liberando cualquier botón del puntero sostenido y limpiando el faro. Para una instalación de uvx usa exec, uvx hypruse stop; para un checkout de fuente, exec, uv run --directory /path/to/hypruse hypruse stop. Matarlo a mitad de acción es seguro de cualquier manera: los pares de presionar/soltar botones nunca abarcan llamadas de herramientas, e incluso el botón sostenido de un arrastre largo se libera al salir.
  4. El asiento es compartido. Hay un cursor y un foco de teclado, y el enfoque-sigue-al-mouse de Hyprland significa que un movimiento del cursor solo puede redirigir las pulsaciones de teclas. No escribas mientras un agente está conduciendo; observa el indicador.
  5. Ámbito: solo stdio (sin listener de red), nada persistido excepto el faro y la caché de capturas limitada en $XDG_RUNTIME_DIR (tmpfs, las 20 más recientes) y, si lo activas, el diario de acciones en disco bajo $XDG_STATE_HOME (rotado, una generación, y con texto redactado por defecto). Sin acceso al portapapeles a menos que optes por ello: HYPRUSE_CLIPBOARD=1 registra una herramienta de clipboard (nunca en modo solo lectura); los portapapeles contienen contraseñas, así que déjalo apagado a menos que un flujo de trabajo lo necesite. Una captura ve todo lo visible, y una captura de ventana también alcanza ventanas en espacios de trabajo ocultos, en scratchpads y bajo otras ventanas: trata una sesión de agente como compartir todo tu escritorio. El modo solo lectura y HYPRUSE_CONFINE limitan lo que el agente puede hacer, no lo que puede ver. Las capturas de ventana se rechazan mientras la sesión está bloqueada.
  6. Lo que el agente lee no es confiable. Los títulos de ventanas, nombres y valores de accesibilidad, y el texto del portapapeles fluyen textualmente al contexto del agente, y cualquier página web, nombre de archivo o documento puede poner instrucciones allí (inyección de prompts). hypruse no puede sanear el significado, por lo que la capa de aprobación es el respaldo: mantén las herramientas consecuentes (launch, keyboard, clipboard) en preguntar-primero cuando el agente mire ventanas no confiables, y trata "la pantalla me lo dijo" como entrada de atacante al revisar una indicación de aprobación.
  7. La entrada nunca aterriza donde silenciosamente no funcionaría. Tres verificaciones siempre activas (sin variable de entorno) se niegan o anotan en lugar de reportar un éxito fantasma: un clic dirigido bajo un lanzador o una superficie de capa de teclado en pantalla (que está por encima de las ventanas y lo tragaría), escribir mientras un lanzador mantiene el agarre del teclado, y cualquier entrada mientras la sesión está bloqueada. Una pantalla de bloqueo es un cliente de ext-session-lock, invisible para las listas de ventanas y capas, por lo que hypruse le pregunta a Hyprland mismo (hyprctl locked), que cubre hyprlock, swaylock, el bloqueo integrado de Omarchy y un bloqueador que se bloqueó y dejó la sesión bloqueada. Mientras está bloqueado, pointer y un keyboard sin ventana se niegan a menos que allow_auth=true diga que un humano quiere que el agente maneje la indicación de desbloqueo (nunca bajo HYPRUSE_CONFINE); keyboard con window= y click_ui siempre se niegan, ya que la entrada dirigida a una ventana no puede alcanzarla detrás del bloqueo. Estos son ayudas de veracidad, no una caja de arena: la verificación de bloqueo falla abierta en un estado del sistema ilegible, por lo que endurecen el caso común sin ser un límite en el que puedas apoyarte. (Mientras HYPRUSE_AUTH_GUARD está activado, una lista de capas ilegible hace que pointer, click_ui y keyboard se nieguen, ya que no se puede descartar una indicación de autenticación.)

Confinamiento opcional

Seis variables de entorno opcionales. Las primeras cuatro reducen lo que un agente puede tocar, y cada una falla hacia menos acción; las últimas dos registran y ensayan en lugar de restringir. Todas se componen con las capas anteriores:

  • HYPRUSE_CONFINE restringe la entrada a un ámbito de ventanas: launched (solo ventanas que hypruse abrió en esta sesión), class:firefox,kitty o workspace:3,special:notes. Las operaciones de teclado, click_ui y hypr de ventanas se rechazan fuera del ámbito; un clic de pointer se rechaza cuando cualquier ventana bajo el punto está fuera del ámbito (la lista de ventanas de Hyprland no está ordenada por z, por lo que hypruse falla de forma segura en lugar de adivinar qué ventana está encima). Esto es lo que te permite dejar a un agente trabajando mientras tu gestor de contraseñas está en otro espacio de trabajo, fuera del alcance de sus clics y teclas (no de sus capturas de pantalla). use_bind se rechaza rotundamente mientras el confinamiento esté activo, porque un atajo de teclado ejecuta una acción arbitraria del compositor que no puede limitarse a una ventana.
  • HYPRUSE_AUTH_GUARD (por defecto activado) se niega a hacer clic o escribir en un diálogo de autenticación del sistema (agentes polkit, ya sea una ventana como hyprpolkitagent o un aviso que el shell dibuja como capa, como hacen Omarchy 4 y los dots de end-4; el aviso del llavero de GNOME; los diálogos propios de Hyprland, que son su aviso de permisos y también sus avisos de aplicación que no responde y de modo seguro, ya que los tres comparten una clase de ventana), para que un agente manipulado no pueda aprobar una escalada de privilegios. click_ui también se niega cuando tal diálogo flota sobre el control sobre el que se le pidió hacer clic. Cuando la lista de capas no se puede leer, se niega en lugar de adivinar. Un aviso que un shell abre como ventana ordinaria de su propia clase, como hace DankMaterialShell, no se reconoce. Establece HYPRUSE_AUTH_GUARD=strict para negarse también a escribir en un campo de contraseña dentro de una ventana ordinaria (un inicio de sesión de navegador), detectado a través del árbol de accesibilidad. Un allow_auth=true por llamada en pointer/keyboard/click_ui lo anula, y porque cambia los argumentos de la herramienta, la anulación aparece de forma distinta en el aviso de aprobación. HYPRUSE_AUTH_GUARD=0 lo desactiva.
  • HYPRUSE_STRICT se niega a actuar cuando el cursor o la ventana enfocada se movieron desde la última acción de hypruse (el humano, o una ventana emergente, tomó el asiento): el agente debe volver a leer desktop/screenshot y reintentar, para que nunca escriba en una ventana a la que acabas de cambiar.
  • HYPRUSE_MARK hace legible la presencia del agente en el escritorio: etiqueta cada ventana que el agente abre con hypruse-owned y muestra un aviso en pantalla cuando el agente abre una ventana o captura la pantalla. También instala una regla de ventana border_color en esa etiqueta para que las ventanas propiedad del agente tengan un contorno de color, pero si una regla en tiempo de ejecución se renderiza depende de tu versión de Hyprland y de la precedencia de configuración (en algunas configuraciones no tiene efecto); cuando no se puede instalar en absoluto, hypruse lo dice en stderr en lugar de dejarte con una capa de marcado que silenciosamente no está funcionando. Para un contorno garantizado, añade la regla a tu propia configuración, que el etiquetado de hypruse luego coincide: windowrule = border_color rgb(ff5555), tag hypruse-owned en hyprland.conf (Hyprland más antiguo: tag:hypruse-owned), o hl.window_rule({ match = { tag = "hypruse-owned" }, border_color = "rgb(ff5555)" }) en hyprland.lua.
  • HYPRUSE_JOURNAL registra lo que hizo el agente: una línea NDJSON por llamada de herramienta en $XDG_STATE_HOME/hypruse/journal.ndjson (HYPRUSE_JOURNAL=1), o una ruta propia. Léelo con hypruse journal, vuelve a ejecutarlo con hypruse replay. Consulta El registro a continuación.
  • HYPRUSE_DRYRUN es un ensayo: cada verificación de argumentos y cada guardia anterior se ejecuta, luego la llamada informa lo que habría hecho y no entrega nada.

El registro: diario, ensayo, reproducción

Las banderas anteriores deciden qué puede hacer un agente en el momento y luego olvidar que sucedió. HYPRUSE_JOURNAL es la memoria. Un objeto JSON por línea, por lo que tail -f, grep y jq funcionan en un archivo en vivo:

{"v":1,"seq":7,"ts":"2026-08-02T09:12:13.456Z","kind":"act","tool":"pointer",
 "args":{"action":"click","x":800,"y":60},"outcome":"ok","ms":37,"result":"click ok"}

kind divide las dos preguntas que la gente realmente hace: act es entrada entregada a tu escritorio, observe es el agente mirando, que es lo que una auditoría de privacidad quiere (cuándo se capturó la pantalla, cuándo se leyó el portapapeles). Los resultados de las observaciones nunca se registran, solo que ocurrieron, por lo que el diario nunca se convierte en una segunda copia de todo lo que el agente vio. Los rechazos también se registran, con el mensaje de la guardia: es el único lugar donde existe la historia de tus capas de confianza haciendo su trabajo.

El texto escrito y copiado se registra como una longitud más un resumen corto, no como texto, porque las pulsaciones de teclas son contraseñas. HYPRUSE_JOURNAL_TEXT=1 lo mantiene textual, que solo necesitas para reproducir la escritura. Ten en cuenta qué es y qué no es un resumen: prueba que dos entradas escribieron lo mismo y no entregará tu contraseña a un lector, pero es un prefijo SHA-256 sin sal junto a un recuento exacto de caracteres, por lo que un PIN de cuatro dígitos se recupera trivialmente de él. Trata el diario como sensible de cualquier manera. Se escribe con permisos 0600 en un directorio 0700, y se rota en HYPRUSE_JOURNAL_MAX_BYTES (8 MiB, una generación anterior se conserva como .1; establece 0 para nunca rotar).

El diario es un grabador, no una guardia: si no se puede escribir, la acción aún ocurre y hypruse advierte una vez en stderr, porque fallar tu escritorio por una línea de registro es el intercambio equivocado. Lo que no registra es una observación de then= como entrada propia: la llamada actuante que la llevó se registra, then=screenshot y todo, pero la captura no recibe una segunda línea propia.

Léelo con hypruse journal (--acts solo para acciones, --refused para lo que las guardias detuvieron, -n N para seguir el final, -v para incluir cada resultado):

    1  09:12:10  session start pid 4211 0.10.0 confine=launched auth_guard=1 strict=True
   14  09:12:13  act  pointer    action=click x=800 y=60
   16  09:12:15  act  keyboard   action=type text=<11 chars>
   19  09:12:19  act  hypr       action=close_window target=0x5f2a10
                  REFUSED  TrustError: 0x5f2a10 (Signal) is outside the agent's confinement scope

312 actions (0 dry), 604 observations, 1 refused by a trust layer, 0 errors

HYPRUSE_DRYRUN=1 convierte la misma sesión en un ensayo. Cada herramienta actuante valida sus argumentos y ejecuta cada guardia de confianza, luego informa el plan en lugar de ejecutarlo, por lo que un ensayo rechaza exactamente lo que una ejecución real rechazaría:

DRY RUN, nothing was delivered: would click push button 'Send' at (1204, 880) in signal

Nada llega al escritorio: ni el clic, ni la pulsación de tecla, ni siquiera el enfoque de ventana que normalmente precede a la escritura. Se aplica dos veces, una en cada herramienta y otra en la propia ruta de entrada, para que una ruta de código que nadie pensó falle ruidosamente en lugar de actuar silenciosamente durante una simulación. Se le dice al agente que el ensayo está activado, por lo que informa un plan en lugar de reintentar una acción que "no funcionó". El ámbito son las acciones del agente, no el inicio del propio servidor: HYPRUSE_MARK, si lo estableces, aún instala su regla de ventana cuando el servidor se inicia.

hypruse replay <journal> reemite las acciones de un diario a través de las mismas funciones de herramienta, por lo que las mismas guardias se aplican a la reproducción. Imprime el plan y se detiene ahí a menos que pases --execute. Antes de tomar el asiento se niega rotundamente, en lugar de fallar a mitad de camino y dejar tu escritorio a mitad del plan de otra persona, cuando: una acción fue registrada por una versión más nueva de hypruse, una ventana registrada ya no existe (--skip-missing ejecuta el resto), el texto escrito se registró como resumen, la entrada es un click_ui(mark=N) cuya numeración murió con la sesión que lo dibujó, la entrada es una escritura de portapapeles y HYPRUSE_CLIPBOARD no está establecido, o HYPRUSE_READONLY o HYPRUSE_DRYRUN está establecido. Se marca el ritmo desde el tiempo registrado, limitado por --max-gap y escalado por --speed, y sus propias acciones se registran y marcan, por lo que reproducir el mismo archivo nuevamente ejecuta el plan original en lugar del plan más la reproducción de él.

El límite honesto son las direcciones de ventana: son punteros de heap, por lo que el diario de ayer nombra principalmente ventanas que ya no existen, y una dirección incluso puede ser reutilizada por una ventana diferente más tarde, lo que ninguna verificación previa puede detectar. La reproducción es para volver a ejecutar un flujo en un escritorio que aún se ve como el registrado.

El ensayo y la reproducción se componen en la dirección obvia: deja que el agente trabaje con HYPRUSE_DRYRUN=1, lee el diario y reprodúcelo con --execute una vez que el plan sea uno que te guste.

Rendimiento

Medido en una sesión en vivo (Hyprland 0.55, 1080p, 20 ventanas): desktop ~20 ms (una llamada hyprctl por lotes), despacho de espacio de trabajo/ventana ~10-20 ms, captura de pantalla de monitor completo ~65 ms (JPEG rápido por defecto; ~800 ms si pides PNG sin pérdida, la ruta zlib de grim domina), capturas de región/zoom muy por debajo de eso. Si las llamadas de herramienta se sienten lentas, casi con certeza es el aviso de aprobación de MCP frente a cada llamada, no el servidor. Pon en la lista blanca las herramientas que confías y la latencia desaparece. Claude Code (.claude/settings.json):

{
  "permissions": {
    "allow": [
      "mcp__hypruse__desktop",
      "mcp__hypruse__screenshot",
      "mcp__hypruse__hypr"
      // add pointer/keyboard/launch once you trust your workflows
    ]
  }
}

Coordenadas

Todo habla en las coordenadas lógicas globales de Hyprland, el espacio que usan hyprctl cursorpos y la ventana at. Las capturas de pantalla están en espacio de píxeles; cada captura devuelve geometry y scale para que global = origin + pixel / scale. En monitores de escala 1.0 (la mayoría de las configuraciones), los píxeles de imagen son coordenadas globales.

La herramienta zoom hace la aritmética de precisión para el agente: dale un punto global estimado y captura una caja de resolución nativa a su alrededor, recortada a la pantalla (o a una ventana), con el mismo contrato de metadatos. Ese bucle de dos pasos, estimar en la vista completa y luego re-estimar en el zoom, es la forma respaldada por investigación de acertar en controles pequeños.

Las capturas usan JPEG q90 por defecto: en un marco de 1080p eso es aproximadamente 12 veces más rápido de codificar que PNG (la ruta zlib de grim domina el tiempo de captura, medido ~65 ms vs ~800 ms) y 3-4 veces más pequeño, mientras que q90 a resolución completa lee bien el texto de la interfaz. Pasa lossless=true para píxeles exactos (PNG). En modo imagen, las capturas también se ajustan al límite de tamaño de resultado del host (Claude Desktop limita los resultados de herramientas a 1 MB) degradando la calidad antes que la resolución, ya que el filtro de reducción de escala de grim es más lento que una captura a resolución completa, y limitan el borde largo a HYPRUSE_MAX_IMAGE_EDGE píxeles (por defecto 1568) para que el host nunca reduzca la imagen bajo el modelo. La escala aplicada se incorpora a los metadatos devueltos, por lo que el mapeo de coordenadas sigue siendo exacto; ajusta con HYPRUSE_MAX_IMAGE_BYTES, o pasa scale para un alejamiento deliberado.

Por defecto, la herramienta de captura de pantalla escribe la imagen bajo $XDG_RUNTIME_DIR/hypruse/ y devuelve su ruta; los hosts MCP con un lector de archivos (Read de Claude Code) la renderizan de forma nativa. Este valor por defecto existe porque algunos hosts (incluido Claude Code 2.1.x) serializan bloques de imagen MCP en línea a texto base64 que el modelo no puede ver. HYPRUSE_SCREENSHOT_MODE=image cambia a bloques de contenido de imagen en línea para hosts que los renderizan correctamente.

Desarrollo

uv sync --group dev
uv run pytest            # unit tests, no compositor needed
uv run pytest -m e2e --override-ini addopts=   # live seat-safe checks
uv run python scripts/e2e_input.py             # supervised: takes the seat ~10s

La e2e de entrada es deliberadamente manual: toma prestado tu cursor y teclado, cuenta atrás, prueba la entrega de clic/desplazamiento/escritura leyendo la pantalla del terminal objetivo a través del control remoto de kitty, y restaura tu enfoque.

Hoja de ruta

Basado en latencias medidas de ruta caliente y el hallazgo de que las llamadas LLM son del 76 al 96% de la latencia de tareas de uso de computadora (OSWorld-Human), por lo que reducir viajes de ida y vuelta supera a afeitar milisegundos. El trabajo de ida y vuelta que motivó ese marco se ha enviado en gran parte: sequence, actuar-y-observar then= (incluyendo then='ui'), y las herramientas de árbol de accesibilidad (ui, marks, click_ui) que apuntan a controles por nombre sin captura de pantalla. Lo que queda:

Más rápido

  • wlr-screencopy en proceso sobre el cable crudo (como la entrada ya funciona): elimina el piso de bifurcación de grim de capturas pequeñas y añade espera-por-estable con seguimiento de daños que devuelve al instante en que la pantalla se asienta.

Menos viajes de ida y vuelta

  • Diff de pantalla semántico: después de una acción, devuelve solo lo que cambió (topología de ventanas del flujo de eventos, o un recorte de región cambiada limitada) en lugar de un marco completo. La expansión de eventos socket2 detrás de wait_for ya rastrea la mayor parte de la topología; la pieza que falta es incorporarla en un delta posterior a la acción.

Lectura más profunda

  • Cobertura de accesibilidad más amplia: cierra las brechas que las herramientas ui y marks encuentran hoy, principalmente los cuadros combinados más nuevos de GTK que no publican ni su texto ni su selección (por lo que un valor de desplegable renderizado aún necesita una captura de pantalla), además de eventos de cambio de valor AT-SPI para que then='ui' pueda informar que un control se asienta sin una encuesta.
  • Notificaciones: leer contenido e historial de notificaciones de escritorio recientes, no solo esperar a que aparezca la ventana emergente (wait_for ya coincide con layer_open en el espacio de nombres de notificaciones).

Confianza

  • Herramienta record: un GIF o mp4 con alcance del agente manejando el escritorio, mediante wf-recorder (un binario de la familia wlroots como grim), un acompañante visual del journal.

Plataforma

  • Soporte para sway / niri: el cliente wire ya habla los protocolos wlr; lo que queda es una capa IPC junto a hyprctl.py (contribuciones bienvenidas).
  • Pruebas headless de extremo a extremo en CI: necesita una VM QEMU virtio-gpu, ya que el backend aquamarine de Hyprland requiere un nodo de renderizado de GPU real que los runners alojados no tienen.

Medición

  • Benchmark de precisión del bucle de zoom: mide la precisión de clic del bucle de grueso a fino contra objetivos conocidos.
  • Benchmark de éxito de tareas de extremo a extremo en Hyprland (estilo OSWorld): el hermano mayor diferido del microbenchmark del bucle de zoom, que puntúa tareas completas de múltiples pasos a través de la superficie MCP real, para que el trabajo de a11y versus visión y de ida y vuelta se juzgue por la finalización de la tarea, no solo por la latencia.

Proyectos relacionados

proyectoenfoqueen Hyprland
computer-use-linuxAT-SPI + portales, respaldo ydotoolprimero GNOME; el portal RemoteDesktop que prefiere no está implementado por xdg-desktop-portal-hyprland
hyprmcpenvoltorio de hyprctlsolo gestión de ventanas; sin capturas de pantalla ni entrada
wayland-mcpentrada evemu, análisis VLMrequiere configuración elevada para entrada; sin semántica de Hyprland
Anthropic computer-use-demoX11 + xdotool en Dockerun entorno de referencia en sandbox en lugar de un escritorio en vivo
Cua (cua-driver)controlador multiplataforma; un plugin opcional del compositor Hyprland le da al agente sus propios asientos de entradael plugin debe compilarse para la versión exacta de Hyprland instalada, y su README lo llama experimental y no publicado

Investigación

hypruse no incluye ningún motor OCR; su mecanismo de precisión universal es el bucle de zoom de grueso a fino: captura una ventana, vuelve a capturar la región objetivo a resolución nativa, haz clic a través del mapeo de coordenadas exacto. Esa elección sigue lo que el campo de agentes GUI convergió. El uso de computadora de Anthropic fundamenta los clics desde píxeles crudos e incluye una acción zoom como la solución documentada para texto pequeño; su guía de solución de problemas para clics casi fallidos prescribe zoom y recorte de región, nunca OCR [1]. El CUA de OpenAI también es fundamentación de píxeles puros bajo disciplina de resolución, sin capa OCR en absoluto [2]. El zoom también es la palanca medida: el zoom iterativo sin entrenamiento aproximadamente duplica la precisión de fundamentación de alta resolución (OS-Atlas-7B, 18.9 → 49.7 en ScreenSpot-Pro) [3], y el arnés oficial del benchmark implementa una docena de adaptadores de modelos de fundamentación más cuatro estrategias de zoom/recorte, pero cero líneas base OCR [4]. Los agentes solo de visión igualan o superan a los agentes que además consumen árboles HTML o de accesibilidad [5], sustratos que Wayland no garantiza de todos modos, y los agentes nativos de última generación funcionan solo desde capturas de pantalla [7]. El OCR fue rechazado porque es ciego a los iconos, la clase de elemento que todos los modelos de fundamentación manejan peor (SeeClick: 30-52% en iconos vs 56-78% en texto) [6]; donde el OCR sobrevive en pilas modernas es un acompañante de desambiguación de texto, no el mecanismo de orientación [8].

Donde una aplicación expone un árbol de accesibilidad, hypruse también lo lee (la herramienta ui, AT-SPI sobre D-Bus mediante busctl) para orientar controles por nombre con coordenadas exactas y sin captura de pantalla. Esto sigue el precedente más fuerte de Linux: OSWorld, el benchmark estándar de uso de computadora, expone el árbol de accesibilidad del escritorio (obtenido en Ubuntu a través de AT-SPI) como una observación de primera clase junto a las capturas de pantalla, e informa la combinación de árbol de accesibilidad más captura de pantalla como su mejor configuración [9]. El árbol da identidad de elemento exacta y coordenadas que los modelos actuales no pueden inferir de manera confiable desde píxeles: Agent-S etiqueta cada elemento con una identificación porque los MLLM "carecen de un sistema de coordenadas interno", elevando el éxito de OSWorld del 11.2 al 20.6 por ciento [10]; el UFO de Microsoft impulsa Windows a través del árbol de UI Automation y lo fusiona con visión [11]; los agentes de navegador leen el árbol de accesibilidad, que Playwright serializa a YAML compacto, en lugar de píxeles por la misma razón [12]. El truco específico de Wayland de hypruse es el mapeo de coordenadas: las coordenadas de pantalla de AT-SPI no son confiables en Wayland porque una aplicación no conoce su posición global, por lo que hypruse usa extensiones relativas a la ventana más la posición de la ventana que ya tiene de hyprctl. La cobertura es desigual por naturaleza: lienzos, juegos, terminales y Electron/Chrome sin una bandera exponen poco o nada [13]. Probar esta implementación contra aplicaciones GTK y Qt reales la agudizó en ambas direcciones: una entrada tipada lee de vuelta su contenido exacto, y los deslizadores y alternadores informan su posición y estado, pero los cuadros combinados más nuevos de GTK no publican ni su texto ni una selección, por lo que leer un valor de desplegable renderizado aún necesita una captura de pantalla. Los toolkits también describen widgets que nunca diseñaron (flechas de desplazamiento de altura cero, páginas de pestañas no renderizadas que informan orígenes en los millones), que hypruse rechaza contra el rectángulo de ventana que hyprctl conoce de manera autoritativa. Un fundamentador visual fuerte puede sustituir el árbol por completo [5], por lo que el árbol de accesibilidad complementa el bucle de zoom en lugar de reemplazarlo, y la visión sigue siendo el respaldo garantizado.

  1. Anthropic, Herramienta de uso de computadora: documentación de plataforma (computer_20251124, enable_zoom, guía de resolución)
  2. OpenAI, Agente de uso de computadora y la guía de uso de computadora
  3. DiMo-GUI: Advancing Test-time Scaling in GUI Grounding via Modality-Aware Visual Reasoning, EMNLP 2025. arXiv:2507.00008
  4. Li et al., ScreenSpot-Pro: GUI Grounding for Professional High-Resolution Computer Use. arXiv:2504.07981; arnés oficial
  5. Gou et al., Navigating the Digital World as Humans Do: Universal Visual Grounding for GUI Agents (UGround), ICLR 2025 Oral. arXiv:2410.05243
  6. Cheng et al., SeeClick: Harnessing GUI Grounding for Advanced Visual GUI Agents, ACL 2024. arXiv:2401.10935
  7. Qin et al., UI-TARS: Pioneering Automated GUI Interaction with Native Agents. arXiv:2501.12326
  8. Agyeya et al., Agent S2: A Compositional Generalist-Specialist Framework for Computer Use Agents (Tesseract como acompañante de fundamentación textual). arXiv:2504.00906
  9. Xie et al., OSWorld: Benchmarking Multimodal Agents for Open-Ended Tasks in Real Computer Environments. arXiv:2404.07972; el árbol a11y se obtiene en Ubuntu a través de AT-SPI (código)
  10. Agashe et al., Agent S: An Open Agentic Framework that Uses Computers Like a Human. arXiv:2410.08164
  11. Zhang et al., UFO: A UI-Focused Agent for Windows OS Interaction (UI Automation + visión). arXiv:2402.07939
  12. Playwright, Capturas ARIA: el árbol de accesibilidad como texto estructurado compacto
  13. Wang et al., GUI Agents: A Survey (brechas de cobertura de API de accesibilidad; a11y complementa la visión). arXiv:2412.13501

Licencia

MIT