Ghost

Control verificado de todo el escritorio para agentes en Windows y Linux: maneja aplicaciones sin API en segundo plano sin robar el foco, gestiona ventanas y escritorios ocultos, ejecuta comandos de shell, controla tu propio navegador Chromium mediante CDP, y verifica cada acción. 54 herramientas, Rust, MIT.

Documentación

Ghost

CI Linux Release License: MIT

Control verificado de todo el escritorio, para agentes y programas, en Windows y Linux. Ghost le da a Claude Code, Codex, Cursor, cualquier plataforma MCP, o un script simple la superficie de control del propio sistema operativo: las aplicaciones sin API, las ventanas, el shell y el navegador en el que ya has iniciado sesión - en segundo plano sin tomar tu pantalla o cursor, con cada acción probada que ha ocurrido.

Como Playwright, pero para el escritorio nativo, y construido para agentes. Ghost hace la percepción, la acción y la verificación; el modelo que ya estás ejecutando hace cualquier inspección que sea necesaria, así que no hay clave de API de visión que configurar.

Una superficie MCP, dos motores: Win32 UI Automation en Windows, AT-SPI2 sobre D-Bus en Linux. Los verbos, los niveles de localizador y el bucle de actuar-luego-verificar se escriben una vez y se comportan igual en ambos. Soporte de plataformas · Configuración de Linux

Por qué Ghost es diferente

  • Se ejecuta en segundo plano, y eso está garantizado. Un agente puede hacer clic, escribir y usar atajos dentro de una aplicación mientras sigues trabajando en otra ventana - sin robo de foco, sin salto de cursor. Publica mensajes de ventana a controles reales y usa patrones de UI Automation en los que no tienen ventana; la mayoría de las herramientas solo pueden manejar lo que está en primer plano. Desde 0.19 esto es una política, no una preferencia: la política de foco por defecto es background. Desde 0.20 también es constructiva: cualquier cosa que Ghost inicie (una aplicación, un navegador con ventana) nace en un escritorio oculto que tiene su propia cola de entrada y no puede tomar tu primer plano, y los verbos ordinarios lo manejan allí por título de ventana. Una llamada que realmente no tiene una ruta en segundo plano falla nombrando la acción en lugar de tomar silenciosamente la pantalla. Desde 0.22 la política está bloqueada allí: ninguna llamada de herramienta puede elevarla, así que un agente no puede decidir por sí mismo tomar tu mouse. Puedes hacerlo, configurando GHOST_FOCUS_LOCK=off en el entorno del servidor. Y desde 0.23 una ventana que toma el primer plano por sí sola - los navegadores lo hacen, en sus propias llamadas de accesibilidad - es devuelta de inmediato, así que tu escritura continúa donde estás mirando. Medido en un escritorio real con una persona escribiendo durante todo el proceso: de aproximadamente 490 pulsaciones de teclas por ejecución, de cero a una llegó a la ventana que el agente estaba manejando. (cómo)
  • Nunca tu ventana por accidente. La sesión recuerda la última ventana que el agente nombró o lanzó y cada verbo con ámbito de ventana la apunta por defecto. La ventana en primer plano del humano se usa solo cuando nada fue anclado, y la respuesta lo dice. Tres semanas de transcripciones reales mostraron "elemento no encontrado en la ventana en primer plano" como el fallo principal antes de esto; era el agente buscando en la ventana que tú tenías abierta.
  • Muchos agentes a la vez. Las solicitudes se despachan en paralelo, así que una espera de 15 segundos en una pestaña no detiene una consulta instantánea detrás de ella, y un segundo proceso de Ghost ejecuta su propio navegador junto al primero sin competir por el mouse.
  • Pruébalo en tu máquina. ghost verify maneja el servidor MCP real a través de stdio y audita cada afirmación anterior contra presupuestos de tiempo estrictos, saliendo con código no cero si alguna no se cumple en tu hardware.
  • Cada acción está verificada. Ghost vuelve a comprobar la pantalla (o lee el valor del control) después de actuar y devuelve verified / focus_confirmed - nunca un ciego ok:true. Los agentes fallan al actuar y no saber si funcionó; Ghost cierra ese bucle.
  • Maneja aplicaciones sin API. Win32 heredado, WPF, Electron, UWP, portales de proveedores - el software que no tiene integración y más necesita automatización. Sin CDP, sin navegador, sin cooperación de la aplicación requerida.
  • Sin clave de visión. El modelo que maneja Ghost lee ghost_see (cada elemento con su nombre, rol y centro en pantalla) o ghost_screenshot por sí mismo. El nivel de visión propio de Ghost es opcional, existe para llamadores sin modelo propio, y está apagado hasta que se configure.
  • Nativo de accesibilidad y profundo. Descubrimiento real de elementos a través de la API de accesibilidad del propio sistema operativo - UI Automation en Windows, AT-SPI2 en Linux - no adivinación de píxeles. Los elementos vuelven con nombres, roles y límites reales.

Véalo en un script: examples/background_agent_demo.py maneja una aplicación en segundo plano mientras el primer plano sigue siendo tuyo. Comparación honesta vs Playwright-MCP / cua-driver / Computer Use: docs/comparison.md.

Para qué lo usa la gente

La visión es la parte más pequeña. En una sesión típica, un agente llama a Ghost principalmente para actuar, gestionar ventanas y procesos, ejecutar comandos y leer el estado de vuelta.

UsoHerramientasLlamador típico
Manejar aplicaciones sin API: instaladores, software de negocio heredado, portales de proveedores, herramientas WPF y Electronghost_act, ghost_key, ghost_scroll, ghost_dragagentes, scripts RPA
Control de ventanas y procesos: lanzar invisiblemente, enfocar, minimizar, restaurar, cerrar, recuperar ventanas ocultas, barrer navegadores huérfanosghost_window, ghost_desktop_*, ghost_statsagentes, scripts de operaciones
Una terminal para el agente: builds, git, CLIs, estado persistente de PowerShell, lanzar otra sesión de Claude Codeghost_shell, ghost_runagentes de codificación en Windows
Manejar el navegador en el que ya has iniciado sesión, a través de su puerto DevTools: pestañas, navegación, clics en DOM, evaluación de JS, texto de página19 herramientas de ghost_browser_* y ghost_tab_*agentes, automatizaciones web
Leer datos de aplicaciones sin exportación: texto de accesibilidad, texto de pestañas, OCRghost_see mode=text, ghost_tab_textagentes, scripts de informes
Hacer de "¿funcionó?" una comprobación de máquina: elemento existe, valor igual, esperar inactividad o textoghost_assert, ghost_waitagentes de QA, CI
Escritorios aislados: trabajo GUI nocturno y agentes paralelos que nunca tocan la pantalla del humanoghost_window op=launch, la política de foco, ghost_desktop_*ejecuciones autónomas
Flujos de varios pasos reproducibles con reintentos y condiciones, sin modelo en el bucleintenciones a través de ghost run, POST /run, ghost_execute_intenttrabajos programados
El portapapeles como puente hacia aplicaciones que resisten la escrituraghost_clipboardtodos los anteriores

