hypruse
Uso de computador para Hyprland - servidor MCP que dá aos agentes de IA mãos nativas no seu desktop Wayland.
Documentação
hypruse
Uso de computador para Hyprland. Um servidor MCP que dá a agentes de IA acesso nativo ao seu desktop Wayland: workspaces, janelas, mouse, teclado, capturas de tela.
Sem daemon ydotool. Sem root. Sem portais. Sem X11.

Por quê
Uso de computador existe no macOS e no Windows, e os aplicativos Linux dos fornecedores ainda vêm sem ele: a documentação Linux do Claude Desktop diz que o uso de computador não está disponível lá, e o uso de computador do ChatGPT cobre apenas macOS e Windows. A implementação de referência da Anthropic é um contêiner X11. Outras ferramentas Wayland dependem de ydotool e uinput, de portais exclusivos do GNOME ou de um plugin de compositor construído para uma versão exata do Hyprland.
Enquanto isso, o Hyprland já expõe tudo o que um agente precisa, melhor do que qualquer ponte de acessibilidade: uma superfície IPC completa para estado e gerenciamento de janelas, e protocolos Wayland de primeira classe para entrada. O hypruse apenas conecta isso ao MCP:
- Semântico primeiro.
desktopretorna a árvore real de janelas/workspaces (endereços, classes, títulos, geometria) em uma única chamada. O agente alterna workspaces e foca janelas do mesmo jeito que você (instantaneamente, via IPC), não olhando para pixels. - Visão quando importa. Capturas de tela de um monitor, de uma janela (com grim 1.5+ no Hyprland 0.54+, capturada como ela mesma mesmo em um workspace oculto ou sob outra janela, embora um aplicativo oculto possa mostrar como estava na última vez), ou de uma região com zoom, com os metadados de geometria/escala para mapear qualquer pixel de volta a uma coordenada clicável: um loop de grosso para fino fundamentado na pesquisa de agentes GUI.
- Entrada nativa. Cliques e rolagens são falados diretamente pelo fio Wayland (
zwlr_virtual_pointer_v1); a digitação passa pelo teclado virtual dowtypecom um keymap XKB adequado, seguro para unicode em qualquer layout.
Como funciona
agent (Claude Code, or any MCP client)
│ stdio
▼
hypruse
├── hyprctl -j ········▶ desktop state: monitors, workspaces, windows, layers
├── hyprctl dispatch ··▶ focus / move / close / launch / movecursor
├── grim ··············▶ screenshots: monitor, window, region
├── busctl (AT-SPI) ···▶ accessibility tree: named controls, current
│ values, exact coords (ui / marks / click_ui)
├── wtype ·············▶ keyboard (zwp_virtual_keyboard_v1, real XKB keymap)
└── raw Wayland wire ··▶ click & scroll (zwlr_virtual_pointer_v1)
Binários opcionais controlam mais duas ferramentas: imagemagick desenha a sobreposição numerada para marks, e wl-clipboard dá suporte à ferramenta opcional clipboard.
Decisões de design:
- Sem ydotool / uinput. Esse caminho precisa de um daemon, regras udev ou root, e digita scancodes dos EUA que quebram em outros layouts. O hypruse é apenas mais um cliente Wayland do seu compositor, com o mesmo status do
wlrctl. - Sem portais.
xdg-desktop-portal-hyprlandnão implementa o portal RemoteDesktop (InputCapture é captura, não injeção), então qualquer coisa construída sobre libei/portais degrada silenciosamente no Hyprland. O hypruse não tenta. - Posicionamento do cursor pelo próprio dispatcher de cursor do compositor (coordenadas lógicas globais, exatas em qualquer layout de monitor), com apenas eventos de botão/eixo no ponteiro virtual, contornando os bugs conhecidos de múltiplos monitores do movimento absoluto do ponteiro virtual (hyprwm/Hyprland#6749).
Ferramentas
| ferramenta | o que faz |
|---|---|
desktop | Snapshot semântico em uma chamada: monitores, workspaces, janelas (endereço/classe/título/geometria), janela ativa, cursor e superfícies de camada (lançadores, barras, popups de notificação) com um tipo e geometria de melhor esforço. Uma camada listada é uma que o compositor rastreia, não uma que você pode ver: superfícies transparentes e dormentes também são relatadas, então capture quando a visibilidade importar |
screenshot | Monitor focado, uma janela por endereço (com grim 1.5+ no Hyprland 0.54+, mesmo oculta ou coberta; os metadados visible dizem se o compositor a desenha, source se os pixels são da própria janela ou um recorte da tela, e uma captura oculta pode estar desatualizada), ou região x,y,WxH; retorna imagem + metadados de mapeamento de coordenadas; JPEG rápido por padrão (lossless=true para PNG); stable=true espera o quadro estabilizar |
zoom | Recaptura em resolução nativa em torno de um ponto estimado (opcionalmente limitado a uma janela): o passo de precisão antes de clicar em controles pequenos, mesmo contrato de metadados |
ui | Lê a árvore de acessibilidade de uma janela (AT-SPI, aplicativos GTK/Qt que a expõem) e retorna elementos clicáveis por nome com coordenadas globais exatas, sem captura de tela; também relata valores atuais (texto digitado, posição do slider, estado da caixa de seleção); cai para visão quando um aplicativo não expõe nada |
marks | Captura Set-of-Marks: a captura da janela com cada controle acessível desenhado como uma marca numerada, mais uma legenda JSON (papel, nome, valor atual, ponto de clique exato por número); precisa do ImageMagick para o desenho, degrada para apenas a legenda sem ele |
click_ui | Clique em um controle pelo NOME acessível ou por um número marks em uma chamada: a coordenada vem da árvore, o clique passa pelo ponteiro real (visível, mesmas garantias de segurança); um nome ambíguo retorna os candidatos em vez de adivinhar |
pointer | mover / clicar / arrastar / rolar (entalhes discretos da roda) em coordenadas globais |
keyboard | Digite texto literal (seguro para unicode) ou pressione combos de nível de aplicativo (ctrl+shift+t, esc, F5); o endereço opcional window foca o alvo primeiro para que as teclas caiam no aplicativo certo. Atalhos do compositor (super+...) passam pelo use_bind, não aqui |
hypr | Alternar workspace, focar/mover/fechar janelas, tela cheia, flutuante (IPC puro, milissegundos; close_window também espera até 1s pelo evento de destruição, então seu resultado e a observação then= refletem o fechamento em vez de correr contra ele) |
launch | Inicie um aplicativo (opcionalmente silencioso em outro workspace), bloqueie no evento real openwindow, retorne seu endereço; detecta aplicativos de instância única (navegadores) cuja janela ignora regras de exec e a move para o workspace solicitado |
binds | Os próprios atalhos do usuário, decodificados (SUPER+Q, ação, descrição); o agente executa um com use_bind |
use_bind | Execute um atalho por combo (SUPER+F), executando sua ação vinculada, para que o agente acione os lançadores e atalhos do próprio dono. Não disponível para atalhos em um hyprland.lua Lua: esses são closures anônimos que o Hyprland não expõe como chamar, então binds os mostra como ação lua e use_bind diz isso em vez de falhar cripticamente |
sequence | Execute uma lista ordenada de ações (pointer/keyboard/click_ui/hypr/wait_for) em uma chamada; para no momento em que o desktop muda de uma forma que o passo atual não esperava, então uma micro-sequência clique/digite/enter custa uma ida e volta em vez de várias |
wait_for | Bloqueie em eventos reais do compositor (abrir/fechar janela, mudar workspace, mudar título, superfícies de camada aparecendo/fechando, urgência, compartilhamento de tela ligado/desligado) com um filtro de correspondência e timeout; uma espera filtrada cuja condição já é verdadeira (janela já foi, workspace já ativo, camada já mapeada) responde instantaneamente com already: true em vez de perder um evento que disparou antes de assinar. Substitui dormir-e-esperar em automações de várias etapas |
clipboard | Leia ou escreva a área de transferência de texto via wl-clipboard; opcional, existe apenas com HYPRUSE_CLIPBOARD=1 no ambiente do servidor |
As ferramentas de ação (pointer, keyboard, click_ui, hypr, use_bind, sequence) aceitam um argumento opcional then que anexa o resultado à mesma chamada, para que o agente veja o efeito sem uma segunda ida e volta: then='desktop' adiciona um snapshot semântico novo (~20 ms, barato, melhor para mudanças de janela/foco), then='screenshot' uma captura estável (melhor para mudanças visuais), then='ui' os controles da janela alvo com seus valores atuais (algumas centenas de tokens exatos, melhor após digitar ou alternar; click_ui lê a janela em que clicou mesmo se o clique deu foco a um diálogo, os outros leem a janela focada), then='none' nada (o padrão em todos exceto sequence, que padroniza para 'desktop').
Toda ferramenta também é um verbo de shell (hypruse desktop, hypruse click_ui Save --window 0x...) para agentes que executam comandos em vez de MCP, com uma skill que os ensina: veja Shell verbs and the agent skill.
Recursos
As ferramentas se agrupam em cinco capacidades, ordenadas da mais confiável e barata primeiro. Um agente que as usa nessa ordem é mais rápido e mais preciso, e muitas tarefas nunca precisam de uma captura de tela.
1. Controle semântico do desktop (comece aqui)
desktop retorna toda a árvore de janelas e workspaces em uma chamada: o endereço, classe, título e geometria de cada janela, a janela ativa, o cursor e quaisquer superfícies de camada que o compositor está rastreando (lançadores, barras, popups de notificação). hypr e launch então agem sobre isso via IPC em milissegundos: alternar workspace, focar/mover/fechar/tela cheia/flutuar uma janela por endereço, ou iniciar um aplicativo.
Use bem: nunca tire uma captura de tela para encontrar ou organizar janelas. Leia desktop, aja no endereço que você quer. launch bloqueia no evento real openwindow e devolve o endereço da nova janela, então não há nada para sondar ou adivinhar; também realoca aplicativos de instância única (navegadores) que ignoram regras de workspace.
2. Clique em controles por nome, sem pixels
Quando um aplicativo expõe uma árvore de acessibilidade (a maioria dos aplicativos GTK e Qt), você pode mirar controles por nome em vez de por pixel. ui lista cada controle com sua coordenada global exata e relata o valor atual dos controles que carregam um: o texto em um campo, a porcentagem de um slider, o estado de uma caixa de seleção. click_ui resolve um nome e clica nele em uma chamada, pelo cursor real (então o beacon e todas as garantias de segurança ainda se aplicam). marks desenha marcas numeradas sobre uma captura de tela com uma legenda, para quando você quiser ver as opções primeiro e então click_ui(mark=N).
Use bem: alcance click_ui name="Save" antes de estimar qualquer pixel, pois é exato e não gasta imagem. Leia o estado de um formulário com ui (a caixa realmente marcou?) em vez de capturar a tela. Um nome ambíguo retorna os candidatos em vez de adivinhar. Quando um aplicativo não expõe árvore (terminais, aplicativos de canvas, Electron/Chrome sem --force-renderer-accessibility) a ferramenta diz isso, e você cai para visão.
3. Visão quando importa: o loop de zoom
Para tudo o que a árvore de acessibilidade não pode nomear, screenshot (monitor, janela ou região) e zoom (uma recaptura em resolução nativa em torno de um ponto) carregam um contrato de coordenadas estrito, global = geometry + pixel / scale, que permanece exato em todo monitor e escala fracionária.
Use bem: não adivinhe um controle pequeno a partir de uma imagem de tela cheia. Trabalhe de grosso para fino: capture a janela, estime o alvo, zoom lá, re-estime no recorte nítido, então clique. Este loop de duas etapas é a maneira fundamentada em pesquisa de acertar alvos pequenos.
4. Menos idas e voltas: a alavanca de latência
Para um agente, as chamadas de modelo dominam a latência da tarefa, não o desktop, então os ganhos reais de velocidade são estruturais. sequence executa um micro-plano ordenado (clique, digite, pressione enter, espere) em uma única chamada, parando no momento em que o desktop muda estruturalmente de uma forma que um passo não pretendia (uma janela abrindo, fechando ou movendo, uma troca de workspace inesperada, ou um lançador que toma o assento ou teclado na tela; deliberadamente ignora mudanças de foco simples e popups de notificação). then='desktop' | 'screenshot' | 'ui' funde uma visão nova do resultado na própria chamada de ação. wait_for bloqueia em eventos reais do compositor (uma janela ou lançador abrindo, um título mudando, uma troca de workspace, um aviso de urgência, compartilhamento de tela começando) em vez de dormir e esperar.
Use bem: colapse um fluxo conhecido de clique/digite/enter em um único sequence. Depois de digitar em um formulário, adicione then='ui' para ler o efeito de volta em algumas centenas de tokens exatos em vez de uma captura de tela. Depois de um lançamento ou atalho que abre algo, wait_for o evento em vez de dormir.
5. Delegação segura: camadas de confiança
hypruse entrega ao agente o seu assento real, então ele entrega os controles para limitar o que esse agente pode fazer. Além dos prompts de aprovação sempre ativos e do beacon de atividade do Waybar, flags de ambiente opcionais restringem o que um agente pode tocar: HYPRUSE_READONLY expõe apenas as ferramentas de observação; HYPRUSE_CONFINE restringe a entrada às janelas que o agente lançou, ou a uma allowlist de classe/workspace; HYPRUSE_AUTH_GUARD (ativado por padrão) se recusa a conduzir diálogos de autenticação; HYPRUSE_STRICT se recusa a agir se você retomou o assento; HYPRUSE_MARK marca janelas de propriedade do agente e anuncia quando o agente abre uma janela ou captura a tela. Mais duas registram em vez de restringir: HYPRUSE_JOURNAL escreve uma linha NDJSON auditável por chamada de ferramenta, incluindo recusas, e HYPRUSE_DRYRUN executa todas as verificações e não entrega nada, para que você possa observar um agente planejar o trabalho antes de tocar no seu desktop.
Use bem: execute somente leitura na primeira semana. Quando você confiar em um fluxo de trabalho, faça allowlist das ferramentas dele e, se quiser se afastar, confine o agente a um escopo para que ele não possa clicar ou digitar no seu gerenciador de senhas em outro workspace. Mantenha um atalho de pânico à mão (hypruse stop, ou pkill -f hypruse). O Modelo de segurança tem a história completa.
Verbos de shell e a habilidade do agente
Nem todo agente fala MCP, e os que falam preferem cada vez mais uma linha de comando: uma lista de ferramentas custa alguns milhares de tokens por sessão antes da primeira chamada, um verbo de shell não custa nada até ser executado. Então as mesmas quinze ferramentas são verbos, passando pelas mesmas funções que o servidor MCP registra, com as mesmas proteções de confiança, diário e beacon de atividade:
hypruse desktop # one line per monitor, workspace, window, layer
hypruse launch --workspace 2 -- firefox --new-window https://example.org
hypruse ui --window 0x55a4479a1200 --name Save # [0] push button "Save" @1204,88
hypruse click_ui Save --window 0x55a4479a1200 --then ui
hypruse screenshot --window 0x55a4479a1200 # a file path, then {"geometry":[x,y,w,h],"scale":1.0,...}
hypruse zoom 1180 840 --window 0x55a4479a1200
hypruse keyboard type "hello" --window 0x55a4479a1200
hypruse wait_for title_change --match Inbox --timeout 10
hypruse sequence '[{"op":"click_ui","name":"Search","window":"0x55a4479a1200"},{"op":"keyboard","action":"type","text":"btop"},{"op":"keyboard","action":"key","keys":"enter"}]'
O contrato é construído para um programa que lê a saída: os verbos são os nomes das ferramentas, o action de uma ferramenta é um sub-verbo posicional (pointer click 800 60, hypr workspace 3, clipboard read), a saída é texto simples compacto (uma linha por fato, --json para o resultado bruto como uma linha), uma captura imprime seu caminho de arquivo e metadados de coordenadas em vez de bytes, e erros são uma linha no stderr com um código de saída significativo: 0 entregue, 1 erro, 2 uso, 3 recusado por uma camada de confiança (ou pelo modo somente leitura), 4 executou mas não encontrou nada para agir (um timeout de wait_for, nenhuma árvore de acessibilidade, um nome ambíguo). hypruse --help lista todos os verbos e hypruse <verb> --help suas flags; --dry-run ensaia um verbo de ação. Um verbo começa em algumas centenas de milissegundos: a pilha MCP nunca é importada nesse caminho.
Entre processos de uso único, o hypruse mantém o pequeno estado que um verbo perderia em $XDG_RUNTIME_DIR/hypruse/cli-state.json, chaveado pela instância do compositor: a numeração marks (para que click_ui --mark N funcione), o conjunto de confinamento launched e a linha de base do assento HYPRUSE_STRICT, que é a que falharia aberta de outra forma.
A habilidade que ensina a um agente os verbos, o fluxo de trabalho desktop-first e as regras de segurança vem dentro do pacote. Instale-a nos diretórios de habilidades dos agentes na sua máquina (Claude Code, Codex, Pi, Hermes, OpenClaw, OpenCode, Gemini, Antigravity, Cursor, Copilot), ou via a CLI de habilidades:
hypruse skill install # ~/.agents/skills/hypruse, linked into each agent that is installed
hypruse skill install --agent codex # one agent, created if absent
npx skills add IlyasKhallouki/hypruse -g
hypruse init oferece a mesma instalação. A habilidade pré-aprova apenas os verbos de observação, doctor, --help e a leitura dos arquivos de captura; verbos de ação permanecem atrás do prompt de aprovação do seu próprio agente, que é o limite no qual o Modelo de segurança se apoia.
Instalação
Requisitos: Hyprland (ambos os gerenciadores de configuração: hyprland.conf e o Lua hyprland.lua que o 0.56 introduziu), grim (grim 1.5+ no Hyprland 0.54+ permite que uma captura de janela capture a própria janela, e hypruse doctor diz se a sua pode), wtype (a maioria das configurações Hyprland já tem ambos), e uv. As ferramentas de acessibilidade (ui/marks/click_ui) usam busctl, que vem com o systemd. Opcional: wl-clipboard para a ferramenta de área de transferência opcional, imagemagick para capturas marks numeradas.
Arch Linux, do AUR:
yay -S hypruse # or hypruse-git for main
Então deixe-o se configurar e verificar o ambiente:
hypruse init # detects your MCP clients, registers (asks first), offers the agent skill, runs doctor
hypruse doctor # just the diagnostics
Registro manual, Claude Code:
claude mcp add -s user hypruse -- uvx hypruse
De um checkout de fonte:
claude mcp add -s user hypruse -- uv run --directory /path/to/hypruse hypruse
Qualquer outro cliente MCP: execute uvx hypruse como um servidor stdio. hypruse também está no registro MCP oficial como io.github.IlyasKhallouki/hypruse, então clientes que navegam no registro podem instalá-lo de lá.
Modo somente leitura: defina HYPRUSE_READONLY=1 na configuração do servidor para expor apenas as ferramentas de observação (desktop, screenshot, zoom, ui, marks, binds, wait_for). O agente pode ver e narrar, mas não pode clicar, digitar ou lançar. Uma boa primeira semana.
Claude Desktop (beta Linux)
O beta Linux vem sem o uso de computador de primeira parte da Anthropic, mas servidores MCP stdio funcionam no chat, o que torna o hypruse a solução alternativa. Em ~/.config/Claude/claude_desktop_config.json:
{
"mcpServers": {
"hypruse": {
"command": "uvx",
"args": ["hypruse"],
"env": { "HYPRUSE_SCREENSHOT_MODE": "image" }
}
}
}
Duas notas específicas do Desktop: use o modo image (o Desktop renderiza imagens MCP inline e não tem ferramenta de leitura de arquivos), e o aplicativo deve rodar nativamente dentro da sua sessão Hyprland para que o servidor herde WAYLAND_DISPLAY/HYPRLAND_INSTANCE_SIGNATURE; de uma VM ou contêiner, ele não consegue alcançar seu compositor. Se a sua instalação do Desktop ignora prompts de aprovação de ferramentas, trate o indicador Waybar + atalho de pânico como obrigatório, não opcional.
Modelo de segurança
Leia esta seção antes de instalar. hypruse entrega ao agente o seu mouse, o seu teclado, o conteúdo da sua tela e um lançador de aplicativos. As camadas que mantêm isso são:
- Aprovação: clientes MCP bloqueiam chamadas de ferramentas. No Claude Code, faça allowlist das ferramentas somente leitura (
desktop,screenshot) e deixepointer/keyboard/hypr/launchem perguntar-primeiro até você confiar em um fluxo de trabalho. - Visibilidade: o servidor mantém um beacon de atividade (
$XDG_RUNTIME_DIR/hypruse/state.json); o módulo Waybar incluído é invisível quando ocioso e mostra um indicador de robô enquanto um agente tem as mãos no seu desktop. - Interrupção: clique no indicador, ou vincule uma tecla de pânico. A forma portátil funciona para toda instalação:
bind = SUPER SHIFT, BackSpace, exec, pkill -f hypruse. Sehypruseestiver no seu PATH (o AUR ou uma instalação pipx),bind = SUPER SHIFT, BackSpace, exec, hypruse stopé melhor: ele sinaliza ao servidor para desligar graciosamente, liberando qualquer botão do ponteiro pressionado e limpando o beacon. Para uma instalaçãouvxuseexec, uvx hypruse stop; para um checkout de fonte,exec, uv run --directory /path/to/hypruse hypruse stop. Matá-lo no meio de uma ação é seguro de qualquer forma: pares de pressionar/soltar botão nunca abrangem chamadas de ferramentas, e até mesmo o botão pressionado de um arrasto longo é liberado na saída. - O assento é compartilhado. Há um cursor e um foco de teclado, e o foco-segue-o-mouse do Hyprland significa que um movimento de cursor sozinho pode redirecionar teclas. Não digite enquanto um agente está dirigindo; observe o indicador.
- Escopo: stdio apenas (sem ouvinte de rede), nada persistido exceto o beacon e o cache de capturas limitado em
$XDG_RUNTIME_DIR(tmpfs, 20 mais recentes) e, se você ativar, o diário de ações em disco sob$XDG_STATE_HOME(rotacionado, uma geração, e com texto redigido por padrão). Sem acesso à área de transferência a menos que você opte:HYPRUSE_CLIPBOARD=1registra uma ferramentaclipboard(nunca em modo somente leitura); áreas de transferência guardam senhas, então deixe desligado a menos que um fluxo de trabalho precise. Uma captura vê tudo visível, e uma captura de janela também alcança janelas em workspaces ocultos, em scratchpads e sob outras janelas: trate uma sessão de agente como compartilhar todo o seu desktop. O modo somente leitura eHYPRUSE_CONFINElimitam o que o agente pode fazer, não o que ele pode ver. Capturas de janela são recusadas enquanto a sessão está bloqueada. - O que o agente lê não é confiável. Títulos de janelas, nomes e valores de acessibilidade, e texto da área de transferência fluem literalmente para o contexto do agente, e qualquer página web, nome de arquivo ou documento pode colocar instruções lá (injeção de prompt). hypruse não pode sanitizar significado, então a camada de aprovação é o último recurso: mantenha ferramentas consequentes (
launch,keyboard,clipboard) em perguntar-primeiro quando o agente olhar para janelas não confiáveis, e trate "a tela me disse" como entrada de atacante ao revisar um prompt de aprovação. - A entrada nunca chega onde silenciosamente não funcionaria. Três verificações sempre ativas (sem flag de ambiente) recusam ou anotam em vez de relatar um sucesso fantasma: um clique mirado sob um lançador ou superfície de camada de teclado na tela (que fica acima das janelas e o engoliria), digitação enquanto um lançador segura o grab de teclado, e qualquer entrada enquanto a sessão está bloqueada. Uma tela de bloqueio é um cliente
ext-session-lock, invisível para as listas de janelas e camadas, então hypruse pergunta ao próprio Hyprland (hyprctl locked), que cobre hyprlock, swaylock, o bloqueio embutido do Omarchy, e um bloqueador que travou e deixou a sessão bloqueada. Enquanto bloqueado,pointere umkeyboardsem janela recusam a menos queallow_auth=truediga que um humano quer o agente dirigindo o prompt de desbloqueio (nunca sobHYPRUSE_CONFINE);keyboardcomwindow=eclick_uisempre recusam, já que entrada mirada em uma janela não pode alcançá-la atrás do bloqueio. Estes são auxílios de veracidade, não uma sandbox: a verificação de bloqueio falha aberta em um estado de sistema ilegível, então eles endurecem o caso comum sem serem um limite em que você pode se apoiar. (EnquantoHYPRUSE_AUTH_GUARDestá ativo, uma lista de camadas ilegível fazpointer,click_uiekeyboardrecusarem, já que um prompt de autenticação não pode ser descartado.)
Confinamento opcional
Seis flags de ambiente opcionais. As primeiras quatro restringem o que um agente pode tocar, e cada uma falha em direção a menos ação; as últimas duas registram e ensaiam em vez de restringir. Todas compõem com as camadas acima:
HYPRUSE_CONFINErestringe a entrada a um escopo de janelas:launched(apenas janelas que o próprio hypruse abriu nesta sessão),class:firefox,kittyouworkspace:3,special:notes. Operações de teclado,click_uiehyprem janelas são recusadas fora do escopo; um clique depointeré recusado quando qualquer janela sob o ponto está fora do escopo (a lista de janelas do Hyprland não é ordenada por z, então o hypruse falha de forma segura em vez de adivinhar qual janela está no topo). É isso que permite deixar um agente trabalhando enquanto seu gerenciador de senhas fica em outro workspace, fora do alcance dos cliques e teclas dele (mas não das capturas de tela).use_bindé recusado de imediato enquanto o confinamento estiver definido, porque um keybind executa uma ação arbitrária do compositor que não pode ser limitada a uma janela.HYPRUSE_AUTH_GUARD(padrão ativado) recusa clicar ou digitar em um diálogo de autenticação do sistema (agentes polkit, seja uma janela como hyprpolkitagent ou um prompt que o shell desenha como camada, como Omarchy 4 e os dots do end-4 fazem; o prompt do chaveiro do GNOME; os próprios diálogos do Hyprland, que são seu prompt de permissão e também seus avisos de aplicativo sem resposta e modo de segurança, já que todos os três compartilham uma classe de janela), para que um agente manipulado não possa aprovar uma elevação de privilégio.click_uitambém recusa quando tal diálogo flutua sobre o controle em que foi solicitado clicar. Quando a lista de camadas não pode ser lida, ele recusa em vez de adivinhar. Um prompt que um shell abre como uma janela comum de sua própria classe, como o DankMaterialShell faz, não é reconhecido. DefinaHYPRUSE_AUTH_GUARD=strictpara também recusar digitar em um campo de senha dentro de uma janela comum (um login de navegador), detectado via árvore de acessibilidade. Umallow_auth=truepor chamada empointer/keyboard/click_uio substitui, e como isso altera os argumentos da ferramenta, a substituição aparece de forma distinta no prompt de aprovação.HYPRUSE_AUTH_GUARD=0o desativa.HYPRUSE_STRICTrecusa agir quando o cursor ou a janela focada se moveu desde a última ação do hypruse (o humano, ou um popup, tomou o assento): o agente deve relerdesktop/screenshote tentar novamente, para que nunca digite em uma janela para a qual você acabou de alternar.HYPRUSE_MARKtorna a presença do agente legível no desktop: ele marca cada janela que o agente abre comhypruse-ownede pisca um aviso na tela quando o agente abre uma janela ou captura a tela. Ele também instala uma regra de janelaborder_colornessa marca para que janelas de propriedade do agente ganhem um contorno colorido, mas se uma regra em tempo de execução é renderizada depende da sua versão do Hyprland e da precedência de configuração (em alguns setups ela não tem efeito); quando não pode ser instalada de forma alguma, o hypruse avisa no stderr em vez de deixar você com uma camada de marcação que silenciosamente não está rodando. Para um contorno garantido, adicione a regra à sua própria configuração, que a marcação do hypruse então corresponde:windowrule = border_color rgb(ff5555), tag hypruse-ownedemhyprland.conf(Hyprland mais antigo:tag:hypruse-owned), ouhl.window_rule({ match = { tag = "hypruse-owned" }, border_color = "rgb(ff5555)" })emhyprland.lua.HYPRUSE_JOURNALregistra o que o agente fez: uma linha NDJSON por chamada de ferramenta em$XDG_STATE_HOME/hypruse/journal.ndjson(HYPRUSE_JOURNAL=1), ou um caminho de sua escolha. Leia comhypruse journal, reexecute comhypruse replay. Veja O registro abaixo.HYPRUSE_DRYRUNé um ensaio: cada verificação de argumento e cada guarda acima é executada, então a chamada relata o que teria feito e não entrega nada.
O registro: diário, ensaio seco, replay
As flags acima decidem o que um agente pode fazer no momento e depois esquecer que aconteceu. HYPRUSE_JOURNAL é a memória. Um objeto JSON por linha, então tail -f, grep e jq funcionam em um arquivo vivo:
{"v":1,"seq":7,"ts":"2026-08-02T09:12:13.456Z","kind":"act","tool":"pointer",
"args":{"action":"click","x":800,"y":60},"outcome":"ok","ms":37,"result":"click ok"}
kind divide as duas perguntas que as pessoas realmente fazem: act é entrada entregue ao seu desktop, observe é o agente olhando, que é o que uma auditoria de privacidade quer (quando a tela foi capturada, quando a área de transferência foi lida). Resultados de observação nunca são registrados, apenas que aconteceram, então o diário nunca se torna uma segunda cópia de tudo que o agente viu. Recusas também são registradas, com a mensagem da própria guarda: é o único lugar onde existe a história das suas camadas de confiança fazendo seu trabalho.
Texto digitado e copiado é registrado como um comprimento mais um digest curto, não como texto, porque teclas são senhas. HYPRUSE_JOURNAL_TEXT=1 o mantém verbatim, que você só precisa para reexecutar a digitação. Note o que um digest é e não é: ele prova que duas entradas digitaram a mesma coisa e não entregará sua senha a um leitor, mas é um prefixo SHA-256 sem salt ao lado de uma contagem exata de caracteres, então um PIN de quatro dígitos é trivialmente recuperado dele. Trate o diário como sensível de qualquer forma. Ele é escrito com 0600 em um diretório 0700, e rotacionado em HYPRUSE_JOURNAL_MAX_BYTES (8 MiB, uma geração anterior mantida como .1; defina 0 para nunca rotacionar).
O diário é um gravador, não uma guarda: se não puder ser escrito, a ação ainda acontece e o hypruse avisa uma vez no stderr, porque falhar seu desktop por causa de uma linha de log é o trade errado. O que ele não registra é uma observação de then= como entrada própria: a chamada de ação que a carregou é registrada, then=screenshot e tudo, mas a captura não ganha uma segunda linha própria.
Leia de volta com hypruse journal (--acts para ações apenas, --refused para o que as guardas pararam, -n N para seguir o final, -v para incluir cada resultado):
1 09:12:10 session start pid 4211 0.10.0 confine=launched auth_guard=1 strict=True
14 09:12:13 act pointer action=click x=800 y=60
16 09:12:15 act keyboard action=type text=<11 chars>
19 09:12:19 act hypr action=close_window target=0x5f2a10
REFUSED TrustError: 0x5f2a10 (Signal) is outside the agent's confinement scope
312 actions (0 dry), 604 observations, 1 refused by a trust layer, 0 errors
HYPRUSE_DRYRUN=1 transforma a mesma sessão em um ensaio. Cada ferramenta de ação valida seus argumentos e executa cada guarda de confiança, então relata o plano em vez de executá-lo, então um ensaio seco recusa exatamente o que uma execução real recusaria:
DRY RUN, nothing was delivered: would click push button 'Send' at (1204, 880) in signal
Nada chega ao desktop: nem o clique, nem a tecla, nem mesmo o foco de janela que normalmente precede a digitação. Aplicado duas vezes, uma em cada ferramenta e uma no próprio caminho de entrada, para que um caminho de código que ninguém pensou falhe alto em vez de agir silenciosamente durante uma simulação. O agente é informado que o ensaio seco está ativo, então ele relata um plano em vez de tentar novamente uma ação que "não funcionou". O escopo são as ações do agente, não a inicialização do próprio servidor: HYPRUSE_MARK, se você definir, ainda instala sua regra de janela quando o servidor inicia.
hypruse replay <journal> reemite as ações de um diário através das mesmas funções de ferramenta, então as mesmas guardas se aplicam ao replay. Ele imprime o plano e para ali, a menos que você passe --execute. Antes de tomar o assento, ele recusa de imediato, em vez de falhar no meio e deixar seu desktop no meio do plano de outra pessoa, quando: uma ação foi registrada por um hypruse mais novo, uma janela registrada não existe mais (--skip-missing executa o resto), texto digitado foi registrado como digest, a entrada é um click_ui(mark=N) cuja numeração morreu com a sessão que o desenhou, a entrada é uma escrita na área de transferência e HYPRUSE_CLIPBOARD não está definido, ou HYPRUSE_READONLY ou HYPRUSE_DRYRUN está definido. Ele se ritma a partir do tempo registrado, limitado por --max-gap e escalado por --speed, e suas próprias ações são registradas e marcadas, então reexecutar o mesmo arquivo novamente executa o plano original em vez do plano mais o replay dele.
O limite honesto são endereços de janela: eles são ponteiros de heap, então o diário de ontem nomeia principalmente janelas que se foram, e um endereço pode até ser reutilizado por uma janela diferente depois, o que nenhum pré-voo pode pegar. Replay é para reexecutar um fluxo em um desktop que ainda se parece com o registrado.
Ensaio seco e replay compõem na direção óbvia: deixe o agente trabalhar com HYPRUSE_DRYRUN=1, leia o diário e reexecute com --execute quando o plano for um que você goste.
Performance
Medido em uma sessão ao vivo (Hyprland 0.55, 1080p, 20 janelas): desktop
~20 ms (uma chamada hyprctl em lote), despacho de workspace/janela ~10-20 ms, captura de tela de monitor inteiro ~65 ms
(JPEG rápido padrão; ~800 ms se você pedir PNG sem perdas, o caminho zlib do grim
domina), capturas de região/zoom bem abaixo disso. Se as chamadas
de ferramenta parecerem lentas, é quase certamente o prompt de aprovação do MCP na
frente de cada chamada, não o servidor. Coloque na allowlist as ferramentas que você confia e a
latência desaparece. Claude Code (.claude/settings.json):
{
"permissions": {
"allow": [
"mcp__hypruse__desktop",
"mcp__hypruse__screenshot",
"mcp__hypruse__hypr"
// add pointer/keyboard/launch once you trust your workflows
]
}
}
Coordenadas
Tudo fala nas coordenadas lógicas globais do Hyprland, o espaço que hyprctl cursorpos e a janela at usam. Capturas de tela são em espaço de pixel; cada captura retorna geometry e scale para que global = origin + pixel / scale. Em monitores com escala 1.0 (a maioria dos setups), pixels de imagem são coordenadas globais.
A ferramenta zoom faz a aritmética de precisão para o agente: dê a ela um ponto global estimado e ela captura uma caixa em resolução nativa ao redor dele, limitada à tela (ou a uma janela), com o mesmo contrato de metadados. Esse loop de dois passos, estimar na visão completa e depois reestimar no zoom, é a maneira respaldada por pesquisa de acertar controles pequenos.
Capturas usam JPEG q90 por padrão: em um quadro 1080p, isso é aproximadamente 12x mais rápido de codificar que PNG (o caminho zlib do grim domina o tempo de captura, medido ~65 ms vs ~800 ms) e 3-4x menor, enquanto q90 em resolução total lê bem texto de UI. Passe lossless=true para pixels exatos (PNG). Em modo de imagem, capturas também se ajustam ao limite de tamanho de resultado do host (Claude Desktop limita resultados de ferramenta a 1 MB) degradando qualidade antes de resolução, já que o filtro de downscale do grim é mais lento que uma captura em resolução total, e limitam a borda longa em HYPRUSE_MAX_IMAGE_EDGE pixels (padrão 1568) para que o host nunca reduza a imagem sob o modelo. A escala aplicada é incorporada aos metadados retornados, então o mapeamento de coordenadas permanece exato; ajuste com HYPRUSE_MAX_IMAGE_BYTES, ou passe scale para um zoom-out deliberado.
Por padrão, a ferramenta de captura de tela escreve a imagem em $XDG_RUNTIME_DIR/hypruse/ e retorna seu caminho; hosts MCP com leitor de arquivos (Read do Claude Code) a renderizam nativamente. Esse padrão existe porque alguns hosts (incluindo Claude Code 2.1.x) serializam blocos de imagem MCP inline em texto base64 que o modelo não consegue ver. HYPRUSE_SCREENSHOT_MODE=image alterna para blocos de conteúdo de imagem inline para hosts que os renderizam corretamente.
Desenvolvimento
uv sync --group dev
uv run pytest # unit tests, no compositor needed
uv run pytest -m e2e --override-ini addopts= # live seat-safe checks
uv run python scripts/e2e_input.py # supervised: takes the seat ~10s
O e2e de entrada é deliberadamente manual: ele pega emprestado seu cursor e teclado, faz contagem regressiva, prova a entrega de clique/scroll/digitação lendo a tela do terminal alvo de volta via controle remoto do kitty e restaura seu foco.
Roadmap
Fundamentado em latências medidas no caminho quente e na descoberta de que chamadas LLM são 76 a 96% da latência de tarefas de uso de computador (OSWorld-Human), então cortar round-trips vence raspar milissegundos. O trabalho de round-trip que esse enquadramento motivou já foi amplamente entregue: sequence, agir-e-observar then= (incluindo then='ui') e as ferramentas de árvore de acessibilidade (ui, marks, click_ui) que miram controles por nome sem captura de tela. O que resta:
Mais rápido
- wlr-screencopy em processo sobre o wire bruto (como a entrada já funciona): remover o piso de fork do grim de capturas pequenas e adicionar espera-por-estável rastreada por dano que retorna no instante em que a tela assenta.
Menos round-trips
- Diff semântico de tela: após uma ação, retornar apenas o que mudou (topologia de janelas do stream de eventos, ou um recorte de região alterada limitado) em vez de um quadro completo. A expansão de eventos socket2 por trás de
wait_forjá rastreia a maior parte da topologia; a peça que falta é dobrá-la em um delta pós-ação.
Leitura mais profunda
- Cobertura de acessibilidade mais ampla: fechar as lacunas que as ferramentas
uiemarksencontram hoje, principalmente os combo boxes mais novos do GTK que não publicam nem texto nem seleção (então um valor de dropdown renderizado ainda precisa de captura de tela), além de eventos de mudança de valor AT-SPI para quethen='ui'possa relatar um controle assentando sem poll. - Notificações: ler conteúdo e histórico de notificações recentes do desktop, não apenas esperar o popup aparecer (
wait_forjá corresponde alayer_openno namespace de notificações).
Confiança
- Ferramenta
record: um GIF ou mp4 com escopo do agente dirigindo a área de trabalho, via wf-recorder (um binário da família wlroots como grim), um acompanhamento visual do journal.
Plataforma
- Suporte a sway / niri: o cliente wire já fala os protocolos wlr; o que resta é uma camada IPC ao lado de
hyprctl.py(contribuições são bem-vindas). - Testes headless de ponta a ponta no CI: precisa de uma VM QEMU virtio-gpu, já que o backend aquamarine do Hyprland exige um nó de renderização de GPU real que os runners hospedados não possuem.
Medição
- Benchmark de precisão do loop de zoom: mede a precisão do clique do loop grosseiro-para-fino contra alvos conhecidos.
- Benchmark de sucesso de tarefas de ponta a ponta no Hyprland (estilo OSWorld): o irmão maior adiado do microbenchmark do loop de zoom, avaliando tarefas completas de múltiplas etapas através da superfície MCP real, para que o trabalho de acessibilidade-versus-visão e de ida e volta seja julgado pela conclusão da tarefa, não apenas pela latência.
Projetos relacionados
| projeto | abordagem | no Hyprland |
|---|---|---|
| computer-use-linux | AT-SPI + portais, fallback ydotool | primeiro no GNOME; o portal RemoteDesktop que ele prefere não é implementado pelo xdg-desktop-portal-hyprland |
| hyprmcp | wrapper hyprctl | apenas gerenciamento de janelas; sem capturas de tela ou entrada |
| wayland-mcp | entrada evemu, análise VLM | requer configuração elevada para entrada; sem semântica do Hyprland |
| Anthropic computer-use-demo | X11 + xdotool no Docker | um ambiente de referência em sandbox em vez de uma área de trabalho ao vivo |
| Cua (cua-driver) | driver multiplataforma; um plugin opcional de compositor Hyprland dá ao agente seus próprios assentos de entrada | o plugin deve ser compilado para a versão exata do Hyprland instalada, e seu README o chama de experimental e não lançado |
Pesquisa
hypruse não inclui nenhum mecanismo de OCR; seu mecanismo universal de precisão é o loop de zoom grosseiro-para-fino: captura uma janela, recaptura a região alvo em resolução nativa, clica através do mapeamento exato de coordenadas. Essa escolha segue o que o campo de agentes GUI convergiu. O computer use da Anthropic fundamenta cliques em pixels brutos e inclui uma ação zoom como a correção documentada para texto pequeno; sua orientação de solução de problemas para cliques quase errados prescreve zoom e recorte de região, nunca OCR [1]. O CUA da OpenAI é igualmente fundamentado em pixels puros sob disciplina de resolução, sem nenhuma camada de OCR [2]. O zoom também é a alavanca medida: o zoom iterativo sem treinamento aproximadamente dobra a precisão de fundamentação em alta resolução (OS-Atlas-7B, 18.9 → 49.7 no ScreenSpot-Pro) [3], e o harness oficial do benchmark implementa uma dúzia de adaptadores de modelos de fundamentação mais quatro estratégias de zoom/recorte, mas zero baselines de OCR [4]. Agentes somente visão correspondem ou superam agentes que adicionalmente consomem árvores HTML ou de acessibilidade [5], substratos que o Wayland não garante de qualquer forma, e agentes nativos de última geração operam apenas a partir de capturas de tela [7]. O OCR foi rejeitado porque é cego a ícones, a classe de elementos que todo modelo de fundamentação lida pior (SeeClick: 30-52% em ícones vs 56-78% em texto) [6]; onde o OCR sobrevive em stacks modernas, é um sidecar de desambiguação de texto, não o mecanismo de direcionamento [8].
Onde um aplicativo expõe uma árvore de acessibilidade, o hypruse também a lê (a ferramenta ui, AT-SPI sobre D-Bus via busctl) para direcionar controles por nome com coordenadas exatas e sem captura de tela. Isso segue o precedente Linux mais forte: o OSWorld, o benchmark padrão de computer use, expõe a árvore de acessibilidade da área de trabalho (obtida no Ubuntu através de AT-SPI) como uma observação de primeira classe ao lado de capturas de tela, e relata a combinação árvore-de-acessibilidade-mais-captura-de-tela como sua melhor configuração [9]. A árvore dá identidade exata de elementos e coordenadas que os modelos atuais não conseguem inferir de forma confiável a partir de pixels: o Agent-S marca cada elemento com um id porque MLLMs "carecem de um sistema de coordenadas interno," elevando o sucesso do OSWorld de 11.2 para 20.6 por cento [10]; o UFO da Microsoft dirige o Windows através da árvore de UI Automation e a funde com visão [11]; agentes de navegador leem a árvore de acessibilidade, que o Playwright serializa em YAML compacto, em vez de pixels pela mesma razão [12]. O truque específico do Wayland do hypruse é o mapeamento de coordenadas: coordenadas de tela AT-SPI são não confiáveis no Wayland porque um aplicativo não sabe sua posição global, então o hypruse usa extensões relativas à janela mais a posição da janela que já tem do hyprctl. A cobertura é desigual por natureza: canvas, jogos, terminais e Electron/Chrome sem uma flag expõem pouco ou nada [13]. Testar esta implementação contra aplicativos GTK e Qt reais afiou isso em ambas as direções: uma entrada digitada lê de volta seu conteúdo exato, e sliders e toggles relatam sua posição e estado, mas os combo boxes mais novos do GTK não publicam nem seu texto nem uma seleção, então ler um valor de dropdown renderizado ainda precisa de uma captura de tela. Toolkits também descrevem widgets que nunca foram dispostos (setas de rolagem de altura zero, páginas de abas não renderizadas relatando origens na casa dos milhões), que o hypruse rejeita contra o retângulo da janela que o hyprctl conhece de forma autoritativa. Um grounder visual forte pode substituir a árvore inteiramente [5], então a árvore de acessibilidade complementa o loop de zoom em vez de substituí-lo, e a visão permanece o fallback garantido.
- Anthropic, Computer use tool: docs da plataforma (
computer_20251124,enable_zoom, orientação de resolução) - OpenAI, Computer-Using Agent e o guia de computer use
- DiMo-GUI: Advancing Test-time Scaling in GUI Grounding via Modality-Aware Visual Reasoning, EMNLP 2025. arXiv:2507.00008
- Li et al., ScreenSpot-Pro: GUI Grounding for Professional High-Resolution Computer Use. arXiv:2504.07981; harness oficial
- Gou et al., Navigating the Digital World as Humans Do: Universal Visual Grounding for GUI Agents (UGround), ICLR 2025 Oral. arXiv:2410.05243
- Cheng et al., SeeClick: Harnessing GUI Grounding for Advanced Visual GUI Agents, ACL 2024. arXiv:2401.10935
- Qin et al., UI-TARS: Pioneering Automated GUI Interaction with Native Agents. arXiv:2501.12326
- Agyeya et al., Agent S2: A Compositional Generalist-Specialist Framework for Computer Use Agents (Tesseract como sidecar de fundamentação textual). arXiv:2504.00906
- Xie et al., OSWorld: Benchmarking Multimodal Agents for Open-Ended Tasks in Real Computer Environments. arXiv:2404.07972; a árvore a11y é obtida no Ubuntu através de AT-SPI (código)
- Agashe et al., Agent S: An Open Agentic Framework that Uses Computers Like a Human. arXiv:2410.08164
- Zhang et al., UFO: A UI-Focused Agent for Windows OS Interaction (UI Automation + visão). arXiv:2402.07939
- Playwright, ARIA snapshots: a árvore de acessibilidade como texto estruturado compacto
- Wang et al., GUI Agents: A Survey (lacunas de cobertura da API de acessibilidade; a11y complementa a visão). arXiv:2412.13501