Ghost
Controle verificado de todo o desktop para agentes no Windows e Linux: opera aplicativos sem API em segundo plano sem roubar o foco, gerencia janelas e desktops ocultos, executa comandos de shell, controla seu próprio navegador Chromium via CDP e verifica cada ação. 54 ferramentas, Rust, MIT.
Documentação
Ghost
Controle verificado de todo o desktop, para agentes e programas, no Windows e no Linux. O Ghost dá ao Claude Code, Codex, Cursor, qualquer harness MCP ou um script simples a superfície de controle do próprio sistema operacional: os apps sem API, as janelas, o shell e o navegador no qual você já está logado - em segundo plano, sem tomar sua tela ou cursor, com cada ação comprovadamente executada.
Como o Playwright, mas para o desktop nativo, e construído para agentes. O Ghost faz a percepção, a ação e a verificação; o modelo que você já está executando faz qualquer análise necessária, então não há chave de API de visão para configurar.
Uma superfície MCP, dois motores: Win32 UI Automation no Windows, AT-SPI2 sobre D-Bus no Linux. Os verbos, os níveis de localizador e o loop agir-e-verificar são escritos uma vez e se comportam da mesma forma em ambos. Suporte de plataforma · Configuração do Linux
Por que o Ghost é diferente
- Roda em segundo plano, e isso é imposto. Um agente pode clicar, digitar e
usar atalhos dentro de um app enquanto você continua trabalhando em outra
janela - sem roubo de foco, sem salto de cursor. Ele envia mensagens de janela
para controles reais e usa padrões de UI Automation em controles sem janela; a
maioria das ferramentas só consegue dirigir o que está em primeiro plano. Desde
a 0.19 isso é uma política, não uma preferência: a política de foco padrão é
background. Desde a 0.20 também é construtiva: qualquer coisa que o Ghost inicia (um app, um navegador com janela) nasce em um desktop oculto que tem sua própria fila de entrada e não pode tomar seu primeiro plano, e os verbos comuns o dirigem lá pelo título da janela. Uma chamada que realmente não tem caminho em segundo plano falha nomeando a ação em vez de silenciosamente tomar a tela. Desde a 0.22 a política está travada lá: nenhuma chamada de ferramenta pode elevá-la, então um agente não pode decidir por conta própria tomar seu mouse. Você pode, definindoGHOST_FOCUS_LOCK=offno ambiente do servidor. E desde a 0.23 uma janela que toma o primeiro plano por conta própria - os navegadores fazem isso, em suas próprias chamadas de acessibilidade - é devolvida imediatamente, então sua digitação continua indo para onde você está olhando. Medido em um desktop real com uma pessoa digitando o tempo todo: de aproximadamente 490 teclas por execução, zero a uma alcançou a janela que o agente estava dirigindo. (como) - Nunca sua janela por acidente. A sessão lembra a última janela que o agente nomeou ou lançou, e todo verbo com escopo de janela a atinge por padrão. A janela em primeiro plano do humano é usada apenas quando nada foi ancorado, e a resposta diz isso. Três semanas de transcrições reais mostraram "elemento não encontrado na janela em primeiro plano" como a principal falha antes disso; era o agente procurando na janela que você tinha aberta.
- Muitos agentes ao mesmo tempo. As solicitações são despachadas em paralelo, então uma espera de 15 segundos em uma aba não trava uma consulta instantânea atrás dela, e um segundo processo do Ghost executa seu próprio navegador ao lado do primeiro sem disputar o mouse.
- Prove na sua máquina.
ghost verifydirige o servidor MCP real via stdio e audita cada afirmação acima contra orçamentos de tempo rígidos, saindo com código não zero se qualquer uma delas não se sustentar no seu hardware. - Cada ação é verificada. O Ghost re-verifica a tela (ou lê o valor do
controle de volta) após agir e retorna
verified/focus_confirmed- nunca umok:truecego. Agentes falham agindo e não sabendo se funcionou; o Ghost fecha esse loop. - Dirige apps sem API. Win32 legado, WPF, Electron, UWP, portais de fornecedores - o software que não tem integração e mais precisa de automação. Sem CDP, sem navegador, sem cooperação do app.
- Sem chave de visão. O modelo que dirige o Ghost lê
ghost_see(cada elemento com seu nome, papel e centro na tela) oughost_screenshotele mesmo. O nível de visão próprio do Ghost é opcional, existe para chamadores sem modelo próprio, e está desligado até ser configurado. - Nativo de acessibilidade e profundo. Descoberta real de elementos através da API de acessibilidade do próprio SO - UI Automation no Windows, AT-SPI2 no Linux - não adivinhação de pixels. Os elementos voltam com nomes, papéis e limites reais.
Veja em um script: examples/background_agent_demo.py
dirige um app em segundo plano enquanto o primeiro plano continua seu.
Comparação honesta vs Playwright-MCP / cua-driver / Computer Use:
docs/comparison.md.
Para que as pessoas usam
Visão é a menor parte disso. Em uma sessão típica, um agente chama o Ghost principalmente para agir, gerenciar janelas e processos, executar comandos e ler o estado de volta.
| Uso | Ferramentas | Chamador típico |
|---|---|---|
| Dirigir apps sem API: instaladores, software de negócios legado, portais de fornecedores, ferramentas WPF e Electron | ghost_act, ghost_key, ghost_scroll, ghost_drag | agentes, scripts RPA |
| Controle de janelas e processos: lançar invisivelmente, focar, minimizar, restaurar, fechar, recuperar janelas ocultas, varrer navegadores órfãos | ghost_window, ghost_desktop_*, ghost_stats | agentes, scripts de operações |
| Um terminal para o agente: builds, git, CLIs, estado persistente do PowerShell, iniciar outra sessão do Claude Code | ghost_shell, ghost_run | agentes de codificação no Windows |
| Dirigir o navegador no qual você já está logado, através da porta DevTools: abas, navegação, cliques no DOM, eval de JS, texto da página | 19 ferramentas ghost_browser_* e ghost_tab_* | agentes, automações web |
| Ler dados de apps sem exportação: texto de acessibilidade, texto de aba, OCR | ghost_see mode=text, ghost_tab_text | agentes, scripts de relatórios |
| Tornar "funcionou?" uma verificação de máquina: elemento existe, valor igual, esperar por inatividade ou texto | ghost_assert, ghost_wait | agentes de QA, CI |
| Desktops isolados: trabalho GUI noturno e agentes paralelos que nunca tocam a tela do humano | ghost_window op=launch, a política de foco, ghost_desktop_* | execuções autônomas |
| Fluxos de múltiplas etapas reproduzíveis com tentativas e condições, sem modelo no loop | intents via ghost run, POST /run, ghost_execute_intent | trabalhos agendados |
| A área de transferência como ponte para apps que resistem à digitação | ghost_clipboard | todos os acima |
Cada linha roda sob as mesmas garantias: a ação retorna verified, a
política padrão nunca toma seu primeiro plano, e Ctrl+Alt+G para todos os
processos do Ghost de uma vez.
O que é o Ghost?
O Ghost é a camada entre um modelo e o desktop. O modelo raciocina; o Ghost vê a tela da forma que o sistema operacional vê, age em controles reais sem tocar seu primeiro plano e reporta se a ação aconteceu. Ele dá controle programático sobre qualquer aplicativo de desktop - Win32 nativo, Electron, WPF, UWP, GTK, Qt, ou outro - para um agente, um script ou um programa.
No Windows ele usa UI Automation para descoberta de elementos, SendInput para
injeção de teclado/mouse e DXGI/GDI para captura de tela. No Linux ele usa
AT-SPI2 sobre D-Bus para descoberta e ações, XTEST (X11) ou o portal RemoteDesktop
/ uinput (Wayland) para entrada, e X11 GetImage ou o portal Screenshot para
captura. O motor Linux é Rust puro - sem pacotes -devel para instalar.
Distribua de três formas:
- Servidor
ghost-mcp- a superfície principal: um servidor Model Context Protocol para Claude Code, Claude Desktop, Codex, Cursor e qualquer cliente MCP (54 ferramentas no Windows) - CLI
ghost- comandos de uso único, ótimo para scripts e CI (ghost click --name "Submit") - Servidor
ghost-http- API REST local, chame-a de Python, Node, curl, qualquer coisa (curl http://127.0.0.1:7878/list-windows)
A superfície MCP é 20 verbos de desktop, 19 ferramentas ghost_browser_* / ghost_tab_*
para dirigir abas individuais de navegador em segundo plano (Chrome, Comet, Edge,
Brave) e 15 ferramentas exclusivas do Windows: a política de foco mais ghost_desktop_*
para controle explícito de desktops Windows isolados que o usuário nunca vê. Sob
a política padrão, você raramente precisa desta última: ghost_window op=launch já inicia o
app no desktop oculto auto, e ghost_see / ghost_act / ghost_key /
ghost_scroll o alcançam com window=<title> exatamente como alcançam uma janela no
seu próprio desktop (target.surface na resposta diz qual). UIA, mensagens de
janela e captura funcionam totalmente lá. SendInput real não funciona, porque
o Windows o recusa fora do desktop de entrada, e a digitação é comprovada lendo o
valor do controle de volta, então um alvo que descarta caracteres postados retorna
um erro em vez de um falso sucesso. Os verbos de desktop e as ferramentas de
navegador também são construídos no Linux; a política de foco e os desktops
ocultos são exclusivos do Windows.
Nenhum Claude necessário. Nenhum navegador necessário. Sem CDP. Ele dirige apps através das APIs de automação e entrada do próprio SO, então funciona com apps nativos que não têm API e nem hooks de automação próprios - a mesma confiabilidade se um app foi construído para ser automatizado ou não.
Plataformas
| Plataforma | Status | Motor |
|---|---|---|
| Windows | ✅ completo e verificado | ghost-core - Win32 UI Automation, SendInput, mensagens de janela postadas, captura DXGI/GDI |
| Linux, X11 | ✅ funcional - verificado por testes CI ao vivo contra um app GTK real | ghost-linux - AT-SPI2 sobre D-Bus, entrada XTEST, captura X11 GetImage |
| Linux, Wayland | ⚠️ implementado, NÃO verificado - nenhum teste o executou em hardware | mesma descoberta e ações AT-SPI2; entrada e captura vão pelos portais RemoteDesktop / Screenshot ou uinput |
| macOS | 🚧 andaime | Accessibility + CGEvent + ScreenCaptureKit - a ser construído em um Mac |
Wayland merece a linha separada em vez de uma nota de rodapé: é a sessão padrão
no Ubuntu e Fedora atuais, então é o que a maioria dos usuários Linux realmente
executaria, e é a parte sem teste por trás. A camada de descoberta e ação é
compartilhada com X11 e está coberta, e é a camada que mais importa aqui -
AT-SPI2 pede ao aplicativo para fazer a coisa, então não há ponteiro para mover
nem janela para elevar. O que não está verificado é o fallback por baixo: entrada
de portal, captura de portal, uinput. Se você executa Wayland, trate ghost doctor
como a primeira coisa a executar e espere relatar bugs. Relatórios são bem-vindos
e são o caminho mais rápido para essa linha mudar.
ghost-session e ghost-mcp são compartilhados: os níveis de localizador,
cascata de ancoragem, loop agir-e-verificar e os 20 verbos MCP centrais são
escritos uma vez e rodam em ambas as plataformas. Apenas o motor por baixo muda,
atrás de um alias cfg de uma linha. As ferramentas de navegador e aba
são independentes do motor e são construídas para ambos; a política de foco e os
desktops isolados são exclusivos do Windows e são reportados como tal em vez de
fingidos.
A cunha sobrevive à portabilidade. No Windows, dirigir um app sem roubar foco é construído em mensagens de janela postadas. O Linux tem um análogo mais limpo nas ações AT-SPI2: o aplicativo executa a operação através de seu próprio toolkit, então não há ponteiro para mover nem janela para elevar. Essa camada é o mesmo código sob X11 e Wayland; entrada sintética é apenas o fallback por baixo dela, e o fallback é a parte que o Wayland não foi testado.
Isso é testado, não afirmado: CI monta um desktop real (Xvfb + D-Bus + at-spi-bus-launcher), dirige um aplicativo GTK real e exige que texto escrito via AT-SPI leia de volta do app e que invocar um botão realmente dispense o diálogo. Entrada e captura de portal Wayland estão implementadas, mas ainda não verificadas em hardware.
Configuração do Linux, checklist de verificação e limitações honestas:
docs/linux-fedora.md. Matriz de capacidades em todas as
três: docs/cross-platform.md.
O Ghost é uma ferramenta de automação de propósito geral. Use-a em sistemas que você possui ou está autorizado a automatizar, e de acordo com os termos do software que você dirige.
Instalar
One-click - MCP Bundle (grátis). Toda versão inclui ghost-windows-x64.mcpb e
ghost-linux-x86_64.mcpb na página de Releases.
Abra um em um cliente que suporte MCP Bundles (Claude Desktop: Settings -> Extensions ->
Install from file) e o Ghost estará registrado, sem edição de PATH ou configuração, e sem chave de API. O Ghost também está listado
no registro MCP como io.github.NORTHTEKDevs/ghost,
para que clientes compatíveis com registro possam instalá-lo a partir daí. O bundle contém apenas o servidor ghost-mcp;
o CLI e o servidor HTTP estão nos arquivos abaixo.
Binários pré-compilados (grátis). Toda versão inclui arquivos assinados por checksum para ambas as plataformas na página de Releases:
# 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: baixe ghost-windows-x64.zip da mesma página. Verifique o
checksum, descompacte e adicione a pasta ao seu PATH. Em seguida, execute ghost doctor.
Verifique a origem de um download. Cada artefato de versão carrega uma atestação de proveniência de build assinada, para que você possa comprovar que um arquivo veio do fluxo de trabalho de releases deste repositório e de nenhum outro lugar, em um commit nomeado:
gh attestation verify ghost-windows-x64.mcpb --repo NORTHTEKDevs/ghost
Os binários ainda não são assinados com código, então o SmartScreen do Windows avisará no primeiro uso (clique em More info
→ Run anyway). Esse aviso é sobre a identidade do editor, que exige um certificado pago vinculado a uma entidade legal
verificada; a atestação acima é a declaração mais forte sobre a origem e não custa nada, mas o Windows não a lê.
O pipeline assina assim que um certificado é configurado, de qualquer CA - veja
docs/code-signing.md e
docs/signing-policy.md para saber o que é assinado, por
quem, e o que sai da sua máquina (nada, a menos que você configure uma chave de visão). Se um antivírus colocar uma versão em quarentena, verifique o
checksum e veja docs/antivirus.md para saber o que os binários fazem para permanecerem reconhecíveis e como
relatar um falso positivo. O kit compra conveniência, não capacidade - tudo o que o Ghost pode fazer está no código-fonte gratuito
abaixo, e compilá-lo você mesmo leva um único comando.
Opção C - Compilar a partir do código-fonte (grátis, MIT). O Ghost é open source. Compile você mesmo:
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 build 19041+ ou Linux com at-spi2-core (e Rust
stable apenas se compilar a partir do código-fonte).
No 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
Nenhum pacote -devel é necessário - o mecanismo Linux é Rust puro. Configuração completa e
solução de problemas: docs/linux-fedora.md.
Verifique sua máquina primeiro:
ghost doctor
Relata PASS/WARN/FAIL e sai com código 1 se algo estiver FAIL. Execute antes de abrir um issue - geralmente ele nomeia o problema diretamente.
- Windows: versão do build, desktop interativo, UI Automation, consciência de DPI, layout de monitores, captura de tela, credenciais opcionais de visão.
- Linux: tipo de sessão (X11/Wayland), acessibilidade do barramento AT-SPI, se os aplicativos estão realmente expondo árvores acessíveis, o backend de entrada selecionado e captura de tela.
Início Rápido - agentes de codificação e clientes MCP
Este é o caminho para o qual o Ghost foi construído. Nada para configurar e sem chave de API.
Claude Desktop: baixe ghost-windows-x64.mcpb (ou o bundle Linux) da
última versão e abra-o:
Settings -> Extensions -> Install from file.
Claude Code:
claude mcp add ghost --scope user -- C:/path/to/ghost-mcp.exe
Qualquer outro cliente MCP (Codex, Cursor, um harness personalizado): registre o binário como um servidor stdio.
{
"mcpServers": {
"ghost": { "command": "C:/path/to/ghost-mcp.exe" }
}
}
O Ghost também está listado no registro MCP
como io.github.NORTHTEKDevs/ghost para clientes que instalam a partir daí.
O Dockerfile do repositório compila uma imagem headless (docker build -t ghost-mcp .) que
responde a initialize e tools/list sem display; registros e CI o usam para
inspecionar o servidor. Um contêiner não tem janelas para controlar, então não é um caminho
de instalação para uso real.
Como um agente o usa. O ciclo é olhar, agir, confirmar:
ghost_see window="Invoice Editor"- cada elemento na janela com seu nome, função, estado habilitado e centro na tela. O modo de texto extrai o texto legível em vez disso, aproximadamente dez vezes mais barato em tokens do que uma imagem.ghost_act window="Invoice Editor" name="Save" action="click"- o Ghost controla o controle em segundo plano e retornaverified: truesomente quando a tela ou o valor do controle mostra que a ação ocorreu.ghost_screenshot window="Invoice Editor"- pixels, para os momentos em que um layout, um gráfico ou um canvas precisa dos próprios olhos do modelo.
O modelo lê o passo 1 e o passo 3 e escolhe; o Ghost nunca precisa adivinhar o que uma imagem significa, e nenhuma chave de visão está envolvida.
Além do ciclo: ghost_shell executa comandos e sessões persistentes do PowerShell,
ghost_window inicia, lista, foca, restaura e fecha janelas (em um desktop oculto
por padrão), ghost_assert e ghost_wait transformam "funcionou?" em uma
verificação, e as ferramentas ghost_tab_* controlam o navegador no qual você já está conectado.
A maioria das sessões reais gasta mais chamadas lá do que olhando.
54 ferramentas no Windows (nomes legados permanecem acionáveis): 20 verbos de desktop cobrindo
ver/capturar/encontrar/agir/teclas/rolar/arrastar/área de transferência/captura de tela/janelas/shell/esperas/consultas/executar,
19 ferramentas ghost_browser_* / ghost_tab_* e 15 ferramentas exclusivas do Windows para a política de foco
e desktops isolados. Compilar a partir do código-fonte em vez de baixar:
cargo build -p ghost-mcp --release.
Cada ferramenta roda em sua própria tarefa, então uma chamada lenta não bloqueia uma rápida, e um
segundo processo do Ghost pode rodar ao lado do primeiro. Depois de montado, execute
ghost verify para auditar isso na sua própria máquina.
Velocidade. O tempo do próprio Ghost é pequeno: cerca de 75 ms para uma leitura de texto, 200 ms para
um clique verificado, 1 ms para listar janelas. O que torna uma sessão de agente lenta é
o que acontece ao redor das chamadas, e três hábitos removem a maior parte disso. Nomeie a
janela uma vez e omita window= depois: a âncora segue essa janela pelo
handle, e um título que ela costumava ter ainda resolve instantaneamente com
title_drift na resposta. Espere por uma condição, não por uma duração:
ghost_wait for=element, for=value e for=navigate (define a barra de endereço
em segundo plano e retorna quando o título muda, cerca de 0,4 a 1,4 s
onde um sleep fixo custa 6) retornam no momento em que a coisa aconteceu. Agrupe com
ghost_run para que uma única rodada do modelo execute vários passos. scripts/speed-probe.mjs
mede tudo isso contra qualquer binário ghost-mcp.
Controle de shell (ghost_shell)
O Ghost controla GUIs e a linha de comando. ghost_shell executa comandos de terminal e
sessões persistentes do PowerShell - builds, git, CLIs, edições de arquivos em hosts sem ferramentas
de arquivo, ou iniciando aplicativos. op=run é de uso único (powershell/pwsh/cmd); op=open
inicia um PowerShell persistente cujas variáveis e diretório de trabalho sobrevivem entre chamadas op=send.
A saída é stdout+stderr mesclados, limitada no final para a janela de contexto do agente; um comando
com timeout continua rodando e é drenado com op=read; ghost_stop mata um processo descontrolado.
op=run com o powershell padrão é servido de um processo sobressalente pré-iniciado, então
um comando custa cerca de 85 ms em vez dos 230-450 ms que uma inicialização nova do PowerShell leva
(o sobressalente é de uso único e substituído imediatamente; GHOST_SHELL_WARM=off o desativa).
Inicie uma nova sessão do Claude Code a partir do agente:
ghost_shell op=run cmd='Start-Process wt -ArgumentList "pwsh","-NoExit","-Command","claude"',
depois controle a nova janela de terminal com ghost_see / ghost_act / ghost_key.
Segurança: o acesso ao shell é poderoso. Defina GHOST_SHELL=off no ambiente do servidor para
desabilitar o verbo inteiramente - cada operação então retorna uma recusa clara, deixando os verbos
de automação de GUI totalmente utilizáveis.
Início 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 -
Tudo gera JSON para facilitar o encadeamento em jq ou scripts.
Início Rápido - Servidor HTTP
Inicie o servidor:
ghost-http --addr 127.0.0.1:7878
Depois, de qualquer linguagem:
# 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" }),
});
Endpoints: /health, /tools, /click, /click-at, /type, /press, /hotkey, /screenshot, /launch, /list-windows, /focus-window, /window-state, /describe, /clipboard (GET/POST), /run.
Início Rápido - SDK 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 Confiabilidade
A automação de desktop controlada a partir de um cliente MCP tem um ambiente de foco hostil: entre chamadas de ferramentas, o terminal do próprio cliente geralmente retoma o foco do SO. O Ghost é construído para isso:
ghost_acté atômico — encontrar → agir → verificar via delta de tela. Uma única chamada, sem corrida entre chamadas. Sob a política padrão debackground, ele aciona o controle no lugar e nunca eleva a janela; aumente a política e ele adicionalmente traz a janela do alvo para o primeiro plano primeiro (AttachThreadInput, confirmado).- Toda resposta de ação é honesta:
verified(a tela realmente mudou?),focus_confirmed(a janela certa estava em primeiro plano?) e umwarningquando qualquer um estiver errado — nunca umok:truecego. Verifiqueverifiedantes de reemitir uma ação. - Nada fica em execução. Os navegadores que o Ghost inicia estão em um objeto de trabalho kill-on-close:
quando o servidor termina, de qualquer forma que termine, eles terminam junto
(
dies_with_serverna resposta de inicialização). Na inicialização, o servidor também varre navegadores abandonados por servidores anteriores e os reporta emghost_stats.orphan_sweep. - Âncora em uma janela —
ghost_see,ghost_find,ghost_act,ghost_key,ghost_click_at,ghost_scroll,ghost_wait,ghost_asserteghost_screenshot(excetofull=true) todos aceitamwindow(uma substring do título, resolvida em sua área de trabalho e nas áreas de trabalho ocultas do Ghost: título exato vence prefixo, que vence substring; uma janela que não está minimizada vence empates). A correspondência se torna a âncora da sessão: chamadas posteriores semwindowa miram, nunca a janela que o humano por acaso está usando.ghost_window op=focusancora sem elevar sob a política de fundo;op=anchordefine, limpa ou reporta; cada resposta carregatarget {hwnd, title, surface, source}. Um título que não corresponde a nada lista as janelas abertas e retorna o código -32007. - Seu próprio navegador, através do próprio protocolo — quando o processo de uma janela foi iniciado
com
--remote-debugging-port(Comet, Chrome, Edge, Brave), os mesmos verbos ancorados roteiam pelo protocolo DevTools em vez de Automação de Interface do Usuário: nomes de DOM earia-labels em vez de uma árvore esparsa, seletores que sobrevivem a re-renderizações, eventos de entrada confiáveis nesse renderizador, combinações completas de modificadores e emulação de foco para que páginas que verificamdocument.hasFocus()ainda aceitem digitação. Nada disso pode alcançar seu primeiro plano. A resposta carregaroute: {browser, port, tab}ecoords: viewport; um navegador sem porta mantém o caminho de Automação de Interface do Usuário inalterado.GHOST_CDP_ROUTE=offdesativa isso. Inicie o Comet ou o Chrome uma vez com--remote-debugging-port=9333para obtê-lo. - Falhas nomeiam as alternativas — "elemento não encontrado" é seguido pelos nomes
de elementos mais próximos nessa janela, para que um agente não gaste uma ida e volta em
ghost_seepara aprender como o aplicativo chama a coisa. - Desambiguar duplicatas —
indexseleciona a enésima correspondência quando vários elementos compartilham um nome/papel (vários botões "Fechar Aba"); as respostas carregam uma contagem dematches. - Ele se audita — um amostrador independente observa a janela em primeiro plano e o
tempo da última entrada do SO; qualquer mudança de primeiro plano sem entrada de hardware real por trás é
registrada como sintética, com as chamadas de ferramenta que estavam em andamento.
ghost_statsreporta o total, então a afirmação principal é comprovada continuamente, não uma vez. - Leia, não faça captura de tela —
ghost_see mode=textextrai o texto legível de uma janela/página diretamente da árvore de acessibilidade: mais rápido e ~10x mais barato em tokens do que imagens. - A latência é visível: cada resposta carrega
ms, eescalated: truesinaliza quando um find teve que pagar uma ida e volta de VLM de rede (camadas locais: cache → UIA → OCR são todas no dispositivo). - Janelas nunca desaparecem: janelas minimizadas permanecem em
ghost_window list(comstate) eop=focusas restaura automaticamente. Uma janela que algo escondeu completamente (não visível, não minimizada) aparece comop=list include_hidden=truecomostate: "hidden", eop=state state=restorea traz de volta sem ativá-la.op=statetambém alcança janelas nas próprias áreas de trabalho ocultas do Ghost, então um aplicativo iniciado comop=launchpode ser fechado pelo nome. - Parar sempre funciona:
ghost_stopantecipa a chamada em andamento no momento em que chega (leitor dedicado de stdin), e Ctrl+Alt+G continua sendo o interruptor de matar no nível do SO.
Modo de fundo (agente-harness / computer-use)
Harnesses de agente (OpenClaw, Hermes/cua-driver e qualquer cliente MCP) montam uma ferramenta de computer-use para permitir que um LLM opere a área de trabalho. Ghost é essa ferramenta — e ele age sem roubar seu foco ou mover seu cursor, então um agente dirige um aplicativo enquanto você continua trabalhando em outra janela.
Desde 0.19, este é o padrão e é aplicado. A política de foco em todo o processo
começa em background, e toda primitiva que só poderia funcionar tomando o cursor real ou a
janela em primeiro plano é bloqueada por ela. Não há fallback silencioso: uma chamada
sem caminho de fundo retorna um erro nomeando a ação e a rota que
não precisa de mudança de política (inicie o aplicativo na área de trabalho oculta, ou o navegador via
CDP).
Desde 0.22, a política também está bloqueada lá. Um padrão só é uma promessa se o
agente não puder alterá-lo, e até 0.22 qualquer agente podia chamar ghost_set_focus_policy foreground no momento em que uma ação de fundo era recusada, que é exatamente quando um
humano percebe o Ghost movendo o mouse. Agora essa chamada também é recusada, com um erro
que diz isso. A chave é do operador, não do agente: defina
GHOST_FOCUS_LOCK=off no ambiente do servidor MCP (a configuração do host que você
escreve) para permitir prefer_background e foreground novamente, e opcionalmente
GHOST_FOCUS_POLICY para começar lá. ghost_focus_policy reporta a política e
se está bloqueada; o servidor registra ambos na inicialização.
// 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" }
}}}
Ao que você está concordando
O Ghost tem duas configurações que decidem quanto do seu computador um agente obtém. Instalar o pacote mostra ambas como caixas de seleção; executar o binário diretamente, elas são variáveis de ambiente. O servidor imprime onde está em ambas na inicialização, então o log do host sempre responde à pergunta.
| Configuração | Padrão | O que "ligado" significa |
|---|---|---|
Manter o Ghost longe do seu mouse e teclado (GHOST_FOCUS_LOCK) | ligado | O agente nunca pode elevar a política de foco, então ele dirige janelas em segundo plano e não pode pegar seu cursor. Desligue apenas se quiser que um agente use sua entrada real. |
Permitir comandos de shell (GHOST_SHELL) | ligado | ghost_shell executa programas com os direitos da sua conta, que é como um agente executa builds, git e scripts — e é por isso que a maioria dos agentes usa o Ghost. É acesso total à máquina. Desligue e toda chamada de shell recusa; janelas, leitura de tela e entrada ainda funcionam. |
O shell está ligado por padrão deliberadamente. É a capacidade, não um bônus, e uma ferramenta que silenciosamente entrega sem a coisa para a qual as pessoas a instalam é pior do que uma que diz claramente o que pode fazer. Se isso é mais do que você quer entregar, a caixa de seleção está bem ali e a recusa é explícita.
Uma política bloqueada ainda deixa uma coisa fora do controle do Ghost: um aplicativo
pode ativar a PRÓPRIA janela, e o Chromium faz exatamente isso quando um agente digita
em uma página ou clica em um botão através da API de acessibilidade. Nada fora
do navegador pode impedir essa chamada. Então, desde 0.23, o Ghost a desfaz. A auditoria
de interferência funciona como sentinela: ela é informada no momento em que qualquer janela assume o
primeiro plano (um evento do Windows, cerca de um milissegundo) e a devolve imediatamente
a menos que você tenha escolhido essa janela você mesmo — clicando nela ou alternando com Alt+Tab para ela,
o que ela pode distinguir de digitação porque observa entrada REAL, não
entrada sintetizada. ghost_session_state reporta com que frequência isso aconteceu
(foreground_handed_back).
Quão bem funciona, medido com um observador independente enquanto uma pessoa digitava
em outra janela durante toda a execução (scripts/background-desktop-probe.mjs,
scripts/interference-watch.ps1):
| antes de 0.23 | agora | |
|---|---|---|
| teclas entregues à janela errada | 48 | 1 em seis execuções de ~493 |
| quão rápido um primeiro plano roubado é notado | nunca | ~1 ms |
Desde 0.23.2, o primeiro plano é observado por evento em vez de polling, então o retorno começa cerca de um milissegundo após a janela assumi-lo. Seis execuções limpas com uma pessoa digitando durante todo o tempo deram 0, 0, 0, 1, 0 e 0 teclas na janela que o Ghost estava dirigindo. Não é uma garantia — desfazer uma ativação nunca pode ser — e para uma garantia, deixe o Ghost iniciar o aplicativo, para que a ativação nunca aconteça.
Para zero ativação em vez de uma breve, deixe o Ghost iniciar o aplicativo: qualquer coisa que ele inicia vive em uma área de trabalho oculta com sua própria fila de entrada e não pode pegar seu primeiro plano, e um navegador que ele inicia é dirigido via 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" }
- Lançamentos nunca aparecem na superfície. Medido no CI box deste repositório: Edge e Chrome
ativam sua primeira janela no lançamento em todos os estilos de lançamento (normal, oculto,
minimizado, a partir de um processo pai em segundo plano, posicionado em -32000,-32000). Uma janela criada em
sua área de trabalho assume seu teclado no momento em que existe. Então, sob a política de
segundo plano, o Ghost nunca cria uma lá:
ghost_window op=launch,ghost_runetapas de lançamento eghost_browser_launch mode=windowediniciam em uma área de trabalho oculta com sua própria fila de entrada, e a janela é ancorada para que o próximoghost_seea mostre. Um observador independente amostrando o primeiro plano a 100 ms durante uma execução completa de lançamento-condução-fechamento relatou zero mudanças. - Verdadeiro segundo plano via mensagens de janela postadas. Controles Win32 reais são conduzidos
com
BM_CLICK/WM_LBUTTONDOWN·UP(clique),WM_SETTEXT(digitação) eWM_MOUSEWHEEL(rolagem). Estes não ativam a janela. - Controles sem janela, sem a tela. Controles UWP/WinUI/Chromium/Electron
não têm um identificador de janela. O Ghost os conduz com padrões de Automação de Interface do Usuário -
Invokepara um clique,ValuePatternpara digitação. O Chromium responde a alguns destes ativando sua própria janela quando o Windows permite (logo após você usar esse navegador): medido no Edge, umSetValueem uma entrada web ou na barra de endereço, umInvokeem um botão de página e um clique postado trouxeram a janela para frente em ~90 ms. Desde 0.21.10 isso é desfeito na hora: o Ghost observa o primeiro plano em torno de cada verbo de área de trabalho do usuário, e quando o alvo ou qualquer janela de seu processo o assume, devolve-o para a janela que você tinha, em 30 a 50 ms, e relatafocus_preserved: falsecom um registrofocus_guarddizendo isso. Teclas únicas postadas alcançam o elemento focado da página e não ativam nada. - Filhos do shell nunca abrem um terminal. O servidor MCP não tem console, então um
shell iniciado simplesmente não tem nenhum também, e cada programa de console que ele executou (node,
python, cargo, cmd) ganhou uma nova janela do Windows Terminal que assumiu o
primeiro plano durante a execução.
ghost_shellagora cria seus shells com um console invisível; os filhos o herdam e nenhuma janela aparece. Medido: nove mudanças de primeiro plano em sete segundos antes, zero depois, saída inalterada. - Verificado mesmo quando ocluído.
typeé confirmado lendo o valor do controle de volta;clickpor um delta antes/depois dePrintWindowque renderiza uma janela que não está visível. Cada resposta carregaverified,focus_preserved,cursor_preserved- o Ghost nunca afirma uma ação em segundo plano que não pode confirmar. - Áreas de trabalho ocultas são o mesmo vocabulário. Uma janela na área de trabalho oculta é
conduzida com as mesmas chamadas
window=<title>;target.surface: "hidden"é a única diferença. Janelas Chromium e Electron lá são conduzidas por mensagens postadas em vez de ações UIA (o Chromium atendeInvoke/SetValueem uma área de trabalho não composta apenas após uma espera interna de ~2 s; um clique postado chega em ~100 ms), e a verificação de pixels é ignorada para elas porque uma renderização por software lá custa segundos - confirme através deghost_tab_evaloughost_see.SendInputreal ainda não funciona em uma área de trabalho oculta (o Windows o recusa fora da área de trabalho de entrada), então um aplicativo que responde apenas a entrada de hardware real precisa da políticaforegroundem sua própria área de trabalho. - Honesto sobre aplicativos de instância única. O Bloco de Notas do Windows 11, o Explorer ou um navegador em
seu perfil padrão entregam um lançamento ao seu processo já em execução, cujas janelas
vivem em sua área de trabalho. O Ghost não pode evitar isso; ele relata
surface: "user"com um aviso em vez de afirmar que o aplicativo está oculto.
Suporta click, type, double_click, right_click, hover e rolagem, além de
ghost_key para teclas únicas (Enter/Tab/teclas F/caractere via WM_KEYDOWN/WM_CHAR). O
sinalizador background: true é aceito para compatibilidade; é o comportamento padrão.
A área de transferência e combinações de edição funcionam em segundo plano também - Ctrl+C, Ctrl+X, Ctrl+V,
Ctrl+Z e Ctrl+A são enviados como as mensagens semânticas que um aplicativo realmente implementa
(WM_COPY, WM_CUT, WM_PASTE, WM_UNDO, EM_SETSEL) em vez de um modificador postado
que aplicativos lendo GetKeyState ignorariam. Combinações fora desse conjunto são
rejeitadas em vez de descartadas silenciosamente, porque postar não pode definir o estado do modificador
que esses aplicativos leem; use a política foreground para elas.
Visão: seu agente é o modelo
O Ghost é olhos e mãos, não um cérebro. Quando um modelo o conduz via MCP, esse modelo
faz a observação: ghost_see dá a ele a janela como elementos estruturados com
coordenadas, ghost_see mode=text dá a ele o texto legível, e
ghost_screenshot dá a ele pixels quando a estrutura não é suficiente. Claude, GPT,
Gemini e os modelos de visão de peso aberto fortes leem todos isso diretamente. Não há
chave para definir e nada para configurar, e o Ghost nunca precisa interpretar uma imagem
em nome do modelo.
A camada de visão integrada opcional existe para chamadores que não têm modelo
próprio - o CLI, a API HTTP, um arquivo de intenção - e para a conveniência de um alvo de
descrição (ghost_find description="the blue Submit button") quando você prefere
que o Ghost resolva isso em vez de ler a árvore você mesmo. Funciona com qualquer
modelo de visão com capacidade de ferramenta por trás de um endpoint compatível com OpenAI (OpenAI, Gemini, Groq,
NVIDIA ou um servidor local vLLM / Ollama / LM Studio) ou Anthropic. Aponte
GHOST_VISION_BASE_URL e GHOST_VISION_MODEL para o endpoint e defina
GHOST_VISION_API_KEY (um servidor local sem chave precisa apenas da URL base). Sem isso,
alvos de descrição retornam um erro claro nomeando a alternativa; todas as outras ferramentas são
afetadas.
Parada de Emergência
Pressione Ctrl+Alt+G a qualquer momento para interromper imediatamente toda chamada de ação.
Consultas somente leitura (ghost_see, ghost_snapshot, lista ghost_window) continuam respondendo, então você
ainda pode inspecionar o que aconteceu enquanto tudo está parado.
- Todas as ações enfileiradas são canceladas
- Quaisquer teclas modificadoras pressionadas (Shift, Ctrl, Alt) são liberadas imediatamente
- Sem teclas travadas, sem estados de modificador travados
- Em toda a sessão desde 0.19. A parada é um evento de kernel nomeado
(
Local\ghost-emergency-stop-event), então um pressionamento interrompe todo processo do Ghost em sua sessão de logon, não apenas aquele que registrou o atalho.ghost_resetretoma o serviço, novamente para todos eles.
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?
Do CLI: ghost click --name "Save" ou ghost click --role button.
Intenções - Fluxos Declarativos
Escreva fluxos de várias etapas reproduzíveis como JSON. O executor FSM suporta tentativas, tempos limite e condições 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" }
]
}
Execute com ghost run flow.json, POST /run ou ghost_execute_intent via MCP.
Arquitetura
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 suporte: ghost-cache (snapshot UIA + delta), ghost-intent (executor FSM +
JSONLogic), ghost-ground (a cascata de camadas do localizador), ghost-platform
(a matriz de capacidades relatada por SO).
A camada de visão integrada (Set-of-Marks)
Esta seção descreve a camada opcional acima; um agente conduzindo o Ghost via MCP
obtém as mesmas informações de ghost_see e não precisa dela.
Quando você localiza um elemento por descrição em linguagem natural (ghost_find description="o botão azul de enviar", ou quando uma busca por nome/texto falha e
escala para o VLM), o Ghost não pede ao modelo para adivinhar coordenadas de
pixels - modelos são não confiáveis nisso (em testes, um simples "me dê as
coordenadas do botão de igual" caiu ~250px fora do alvo). Em vez disso, ele usa
Set-of-Marks: ele sobrepõe crachás numerados nos elementos detectados da janela,
envia essa captura de tela marcada mais o rótulo de nome acessível de cada crachá, e
pergunta ao modelo qual número corresponde. O número mapeia de volta para o retângulo exato
daquele elemento, então o resultado é uma coordenada real no elemento, não um palpite de regressão.
Em uma verificação ao vivo na Calculadora, quatro descrições ("o botão de igual", "o botão de mais", "a tecla do número sete", "o botão de multiplicar") cada uma caiu exatamente em o botão correto - versus ~250px fora com regressão de coordenadas.
Escopo honesto: quando elementos detectados carregam nomes acessíveis (a maioria dos aplicativos), os rótulos fazem grande parte da desambiguação; para ícones sem rótulo, o modelo se apoia na posição/aparência visual do crachá.
Aplicativos de tela / sem árvore de acessibilidade. Quando a árvore UIA é esparsa (UIs
desenhadas sob medida, superfícies de área de trabalho remota, telas de jogos), o Ghost aumenta os candidatos
Set-of-Marks com um detector clássico de CV por CPU integrado (ghost_ground::cv_detect):
densidade de bordas → componentes conectados → filtro de tamanho/proporção, sem GPU e sem download
de modelo. Ele dá ao VLM caixas reais para escolher onde a árvore de acessibilidade
não tem nada. É mais grosseiro que um detector treinado - uma camada opcional OmniParser ONNX
(--features yolo + GHOST_YOLO_MODEL) se conecta ao mesmo caminho Set-of-Marks
quando um modelo de GPU está disponível. O fluxo de ponta a ponta CV-marks → VLM-pick precisa de uma
chave de visão configurada.
Benchmark - sucesso de tarefa, não "a chamada retornou ok"
bench/ contém um benchmark reproduzível de ponta a ponta: ele conduz o binário
ghost-mcp real através de 14 tarefas de desktop do Windows e pontua cada uma por
re-observar o resultado real (a tela da Calculadora realmente lê 42?
o valor digitado está realmente presente?), nunca confiando no retorno de uma chamada de ferramenta.
Última execução (veja bench/results/latest.md):
14/14 tarefas passaram (100%), mediana ~2,7 s por tarefa (tempo total de parede incl. lançamento do aplicativo) - percepção, ação de clique/teclado+verificação, esperas, gerenciamento de janela (listar/minimizar/restaurar), extração de texto, desambiguação, encadeamento de fluxo, ida e volta da área de transferência, erros estruturados, capturas de tela de elementos e asserções de valor.
E prova que pode falhar: --self-test executa controles negativos deliberadamente errados
(afirma que a tela lê 99 quando lê 42, etc.) e passa apenas se o
harness pontuar cada um como FALHA - então a execução verde acima é um sinal real,
não um carimbo de borracha.
Reproduza em qualquer 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
Teste de confiabilidade
bench/soak.py conduz muitos ciclos de agir-depois-verificar e limita nos sinais que os testes
de unidade não podem ver: com que frequência verified retorna nulo/falso, taxa de perda de foco,
taxa de erro, se o efeito real de cada ação aconteceu (a tela é
re-observada, nunca confiada no retorno), e percentis de latência.
Último (160 atos): PASSOU - verificar-nulo 0,0, perda de foco 0,0, incompatibilidade de efeito 0 (100% correto), p50 85ms / p95 117ms. Veja
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 apenas os números medidos do próprio Ghost - nunca colunas inventadas
para outras ferramentas. bench/README.md dá um protocolo honesto para
comparar contra Playwright-MCP / Computer Use / UI-TARS, e explica por que uma
comparação ingênua com a mesma suíte não é maçãs com maçãs (Playwright é só navegador;
agentes de visão precisam de uma API + VM).
Microbenchmarks
| Operação | Medido |
|---|---|
| Captura de região, GDI, qualquer tamanho | ~16,5 ms |
| Captura de região, DXGI, 1600x900 | ~70-83 ms |
| Conversão BGRA→RGBA, região 400x300 | ~206 µs |
| JSONLogic eq/var | 32,2 ns |
| Compilação de intenção (3op) | 1,49 µs |
Medição de captura de ponta a ponta (release, crates/ghost-core/tests/capture_latency_probe.rs)
corrigiu a suposição da v0.10.0: o acquire DXGI domina e atinge um penhasco em
janelas grandes, então capturas de região (verificação de ação, capturas de tela, Set-of-Marks) roteiam
através de GDI BitBlt plano de ~16,5ms na v0.11.0; tela cheia ainda usa DXGI. Execute o
microbenchmark de conversão: cargo bench -p ghost-core --bench convert. Linhas de base mais antigas:
docs/benches/v030-baseline.md.
Requisitos
- Windows 10 build 19041 ou posterior
- Linux com
at-spi2-coree uma sessão de desktop (X11 ou Wayland);xdg-desktop-portal-gnomeadicionalmente para entrada e captura no Wayland - Um navegador da família Chromium (Chrome, Comet, Edge ou Brave) apenas para as
ferramentas
ghost_browser_*/ghost_tab_*; os verbos de desktop não precisam de nenhum - Rust estável (apenas para compilar a partir do código-fonte)
Licença
MIT - Copyright 2026 Northtek