Cada fila se ejecuta bajo las mismas garantías: la acción devuelve verified, la política por defecto nunca toma tu primer plano, y Ctrl+Alt+G detiene todos los procesos de Ghost a la vez.

¿Qué es Ghost?

Ghost es la capa entre un modelo y el escritorio. El modelo razona; Ghost ve la pantalla como lo hace el sistema operativo, actúa sobre controles reales sin tocar tu primer plano, y reporta si la acción tuvo efecto. Da control programático sobre cualquier aplicación de escritorio - Win32 nativo, Electron, WPF, UWP, GTK, Qt, o cualquier otro - a un agente, un script o un programa.

En Windows usa UI Automation para el descubrimiento de elementos, SendInput para la inyección de teclado/mouse, y DXGI/GDI para la captura de pantalla. En Linux usa AT-SPI2 sobre D-Bus para descubrimiento y acciones, XTEST (X11) o el portal RemoteDesktop / uinput (Wayland) para entrada, y X11 GetImage o el portal de captura de pantalla para captura. El motor de Linux es Rust puro - sin paquetes -devel para instalar.

Entrégalo de tres maneras:

  • Servidor ghost-mcp - la superficie principal: un servidor de Protocolo de Contexto de Modelo para Claude Code, Claude Desktop, Codex, Cursor y cualquier cliente MCP (54 herramientas en Windows)
  • CLI ghost - comandos de una sola vez, excelente para scripts y CI (ghost click --name "Submit")
  • Servidor ghost-http - API REST local, llámalo desde Python, Node, curl, cualquier cosa (curl http://127.0.0.1:7878/list-windows)

La superficie MCP es 20 verbos de escritorio, 19 herramientas de ghost_browser_* / ghost_tab_* para manejar pestañas individuales del navegador en segundo plano (Chrome, Comet, Edge, Brave), y 15 herramientas solo de Windows: la política de foco más ghost_desktop_* para control explícito de escritorios de Windows aislados que el usuario nunca ve. Bajo la política por defecto rara vez necesitas lo último: ghost_window op=launch ya inicia la aplicación en el escritorio oculto auto, y ghost_see / ghost_act / ghost_key / ghost_scroll la alcanzan con window=<title> exactamente como alcanzan una ventana en tu propio escritorio (target.surface en la respuesta te dice cuál). UIA, mensajes de ventana y captura funcionan completamente allí. El SendInput real no, porque Windows lo rechaza fuera del escritorio de entrada, y la escritura se prueba leyendo el valor del control de vuelta, así que un objetivo que descarta caracteres publicados devuelve un error en lugar de un éxito falso. Los verbos de escritorio y las herramientas de navegador se construyen también en Linux; la política de foco y los escritorios ocultos son solo de Windows.

No se requiere Claude. No se requiere navegador. Sin CDP. Maneja aplicaciones a través de las APIs de automatización y entrada del propio sistema operativo, así que funciona con aplicaciones nativas que no tienen API ni ganchos de automatización propios - la misma fiabilidad ya sea que una aplicación fue construida para ser automatizada o no.

Plataformas

PlataformaEstadoMotor
Windows✅ completo y verificadoghost-core - Win32 UI Automation, SendInput, mensajes de ventana publicados, captura DXGI/GDI
Linux, X11✅ funcional - verificado por pruebas CI en vivo contra una aplicación GTK realghost-linux - AT-SPI2 sobre D-Bus, entrada XTEST, captura X11 GetImage
Linux, Wayland⚠️ implementado, NO verificado - ninguna prueba lo ha ejecutado en hardwaremismo descubrimiento y acciones AT-SPI2; entrada y captura van a través de los portales RemoteDesktop / Screenshot o uinput en su lugar
macOS🚧 andamiajeAccessibility + CGEvent + ScreenCaptureKit - por construir en una Mac

Wayland merece la fila separada en lugar de una nota al pie: es la sesión por defecto en Ubuntu y Fedora actuales, así que es lo que la mayoría de los usuarios de Linux ejecutarían realmente, y es la parte sin pruebas detrás. La capa de descubrimiento y acción se comparte con X11 y está cubierta, y es la capa que más importa aquí - AT-SPI2 le pide a la aplicación que haga la cosa, así que no hay puntero que mover ni ventana que elevar. Lo que no está verificado es el respaldo debajo: entrada de portal, captura de portal, uinput. Si ejecutas Wayland, trata ghost doctor como lo primero a ejecutar y espera reportar errores. Los informes son bienvenidos y son la forma más rápida de que esa fila cambie.

ghost-session y ghost-mcp se comparten: los niveles de localizador, la cascada de anclaje, el bucle de actuar-luego-verificar y los 20 verbos MCP centrales se escriben una vez y se ejecutan en ambas plataformas. Solo el motor debajo cambia, detrás de un alias de cfg de una línea. Las herramientas de navegador y pestañas son independientes del motor y se construyen para ambas; la política de foco y los escritorios aislados son solo de Windows y se reportan como tales en lugar de fingirse.

La cuña sobrevive al puerto. En Windows, manejar una aplicación sin robar el foco se construye sobre mensajes de ventana publicados. Linux tiene un análogo más limpio en las acciones AT-SPI2: la aplicación realiza la operación a través de su propio toolkit, así que no hay puntero que mover ni ventana que elevar. Esa capa es el mismo código bajo X11 y Wayland; la entrada sintética es solo el respaldo debajo, y el respaldo es la parte que Wayland no ha sido probado.

Esto está probado, no afirmado: CI levanta un escritorio real (Xvfb + D-Bus + at-spi-bus-launcher), maneja una aplicación GTK real, y requiere que el texto escrito a través de AT-SPI se lea de vuelta desde la aplicación y que invocar un botón realmente cierre el diálogo. La entrada y captura del portal Wayland están implementadas pero aún no verificadas en hardware.

Configuración de Linux, lista de verificación y limitaciones honestas: docs/linux-fedora.md. Matriz de capacidades en las tres: docs/cross-platform.md.

Ghost es una herramienta de automatización de propósito general. Úsala en sistemas que posees o estás autorizado a automatizar, y de acuerdo con los términos del software que manejas.

Instalar

Un clic: paquete MCP (gratis). Cada versión incluye ghost-windows-x64.mcpb y ghost-linux-x86_64.mcpb en la página de versiones. Ábrelo en un cliente compatible con paquetes MCP (Claude Desktop: Configuración -> Extensiones -> Instalar desde archivo) y Ghost queda registrado, sin necesidad de editar PATH ni configuración, y sin clave API. Ghost también aparece en el registro MCP como io.github.NORTHTEKDevs/ghost, por lo que los clientes compatibles con registros pueden instalarlo desde allí. El paquete contiene únicamente el servidor ghost-mcp; la CLI y el servidor HTTP están en los archivos comprimidos de abajo.

Binarios precompilados (gratis). Cada versión incluye archivos comprimidos verificados por suma de comprobación para ambas plataformas en la página de versiones:

# Linux x86_64
curl -LO https://github.com/NORTHTEKDevs/ghost/releases/latest/download/ghost-linux-x86_64.tar.gz
curl -LO https://github.com/NORTHTEKDevs/ghost/releases/latest/download/ghost-linux-x86_64.tar.gz.sha256
sha256sum -c ghost-linux-x86_64.tar.gz.sha256
tar -xzf ghost-linux-x86_64.tar.gz && ./install.sh

Windows: descarga ghost-windows-x64.zip desde la misma página. Verifica la suma de comprobación, descomprime y añade la carpeta a tu PATH. Luego ejecuta ghost doctor.

Comprueba de dónde viene una descarga. Cada artefacto de versión incluye una atestación firmada de procedencia de compilación, para que puedas demostrar que un archivo salió del flujo de trabajo de versiones de este repositorio y de ningún otro lugar, en un commit con nombre:

gh attestation verify ghost-windows-x64.mcpb --repo NORTHTEKDevs/ghost

Los binarios aún no están firmados con código, por lo que Windows SmartScreen te advertirá en el primer uso (haz clic en Más informaciónEjecutar de todos modos). Esa advertencia se refiere a la identidad del editor, que requiere un certificado de pago vinculado a una entidad legal verificada; la atestación anterior es la declaración más sólida sobre el origen y no cuesta nada, pero Windows no la lee. La canalización firma en cuanto se configura un certificado, de cualquier CA; consulta docs/code-signing.md y docs/signing-policy.md para saber qué se firma, por quién y qué sale de tu máquina (nada, a menos que configures una clave de visión). Si un motor antivirus pone en cuarentena una versión, verifica la suma de comprobación y consulta docs/antivirus.md para saber qué hacen los binarios para seguir siendo reconocibles y cómo informar de un falso positivo. El kit compra comodidad, no capacidad: todo lo que Ghost puede hacer está en el código fuente gratuito de abajo, y compilarlo tú mismo lleva un solo comando.

Opción C: compilar desde el código fuente (gratis, MIT). Ghost es de código abierto. Compílalo tú mismo:

git clone https://github.com/NORTHTEKDevs/ghost
cd ghost
cargo build --release --bin ghost --bin ghost-http --bin ghost-mcp
# binaries in target/release/

Requisitos: Windows 10 compilación 19041 o superior, o Linux con at-spi2-core (y Rust estable solo si compilas desde el código fuente).

En Linux:

sudo dnf install at-spi2-core xdg-desktop-portal xdg-desktop-portal-gnome
gsettings set org.gnome.desktop.interface toolkit-accessibility true
./scripts/install.sh          # build, install, register the MCP server, run doctor

No se necesitan paquetes de -devel: el motor de Linux es Rust puro. Configuración completa y solución de problemas: docs/linux-fedora.md.

Comprueba primero tu máquina:

ghost doctor

Informa de PASA/ADVERTENCIA/FALLA y sale con código 1 si algo está en FALLA. Ejecútalo antes de abrir un informe de problema: normalmente identifica el problema directamente.

  • Windows: versión de compilación, escritorio interactivo, automatización de interfaz de usuario, conocimiento de DPI, diseño de monitores, captura de pantalla, credenciales de visión opcionales.
  • Linux: tipo de sesión (X11/Wayland), accesibilidad del bus AT-SPI, si las aplicaciones exponen realmente árboles accesibles, el backend de entrada seleccionado y la captura de pantalla.

Inicio rápido: agentes de codificación y clientes MCP

Este es el camino para el que Ghost está diseñado. Nada que configurar y sin clave API.

Claude Desktop: descarga ghost-windows-x64.mcpb (o el paquete de Linux) desde la última versión y ábrelo: Configuración -> Extensiones -> Instalar desde archivo.

Claude Code:

claude mcp add ghost --scope user -- C:/path/to/ghost-mcp.exe

Cualquier otro cliente MCP (Codex, Cursor, un entorno personalizado): registra el binario como servidor stdio.

{
  "mcpServers": {
    "ghost": { "command": "C:/path/to/ghost-mcp.exe" }
  }
}

Ghost también aparece en el registro MCP como io.github.NORTHTEKDevs/ghost para clientes que instalan desde allí.

El Dockerfile del repositorio compila una imagen sin interfaz (docker build -t ghost-mcp .) que responde a initialize y tools/list sin pantalla; los registros y la CI la usan para inspeccionar el servidor. Un contenedor no tiene ventanas que controlar, por lo que no es una vía de instalación para uso real.

Cómo lo usa un agente. El bucle es mirar, actuar, confirmar:

  1. ghost_see window="Invoice Editor": cada elemento de la ventana con su nombre, rol, estado habilitado y centro en pantalla. El modo de texto extrae el texto legible en su lugar, aproximadamente diez veces más barato en tokens que una imagen.
  2. ghost_act window="Invoice Editor" name="Save" action="click": Ghost controla el control en segundo plano y devuelve verified: true solo cuando la pantalla o el valor del control muestran que la acción se realizó.
  3. ghost_screenshot window="Invoice Editor": píxeles, para los momentos en que un diseño, un gráfico o un lienzo necesitan los propios ojos del modelo.

El modelo lee el paso 1 y el paso 3 y elige; Ghost nunca tiene que adivinar qué significa una imagen, y no se necesita ninguna clave de visión.

Más allá del bucle: ghost_shell ejecuta comandos y sesiones persistentes de PowerShell, ghost_window lanza, lista, enfoca, restaura y cierra ventanas (en un escritorio oculto de forma predeterminada), ghost_assert y ghost_wait convierten "¿funcionó?" en una comprobación, y las herramientas de ghost_tab_* controlan el navegador en el que ya has iniciado sesión. La mayoría de las sesiones reales gastan más llamadas allí que en mirar.

54 herramientas en Windows (los nombres heredados siguen siendo utilizables): 20 verbos de escritorio que cubren ver/capturar/encontrar/actuar/teclas/desplazar/arrastrar/portapapeles/captura de pantalla/ventanas/shell/esperas/consultar/ejecutar, 19 herramientas de ghost_browser_* / ghost_tab_* y 15 herramientas solo de Windows para la política de enfoque y escritorios aislados. Compilar desde el código fuente en lugar de descargar: cargo build -p ghost-mcp --release.

Cada herramienta se ejecuta en su propia tarea, por lo que una llamada lenta no bloquea una rápida, y un segundo proceso de Ghost puede ejecutarse junto al primero. Una vez montado, ejecuta ghost verify para auditar eso en tu propia máquina.

Velocidad. El tiempo propio de Ghost es pequeño: unos 75 ms para una lectura de texto, 200 ms para un clic verificado, 1 ms para listar ventanas. Lo que hace lenta una sesión de agente es lo que ocurre alrededor de las llamadas, y tres hábitos eliminan la mayor parte. Nombra la ventana una vez y omite window= después: el ancla sigue a esa ventana por identificador, y un título que solía tener aún se resuelve al instante con title_drift en la respuesta. Espera una condición, no una duración: ghost_wait for=element, for=value y for=navigate (establece la barra de direcciones en segundo plano y regresa cuando cambia el título, unos 0,4 a 1,4 s donde una espera fija cuesta 6) regresan en el momento en que ocurre la acción. Procesa por lotes con ghost_run para que un turno del modelo haga varios pasos. scripts/speed-probe.mjs mide todo esto contra cualquier binario de ghost-mcp.

Control de shell (ghost_shell)

Ghost controla interfaces gráficas y la línea de comandos. ghost_shell ejecuta comandos de terminal y sesiones persistentes de PowerShell: compilaciones, git, CLI, ediciones de archivos en hosts sin herramientas de archivos, o lanzamiento de aplicaciones. op=run es de un solo uso (powershell/pwsh/cmd); op=open inicia un PowerShell persistente cuyas variables y directorio de trabajo sobreviven entre llamadas de op=send. La salida combina stdout+stderr, limitada al final para la ventana de contexto del agente; un comando con tiempo agotado sigue ejecutándose y se drena con op=read; ghost_stop mata un proceso descontrolado. op=run con el powershell predeterminado se sirve desde un proceso adicional previamente iniciado, por lo que un comando cuesta unos 85 ms en lugar de los 230-450 ms que tarda un inicio nuevo de PowerShell (el adicional es de un solo uso y se reemplaza de inmediato; GHOST_SHELL_WARM=off lo desactiva).

Inicia una sesión nueva de Claude Code desde el agente: ghost_shell op=run cmd='Start-Process wt -ArgumentList "pwsh","-NoExit","-Command","claude"', luego controla la nueva ventana de terminal con ghost_see / ghost_act / ghost_key.

Seguridad: el acceso al shell es potente. Establece GHOST_SHELL=off en el entorno del servidor para desactivar el verbo por completo: cada operación devuelve entonces un rechazo claro, dejando los verbos de automatización de interfaz gráfica totalmente utilizables.

Inicio rápido: CLI

# Launch Notepad and type into it
ghost launch notepad.exe
ghost focus-window "Notepad"
ghost type --role edit --text "hello from ghost"

# Keys and hotkeys
ghost press Enter
ghost hotkey --mods Ctrl --key s

# Screenshot
ghost screenshot --out shot.png

# Enumerate windows or UI
ghost list-windows
ghost describe --window "Notepad"

# Click at coords or by name
ghost click-at 500 300
ghost click --name "Save"

# Run a JSON intent (finite-state machine with retries, timeouts, conditions)
ghost run my-flow.json
echo '{"ops":[{"op":"launch","exe":"notepad.exe"}]}' | ghost run -

Todo genera JSON para facilitar la canalización hacia jq o scripts.

Inicio rápido: servidor HTTP

Inicia el servidor:

ghost-http --addr 127.0.0.1:7878

Luego desde cualquier lenguaje:

# Bash / curl
curl http://127.0.0.1:7878/list-windows
curl -X POST http://127.0.0.1:7878/click \
  -H 'content-type: application/json' \
  -d '{"name":"Submit"}'
curl http://127.0.0.1:7878/screenshot -o shot.png
# Python
import requests
requests.post("http://127.0.0.1:7878/launch", json={"exe": "notepad.exe"})
requests.post("http://127.0.0.1:7878/type",
              json={"role": "edit", "text": "hello from python"})
// Node
await fetch("http://127.0.0.1:7878/hotkey", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ mods: ["Ctrl"], key: "s" }),
});

