Communitygithub.com

iwishwp/AgentOS

Opera el escritorio AgentOS (niri/Wayland): gestión de ventanas y espacios de trabajo, accesibilidad de aplicaciones GUI, automatización del navegador, artefactos de archivos, notificaciones y presentación del escritorio. Funciona con cualquier framework de agente que monte las ocho extensiones MCP de AgentOS (niri/desktop/system/files/session/a11y/browser/cred). Úsalo cuando se trate de “operar aplicaciones/ventanas/archivos/notificaciones en el escritorio del usuario”.

¿Qué es AgentOS?

AgentOS es un conjunto de habilidades para agentes de IA (compatible con Claude Code, Cursor, Z Code, Goose) que permite controlar completamente un escritorio Linux basado en niri/Wayland mediante ocho extensiones MCP (Model Context Protocol). Está organizado en cuatro capas de capacidad descendentes: L0 (sistema: ventanas, espacios de trabajo, archivos, notificaciones, portapapeles), L1 (árbol de accesibilidad AT-SPI2 para clics y lectura de texto en aplicaciones GUI sin robar el foco), L2 (navegador Chromium sin cabeza para automatización web) y L3 (captura de pantalla e inyección de teclado como último recurso). El flujo de trabajo típico prioriza siempre L0, luego L1 para aplicaciones nativas (GTK/Qt), L2 para contenido web, y L3 solo si fallan los anteriores. Las extensiones se montan mediante scripts de entorno que descubren automáticamente el socket IPC de niri y completan las variables Wayland/DBus, por lo que funcionan incluso desde sesiones SSH. El agente opera dentro de un “acuario” (sesión niri anidada) para no interferir con el escritorio del usuario, y los resultados se notifican con notificaciones del escritorio o confirmaciones interactivas. Los archivos se almacenan en ~/Agent/ con una estructura predefinida, y las credenciales se gestionan exclusivamente mediante referencias de la extensión cred, nunca en texto plano.

Compatible con✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/iwishwp/AgentOS/tree/HEAD/skills/agentos-desktop

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Manual de operación del escritorio AgentOS (válido para cualquier agente)

Este manual es autocontenido: si tu framework puede montar servidores MCP stdio (Goose / Claude Code / Z Code / Cursor, etc.), al montarlos según §1 obtendrás todas las capacidades descritas abajo. Todos los elementos han sido probados en hardware real (Fedora + niri Wayland, evidencias de extremo a extremo en el repositorio docs/capabilities.md, octubre 2026).

0. Modelo mental: cuatro capas de capacidad, en orden de prioridad descendente

  1. Capa L0 — Sistema: ventanas/espacios de trabajo/apertura de aplicaciones/archivos/notificaciones/portapapeles (extensiones niri/desktop/system/files). La más estable, úsala primero.
  2. Capa L1 — Árbol de accesibilidad: clics por nombre y lectura/escritura de texto dentro de aplicaciones GUI (extensión a11y, AT-SPI2). No roba el foco, no molesta al usuario. Probado en GTK3/GTK4/Qt (el interruptor global de Qt y toolkit-accessibility de Chromium ya están activados por defecto en el sistema desde el 18 de octubre de 2026). El árbol de Chromium se puede leer y escribir texto (los clics en páginas van por L2). Java no está instalado (consulta el apéndice B de capabilities.md). Las aplicaciones puramente X11 (tipo xterm) no tienen árbol, solo L3.
  3. Capa L2 — Navegador CDP: todas las operaciones en páginas web (extensión browser, Chromium sin cabeza dedicado al agente).
  4. Capa L3 — Visual/entrada de último recurso: captura de pantalla con grim (fiable), inyección de teclado (scripts/kb-inject.sh: wtype a nivel de usuario como principal, fiable para texto y combinaciones de teclas; las teclas de control como Enter/Tab recurren a ydotool que requiere sudo), inyección de puntero (no fiable: se desplaza con la aceleración, solo como último recurso).

Si una aplicación “no se abre / no funciona bien”: primero piensa si no se cumple una condición previa de L1 (interruptor de accesibilidad), luego usa una captura de pantalla L3 para ver el estado real. No lo reintentes a ciegas.

1. Montaje (una sola vez)

En Goose (~/.config/goose/config.yaml, formato probado en v1.54; el campo name: es obligatorio; si falta, toda la extensión se descarta silenciosamente):

extensions:
  niri:
    type: stdio
    name: niri
    enabled: true
    cmd: /ruta/a/AgentOS/scripts/env/with-niri-env.sh
    args: []
    env_keys: []
    envs: {}
    timeout: 300          # segundos
  # desktop/system/files/session/a11y/browser/cred son iguales,
  # cmd usa respectivamente with-desktop-env.sh / with-system-env.sh / ... (ocho lanzadores en scripts/env/)

