Communitygithub.com

iwishwp/AgentOS

Opere o desktop AgentOS (niri/Wayland): gerenciamento de janelas e workspaces, operações acessíveis em aplicativos GUI, automação de navegador, artefatos de arquivo, notificações e apresentação na área de trabalho. Funciona com qualquer framework de agente que monte as oito extensões MCP do AgentOS (niri/desktop/system/files/session/a11y/browser/cred). Use quando envolver 'operar aplicativos/janelas/arquivos/notificações no desktop do usuário'.

O que é AgentOS?

AgentOS é um conjunto de oito extensões MCP (Model Context Protocol) que concede a agentes de IA como Claude Code, Cursor ou Goose controle completo sobre um desktop Linux rodando niri/Wayland. Ele organiza as capacidades em quatro camadas hierárquicas: L0 (sistema: janelas, workspaces, arquivos), L1 (árvore de acessibilidade AT-SPI2 para clicar e ler textos em aplicativos GUI), L2 (navegador headless Chromium para automação de páginas web) e L3 (fallback visual com screenshots e injeção de teclado). As extensões se comunicam via servidores stdio MCP, exigindo scripts de inicialização especiais que descobrem dinamicamente o socket IPC do niri e configuram variáveis de ambiente Wayland/DBus. O AgentOS é particularmente útil para agentes que precisam interagir com aplicações desktop do usuário sem roubar o foco, gerenciar múltiplos workspaces, automatizar tarefas no navegador ou manipular arquivos em uma sandbox segura. Inclui um ambiente 'aquário' (niri aninhado) onde o agente pode executar aplicações GUI sem interferir na sessão do usuário, e um sistema de confirmação em faixas (T1/T2) para operações que exigem consentimento humano. O manual documenta dezenas de armadilhas reais (como links simbólicos do socket do niri, bloqueio de rede do Chromium por chaveiro, árvores do GTK4 incompletas) e fornece receitas testadas para contorná-las.

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Manual de Operação do Desktop AgentOS (genérico para qualquer agente)

Este manual é autocontido: contanto que seu framework consiga montar servidores MCP stdio (goose / Claude Code / Z Code / Cursor etc.), sigam a §1 para montar e obter todas as capacidades abaixo. Todos os itens foram testados em hardware real (Fedora + niri Wayland, evidenciados de ponta a ponta em 2026-10 no repositório docs/capabilities.md).

0. Modelo Mental: Quatro Camadas de Capacidade, em Ordem Decrescente de Prioridade

  1. L0 – Camada de Sistema — janelas / workspaces / inicialização / arquivos / notificações / área de transferência (extensões niri/desktop/system/files): a mais estável, use primeiro;
  2. L1 – Árvore de Acessibilidade — clicar por nome e ler/escrever texto dentro de aplicativos GUI (extensão a11y, AT-SPI2): não requer foco, não incomoda o usuário, testado em GTK3/GTK4/Qt (a chave global do Qt e o toolkit-accessibility do Chromium já são padrão do sistema desde 2026-10-18); leitura de árvore e entrada de texto no Chromium são possíveis (cliques em página vão para L2); Java não instalado (caminho no apêndice B do capabilities.md); aplicativos puramente X11 (classe xterm) não têm árvore, só L3;
  3. L2 – CDP do Navegador — todas as operações em páginas web (extensão browser, Chromium headless dedicado ao agente);
  4. L3 – Fallback Visual/Entrada — screenshot (grim, confiável), injeção de teclado (scripts/kb-inject.sh: wtype a nível de usuário como principal, texto/combinações de teclas confiáveis; teclas de controle (Enter/Tab) caem para ydotool que requer sudo), injeção de ponteiro (não confiável: desvia com aceleração, apenas como último recurso).

Ao encontrar um aplicativo que "não abre/não funciona bem": primeiro pense se as pré-condições L1 não foram atendidas (chave a11y), depois use L3 com screenshot para ver o estado real, não tente repetir cegamente.

1. Montagem (única vez)

goose (~/.config/goose/config.yaml, formato testado na versão 1.54; o campo name: é obrigatório, sem ele a extensão inteira é descartada silenciosamente):