Puntos finales: /health, /tools, /click, /click-at, /type, /press, /hotkey, /screenshot, /launch, /list-windows, /focus-window, /window-state, /describe, /clipboard (GET/POST), /run.

Inicio rápido: SDK de Rust

[dependencies]
ghost-session = { git = "https://github.com/NORTHTEKDevs/ghost" }
use ghost_session::{GhostSession, By, session::Region};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let session = GhostSession::new()?;
    session.launch("notepad.exe").await?;
    let edit = session.find(By::role("edit")).await?;
    edit.type_text("hello world")?;
    let png = session.screenshot(Region::full()).await?;
    std::fs::write("screen.png", png)?;
    Ok(())
}

Modelo de fiabilidad

La automatización de escritorio controlada desde un cliente MCP tiene un entorno de enfoque hostil: entre llamadas de herramientas, la terminal del propio cliente suele recuperar el enfoque del sistema operativo. Ghost está diseñado para eso:

  • ghost_act es atómico — encontrar → actuar → verificar mediante delta de pantalla. Una sola llamada, sin condición de carrera entre llamadas. Bajo la política background predeterminada, controla el elemento en su lugar y nunca eleva la ventana; eleva la política y además trae la ventana del objetivo al primer plano primero (AttachThreadInput, confirmado).
  • Cada respuesta de acción es honesta: verified (¿cambió realmente la pantalla?), focus_confirmed (¿estaba la ventana correcta en primer plano?) y un warning cuando alguno falla — nunca un ok:true a ciegas. Verifica verified antes de reemitir una acción.
  • No queda nada en ejecución. Los navegadores que Ghost lanza están en un objeto de trabajo kill-on-close: cuando el servidor termina, sin importar cómo termine, ellos terminan con él (dies_with_server en la respuesta de lanzamiento). Al inicio, el servidor también limpia los navegadores abandonados por servidores anteriores y los reporta en ghost_stats.orphan_sweep.
  • Ancla a una ventanaghost_see, ghost_find, ghost_act, ghost_key, ghost_click_at, ghost_scroll, ghost_wait, ghost_assert y ghost_screenshot (a menos que full=true) todas aceptan window (una subcadena del título, resuelta en tu escritorio y en los escritorios ocultos de Ghost: el título exacto supera al prefijo, el prefijo supera a la subcadena; una ventana que no está minimizada gana en empates). La coincidencia se convierte en el ancla de la sesión: llamadas posteriores sin window la apuntan a ella, nunca a la ventana que el humano esté usando. ghost_window op=focus ancla sin elevar bajo la política de fondo; op=anchor establece, limpia o reporta el ancla; cada respuesta lleva target {hwnd, title, surface, source}. Un título que no coincide con nada lista las ventanas abiertas y devuelve el código -32007.
  • Tu propio navegador, a través de su propio protocolo — cuando el proceso de una ventana se inició con --remote-debugging-port (Comet, Chrome, Edge, Brave), los mismos verbos anclados se enrutan a través del protocolo DevTools en lugar de UI Automation: nombres de DOM y aria-labels en lugar de un árbol disperso, selectores que sobreviven a re-renderizados, eventos de entrada confiables en ese renderizador, combinaciones completas de modificadores y emulación de foco para que las páginas que verifican document.hasFocus() sigan aceptando escritura. Nada de esto puede alcanzar tu primer plano. La respuesta lleva route: {browser, port, tab} y coords: viewport; un navegador sin puerto mantiene la ruta de UI Automation sin cambios. GHOST_CDP_ROUTE=off lo desactiva. Inicia Comet o Chrome una vez con --remote-debugging-port=9333 para obtenerlo.
  • Los fallos nombran las alternativas — "elemento no encontrado" va seguido de los nombres de los elementos más cercanos en esa ventana, para que un agente no gaste un viaje de ida y vuelta en ghost_see para aprender cómo llama la aplicación a la cosa.
  • Desambiguar duplicadosindex selecciona la enésima coincidencia cuando varios elementos comparten un nombre/rol (múltiples botones "Cerrar pestaña"); las respuestas llevan un conteo de matches.
  • Se audita a sí mismo — un muestreador independiente observa la ventana en primer plano y el tiempo de última entrada del sistema operativo; cualquier cambio de primer plano sin entrada de hardware real detrás se registra como sintético, con las llamadas de herramienta que estaban en vuelo. ghost_stats reporta el recuento, por lo que la afirmación principal se demuestra continuamente, no una sola vez.
  • Lee, no captura de pantallaghost_see mode=text extrae el texto legible de una ventana/página directamente del árbol de accesibilidad: más rápido y ~10 veces más barato en tokens que las imágenes.
  • La latencia es visible: cada respuesta lleva ms, y escalated: true marca cuando una búsqueda tuvo que pagar un viaje de ida y vuelta de VLM por red (niveles locales: caché → UIA → OCR están todos en el dispositivo).
  • Las ventanas nunca desaparecen: las ventanas minimizadas permanecen en ghost_window list (con state) y op=focus las restaura automáticamente. Una ventana que algo ocultó por completo (no visible, no minimizada) aparece con op=list include_hidden=true como state: "hidden", y op=state state=restore la trae de vuelta sin activarla. op=state también alcanza ventanas en los propios escritorios ocultos de Ghost, por lo que una aplicación iniciada con op=launch puede cerrarse por nombre.
  • Detener siempre funciona: ghost_stop adelanta la llamada en vuelo en el momento en que llega (lector dedicado de stdin), y Ctrl+Alt+G sigue siendo el interruptor de apagado a nivel del sistema operativo.