Otros frameworks (Claude Code / Z Code, etc., estilo JSON mcpServers):

{
  "mcpServers": {
    "niri":    { "command": "/ruta/a/AgentOS/scripts/env/with-niri-env.sh" },
    "desktop": { "command": "/ruta/a/AgentOS/scripts/env/with-desktop-env.sh" },
    "system":  { "command": "/ruta/a/AgentOS/scripts/env/with-system-env.sh" },
    "files":   { "command": "/ruta/a/AgentOS/scripts/env/with-files-env.sh" },
    "session": { "command": "/ruta/a/AgentOS/scripts/env/with-session-env.sh" },
    "a11y":    { "command": "/ruta/a/AgentOS/scripts/env/with-atspi-env.sh" },
    "browser": { "command": "/ruta/a/AgentOS/scripts/env/with-browser-env.sh" },
    "cred":    { "command": "/ruta/a/AgentOS/scripts/env/with-cred-env.sh" }
  }
}

Puntos clave:

  • Usa los scripts lanzadores, no apuntes directamente a node dist/index.js — los lanzadores se encargan de descubrir el socket IPC de niri (la ruta contiene el PID del compositor, cambia en cada sesión, p. ej. /run/user/1000/niri.wayland-1.2762.sock) y de completar las variables de entorno Wayland/dbus (XDG_RUNTIME_DIR/WAYLAND_DISPLAY/DBUS_SESSION_BUS_ADDRESS). Solo así las herramientas funcionan cuando se arrancan desde SSH o un entorno de servicio.
  • Prueba manual del lanzador: timeout 2 scripts/env/with-niri-env.sh </dev/null; si devuelve exit 0, funciona.
  • Requisitos previos: Node ≥ 20, el repositorio ha ejecutado npm install && npm run build, y se ejecuta bajo el mismo usuario que tiene la sesión gráfica de niri.

2. Referencia rápida de herramientas (agrupadas por extensión; nombre de herramienta = <extensión>__<herramienta>)

niri — Ventanas/espacios de trabajo/apertura (L0)

HerramientaPropósitoParámetros clave
list_windowsListar todas las ventanas (id/app_id/título/espacio/foco)—
list_workspacesListar espacios de trabajo (idx numérico e id son dos cosas distintas; move usa número o nombre)—
list_outputsListar monitores—
focus_windowCambiar el foco al frente (cambia la vista del usuario, úsalo con cuidado)id
focus_workspaceCambiar de espacio de trabajo (cambia la vista del usuario)reference: "3" o nombre
move_window_to_workspaceMover ventana (sin robar foco, para organización)id? (por defecto = ventana con foco), reference
close_windowCerrar ventanaid?
open_appIniciar aplicación en el escritorio del usuariocommand: array, ej. ["ghostty"]

a11y — Operaciones dentro de aplicaciones GUI (L1, AT-SPI2)

HerramientaPropósitoParámetros clave
a11y_list_appsListar aplicaciones registradas en el bus de accesibilidad—
a11y_dump_treeVolcar el árbol de accesibilidad de una aplicación (para encontrar nombres de botones/estructura)app
a11y_clickHacer clic por nombre accesible (sin robar foco, sin molestar al usuario)app, buttonName
a11y_read_textsLeer todo el texto no vacío de una aplicación (pantalla/resultados/etiquetas)app
a11y_set_textEscribir en un campo de texto por nombre de nodoapp, match (subcadena del nombre, por defecto * = primero), text

Disciplina probada: dirígete por nombre, no por índice del árbol (la estructura del árbol se reconstruye al reconectar AT); el árbol de GTK4 solo es completo después de que un cliente AT se registre; en caso de múltiples instancias con el mismo nombre, el puente resuelve a la primera registrada — primero lee el texto para distinguir la instancia y, si es necesario, cierra las sobrantes. Excepción de Chromium: el árbol se construye de forma perezosa (el puente lo activa automáticamente; la primera volcada puede tardar 1-2 segundos, es normal); para escribir en campos de texto usa la combinación “grabFocus + kb-inject type” (las entradas de Chromium no aceptan setTextContents); los clics en botones de la página no funcionan (doAction se envía pero onclick no se ejecuta); todas las operaciones en páginas deben hacerse con la extensión browser.

browser — Operaciones web (L2, Chromium sin cabeza dedicado al agente)