extensions:
  niri:
    type: stdio
    name: niri
    enabled: true
    cmd: /path/to/AgentOS/scripts/env/with-niri-env.sh
    args: []
    env_keys: []
    envs: {}
    timeout: 300          # unidade: segundos
  # desktop/system/files/session/a11y/browser/cred são isomórficos,
  # cmd usa com with-desktop-env.sh / with-system-env.sh / ... (oito lançadores em scripts/env/)

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

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

Pontos importantes:

  • Use os scripts lançadores, não aponte diretamente para node dist/index.js — o lançador descobre o socket IPC do niri (caminho contém o PID do compositor, diferente a cada sessão, ex.: /run/user/1000/niri.wayland-1.2762.sock) e completa o ambiente Wayland/dbus (XDG_RUNTIME_DIR/WAYLAND_DISPLAY/DBUS_SESSION_BUS_ADDRESS), para que a ferramenta funcione quando iniciada a partir de SSH/ambiente de serviço;
  • Teste manual do lançador: timeout 2 scripts/env/with-niri-env.sh </dev/null, exit 0 significa OK;
  • Pré-requisitos: Node ≥ 20, repositório com npm install && npm run build já executado, executar sob o mesmo usuário da sessão gráfica niri.

2. Referência Rápida de Ferramentas (agrupadas por extensão, nome da ferramenta = <extensão>__<ferramenta>)

niri —— Janelas / Workspaces / Inicialização (L0)

FerramentaUsoParâmetros Chave
list_windowsLista todas as janelas (id/app_id/título/workspace/foco)—
list_workspacesLista workspaces (idx numérico é diferente de id; para mover use número ou nome)—
list_outputsLista monitores—
focus_windowMuda o foco para a janela (muda a perspectiva do usuário, use com cautela)id
focus_workspaceMuda de workspace (muda a perspectiva do usuário)reference: "3" ou nome
move_window_to_workspaceMove janela (não rouba o foco, para organizar)id? (padrão = janela em foco), reference
close_windowFecha janelaid?
open_appInicia um programa no desktop do usuáriocommand: array, ex.: ["ghostty"]

a11y —— Operações dentro de aplicativos GUI (L1, AT-SPI2)

FerramentaUsoParâmetros Chave
a11y_list_appsLista aplicativos registrados no barramento de acessibilidade—
a11y_dump_treeDespeja a árvore de acessibilidade de um aplicativo (encontre nomes de botões / estrutura)app
a11y_clickClica pelo nome acessível (não requer foco, não incomoda o usuário)app, buttonName
a11y_read_textsLê todos os textos não vazios de um aplicativo (tela / resultados / rótulos)app
a11y_set_textEscreve em um campo de texto pelo nome do nóapp, match (substring do nome, padrão * primeiro), text

Disciplina comprovada: enderece por nome, não por índice da árvore (a estrutura da árvore é reconstruída ao reconectar o AT); árvores do GTK4 só ficam completas após o registro do cliente AT; instâncias múltiplas com o mesmo nome – a ponte resolve para a primeira registrada – leia o texto para distinguir o estado da instância, feche as extras se necessário. Exceção do Chromium: árvore construída lentamente (a ponte a aciona automaticamente, primeiro dump pode levar 1-2 segundos extras – normal); escrever em campos de texto use combinação grabFocus + kb-inject type (o entry do Chromium não aceita setTextContents); cliques em botões de página não funcionam (doAction é despachado mas onclick não executa), operações em página vão sempre pela extensão browser.

browser —— Operações em Páginas Web (L2, Chromium headless dedicado ao agente)

FerramentaUsoParâmetros Chave
browser_openNavega (primeira chamada inicia o navegador automaticamente)url
browser_evalExecuta JS na página, preenche formulários / clica / lê conteúdo – tudo por elaCódigo JS
browser_screenshotScreenshot (navegador headless, visual depende totalmente dele)—

Ação padrão para preencher formulários: após el.value = "..." é obrigatório el.dispatchEvent(new Event("input", {bubbles: true})), caso contrário frameworks modernos não recebem a entrada. Ao encontrar CAPTCHA: pare e informe o usuário, nunca contorne automaticamente.