Modo de fondo (agente-harness / computer-use)

Los agentes-harness (OpenClaw, Hermes/cua-driver y cualquier cliente MCP) montan una herramienta de computer-use para permitir que un LLM opere el escritorio. Ghost es esa herramienta — y actúa sin robar tu foco ni mover tu cursor, para que un agente maneje una aplicación mientras tú sigues trabajando en otra ventana.

Desde 0.19 esto es el valor predeterminado y se aplica. La política de foco a nivel de proceso comienza en background, y cada primitiva que solo podría funcionar tomando el cursor real o la ventana en primer plano está bloqueada detrás de ella. No hay respaldo silencioso: una llamada sin ruta de fondo devuelve un error que nombra la acción y la ruta que no necesita cambio de política (lanzar la aplicación en el escritorio oculto, o el navegador a través de CDP).

Desde 0.22 la política también está bloqueada allí. Un valor predeterminado solo es una promesa si el agente no puede cambiarlo, y hasta 0.22 cualquier agente podía llamar a ghost_set_focus_policy foreground en el momento en que se rechazaba una acción de fondo, que es exactamente cuando un humano nota que Ghost mueve el mouse. Ahora esa llamada también se rechaza, con un error que lo dice. La clave es del operador, no del agente: establece GHOST_FOCUS_LOCK=off en el entorno del servidor MCP (la configuración del host que escribes) para permitir prefer_background y foreground nuevamente, y opcionalmente GHOST_FOCUS_POLICY para iniciar allí. ghost_focus_policy reporta la política y si está bloqueada; el servidor registra ambas al inicio.