HerramientaPropósitoParámetros clave
browser_openNavegar (la primera llamada inicia el navegador automáticamente)url
browser_evalEjecutar JS en la página; rellenar formularios, hacer clics, leer contenido, todo con estoCódigo JS
browser_screenshotCaptura de pantalla (el navegador no tiene cabeza, así que la visión es solo mediante capturas)—

Acción estándar para rellenar formularios: después de el.value = "..." es obligatorio el.dispatchEvent(new Event("input", {bubbles: true})); de lo contrario, los frameworks modernos no reciben la entrada. Si aparece un captcha: detente e informa al usuario; nunca lo intentes saltar automáticamente.

files — Caja de arena de archivos (L0, raíz = ~/Agent/; todas las rutas son relativas)

HerramientaPropósitoParámetros clave
read_file / write_fileLeer/escribir texto (crea automáticamente los directorios padre)path, content
list_dir / create_dirListar/crear directoriospath
move / deleteMover / eliminar (va a .trash, recuperable; no uses shell rm)source/dest, path
find_by_nameBuscar archivos por nombrepattern
downloadDescargar http(s) a la caja de arena (≤50MB / 60s; no uses shell curl)url, path

desktop — Presentación/notificaciones/portapapeles/confirmación (L0)

HerramientaPropósitoParámetros clave
openAbrir un artefacto: URL o archivo; para documentos de Office es obligatorio app: "libreoffice" (lista blanca; las asociaciones MIME del sistema no son fiables)target, app?
notifyNotificación de escritorio (tres niveles, ver §3)summary (obligatorio), body, urgency, action?
confirmPedir autorización/decisión al usuario (T1 cuatro botones: Permitir/Permitir esta sesión/Denegar/Nunca; 30s sin respuesta = denegar)summary (sin contenido sensible), tier? (t1/t2, afecta el texto)
clipboard_read / clipboard_writeLeer/escribir portapapeles—

session — Acuario (sesión niri anidada exclusiva del agente; todas las tareas GUI se hacen aquí)

HerramientaPropósito
agent_session_start / agent_session_stop / agent_session_statusCiclo de vida de la sesión anidada (aparece una ventana que se puede observar en el escritorio)
agent_open_appIniciar aplicación dentro del acuario (p. ej. gnome-calculator, chromium)
agent_list_windowsListar ventanas dentro del acuario
agent_screenshotCapturar la pantalla del acuario (con grim)

system — Consultas del sistema (L0 solo lectura, todo permitido)

system_status / list_services / service_status / journal / network_info / list_packages / package_info / package_install (T2 confirmación fuerte: muestra cuadro de diálogo polkit con contraseña; requiere presencia humana; si se ejecuta sin supervisión, timeout de 300s lo deniega automáticamente — no lo llames en modo desatendido).

cred — Credenciales (el agente obtiene referencias, no texto plano)

cred_list (credenciales disponibles y su referencia/nombre de variable de entorno) · cred_autofill (canal A: autocompletado en página, el texto plano se descarta inmediatamente) · cred_exec (canal B: ejecución delegada con lista blanca + salida censurada) · cred_inject (canal C: inyección de variables de entorno con TTL corto, se reúnen todas al expirar). Cualquier operación que requiera contraseña/token solo debe hacerse a través de cred; está prohibido pedir texto plano al usuario.