files —— Sandbox de Arquivos (L0, raiz = ~/Agent/, caminhos sempre relativos)

FerramentaUsoParâmetros Chave
read_file / write_fileLê / escreve texto (cria diretório pai automaticamente)path, content
list_dir / create_dirLista / cria diretóriopath
move / deleteMove / deleta (vai para .trash, recuperável, não use shell rm)source/dest, path
find_by_nameEncontra arquivos por nomepattern
downloadDownload http(s) para dentro da sandbox (≤50MB / 60s, não use shell curl)url, path

desktop —— Apresentação / Notificações / Área de Transferência / Confirmação (L0)

FerramentaUsoParâmetros Chave
openAbre artefato: URL ou arquivo; documentos office devem usar app: "libreoffice" (lista branca, associação MIME do sistema não é confiável)target, app?
notifyNotificação no desktop (três níveis, veja §3)summary (obrigatório), body, urgency, action?
confirmPede autorização/decisão ao usuário (T1: quatro banners: permitir / permitir na sessão / negar / nunca; 30s sem resposta = negar)summary (sem conteúdo sensível), tier? (t1/t2, afeta o texto)
clipboard_read / clipboard_writeLê / escreve na área de transferência—

session —— Aquário (sessão niri aninhada dedicada ao agente, toda ação GUI ocorre aqui)

FerramentaUso
agent_session_start / agent_session_stop / agent_session_statusCiclo de vida da sessão aninhada (aparece uma janela observável no desktop)
agent_open_appInicia aplicativo dentro do aquário (ex.: gnome-calculator, chromium)
agent_list_windowsLista janelas dentro do aquário
agent_screenshotScreenshot direcionado do interior do aquário (grim)

system —— Consultas ao Sistema (L0, somente leitura, tudo liberado)

system_status / list_services / service_status / journal / network_info / list_packages / package_info / package_install (T2 confirmação forte: abre janela de senha polkit, requer presença humana; se headless, timeout de 300s e recusa – não chame em modo não supervisionado).

cred —— Credenciais (agente recebe referência, não texto claro)

cred_list (credenciais disponíveis e suas referências/nomes de env var) · cred_autofill (canal A: preenchimento automático na página, texto claro descartado) · cred_exec (canal B: execução delegada em lista branca + saída mascarada) · cred_inject (canal C: injeção de variáveis de ambiente com TTL curto, toda a série removida ao expirar). Qualquer operação que precise de senha/token deve usar apenas cred, nunca peça texto claro ao usuário.