// Only if you WANT an agent to be able to drive your real mouse and keyboard:
{ "mcpServers": { "ghost": {
    "command": "ghost-mcp",
    "env": { "GHOST_FOCUS_LOCK": "off", "GHOST_FOCUS_POLICY": "background" }
}}}

A lo que te estás comprometiendo

Ghost tiene dos configuraciones que deciden cuánto de tu computadora obtiene un agente. Instalar el paquete muestra ambas como casillas de verificación; ejecutar el binario directamente, son variables de entorno. El servidor imprime dónde se encuentra en ambas al inicio, por lo que el registro del host siempre responde la pregunta.

ConfiguraciónPredeterminadoQué significa "activado"
Mantener a Ghost fuera de tu mouse y teclado (GHOST_FOCUS_LOCK)activadoEl agente nunca puede elevar la política de foco, por lo que maneja ventanas en segundo plano y no puede tomar tu cursor. Desactívalo solo si quieres que un agente use tu entrada real.
Permitir comandos de shell (GHOST_SHELL)activadoghost_shell ejecuta programas con los derechos de tu cuenta, que es como un agente ejecuta builds, git y scripts — y es por eso que la mayoría de los agentes usan Ghost. Es acceso completo a la máquina. Desactívalo y cada llamada de shell se rechaza; las ventanas, la lectura de pantalla y la entrada siguen funcionando.