3. Convenciones de comportamiento (disciplinas probadas y efectivas)

  1. Todos los artefactos van a ~/Agent/, clasificados en downloads/ inbox/ reports/ notes/ canvas/ screenshots/; al guardarlos entran automáticamente en el índice de artefactos (http://127.0.0.1:7788/artifacts). Cuando el usuario pregunte “¿dónde está mi informe anterior?”, abre esa página o informa la ruta relativa.
  2. Prioridad de presentación: paneles/informes/contenido interactivo → escribe un archivo HTML autocontenido en canvas/<nombre>/index.html y luego open para abrir http://127.0.0.1:7788/<nombre>/; documentos de Office → open con app: "libreoffice"; páginas web → extensión browser.
  3. Tres niveles de notificación: completado → notify con urgency=low y acción ({kind:"open_path", path:"reports/x.fodt"} o {kind:"open_url", url:...}, al hacer clic en la notificación se accede directamente al artefacto); fallo/se necesita saber urgentemente → urgency=critical con una frase de conclusión + causa y sugerencia; cuando se necesita una decisión del usuario → no uses notify, usa confirm (notify no tiene semántica de elección). Los resultados asíncronos siempre deben notificarse; no los completes en silencio.
  4. Confirmación y moderación: no toques la ventana que el usuario está usando a menos que se te pida explícitamente (primero haz list_windows para identificar el objetivo); si hay una denegación por política (isError con mensaje “denegado por política”), infórmalo con honestidad, no intentes sortearla; las operaciones GUI se realizan dentro del acuario, sin robar el foco del usuario.
  5. Las credenciales solo se usan mediante referencias de cred-mcp (la disciplina que aparece al final de la tabla de §2, sección cred).

4. Problemas comunes de entorno (todos probados en la práctica)

ProblemaSíntomaSolución
La ruta del socket IPC de niri cambia cada sesiónniri msg no conectaUsa el lanzador (descubre automáticamente NIRI_SOCKET); no lo codifiques
El llavero de Chromium bloquea servicios de redEl navegador se queda colgado al iniciarInícialo con --password-store=basic (ya está incorporado en la extensión browser; si inicias chromium por tu cuenta, recuerda añadirlo)
Bloqueo de instancia única de sofficeAl volver a abrir un documento similar con LibreOffice ya abierto, puede que no aparezca ventana o se quede colgadoPrimero verifica el estado del proceso soffice; para abrir documentos usa app:"libreoffice" que sigue la semántica del lanzador; si la salida anterior fue anormal, puede aparecer una ventana “Document Recovery” (probado el 18-10-2026); al listar ventanas, no la confundas con la ventana del documento objetivo
Asociación MIME de LibreOffice no fiableFedora identifica los archivos fodt como text/xml y los abre con un editor de textoopen debe incluir app:"libreoffice"
Las aplicaciones Qt no aparecen en el bus a11ya11y_list_apps no las muestraEl sistema ya tiene activada la variable global (QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1 en /etc/environment, persiste tras reinicio); si sigue sin verlas, la aplicación se inició antes de que la variable estuviera disponible o no es una vinculación oficial de Qt; reinicia la aplicación
El árbol a11y de Chromium/Electron está vacíoEl volcado no muestra contenido① Inicia con --force-renderer-accessibility (la extensión browser ya lo incluye por defecto); ② toolkit-accessibility debe estar a true antes de iniciar la aplicación (ya está activado globalmente; cambiarlo después no tiene efecto; hay que reiniciar la aplicación); ③ el árbol se construye de forma perezosa; haz un volcado para activar el puente (ver disciplina de §2 a11y)
Elección de método de inyección de tecladoNecesitas escribir texto o usar atajos de tecladoscripts/kb-inject.sh: para texto y combinaciones usa wtype (nivel de usuario); para teclas de control como Enter/Tab, wtype no funciona en GTK, usa ydotool (sudo); el chino puede perder el primer carácter; después de escribir, verifica leyendo el árbol a11y
El acuario tiene una superposición de teclas de niri al inicioLa captura de pantalla aparece tapada por “Important Hotkeys”Inyecta Esc para cerrarla; el sandbox del agente no puede conectar al socket de ydotoold (root 600); usa niri__open_app para ejecutar la inyección en el entorno del escritorio real
Deriva del puntero de ydotoolEl posicionamiento absoluto es impreciso (la aceleración de libinput ≈0.5)No confíes en el puntero; la inyección de teclado es fiable; presta atención a la diferencia de ruta del socket (/tmp/.ydotool_socket vs $XDG_RUNTIME_DIR)
El árbol de GTK4 no está completo inicialmenteEl volcado solo muestra unas decenas de nodosPrimero llama a a11y_list_apps/dump una vez para que el cliente AT se registre; luego el segundo volcado será completo (de 16 a 105 nodos, probado)
Confirmaciones T1/T2 en modo desatendido30s/300s sin respuesta, se deniega automáticamenteComportamiento esperado: las operaciones de escritura requieren que el usuario esté presente; en pruebas, se puede responder mediante programación con org.agentos.Confirm1.Respond
Instalación de paquetes bloqueada por packagekitddnf falla esporádicamenteAntes de instalar, ejecuta systemctl stop packagekit (el helper T2 ya lo maneja)

5. Ruta de actualización (cuando la aplicación objetivo no se abre, prueba en este orden)

L0 (capa de sistema, pruébala siempre primero) → L1 (a11y: GTK3/GTK4/Qt ya accesibles por defecto; Chromium verifica el flag y el orden de toolkit-accessibility; Electron de terceros añade el flag según el apéndice B de capabilities.md) → L2 (contenido web, obligatorio) → L3 último recurso (grim para ver + kb-inject para teclado; el puntero no es fiable). Tipos que aún no se pueden abrir: aplicaciones puramente X11 (tipo xterm, sin árbol, L3 es el final), Java (requiere JAB, consulta el apéndice B de capabilities.md), la interfaz propia del compositor solo admite inyección de entrada — tabla detallada en el repositorio docs/capabilities.md.

Skills relacionados