3. Convenções Comportamentais (disciplina comprovada em testes)

  1. Artefatos sempre caem em ~/Agent/, categorizados em downloads/ inbox/ reports/ notes/ canvas/ screenshots/; a queda já entra automaticamente no índice de artefatos (http://127.0.0.1:7788/artifacts); se o usuário perguntar "onde está meu relatório da última vez" → abra essa página ou informe o caminho relativo;
  2. Prioridade de apresentação: dashboard / relatório / conteúdo interativo → escreva HTML autocontido em canvas/<nome>/index.html e depois open para abrir http://127.0.0.1:7788/<nome>/; documentos office → open com app: "libreoffice"; páginas web → extensão browser;
  3. Três níveis de notificação: conclusão → notify com urgency=low + action ({kind:"open_path", path:"reports/x.fodt"} ou {kind:"open_url", url:...}, clicar na notificação leva direto ao artefato); falha / precisa saber rápido → urgency=critical + conclusão em uma frase + causa e sugestão; quando precisa de decisão do usuário → não use notify, use confirm (notify não tem semântica de escolha). Resultados assíncronos sempre notificam, nunca concluir silenciosamente;
  4. Confirmação e bom senso: não mexa na janela que o usuário está usando, a menos que explicitamente solicitado (primeiro list_windows para identificar o alvo); quando houver recusa por política (isError e mensagem "recusa por política"), informe honestamente, não tente contornar; operações GUI faz no aquário, não roube o foco do usuário;
  5. Credenciais apenas via referência cred-mcp (a disciplina após a tabela cred na §2).

4. Referência Rápida de Armadilhas do Ambiente (todas já enfrentadas)

ArmadilhaFenômenoAção
Caminho do socket IPC do niri muda a cada sessãoniri msg não conectaUse o lançador (descobre automaticamente NIRI_SOCKET), nunca hardcode
Chaveiro do Chromium trava serviços de redeNavegador inicia e travaInicie com --password-store=basic (extensão browser já faz internamente; se iniciar chromium manualmente, lembre de usar)
Bloqueio de instância única do sofficeSe LibreOffice já estiver aberto, open para documento similar pode não abrir janela ou travarPrimeiro verifique o status do processo soffice; abertura de documento use app:"libreoffice" que segue semântica de lançador; se houve saída anormal anterior, pode aparecer janela "Document Recovery" (testado em 2026-10-18) – ao listar janelas para confirmar, não confunda com a janela do documento alvo
Associação MIME do LibreOffice não confiávelFedora reconhece fodt como text/xml e abre com editor de textoopen deve sempre usar app:"libreoffice"
Aplicativo Qt não aparece no barramento a11ya11y_list_apps não o vêO sistema já tem ativação global (QT_LINUX_ACCESSIBILITY_ALWAYS_ON=1 em /etc/environment, persistente após reinício); se ainda não aparecer = aplicativo foi iniciado antes da variável de ambiente ou não é vinculação oficial Qt, reinicie o aplicativo
Árvore a11y do Chromium/Electron vaziadump não retorna conteúdo① Inicie com --force-renderer-accessibility (extensão browser já usa por padrão); ② toolkit-accessibility deve estar true antes do aplicativo iniciar (já ativado globalmente; alterar depois não funciona, reinicie o aplicativo); ③ árvore construída lentamente, faça um dump para a ponte acionar (veja disciplina a11y na §2)
Escolha da injeção de tecladoPrecisa digitar / atalhos de tecladoscripts/kb-inject.sh: texto e combinações de teclas usam wtype (nível de usuário); teclas de controle como Enter/Tab não funcionam com wtype no GTK, use ydotool (sudo); chinês pode perder o primeiro caractere, após digitar leia de volta da árvore a11y para conferir
Aquário inicia com overlay de atalhos do niriScreenshot fica coberto por "Important Hotkeys"Injete Esc para fechar; o sandbox do agente não consegue conectar ao socket do ydotoold (root 600), use niri__open_app para executar a injeção no ambiente real do desktop
Desvio do ponteiro do ydotoolPosicionamento absoluto impreciso (aceleração libinput ≈0.5)Não confie no ponteiro; injeção de teclado é confiável; diferença de caminho do socket /tmp/.ydotool_socket vs $XDG_RUNTIME_DIR
Árvore inicial do GTK4 incompletadump retorna apenas dezenas de nósPrimeiro faça a11y_list_apps/dump uma vez para o cliente AT se registrar, depois o dump fica completo (testado: 16 → 105 nós)
Confirmação T1/T2 em execução headless30s/300s sem resposta nega automaticamenteComportamento esperado: operações de escrita requerem presença do usuário, ou durante testes responda programaticamente via org.agentos.Confirm1.Respond
Instalação de pacote bloqueada por packagekitddnf falha ocasionalmenteAntes de instalar: systemctl stop packagekit (helper T2 já trata isso)

5. Caminho de Upgrade (quando o aplicativo alvo não abrir, tente nesta ordem)

L0 (camada de sistema, sempre tente primeiro) → L1 (a11y: GTK3/4/Qt já acessíveis por padrão; Chromium verifique flag e ordem do toolkit-accessibility; Electron de terceiros adicione flag conforme apêndice B do capabilities.md) → L2 (páginas web obrigatoriamente) → L3 fallback (grim para ver + kb-inject para teclado; ponteiro não confiável). Tipos que ainda não abrem: aplicativos puramente X11 (classe xterm, sem árvore, L3 é o fim); Java (requer JAB, caminho no apêndice B do capabilities.md); UI do próprio compositor - apenas injeção de entrada. Tabela detalhada no repositório docs/capabilities.md.

Habilidades Relacionadas