El shell está activado por defecto deliberadamente. Es la capacidad, no un extra, y una herramienta que se envía silenciosamente sin lo que la gente la instala es peor que una que te dice claramente lo que puede hacer. Si eso es más de lo que quieres entregar, la casilla está ahí mismo y el rechazo es explícito.

Una política bloqueada aún deja una cosa fuera del control de Ghost: una aplicación puede activar SU PROPIA ventana, y Chromium hace exactamente eso cuando un agente escribe en una página o hace clic en un botón a través de la API de accesibilidad. Nada fuera del navegador puede detener esa llamada. Entonces, desde 0.23, Ghost lo deshace. La auditoría de interferencia funciona como centinela: se le informa en el momento en que cualquier ventana toma el primer plano (un evento de Windows, aproximadamente un milisegundo) y lo devuelve directamente a menos que tú hayas elegido esa ventana tú mismo — al hacer clic en ella o con Alt+Tab hacia ella, lo que puede distinguir de la escritura porque observa la entrada REAL, no la entrada sintetizada. ghost_session_state reporta con qué frecuencia sucedió eso (foreground_handed_back).

Qué tan bien funciona, medido con un observador independiente mientras una persona escribía en otra ventana durante toda la ejecución (scripts/background-desktop-probe.mjs, scripts/interference-watch.ps1):

antes de 0.23ahora
pulsaciones de teclas entregadas a la ventana equivocada481 en seis ejecuciones de ~493
qué tan pronto se nota un primer plano robadonunca~1 ms

Desde 0.23.2 el primer plano se observa por evento en lugar de por sondeo, por lo que la devolución comienza aproximadamente un milisegundo después de que la ventana lo toma. Seis ejecuciones limpias con una persona escribiendo durante todo el proceso dieron 0, 0, 0, 1, 0 y 0 pulsaciones en la ventana que Ghost estaba manejando. No es una garantía — deshacer una activación nunca puede serlo — y para una garantía deja que Ghost inicie la aplicación, para que la activación nunca ocurra en absoluto.

Para cero activación en lugar de una breve, deja que Ghost inicie la aplicación: cualquier cosa que lance vive en un escritorio oculto con su propia cola de entrada y no puede tomar tu primer plano en absoluto, y un navegador que lance se maneja a través de CDP.

// Drive an app while the human keeps working. No flag needed: background is the default.
ghost_window { "op": "launch", "exe": "notepad.exe" }
// -> { "surface": "hidden", "desktop": "auto", "window": { "title": "Notepad", ... }, "target": {...} }
ghost_act { "role": "edit", "action": "type", "text_input": "hello" }   // targets the anchor
// -> { "verified": true, "focus_preserved": true, "cursor_preserved": true, "mode": "hidden" }
ghost_act { "window": "Comet", "name": "Post", "action": "click" }      // a window on YOUR desktop
// -> { "verified": true, "focus_preserved": true, "cursor_preserved": true, "mode": "background" }
  • Los lanzamientos nunca salen a la superficie. Medido en la máquina de CI de este repositorio: Edge y Chrome activan su primera ventana al lanzarse en todos los estilos de lanzamiento (normal, oculto, minimizado, desde un padre en segundo plano, colocado en -32000,-32000). Una ventana creada en tu escritorio toma tu teclado en el momento en que existe. Así que bajo la política de segundo plano, Ghost nunca crea una allí: ghost_window op=launch, ghost_run pasos de lanzamiento y ghost_browser_launch mode=windowed comienzan en un escritorio oculto con su propia cola de entrada, y la ventana está anclada para que el siguiente ghost_see la muestre. Un observador independiente muestreando el primer plano a 100 ms a lo largo de una ejecución completa de lanzamiento-conducción-cierre reportó cero cambios.
  • Verdadero segundo plano mediante mensajes de ventana publicados. Los controles Win32 reales se manejan con BM_CLICK / WM_LBUTTONDOWN·UP (clic), WM_SETTEXT (escribir) y WM_MOUSEWHEEL (desplazar). Estos no activan la ventana.
  • Controles sin ventana, sin pantalla. Los controles UWP/WinUI/Chromium/Electron no tienen un identificador de ventana. Ghost los maneja con patrones de Automatización de UI - Invoke para un clic, ValuePattern para escribir. Chromium responde a algunos de estos activando su propia ventana cuando Windows lo permite (justo después de que usaste ese navegador): medido en Edge, un SetValue en una entrada web o la barra de direcciones, un Invoke en un botón de página y un clic publicado trajeron la ventana al frente en ~90 ms. Desde 0.21.10 eso se deshace en el acto: Ghost observa el primer plano alrededor de cada verbo de escritorio de usuario, y cuando el objetivo o cualquier ventana de su proceso lo toma, lo devuelve a la ventana que tenías, en 30 a 50 ms, y reporta focus_preserved: false con un registro focus_guard diciéndolo. Las teclas individuales publicadas llegan al elemento enfocado de la página y no activan nada.
  • Los hijos del shell nunca abren una terminal. El servidor MCP no tiene consola, por lo que un shell iniciado sin más tampoco tiene una, y cada programa de consola que ejecutó (node, python, cargo, cmd) obtuvo una ventana nueva de Windows Terminal que tomó el primer plano durante la duración de la ejecución. ghost_shell ahora crea sus shells con una consola invisible; los hijos la heredan y ninguna ventana aparece nunca. Medido: nueve cambios de primer plano en siete segundos antes, cero después, salida sin cambios.
  • Verificado incluso mientras está ocluido. type se confirma leyendo el valor del control de vuelta; click mediante un delta de PrintWindow antes/después que renderiza una ventana que no es visible. Cada respuesta lleva verified, focus_preserved, cursor_preserved - Ghost nunca afirma una acción en segundo plano que no puede confirmar.
  • Los escritorios ocultos son el mismo vocabulario. Una ventana en el escritorio oculto se maneja con las mismas llamadas window=<title>; target.surface: "hidden" es la única diferencia. Las ventanas de Chromium y Electron allí se manejan con mensajes publicados en lugar de acciones UIA (Chromium atiende Invoke/SetValue en un escritorio no compuesto solo después de una espera interna de ~2 s; un clic publicado aterriza en ~100 ms), y la verificación de píxeles se omite para ellas porque un render por software allí cuesta segundos - confirma a través de ghost_tab_eval o ghost_see. El SendInput real todavía no funciona en un escritorio oculto (Windows lo rechaza fuera del escritorio de entrada), por lo que una aplicación que responde solo a entrada de hardware real necesita la política foreground en tu propio escritorio.
  • Honesto sobre aplicaciones de instancia única. El Bloc de notas de Windows 11, el Explorador o un navegador en su perfil predeterminado entregan un lanzamiento a su proceso ya en ejecución, cuyas ventanas viven en tu escritorio. Ghost no puede prevenir eso; reporta surface: "user" con una advertencia en lugar de afirmar que la aplicación está oculta.

Soporta click, type, double_click, right_click, hover y desplazamiento, además de ghost_key para teclas individuales (Enter/Tab/teclas F/carácter mediante WM_KEYDOWN/WM_CHAR). El indicador background: true se acepta por compatibilidad; es el comportamiento predeterminado.

El portapapeles y las combinaciones de edición también funcionan en segundo plano - Ctrl+C, Ctrl+X, Ctrl+V, Ctrl+Z y Ctrl+A se envían como los mensajes semánticos que una aplicación realmente implementa (WM_COPY, WM_CUT, WM_PASTE, WM_UNDO, EM_SETSEL) en lugar de como un modificador publicado que las aplicaciones que leen GetKeyState ignorarían. Las combinaciones fuera de ese conjunto se rechazan en lugar de descartarse silenciosamente, porque publicar no puede establecer el estado del modificador que esas aplicaciones leen; usa la política foreground para ellas.

Visión: tu agente es el modelo

Ghost es ojos y manos, no un cerebro. Cuando un modelo lo maneja a través de MCP, ese modelo hace la observación: ghost_see le da la ventana como elementos estructurados con coordenadas, ghost_see mode=text le da el texto legible, y ghost_screenshot le da píxeles cuando la estructura no es suficiente. Claude, GPT, Gemini y los modelos de visión de peso abierto fuertes leen todo eso directamente. No hay clave que configurar ni nada que ajustar, y Ghost nunca tiene que interpretar una imagen en nombre del modelo.

El nivel de visión integrado opcional existe para llamadores que no tienen un modelo propio - la CLI, la API HTTP, un archivo de intención - y para la conveniencia de un objetivo de descripción (ghost_find description="the blue Submit button") cuando prefieres que Ghost lo resuelva en lugar de leer el árbol tú mismo. Funciona con cualquier modelo de visión con capacidad de herramientas detrás de un endpoint compatible con OpenAI (OpenAI, Gemini, Groq, NVIDIA, o un servidor local vLLM / Ollama / LM Studio) o Anthropic. Apunta GHOST_VISION_BASE_URL y GHOST_VISION_MODEL al endpoint y establece GHOST_VISION_API_KEY (un servidor local sin clave necesita solo la URL base). Sin él, los objetivos de descripción devuelven un error claro nombrando la alternativa; cada otra herramienta no se ve afectada.

Parada de emergencia

Presiona Ctrl+Alt+G en cualquier momento para detener inmediatamente cada llamada de acción. Las consultas de solo lectura (ghost_see, ghost_snapshot, ghost_window lista) siguen respondiendo, para que puedas inspeccionar lo que sucedió mientras todo está detenido.

  • Todas las acciones en cola se cancelan
  • Cualquier tecla modificadora mantenida (Shift, Ctrl, Alt) se libera inmediatamente
  • Sin teclas atascadas, sin estados de modificador atascados
  • A nivel de sesión desde 0.19. La parada es un evento de kernel nombrado (Local\ghost-emergency-stop-event), por lo que una pulsación detiene cada proceso de Ghost en tu sesión de inicio de sesión, no solo el que registró la tecla de acceso rápido. ghost_reset reanuda el servicio, nuevamente para todos ellos.

Localizadores de elementos

session.find(By::name("Save")).await?          // by accessible name (substring)
session.find(By::role("edit")).await?          // by UIA control type
session.find(By::role("button")).await?

Desde la CLI: ghost click --name "Save" o ghost click --role button.

Intenciones - Flujos declarativos

Escribe flujos de varios pasos reproducibles como JSON. El ejecutor FSM admite reintentos, tiempos de espera y condiciones JSONLogic para abort_if / retry_if.

{
  "ops": [
    { "op": "launch", "exe": "notepad.exe" },
    { "op": "focus_window", "name": "Notepad" },
    { "op": "type", "role": "edit", "text": "hello" },
    { "op": "hotkey", "mods": ["Ctrl"], "key": "s" }
  ]
}

Ejecuta con ghost run flow.json, POST /run o ghost_execute_intent a través de MCP.

Arquitectura

ghost-cli     ghost-http     ghost-mcp     Rust SDK
    \            |            /   |           |
     \           |           /    |           |
      +-----> ghost-session <-----|-----------+   ← safe Rust API
              /           \       |
      ghost-core      ghost-linux |               ← one cfg alias picks the engine
          |                |      |
    Win32 UIA,       AT-SPI2 over |               ← ghost-core: SendInput, DXGI/GDI
    posted msgs      D-Bus, XTEST |               ← ghost-linux: portal / uinput
          |                |      |
      Windows OS        Linux     +-> ghost-browser  ← CDP over the DevTools port,
                                                        engine-independent

Crates de soporte: ghost-cache (instantánea UIA + delta), ghost-intent (ejecutor FSM + JSONLogic), ghost-ground (la cascada de niveles de localizador), ghost-platform (la matriz de capacidades reportada por SO).

El nivel de visión integrado (Set-of-Marks)

Esta sección describe el nivel opcional anterior; un agente que maneja Ghost a través de MCP obtiene la misma información de ghost_see y no lo necesita.

Cuando localizas un elemento por descripción en lenguaje natural (ghost_find description="el botón azul de enviar", o cuando una búsqueda de nombre/texto falla y escala al VLM), Ghost no le pide al modelo que adivine coordenadas de píxeles - los modelos no son confiables en eso (en pruebas, un simple "dame las coordenadas del botón de igual" aterrizó ~250px fuera del objetivo). En su lugar usa Set-of-Marks: superpone insignias numeradas en los elementos detectados de la ventana, envía esa captura marcada más la etiqueta de nombre accesible de cada insignia, y le pide al modelo qué número coincide. El número se mapea de vuelta al rectángulo exacto de ese elemento, por lo que el resultado es una coordenada real sobre el elemento, no una suposición de regresión.

En una verificación en vivo en Calculadora, cuatro descripciones ("el botón de igual", "el botón de más", "la tecla del número siete", "el botón de multiplicar") cada una aterrizó exactamente en el botón correcto - versus ~250px fuera con regresión de coordenadas.

Alcance honesto: cuando los elementos detectados llevan nombres accesibles (la mayoría de las aplicaciones), las etiquetas hacen gran parte de la desambiguación; para íconos sin etiqueta el modelo se apoya en la posición/apariencia visual de la insignia.

Aplicaciones de lienzo / sin árbol de accesibilidad. Cuando el árbol UIA es escaso (UIs dibujadas a medida, superficies de escritorio remoto, lienzos de juegos), Ghost aumenta los candidatos de Set-of-Marks con un detector clásico de CV por CPU integrado (ghost_ground::cv_detect): densidad de bordes → componentes conectados → filtro de tamaño/aspecto, sin GPU y sin descarga de modelo. Le da al VLM cajas reales para elegir donde el árbol de accesibilidad no tiene nada. Es más grueso que un detector entrenado - un nivel opcional OmniParser ONNX (--features yolo + GHOST_YOLO_MODEL) se conecta al mismo camino de Set-of-Marks cuando hay un modelo GPU disponible. El flujo completo CV-marcas → VLM-elección necesita una clave de visión configurada.

Benchmark - éxito de tarea, no "la llamada devolvió ok"

bench/ contiene un benchmark reproducible de extremo a extremo: maneja el binario real ghost-mcp a través de 14 tareas de escritorio de Windows y puntúa cada una por re-observar el resultado real (¿la pantalla de Calculadora realmente lee 42? ¿el valor escrito realmente está presente?), nunca confiando en el retorno de una llamada de herramienta.

Última ejecución (ver bench/results/latest.md):

14/14 tareas aprobadas (100%), mediana ~2.7 s por tarea (tiempo total de pared incl. lanzamiento de aplicación) - percepción, acción de clic/teclado+verificación, esperas, gestión de ventanas (listar/minimizar/restaurar), extracción de texto, desambiguación, encadenamiento de flujos, ida y vuelta del portapapeles, errores estructurados, capturas de elementos y aserciones de valor.

Y demuestra que puede fallar: --self-test ejecuta controles negativos deliberadamente incorrectos (afirma que la pantalla lee 99 cuando lee 42, etc.) y pasa solo si el arnés puntúa cada uno como FALLO - por lo que la ejecución verde anterior es una señal real, no un sello de goma.

Reproduce en cualquier máquina Windows 10/11:

cargo build --release -p ghost-mcp
python bench/run_bench.py             # exit 0 iff every task passed
python bench/run_bench.py --self-test # exit 0 iff the harness caught every planted failure

Prueba de confiabilidad

bench/soak.py maneja muchos ciclos de actuar-luego-verificar y se basa en las señales que las pruebas unitarias no pueden ver: con qué frecuencia verified devuelve nulo/falso, tasa de pérdida de enfoque, tasa de error, si el efecto real de cada acción sucedió (la pantalla se re-observa, nunca se confía en el retorno), y percentiles de latencia.

Última (160 actos): APROBADO - verificar-nulo 0.0, pérdida de enfoque 0.0, desajuste de efecto 0 (100% correcto), p50 85ms / p95 117ms. Ver bench/results/soak.md.

python bench/soak.py                  # exit 0 iff every reliability threshold holds
python bench/soak.py --cycles 250     # ~1000 acts
python bench/soak.py --self-test      # exit 0 iff the harness flags a planted-wrong effect

Publicamos deliberadamente solo los números medidos de Ghost - nunca columnas inventadas para otras herramientas. bench/README.md da un protocolo honesto para comparar contra Playwright-MCP / Computer Use / UI-TARS, y explica por qué una comparación ingenua con el mismo conjunto no es comparable (Playwright es solo navegador; los agentes de visión necesitan una API + VM).

Microbenchmarks

OperaciónMedido
Captura de región, GDI, cualquier tamaño~16.5 ms
Captura de región, DXGI, 1600x900~70-83 ms
Conversión BGRA→RGBA, región 400x300~206 µs
JSONLogic eq/var32.2 ns
Compilación de intención (3op)1.49 µs

La medición de captura de extremo a extremo (release, crates/ghost-core/tests/capture_latency_probe.rs) corrigió la suposición de v0.10.0: la adquisición DXGI domina y golpea un acantilado en ventanas grandes, por lo que las capturas de región (actuar-verificar, capturas, Set-of-Marks) se enrutan a través de GDI BitBlt plano de ~16.5ms en v0.11.0; pantalla completa todavía usa DXGI. Ejecuta el microbenchmark de conversión: cargo bench -p ghost-core --bench convert. Líneas base anteriores: docs/benches/v030-baseline.md.

Requisitos

  • Windows 10 compilación 19041 o posterior
  • Linux con at-spi2-core y una sesión de escritorio (X11 o Wayland); xdg-desktop-portal-gnome adicionalmente para entrada y captura en Wayland
  • Un navegador de la familia Chromium (Chrome, Comet, Edge o Brave) para las herramientas ghost_browser_* / ghost_tab_* únicamente; los verbos de escritorio no requieren ninguno
  • Rust estable (solo para compilar desde el código fuente)

Licencia

MIT - Copyright 2026 Northtek