[{"content":"Cada agente de código guarda as próprias skills, sessões e configuração numa pasta diferente, num formato diferente. O lazyagents junta tudo num terminal só, no espírito do lazygit.\nFunciona com: Claude Code, Codex, Gemini CLI, OpenCode e Hermes Agent.\nAba Para que serve Skills Instala de um repositório do GitHub, pasta ou zip, e ativa por agente com um symlink, sem copiar nada Sessões Retoma qualquer conversa no próprio CLI e na pasta certa, lê o transcript e busca em todos os agentes Consumo Limites da assinatura (janela de sessão e semanal) e tokens por dia, agente, projeto e modelo Providers e hooks Perfis de endpoint e hooks aplicados na configuração de cada agente, com confirmação e backup antes de escrever Plugins Qualquer executável vira uma aba e um comando novo, em qualquer linguagem Instalar # go install github.com/rogeriojunior31/lazyagents@latest Também há binários para Linux, macOS e Windows na página de releases. O passo a passo completo está em Primeiros passos.\n","externalUrl":null,"permalink":"/docs/lazyagents/visao-geral/","section":"Documentação","summary":"Cada agente de código guarda as próprias skills, sessões e configuração numa pasta diferente, num formato diferente. O lazyagents junta tudo num terminal só, no …","title":"Visão geral · lazyagents","type":"docs"},{"content":"Esta página leva você da instalação a uma skill ativada em dois agentes e uma sessão retomada, em cerca de cinco minutos.\nInstalação # Com Go 1.26 ou mais recente:\ngo install github.com/rogeriojunior31/lazyagents@latest Ou baixe um binário em Releases (Linux, macOS Intel e Apple Silicon, Windows) e confira-o usando SHA256SUMS:\ntar -xzf lazyagents_\u0026lt;version\u0026gt;_linux_amd64.tar.gz ./lazyagents --version Nenhuma outra ferramenta é obrigatória. Alguns recursos usam ferramentas que você talvez já tenha:\nFerramenta Uso git instalar skills do GitHub gh, autenticado buscar skills no GitHub (S na aba Skills) sqlite3 ler sessões do OpenCode lsof fora do Linux, indicar quais sessões do Claude Code estão em execução (no Linux, usa /proc) Confira o que o lazyagents encontra # lazyagents doctor O doctor lista os agentes encontrados, valida cada skill e informa links quebrados, hooks e plugins. Um agente é considerado instalado quando seu binário está no PATH ou seu diretório de configuração existe. A matriz completa dos recursos de cada agente está na referência de suporte dos agentes.\nAbra a TUI # lazyagents As abas ficam no topo: tab e shift+tab alternam entre elas; 1–9 vão direto à aba correspondente (clicar também funciona). ? lista as teclas da aba atual e : abre a paleta de comandos. q sai. O painel de detalhes fica ao lado da tabela em terminais largos e abaixo dela nos estreitos; a roda do mouse rola o conteúdo e um clique seleciona.\nAtive uma skill em dois agentes # Na aba Skills, pressione i e informe uma origem: um repositório do GitHub (usuario/repo ou sua URL), uma pasta local ou um .zip. Se a origem tiver várias skills, escolha quais instalar; uma skill única é instalada diretamente. Elas são copiadas para sua biblioteca, ~/.local/share/lazyagents/skills/. Selecione uma skill, vá até a coluna de um agente com ←/→ e pressione space. O lazyagents cria um link simbólico no diretório de skills desse agente. Pressionar space novamente remove o link. a ativa a skill em todos os agentes de uma vez; x desativa em todos. Skills que já estavam dentro de um agente também aparecem, como skills locais. o incorpora uma delas à biblioteca para que os outros agentes possam usá-la. Veja o guia de skills.\nRetome uma sessão # Abra a aba Sessions. Ela lista conversas do Claude Code, Codex, Gemini CLI, OpenCode, Pi e Crush, das mais recentes para as mais antigas. Digite / para filtrar ou f para mostrar apenas um agente. Pressione enter: o lazyagents suspende sua interface e retoma a sessão na CLI do próprio agente, na pasta correta. Ao sair do agente, você volta ao lazyagents. v permite ler a conversa sem retomar a sessão. Veja o guia de sessões.\nConsulte seu consumo # A aba Usage mostra os limites da assinatura (janelas de sessão e semanais, com os horários de renovação) e o consumo de tokens das conversas locais. p altera o período e ←/→ muda a visualização. Os limites do Claude Code são consultados pela rede somente quando você abre a aba ou executa lazyagents usage ou doctor, e ficam em cache por cinco minutos. Até você entrar em um agente ou usá-lo pela primeira vez, seus limites aparecem como ainda indisponíveis: isso é esperado. Veja o guia de consumo.\nUse em scripts # Cada aba tem uma alternativa sem interface, e os comandos de consulta aceitam --json:\nlazyagents list --json # skills e onde estão ativadas lazyagents enable my-skill --all # ativar em todos os agentes lazyagents sessions --here --limit 5 # sessões recentes nesta pasta lazyagents usage daily --since 30d lazyagents help \u0026lt;comando\u0026gt; explica cada comando; o mesmo texto está na referência da CLI.\nDesinstalação # Desfaça o que o lazyagents colocou nos diretórios dos agentes antes de apagar seus dados. Caso contrário, os links das skills apontarão para uma biblioteca que não existe mais (lazyagents doctor lista links quebrados):\nExecute lazyagents disable \u0026lt;skill\u0026gt; para cada skill ativada (lazyagents list mostra quais são). Para manter uma skill em um agente, primeiro copie sua pasta da biblioteca para o diretório de skills desse agente. Execute lazyagents provider clear e lazyagents hooks disable \u0026lt;nome\u0026gt; para cada hook instalado. Apague o binário, ~/.config/lazyagents e ~/.local/share/lazyagents. A pasta de backups fica dentro da última: preserve-a se houver algo que você possa querer recuperar. Próximos passos # Alterar o tema, a ordem das abas ou a aba inicial: Configuração e Temas. Apontar um agente para outro endpoint de API: Providers. Executar um comando em eventos dos agentes: Hooks. Entender o que o lazyagents altera no disco antes de usá-lo: Segurança e dados. ","externalUrl":null,"permalink":"/docs/lazyagents/getting-started/","section":"Documentação","summary":"Esta página leva você da instalação a uma skill ativada em dois agentes e uma sessão retomada, em cerca de cinco minutos.\nInstalação # Com Go 1.26 ou mais …","title":"Primeiros passos · lazyagents","type":"docs"},{"content":"Há dois caminhos. A maioria das pessoas quer um tema para um app que já usa, e para isso não precisa de ferramenta nenhuma. O restante quer criar um port ou reajustar a paleta, e é para isso que serve o spn.\nUsar um tema # Cada port é um repositório próprio em github.com/sp-night e traz arquivos de tema prontos, sem etapa de build. Instalar um é sempre os mesmos três passos:\nEscolha uma variação. noite é a padrão, garoa é a de cinza chapado, jaragua puxa o escuro para o verde. As três são escuras. Copie o arquivo dessa variação da pasta themes/ do port para o caminho que o app lê. Ative com a linha que o app espera. No Ghostty, por exemplo:\nmkdir -p ~/.config/ghostty/themes curl -fsSL -o ~/.config/ghostty/themes/sp_night_noite \\ https://raw.githubusercontent.com/sp-night/ghostty/main/themes/sp_night_noite echo \u0026#39;theme = sp_night_noite\u0026#39; \u0026gt;\u0026gt; ~/.config/ghostty/config O README de cada port, e a página dele em sp-night.github.io/ports, traz o caminho de instalação e a linha de ativação exatos, uma prévia por variação e a tabela de qual chave do app recebe qual papel. Essas páginas são geradas do mesmo catálogo que os arquivos de tema, então não têm como divergir do que você instala.\nInstalar o spn # Você só precisa do motor para criar um port, mudar um mapeamento ou reajustar a paleta.\ngo install github.com/sp-night/sp-night/cmd/spn@latest spn version Binários de release para Linux e macOS (amd64 e arm64) estão na página de releases. A paleta e o catálogo de ports vão dentro do binário, então o spn funciona em qualquer diretório.\nCompilar do código-fonte # git clone https://github.com/sp-night/sp-night cd sp-night go build ./cmd/spn go test ./... go run ./cmd/spn check -v --palette palette Uma dependência, para YAML. A suíte de testes renderiza os mapeamentos dos ports já publicados e compara a saída com os arquivos que os usuários instalaram, byte a byte.\nVer a paleta # spn palette # every colour, per flavour spn palette --roles # what each role resolves to spn check -v # the contrast audit, pair by pair Próximos passos # Antes de escrever ou mudar um mapeamento, leia a especificação. Para adicionar um app, siga Criar um port. Todos os comandos e opções estão na referência de comandos. ","externalUrl":null,"permalink":"/docs/sp-night/getting-started/","section":"Documentação","summary":"Há dois caminhos. A maioria das pessoas quer um tema para um app que já usa, e para isso não precisa de ferramenta nenhuma. O restante quer criar um port ou …","title":"Primeiros passos · SP Night","type":"docs"},{"content":"\nInstalação # As releases trazem um .deb e um .rpm (Ubuntu 22.04, Debian 12, Fedora e mais novos) e um instalador de prévia para Windows (ainda sem atalhos globais, notificações do desktop, Open terminal nem os presets da bandeja). Por enquanto não há AppImage. Baixe-os da release mais recente e confira um download com sha256sum -c SHA256SUMS --ignore-missing. Para conferir que ele foi gerado pelo workflow de release deste repositório: gh attestation verify \u0026lt;arquivo\u0026gt; --repo rogeriojunior31/Vults.\nNo Arch Linux, gere o pacote com makepkg: packaging/aur/vults compila a release mais recente, packaging/aur/vults-git acompanha a main. Os dois compilam do código-fonte, então a primeira instalação demora um pouco. Eles ainda não estão no AUR.\ngit clone https://github.com/rogeriojunior31/Vults cd Vults/packaging/aur/vults \u0026amp;\u0026amp; makepkg -si Ou compile do código-fonte:\ngit clone https://github.com/rogeriojunior31/Vults cd Vults npm install npm run tauri dev # executa npm run bundle:linux # ou gera o .deb e o .rpm em target/release/bundle/ O Linux precisa de webkit2gtk-4.1, gtk3, gtk-layer-shell, libayatana-appindicator, openssl, alsa-lib, gst-plugins-good (o WebKitGTK toca os sons da ilha pelo GStreamer) e do loader do Vulkan (para compilar, também cmake, os headers do Vulkan e glslc). No KDE Plasma, Hyprland, Sway e outros compositores com layer-shell, a ilha fica na borda de cima como um painel; no GNOME ela é uma janela comum, sempre por cima. Settings → General → Start with the desktop abre o Vults quando você entra na sessão.\nConectando seus agentes # Abra Set up agents… pelo ícone da bandeja e clique em Install hooks… ao lado de um agente. Você vê o arquivo que vai mudar, o diff exato e um botão Write the file; antes é feito um backup datado, e os hooks de outras ferramentas são mantidos. Remove hooks… tira só o que o Vults adicionou.\nAgente Arquivo Depois de instalar Claude Code ~/.claude/settings.json Nada: as novas sessões aparecem na ilha Codex ~/.codex/hooks.json Abra o Codex, digite /hooks e confie nos hooks do Vults (o Codex só roda um hook quando ele é confiável e está ligado); as configurações mostram quantos ainda esperam. Uma reinstalação pede de novo Antigravity ~/.gemini/config/hooks.json Nada (ele pergunta no próprio terminal) OpenCode ~/.config/opencode/plugins/vults.js, um plugin nosso Reinicie o OpenCode (os cards dele) Qwen Code ~/.qwen/settings.json Reinicie o Qwen Code (os cards dele) Copilot CLI ~/.copilot/hooks/vults.json, um arquivo nosso Reinicie o Copilot CLI (os cards dele) Cursor ~/.cursor/hooks.json Reinicie o Cursor (ele pergunta no próprio prompt) Factory Droid ~/.factory/settings.json Reinicie o Droid (ele pergunta no próprio prompt) Kimi Code ~/.kimi-code/config.toml Reinicie o Kimi (ele pergunta no próprio prompt) Com CLAUDE_CONFIG_DIR, CODEX_HOME, QWEN_HOME, COPILOT_HOME, FACTORY_HOME_OVERRIDE, KIMI_CODE_HOME ou XDG_CONFIG_HOME definida, o arquivo nessa pasta é o usado (detalhes). O do Antigravity é sempre ~/.gemini/config/hooks.json: o GEMINI_CLI_HOME não o muda de lugar.\nOutras ferramentas (Pi…) também podem reportar, com algumas linhas na própria configuração delas: veja Outros agentes.\nVindo do Vultures AI # O Vults se chamava Vultures AI até a 0.1.5; na primeira vez que abre, ele move as pastas antigas, a entrada do chaveiro e a de login para os nomes novos, e o .deb e o .rpm substituem o pacote antigo. Depois clique em Update hooks… ao lado de cada agente em Set up agents… (o Codex pede a confiança dele de novo).\nTeclas # No Linux, de qualquer lugar: Ctrl+Alt+Space abre a ilha e entrega o teclado a ela, Ctrl+Alt+Y / Ctrl+Alt+N permitem ou negam o card da frente, Ctrl+Alt+J / Ctrl+Alt+K põem a próxima ou a sessão anterior na frente, e segurar Ctrl+Alt+V fala com o Zeca (todas elas).\nIdioma # O Vults fala inglês, português do Brasil, espanhol e chinês simplificado. Ele segue o idioma do seu desktop; Settings → General → Language escolhe outro para a ilha, as configurações, a bandeja e as notificações. O que os seus agentes dizem fica nas palavras deles.\nPróximos passos # A ilha: o bando, recolhido e aberto, chegando a uma sessão Aprovando pela ilha Atividade Outros agentes O Nest: o bando inteiro, tarefas, registros e conexões Tarefas Conversando com o Zeca A memória do Zeca Conectores O telefone ","externalUrl":null,"permalink":"/docs/vults/getting-started/","section":"Documentação","summary":"\nInstalação # As releases trazem um .deb e um .rpm (Ubuntu 22.04, Debian 12, Fedora e mais novos) e um instalador de prévia para Windows (ainda sem atalhos …","title":"Primeiros passos · Vults","type":"docs"},{"content":"Este documento existe para responder a uma pergunta: quando eu levo o tema para uma nova plataforma, qual cor vai onde? Sem uma resposta escrita, cada port vira uma interpretação diferente do tema, e foi assim que os ports do Dracula foram se afastando uns dos outros.\nAs mesmas regras estão publicadas em sp-night.github.io/spec. Esta cópia é a que a ferramenta aplica.\nAs três camadas # palette/sp_night.json 23 colours per flavour. São Paulo names. ↓ palette/roles.json semantic roles → a palette key ↓ \u0026lt;app\u0026gt;.tmpl asks for a role, never the raw palette Regra rígida: um mapeamento nunca referencia uma cor da paleta diretamente.\n✗ palette = 4={{ .C.marginal }} ✓ palette = 4={{ .R.ansi.blue }} Por quê: mover syntax.keyword de marginal para temporal tem que repintar Neovim, bat, fish e o site de uma vez. Um mapeamento com marginal escrito nele fica para trás e ninguém percebe.\nO spn lint falha na primeira forma. Ele percorre a árvore de parse, não o texto, então um contraexemplo dentro de um comentário não conta como achado.\nA exceção são as listas de variáveis (waybar.css, gtk.css, hyprland.conf), que publicam a paleta crua como @define-color / $var porque o usuário final vai querer escrever @sp_sodio na própria folha de estilo. Elas declaram raw_palette: true no frontmatter. Mesmo nelas, tudo o que o próprio template estiliza continua usando um papel.\nA paleta # As quatro faixas abaixo não são títulos deste documento: são o bloco groups de sp_night.json, e elas particionam a paleta. Toda cor pertence a exatamente uma faixa, e a ferramenta recusa uma paleta em que alguma esteja faltando, duplicada ou desconhecida.\nElas são dados, e não Go, porque o site incorpora o contrato e o publica. Quando a partição vivia na ferramenta, o site tinha que redigitá-la, e uma cor que a paleta declarava mas a cópia do site não conhecia sumia da paleta publicada sem nada falhar em lugar nenhum. accents e vivo são as duas faixas que a auditoria chama pelo nome; o resto de uma faixa é o rótulo e os membros.\nSuperfícies: nomes neutros quanto à luminosidade # Esses nomes descrevem função e profundidade, não um hex específico. É isso que permite que um único mapeamento sirva a todas as variações.\nchave função referência vao o recuo mais fundo: janela flutuante, popup, barra de abas o vão livre do MASP laje o fundo padrão, o plano sobre o qual tudo fica uma laje de concreto concreto painéis, cards, cursorline, statusline concreto aparente vidro seleção, modo visual, item ativo vidro refletindo a rua fiacao bordas, divisórias, guias de indentação a fiação aérea Texto # chave uso fg_vivo texto padrão em negrito, ansi.bright_white fg texto principal, identificadores, variáveis fg_dim comentários, pontuação, texto secundário fg_muted números de linha, guias, texto desabilitado Acentos # chave ANSI referência brasa red o MASP, luzes de freio sodio — a lâmpada de sódio dos postes taxi yellow semáforo, táxi ibira green Ibirapuera, sinal verde estaiada — a ponte Estaiada iluminada sereno cyan o sereno antes do amanhecer marginal blue a Marginal, o metrô temporal magenta o céu logo antes da chuva ANSI brilhante # Os seis brilhantes do terminal (brasa_vivo, taxi_vivo, ibira_vivo, sereno_vivo, marginal_vivo, temporal_vivo) são a mesma cor com +0.06 de luminosidade Oklch, com matiz e croma intactos. Texto em negrito no terminal usa o brilhante; se o brilhante for igual ao normal, essa informação desaparece. Eles ficam na paleta em vez de serem derivados num template, então passam pela mesma auditoria de contraste que todo o resto.\nfg_vivo é esse mesmo aumento aplicado à rampa de texto, e existe pelo mesmo motivo. Um alvo que separa o texto padrão do texto padrão em negrito (o colors.primary.bright_foreground do Alacritty, a cor da fonte em negrito do kitty) não tinha nada acima de ui.fg para onde apontar, então o mapeamento precisava escrever fg nas duas chaves e alegar um aumento que não existia. ui.fg_bright dá nome a ele, e ansi.bright_white resolve para ele. ansi.white continua fg_dim: a tabela ANSI fica com as duas pontas da rampa, e fg continua sendo o foreground simples do terminal.\nPara a rampa de texto, +0.06 é o teto, não uma constante herdada. Em noite, fg já está em Oklch L 0.88; com +0.07 o canal azul satura e o croma começa a cair (0.028 → 0.023). Com +0.06 as três variações recebem o aumento exato com o croma intacto. Foi medido, e foi isso que decidiu o valor.\nsodio é a cor assinatura: cursor, borda ativa, workspace ativo, relógio, título. Se um port precisa da \u0026ldquo;cor do tema\u0026rdquo;, é ela, num terminal ou numa barra. Num widget de aplicação (seleção e foco em GTK/Qt/KDE) o acento é ui.accent_alt, azul: um acento de sistema laranja faz um gerenciador de arquivos inteiro parecer um aviso. O Tokyo Dark faz a mesma divisão, e a cor primária dele sempre foi azul.\nsodio e estaiada não têm posição ANSI, porque as 16 posições já têm dono. Elas existem para a interface, não para o terminal.\nRegras de atribuição # Sintaxe: a lógica é que o que o código faz fica com azul-ciano, o que o código é fica com roxo-laranja, e dados literais ficam com verde-laranja.\npapel cor keyword, conditional, repeat marginal function, method, operator sereno type, namespace temporal constant, number, boolean sodio string, character ibira parameter, macro, escape estaiada builtin, attribute taxi tag brasa variable, property, field fg comment, punctuation fg_dim As variáveis ficam em fg de propósito. Um tema em que tudo é colorido não tem hierarquia: o olho precisa de descanso, e o identificador comum é o maior volume de texto na tela.\nDiagnósticos e git seguem a convenção universal e não devem ser reinterpretados: erro = vermelho, aviso = amarelo, info = azul, dica = ciano, ok/adicionado = verde, modificado = amarelo, removido = vermelho.\nUm diff tem um único padrão, em todos os alvos: adicionado = ibira, modificado e renomeado = taxi, removido e conflito = brasa. Toda a estrutura (hunk, cabeçalho, índice, não rastreado) é neutra (fg_dim / fg_muted). Um diff que também usa roxo, azul e laranja vira um arco-íris onde só três estados importam.\nTemperatura da superfície # A oposição azul-amarelo é o eixo mais forte que um tema tem, e num tema escuro ela não se resolve nos acentos: o azul tem luminância intrinsecamente baixa, então um azul que passa no AA sobre concreto precisa ser claro e dessaturado, o oposto de um polo. Medido: repintar os acentos move o eixo de 1.03 para 1.35 e custa o caráter da paleta inteira.\nEla se resolve no fundo, que não é texto e por isso não tem restrição de contraste. noite tem uma laje azul-violeta com croma 0.037; os acentos continuam quentes. A tensão entre o campo e a massa de acentos vai de 0.020 para 0.051 sem mudar um único acento.\nDaí a divisão entre as duas variações escuras: noite é fria e saturada, garoa é cinza chapado (croma 0.005). A garoa não esfria a cidade, ela a desbota; a diferença é saturação, não temperatura.\nA lição dos temas robustos (KDE) # O que faz o Breeze Dark e o Catppuccin funcionarem em qualquer app não é a paleta, é a disciplina do esquema:\nUm único conjunto de cores de primeiro plano, repetido literalmente em View, Window, Button, Tooltip, Complementary e Header. Nada é derivado por seção; consistência é a ausência de derivação. A seção Selection é autocontida. Cada cor de primeiro plano nela é escolhida para ser lida sobre o acento, e o BackgroundAlternate dela é vizinho do acento, nunca o alternate geral. Foi essa substituição que produziu 1.11:1 no Dolphin. [WM] é escuro e calmo. Uma barra de título nunca recebe o acento. E uma que nenhum deles tem: a ferramenta analisa o arquivo .colors que acabou de gerar e falha o build se qualquer par fg/bg de qualquer seção ficar abaixo de 4.5:1 (internal/audit/kde.go). O Breeze de verdade tem pares de 2–3:1 em Selection; o SP Night não compila com nenhum.\nContraste # O spn check mede cada par texto/superfície de cada variação e falha o build quando algum não atinge o mínimo. O piso depende do que é a superfície:\nsuperfície piso por quê laje, vao, concreto 4.5:1 (AA) onde você lê código por horas vidro 3.0:1 seleção: um estado passageiro, você olha a forma fg_muted sobre qualquer uma 3.0:1, aviso ornamento, não texto de leitura fiacao sobre laje/vao 1.5:1, aviso uma borda, não texto 74 pares por variação. Uma verificação que falha interrompe o build; um aviso é reportado.\nfg_dim é o caso delicado: comentários precisam de AA completo sobre laje. Comentário ilegível é o problema número um de todo tema escuro popular, e sempre porque ninguém mediu.\nSeparação entre acentos # Contraste contra o fundo não basta. Dois acentos podem passar no AA com folga e ainda assim ser confundidos entre si; foi assim que estaiada e sereno escaparam da primeira versão desta auditoria: luminância quase idêntica sobre laje, distinguíveis só pelo matiz.\nΔE sozinho não é um limiar utilizável. Numa paleta de oito acentos cobrindo o círculo de matizes, matizes vizinhos caem naturalmente em ΔE 0.07–0.09 no Oklab; exigir mais de cada par seria exigir uma paleta com menos cores. Medido nas variações, os pares realmente confundíveis não são os de menor ΔE, e sim os de menor ΔL.\nA regra: um par perceptualmente vizinho (ΔE \u0026lt; 0.10) precisa se separar pela luminosidade (ΔL ≥ 0.04). É isso que mantém os dois distinguíveis em escala de cinza e, pelo mesmo motivo, para quem tem deficiência na visão de cores.\nDeficiência na visão de cores # O spn check -v também simula protanopia, deuteranopia e tritanopia (matrizes de Viénot 1999) e informa quantos pares de acentos ficam próximos demais em cada uma.\nIsso é um diagnóstico, não uma barreira, por um motivo concreto: separar oito acentos sob daltonismo, manter o caráter enfumaçado da paleta e passar no AA sobre um fundo escuro é um sistema sobredeterminado. Uma busca em matiz, croma e luminosidade encontra soluções com separação muito melhor, mas todas chegam lá levando o tema para outro lugar: o amarelo vira oliva, o vermelho vira terracota, os cianos batem na borda do gamut e ficam neon. Nenhum tema popular resolve as três coisas; Catppuccin, Tokyo Night e Dracula também não.\nO número existe para que a escolha seja deliberada. Se a prioridade mudar algum dia, a ferramenta já mede isso.\nSobre a regra do ΔL # Ela tem um ponto cego que vale conhecer: só examina pares de matiz vizinho na visão normal. Na deuteranopia, os pares que colapsam são os distantes: vermelho e verde caem no mesmo lugar. Uma medida não cobre a outra, e por isso as duas coexistem.\nÉ um aviso, não uma falha: essas são as cores de identidade do tema, e a decisão de repintá-las é de quem mantém o projeto. A escada de luminosidade dos acentos mantém a lista vazia hoje.\nRode spn check antes de mexer em uma cor.\nAdicionar uma cor # Adicione-a em colors em todas as variações, e em meaning. Adicione-a à faixa a que pertence em groups. spn check, depois go test ./.... O passo 2 não é burocracia opcional: uma cor fora de todas as faixas falha na validação, porque tudo o que percorre a paleta percorre as faixas. Se for texto ou acento, decida o piso que ela precisa atingir (internal/audit nomeia as chaves que mede) e, se for um _vivo, ela aumenta a base em 0.06 de luminosidade Oklch, e a suíte verifica que isso acontece.\nAdicionar uma variação # Adicione o bloco em palette/sp_night.json → flavors. spn check. Só isso: a ordem vem do próprio JSON, então não há uma segunda lista em Go para manter em sincronia.\nUma nova variação precisa se distinguir das existentes pelo matiz, não só pela luminosidade. garoa e noite são o exemplo: a primeira versão da garoa era a noite com os pretos clareados, e dos ΔE 0.034 entre as superfícies, 0.033 eram ΔL, a mesma cor mais clara. Puxar o cinza para o azul (Oklab B de −0.005 para −0.017) aumentou o Δcroma 7× e reduziu o ΔL: elas viraram duas atmosferas em vez de dois brilhos.\nNenhum mapeamento muda. Se um mapeamento precisa mudar para acomodar uma nova variação, é sinal de que ele está usando a paleta crua onde deveria usar um papel.\nAdicionar um alvo # Liste-o em registry/ports.yml. spn new \u0026lt;slug\u0026gt;. Escreva o mapeamento usando .R. O frontmatter aceita um matrix vazio para renderizar uma vez só, no caso de um app que lê um único arquivo de configuração fixo. Formatos que precisam de um bloco claro ao lado do escuro espelham o lado escuro, já que o tema é só escuro; .All alcança as outras variações: {{ (index .All \u0026quot;garoa\u0026quot;).R.ui.bg }}.\nPara \u0026ldquo;texto legível sobre este acento\u0026rdquo;, use readable, que escolhe entre duas opções pelo contraste medido em vez de chutar:\n\u0026#34;mOnPrimary\u0026#34;: \u0026#34;{{ readable .C.vao .C.fg .R.ui.accent }}\u0026#34; Helpers disponíveis num mapeamento: nohash, rgb, rgbn, rgba, hexa, argb, sgrfg, sgrbg, mix, lighten, darken, contrast, readable, kebab, pad, repeat, tojson, upper, lower, r, g, b.\n","externalUrl":null,"permalink":"/docs/sp-night/spec/","section":"Documentação","summary":"Este documento existe para responder a uma pergunta: quando eu levo o tema para uma nova plataforma, qual cor vai onde? Sem uma resposta escrita, cada port vira …","title":"A especificação do SP Night · SP Night","type":"docs"},{"content":"A ilha fica pendurada na borda de cima da tela. No KDE Plasma, Hyprland, Sway e outros compositores com layer-shell, ela fica acima de todas as janelas, como um painel; no GNOME, é uma janela comum sempre no topo. No X11, ela aparece em todas as áreas de trabalho. Ela só pega o teclado enquanto você digita no chat, ou depois de Ctrl+Alt+Space (abaixo).\nCom mais de uma tela, o desktop escolhe uma (em geral, a tela em foco na inicialização). Para fixar a ilha numa tela, escolha-a em Settings → General → Screen. Se essa tela sumir, a ilha passa para outra e volta quando ela retornar.\nNo Windows (uma versão de prévia) ainda não há atalhos globais, notificações do desktop, Open terminal nem predefinições na bandeja.\nO bando # Cada sessão de agente é uma ave, um urubu. Um projeto é uma espécie: todas as sessões dele a compartilham, e ele a mantém toda vez que o app inicia. Uma pequena faixa na base de cada pescoço mostra o agente: laranja para Claude Code, verde-azulado para Codex, rosa para OpenCode, índigo para Qwen Code, azul para Copilot CLI, e violeta para qualquer outra ferramenta (Antigravity, Pi, Cursor…).\nO Zeca não é uma sessão: ele fica no fio quando nada roda, e é com ele que você fala no chat. A sessão da frente (a que precisa de você, a que você clicou ou, senão, a primeira a chegar) ocupa o lugar dele. Toda outra sessão é um vult.\nAs aves encenam o que as sessões fazem: leem, bicam o fio enquanto editam, levantam voo para a web e abrem as asas quando uma permissão espera (com uma marca sobre a cabeça; ao amanhecer as aves em descanso abrem as delas ao sol, sem marca). Sessões novas chegam voando (uma que uma tarefa sua começou decola do lugar do Zeca na pílula, ou da ave da frente quando há uma lá); as que terminam vão embora. Com movimento reduzido, elas ficam nos poleiros. Settings → Flock \u0026amp; Zeca escolhe o conjunto de espécies, a espécie do Zeca e os visitantes raros. Animações lista cada clipe.\nOs visuais sazonais do Zeca # O Zeca se veste para a estação: um chapéu de bruxa em outubro, um gorro de Papai Noel em dezembro, um chapéu de festa no Ano-Novo e orelhas de coelho na Páscoa, pela data do seu computador. Settings → Flock → Look (com o Zeca desenhado ao lado: no visual que você escolhe, com as próprias penas no Auto) mantém um visual o ano todo, ou nenhum, e acrescenta óculos escuros e catorze trajes sem estação. Clique com o botão direito no Zeca na ilha para escolher ali mesmo: ele veste o que estiver sob o ponteiro, um clique fica com ele, Escape o deixa como estava. Só o Zeca os usa.\nSem o Zeca # O Zeca é opcional. Settings → Flock \u0026amp; Zeca → Zeca o desliga; o bando continua funcionando: sessões no fio, cards de permissão e de pergunta, os atalhos de Allow / Deny, notificações, conectores e as predefinições. O que vai com ele:\nO chat, sua aba, os arquivos soltos na ilha, o Chat do Nest, o Chat… da bandeja, o microfone e o atalho de fala. Os medidores de uso ficam: eles leem as assinaturas dos seus agentes. O olá dele na inicialização. O lugar dele no fio: a sessão da frente fica ali como a própria ave, e sem ninguém rodando a pílula diz Nothing running. Ligue-o de volta no mesmo lugar; sem reiniciar, nos dois casos.\nCompacta, aberta e escondida # Compacta (o Mini do seletor de tamanho), a ilha é uma pequena pílula sem texto, só o bando: o Zeca à esquerda com a sessão da frente, até oito vults espalhados pelo fio e, embaixo, uma linha fina por plano com o uso dele, nas cores dos medidores de uso (âmbar a partir de 70%, vermelho a partir de 90%). Para as sessões, as cores significam o mesmo em todo lugar: âmbar para uma permissão, ciano para uma pergunta, verde quando concluiu, vermelho quando falhou. Um vult num desses estados usa um selo dessa cor e com uma forma própria, para que nenhum estado dependa só da cor: um triângulo para uma permissão, um losango para uma pergunta, um círculo quando concluiu, um quadrado quando falhou. Enquanto alguém precisa de você a borda da pílula pulsa em âmbar; quando uma sessão falhou (e ninguém precisa de você) ela fica vermelha; um ponto ciano no canto diz que um conector tem novidade. Deixe o ponteiro sobre um vult e ele olha para você (um que está no ar desce); clique nele para abrir a ilha na sessão dele, ou clique com o botão direito para as ações rápidas dele. As novidades de conectores esperam na ilha aberta.\nClique em qualquer outro ponto da pílula para abrir a ilha. Ela se recolhe 15 segundos depois que o ponteiro sai (uma linha fina embaixo faz a contagem; voltar com o ponteiro cancela). O seletor de tamanho no canto superior direito muda o quanto você vê, mantendo o que você olhava: Mini recolhe na hora para a pílula, Quick é a ilha, Room abre o Nest no que a ilha mostra (o bando, o chat, as suas conexões ou esta semana; as Settings a partir da engrenagem) e o botão de tela cheia ao lado o abre na tela toda. Enquanto um card espera, ele ocupa o lugar do bando. Settings → General → Fold the island define a espera.\nCom Settings → General → Open on hover ligado, deixar o ponteiro sobre a pílula a abre sem clique. Aberta assim, ela se recolhe assim que o ponteiro sai, a não ser que você tenha clicado nela. Desligado por padrão, e não vale no Panel.\nDuas coisas a mantêm aberta até você terminar:\nUm card de permissão. Ele abre a ilha sozinho e fica até você responder. Nada mais a abre sozinho: uma sessão que termina, falha ou pergunta algo toca seu som e ganha seu selo. O chat. A ilha nunca se recolhe enquanto você digita. Sem ninguém no fio por um minuto, a ilha se esconde. Leve o ponteiro ao meio da borda de cima da tela para trazê-la de volta.\nPresença: quanto ela mostra # Settings → General → Presence, ou o menu da bandeja (Linux), escolhe uma de quatro predefinições, na hora.\nPredefinição Em repouso Um card que precisa de você Island (o padrão) O bando no topo da tela Abre a ilha, com seu som Panel Nada no topo; o Zeca na bandeja Abre a ilha junto ao painel, com seu som Quiet Nada, e nenhum som para sessões que terminam ou falham nem para novidades de conectores. A borda de cima ainda traz a ilha de volta Abre a ilha no topo, com seu som Paused Uma pílula que diz Paused Nenhum: o agente pergunta no terminal, como se o app estivesse fechado Nada esconde ou silencia um card pelo qual um agente espera: nem uma predefinição (exceto Paused), nem silenciar ou esconder um projeto, nem o Do not disturb. O card abre a ilha e espera o seu clique.\nPaused é para nenhuma interrupção: permissões e perguntas, inclusive cards que já esperavam, vão para o terminal do agente, e suas regras Always não respondem nada. Os conectores param de verificar, e nenhuma notificação do desktop aparece. Escolha outra predefinição para voltar.\nNo painel # Nada é desenhado no topo da tela. O Zeca fica na bandeja do painel e mostra o estado do bando: empoleirado, trabalhando, de asas abertas com uma marca âmbar (algo espera por você), brilhos verdes (concluído), uma marca vermelha (falhou).\nClique nele e a ilha abre no canto do painel. Ela se recolhe quando o ponteiro sai, com Mini ou Escape, e quando você abre as Settings. Clique com o botão direito nele para o menu: Chat… (com o Zeca ligado), Nest… (também com o Zeca desligado), Set up agents…, as quatro predefinições (Linux), Quit. Um card abre a ilha junto ao painel, e o Zeca chama atenção na bandeja até você responder. Allow e Deny são sempre cliques no card. Novidades de conectores tocam seu som mas não abrem a ilha: clique no Zeca para lê-las. No KDE Plasma a ilha abre ao lado do painel que tem a bandeja; nos outros, no canto inferior direito. A bandeja precisa de um painel que mostre StatusNotifierItems (o Plasma mostra; no GNOME, a extensão AppIndicator, onde um clique esquerdo pode abrir o menu). Sem bandeja, inicie o Vults de novo para abrir as configurações.\nNas outras predefinições o Zeca também fica na bandeja, com os mesmos estados e menu, e um clique abre a ilha no topo.\nO widget de canto # Settings → General → Corner widget põe uma pequena janela num canto que você escolhe; fica desligado até você escolher um. Funciona com todas as predefinições. Mostra até três aves (a sessão da frente, depois as que mais querem você) e quantas sessões precisam de você ou estão trabalhando. Uma borda âmbar significa que alguém precisa de você.\nClique nele para abrir a ilha, no card quando um espera. Clique numa ave para pôr a sessão dela na frente antes; se o card dessa ave espera atrás de outro, ele vem primeiro. O widget nunca responde a um card.\nEle fica longe dos painéis e embaixo de janelas em tela cheia. Sem layer-shell, é uma janela sempre no topo. Custa cerca de 40 MiB de memória enquanto está ligado.\nNotificações do desktop # Só no Panel, onde a ilha fica fora de vista, o Vults também usa as notificações do desktop (qualquer desktop Linux com um servidor de notificações). No topo da tela a ilha já mostra tudo, então você nunca é avisado duas vezes; Paused não mostra nenhuma.\nElas avisam quando uma sessão terminou (com a primeira linha da resposta), falhou (com o erro), precisa de você (um card espera) ou ficou quieta. Cada sessão tem no máximo uma, com o nome do projeto no título; ela some quando o card é respondido, a sessão volta a trabalhar ou sai (uma sessão concluída sai do fio depois de 10 minutos, uma calada depois de 30). O que aconteceu enquanto elas estavam desligadas não é avisado depois.\nOpen (ou um clique) traz a ilha com aquela sessão na frente. Uma notificação nunca tem Allow nem Deny. Desligue-as em Settings → General → Notifications.\nA ilha aberta # Aberta, o cabeçalho da ilha tem a marca e o nome, um botão de som, a busca (a paleta, como Ctrl+K), o seletor de tamanho e o botão de tela cheia. Embaixo, as cinco abas como ícones, como o protótipo as desenha:\nFlock, com quantas sessões precisam de você; Chat, do Zeca, numa forma compacta: o motor e as suas conversas no topo, o campo com um clipe (para entregar arquivos ao Zeca) e o microfone, a pasta e o modelo embaixo; Activity: esta semana, contada neste computador, os quatro números e uma barra por projeto (o maior primeiro; por dia quando nenhum projeto tem nome), e ‹ Previous week / This week; Connections, com quantas linhas os conectores mostram e você não marcou como vistas: um chip por conector e um card por linha, com Ask Zeca why, Review with Zeca, Squash and merge e ✓ (Conectores); sem nenhum ligado, + leva às Connections do Nest; Settings (a engrenagem): Presence e Fold the island ali mesmo; a lista de páginas também desenha Activity (o interruptor do histórico local) e Flock \u0026amp; Zeca (o interruptor do Zeca e de onde o bando vem) ali mesmo; qualquer outra página das Settings no Nest, e All settings (em Agents enquanto os hooks de um agente faltam ou estão desatualizados, em General nos outros casos). Sobre as abas Chat, Activity, Connections e Settings, os chips das sessões que precisam de você ficam embaixo das abas; um deles abre a sessão. Activity tem Open in the Nest para o resto, e as suas tarefas ficam no Nest, a janela do próprio Vults, com abas próprias, que a seta no topo do chat também abre. A música e o uso dos seus planos ficam numa linha abaixo das abas. Embaixo, na largura toda da ilha (cerca de 500 px na tela, o Quick do seletor de tamanho):\nem repouso, o bando: o vult de cada sessão num fio, com o dobro do tamanho, o nome do projeto embaixo (numa caixa para a que está na frente) e ! quando precisa de você (até seis; além disso, cinco ficam e +N ocupa o último lugar, abrindo o Flock do Nest, em âmbar quando uma delas precisa de você), com o selo; deixe o ponteiro sobre um para ver o projeto, o agente e o que ele está fazendo. Embaixo do fio, um chip para cada sessão que pede um olhar: um card ou uma pergunta, uma falha, um pássaro quieto demais; uma sessão, quando você clica no vult ou no chip dela: ‹ Flock volta, e um ponto por sessão, na cor do agente, abre outra. Um card de permissão abre aqui sozinho e mantém a sessão na frente até você responder. À esquerda o Zeca, grande, com um brilho e uma marca na cor do estado da sessão (um ! âmbar para uma permissão, um ? ciano, brilhos verdes quando concluiu, um # vermelho quando falhou, suor num limite de uso); ao lado o projeto, o agente e o estado, e embaixo dos dois o card da sessão. Sessão Card Trabalhando O projeto, o agente, os passos até agora, os subagentes rodando e, para o Claude Code, ≈$1.37: quanto os tokens dela custariam a preços de API (uma assinatura não é cobrada disso), depois o passo que acabou e o atual Ociosa Waiting for the next prompt, e o último passo Precisa de permissão O comando, arquivo ou URL exato, com Deny e Allow (Aprovações) Tem uma pergunta Para uma pergunta que a ilha não consegue responder (Qwen Code, OpenCode 2): a pergunta, e Open terminal. As perguntas do Claude Code e do OpenCode 1 ganham um card Concluída O primeiro parágrafo da última resposta do agente, OK e Open terminal Falhou O erro, OK e Open terminal Um passo se lê como Editing main.rs, Running cargo build ou, para uma ferramenta MCP, Calling github · list_prs.\nUma edição concluída mostra as linhas que acrescentou e removeu (Editing main.rs +4 −2). Clique nelas para ver o diff no lugar do card, com números de linha quando o agente os manda (o Claude Code manda; os diffs do Codex não têm). × ou Esc volta. Os diffs ficam guardados para os últimos oito passos da sessão, até 400 linhas cada; um mais longo avisa que para antes.\nOK diz que você viu: o selo some e a sessão aparece como ociosa. Sem ninguém no fio, o card oferece Ask Zeca.\nO Zeca repara em você: olha para o ponteiro, ajeita as penas se você o deixa sobre ele e se assusta com um clique. Na inicialização ele diz olá, pelo seu primeiro nome quando a sua conta de usuário tem um nome completo (nunca tirado da rede).\nTocando agora # Ligue Settings → General → Now playing e a ilha mostra a música que o seu player está tocando (qualquer player que fale MPRIS: Spotify, uma aba do navegador, mpv). A ilha compacta a mostra quando nada roda; a ilha aberta a mostra na barra de cima, com anterior, tocar/pausar e próxima ao passar o ponteiro. Enquanto ela toca, o Zeca dança e as aves ociosas do bando fazem o cortejo no fio em vez de planar.\nUso da assinatura # A barra de cima da ilha aberta mostra quanto dos limites dos seus planos você já usou, ao lado do ponto de cada agente: 7d 12% é 12% da janela semanal. Fica âmbar em 70% e vermelho em 90%; passe o ponteiro para ver quando reinicia. Nenhum token seu é lido: cada número vem da CLI em que você fez login.\nCodex: com Settings → General → Codex usage ligado, consultado a cada 5 minutos, só leitura, nunca com a tela bloqueada. Chega à OpenAI pelo seu codex, então fica desligado numa instalação nova. Claude Code (Pro ou Max): ele só informa o uso a uma linha de status, então instalar os hooks acrescenta uma nossa, que roda a sua se você tiver uma (como). Os números chegam depois da primeira resposta de uma sessão. Chegando a uma sessão # Clique num vult do bando para abrir aquela sessão; ela fica na frente até você escolher outra ou ela sair. Um card esperando ainda vem primeiro. Pelo teclado (Ctrl+Alt+Space), ↑ e ↓ passam de uma sessão a outra: em repouso o nome na caixa muda, numa sessão a próxima abre.\nOpen terminal no card dela traz o terminal para a frente:\num painel do herdr, tmux, kitty ou wezterm, em qualquer desktop (o kitty precisa de listen_on unix:/tmp/kitty e allow_remote_control socket-only no kitty.conf); a própria janela do terminal, no KDE Plasma (Wayland ou X11) e em qualquer sessão X11, na sua área de trabalho e desminimizada (de várias janelas, primeiro a que tem no título a pasta da sessão); no GNOME, Hyprland ou Sway sob Wayland, só um terminal rodando pelo XWayland. Quando não há nada para trazer, o card avisa. Uma sessão iniciada no terminal do VS Code ou do Cursor leva uma etiqueta VS Code ou Cursor, e o botão dela traz esse editor, no KDE e em sessões X11.\nOs atalhos globais funcionam de qualquer janela:\nCtrl+Alt+Y / Ctrl+Alt+N permitem ou negam a permissão na tela (Aprovações). Ctrl+Alt+J / Ctrl+Alt+K põem a próxima ou a anterior sessão na frente. Um card esperando fica na frente; as teclas escolhem quem vem depois dele. Ctrl+Alt+V, segurado, fala com o chat (Falar). Ctrl+Alt+1, Ctrl+Alt+2 e Ctrl+Alt+3 trocam para Mini, Quick e Room. Ctrl+K, na ilha aberta ou no Nest, abre a paleta. Ctrl+Alt+Space abre a ilha e entrega o teclado a ela até ela se recolher: ↑ ↓ (ou K J) trocam a sessão da frente; Enter abre o terminal dela; M abre as ações rápidas dela; C abre o chat. Y ou N respondem a uma permissão; 1 a 9 escolhem uma opção de uma pergunta. Esc recolhe a ilha e devolve as teclas. No Wayland, é o caminho de volta ao seu terminal. Aberta com um clique, a ilha não pega teclas. Os atalhos passam pelo portal do desktop: o KDE pergunta uma vez, e System Settings → Shortcuts muda as teclas (vale a pena se o seu editor usa Ctrl+Alt+J ou K, como as IDEs da JetBrains). Settings → General os lista.\nAções rápidas # Clique com o botão direito num vult da pílula ou do bando, ou no card de uma sessão (longe do Zeca) para as ações rápidas daquela sessão:\nOpen terminal, como acima. Onde o desktop não consegue, fica acinzentado e oferece a pasta. Open folder: no VS Code quando code está no seu PATH, senão no gerenciador de arquivos. Só uma pasta que existe, pelo caminho completo, é aberta, sem shell. Activity: os últimos oito passos da sessão, cada edição concluída com seu diff. View the last diff, e Open its file in VS Code na primeira linha alterada (ou mostrá-lo na pasta; um arquivo nunca é executado nem aberto pelo programa associado ao tipo dele). Keep in front, ou Let the flock choose. Mute, Pin ou Hide this project, e This project\u0026rsquo;s bird… (abaixo). O menu nunca tem Allow nem Deny, e não abre sobre um card esperando. Para chegar a um card que espera atrás de outro, veja Mais de um por vez.\nEnquanto você estava fora # Com a tela bloqueada (num desktop que avisa pelo org.freedesktop.ScreenSaver, como o Plasma e o GNOME), a ilha descansa (sem animação) e os conectores param de verificar. Agentes e cards seguem como sempre.\nQuando você desbloqueia, ou sai do Paused, uma linha diz o que aconteceu nesse meio-tempo: While you were away: 2 finished, 1 failed, 1 waits for you for 12 min. No Island ela abre a ilha uma vez; fica até você dispensá-la com ×. Projetos escondidos e silenciados ficam de fora.\nUma ave quieta # Uma sessão que está trabalhando e não manda nada por 5 minutos pode estar travada (um comando esperando entrada, uma ferramenta pendurada). A ave dela ganha um selo cinza: No news for 5 min. Aos 15 minutos o selo fica âmbar, um alerta toca e, no Panel, uma notificação avisa. Pensar por muito tempo não é sinalizado; qualquer novidade limpa o sinal.\nO card oferece três respostas, e nenhuma mexe no agente:\nSnooze: some por 15 minutos, depois volta se ela ainda estiver quieta. Keep going: está tudo bem; o sinal cinza só volta depois de 30 minutos, o âmbar 10 minutos depois. Dismiss: nenhum sinal de novo até a próxima pergunta dela. Cada resposta conta como novidade, então a ave fica no fio (uma calada sai depois de 30 minutos); depois de Keep going ela fica até o sinal poder voltar.\nPor projeto: silenciar, fixar, esconder # Essas escolhas pertencem ao projeto (a pasta dele): toda sessão nela as segue, agora e depois.\nMute: sem sons nem notificações quando as sessões dele terminam ou falham. Pin: as sessões dele vêm primeiro no fio, na pílula e no bando. Hide: as sessões dele ficam fora da ilha, da bandeja e do widget de canto. This project\u0026rsquo;s bird…: escolhe a espécie de todas as sessões dele; Automatic o devolve ao sorteio do bando. Settings → Projects os lista, e é o caminho de volta para um projeto escondido.\nSons # Bipes curtos de 8 bits quando uma sessão precisa de você, termina ou falha, e para novidades de conectores; outros mais suaves quando a ilha abre ou se recolhe e quando o Zeca reage a você. O botão de alto-falante na ilha, ou Settings → General → Sounds, os desliga; Volume define o quão alto. Um card que continua esperando soa de novo, e o Do not disturb silencia sons e notificações por um tempo: veja Quando ninguém responde.\n","externalUrl":null,"permalink":"/docs/vults/guide/island/","section":"Documentação","summary":"A ilha fica pendurada na borda de cima da tela. No KDE Plasma, Hyprland, Sway e outros compositores com layer-shell, ela fica acima de todas as janelas, como um …","title":"A ilha · Vults","type":"docs"},{"content":"Um port é um mapeamento, não uma cópia de cores: ele decide qual chave da configuração de um app recebe qual papel, e a ferramenta resolve o resto. Leia primeiro o SPEC.md, em especial a regra de que um mapeamento nunca referencia a paleta crua.\nO exemplo canônico é sp-night/ghostty.\nInegociáveis # Nenhum hex é escolhido à mão. Nem num arquivo de tema, nem num README, nem numa prévia. Se algo precisa mudar, muda o mapeamento ou o catálogo, e tudo é regenerado. Conventional Commits, em inglês, em minúsculas, sem ponto final: feat(themes):, docs(readme):, feat(ports):, ci:, test:, chore:. Nunca faça commit direto na main. Branch → pull request → merge. Documentação pública em inglês. Os nomes das cores e das variações ficam em português: eles são a identidade. MIT em todos os repositórios. 1 — Listar o alvo no catálogo # registry/ports.yml é de onde o README, a prévia e o cabeçalho gerado leem. Nada pode ser gerado para um port que não está listado.\nComece de uma entrada impressa em vez de uma página em branco:\nspn entry \u0026lt;slug\u0026gt; \u0026gt;\u0026gt; registry/ports.yml Isso escreve todos os campos obrigatórios, uma tabela de mapeamento para completar e uma prévia completa: a sessão fictícia, trecho por trecho, no formato que as prévias publicadas compartilham. Ela já é válida do jeito que é impressa, então a entrada pode ser commitada enquanto os TODOs ainda estão sendo substituídos. A prévia é só um ponto de partida: reescreva a sessão quando o port tiver uma voz própria, como aconteceu com a do eza.\nOs campos que ela deixa para você:\n- slug: kitty # also the repository name under the org name: kitty group: terminal blurb: One line on what the port covers. homepage: https://sw.kovidgoyal.net/kitty/ repo: https://github.com/sp-night/kitty # derived from slug, and checked install: ~/.config/kitty/sp_night_{flavor}.conf activate: include sp_night_{flavor}.conf template: kitty.conf.tmpl mapping: - key: \u0026#34;`background`\u0026#34; role: \u0026#34;`ui.bg`\u0026#34; meaning: \u0026#34;*laje* under the main text\u0026#34; preview: title: kitty — sp_night_{flavor} frame: terminal # terminal | editor | app | pane swatches: {label: palette 0–15, roles: [ansi.black, ...]} body: - - {t: \u0026#34;~/sp-night \u0026#34;, r: ui.accent} - {t: \u0026#34;❯ \u0026#34;, r: ui.accent_alt} - {t: \u0026#34;kitty +kitten themes --dump-theme\u0026#34;, r: ui.fg} Depois verifique:\nspn registry --registry registry/ports.yml --copy registry/copy.yml mapping não é enfeite: é a tabela que o leitor confere antes de confiar num port, e a validação recusa uma entrada sem ela.\nframe é a moldura em que a prévia é desenhada, e deve ser o tipo de janela em que o app realmente vive. O body é só a sessão; a moldura desenha o resto, então um port nunca precisa simular uma gutter ou uma statusline trecho por trecho.\nframe para o que o renderizador acrescenta aceita terminal (padrão) um emulador de terminal barra de título com três pontos e o title centralizado — editor um editor uma bufferline com o title como aba aberta, linhas numeradas, uma statusline bar, cursor_line app uma TUI de tela cheia title como cabeçalho, uma barra inferior bar pane uma CLI que roda no terminal de outra pessoa nada além da borda — bar é {left: [spans], right: [spans]}, no mesmo formato de trechos do body; cursor_line é a linha do body (contando a partir de 1) que o editor destaca. Cada moldura comporta um número fixo de linhas do body acima da faixa de cores (13 para um pane, 11 para os demais), e o spn registry recusa uma sessão que passe disso.\n2 — Criar o repositório # gh repo create sp-night/\u0026lt;slug\u0026gt; --public --license mit \\ --description \u0026#34;🌃 SP Night for \u0026lt;App\u0026gt; — a dark colour scheme with São Paulo as its reference\u0026#34; O commit inicial traz só o LICENSE. Clone-o ao lado dos outros e crie a estrutura:\nspn new \u0026lt;slug\u0026gt; Isso escreve o esboço do mapeamento com o cabeçalho canônico já ligado ao catálogo, o workflow de seis linhas, a configuração do Renovate e as configurações de editor.\n3 — Escrever o mapeamento # Este é o único arquivo que uma pessoa escreve. Peça um papel, nunca uma cor:\n✗ background {{ .C.laje }} ✓ background {{ .R.ui.bg }} spn palette --roles lista todos os papéis e para o que cada um resolve em cada variação. O que cada um significa está no SPEC.md.\nO frontmatter declara o contrato:\n--- spn: version: \u0026#34;1.2.0\u0026#34; # the exact engine this was generated with matrix: [flavor] # one file per flavour filename: \u0026#34;themes/sp_night_{{ .Flavor }}.conf\u0026#34; # where it goes --- Deixe matrix de fora para um app que lê um único arquivo de configuração fixo. O eza é esse caso: o mapeamento dele renderiza uma vez só, e cada variação ainda é publicada como um arquivo em themes/.\nversion é uma versão exata, não um intervalo, e ninguém a edita à mão. O spn new escreve a versão do binário que criou a estrutura do port e, a partir daí, a propagação de release do motor a atualiza no mesmo pull request que regenera os arquivos de tema.\nEsse pareamento é o ponto. Os arquivos commitados e a versão que os produziu são um único fato, então o CI de um port instala o motor fixado e verifica os arquivos contra ele. Um intervalo (^1.0 era o original) faz o CI resolver para o que for mais novo, e o pull request de um port passa de verde para vermelho porque o motor lançou uma versão, sem nada ter mudado no port. Também deixava inerte a regra do Renovate que deveria propagar as atualizações do motor: todo 1.x satisfaz ^1.0, então nunca havia nada para atualizar.\nDepois gere todo o resto:\nspn gen \u0026amp;\u0026amp; spn readme \u0026amp;\u0026amp; spn preview spn lint \u0026amp;\u0026amp; spn gen --check 4 — Histórico de commits # Na branch feat/\u0026lt;slug\u0026gt;-port, espelhando o ghostty:\nfeat(themes): add the noite, garoa and jaragua flavours docs(readme): add install guide and palette-generated previews ci: check the mapping and the generated files Depois gh pr create, e faça o merge pelo pull request.\nAntes de dar push, confirme que o cabeçalho gerado aponta para o repositório deste port e traz o caminho de instalação e a linha de ativação. Se não trouxer, a entrada do catálogo está errada; não edite um arquivo gerado.\n5 — O site, que não é um passo # Não há nada a fazer aqui, nem nada a editar. O site incorpora este catálogo em vez de manter a própria lista, então fazer o merge do passo 1 na main é o que publica o port: o push dispara o sync-ports.yml, cujo job site copia ports.yml e copy.yml, redesenha as prévias, regenera os assets derivados do site, roda a suíte dele e abre um pull request. Fazer o merge desse pull request publica /ports/\u0026lt;slug\u0026gt;, uma página montada a partir da entrada, com o guia de instalação, a tabela de chave para papel e uma captura de tela por variação.\nListar um port é publicá-lo. Se você se pegar editando src/data/ à mão, a mudança vai sumir na próxima sincronização sem deixar rastro.\nChecklist # Listado em registry/ports.yml (comece com spn entry \u0026lt;slug\u0026gt;), spn registry sem erros spn lint sem erros: o mapeamento pede papéis, nunca cores spn gen --check, spn readme --check, spn preview --check todos sem erros Três variações presentes (noite, garoa, jaragua) Cabeçalho gerado aponta para o repositório deste port .github/workflows/theme.yml chama o workflow reutilizável Branch feat/\u0026lt;slug\u0026gt;-port, Conventional Commits, merge via pull request Catálogo com merge na main, e o pull request de sincronização do site com merge feito Quando um port precisa de algo que os papéis não oferecem # Isso é um achado real, não um motivo para recorrer à paleta. Um papel faltando significa que a camada semântica tem um buraco: abra uma issue neste repositório descrevendo a chave que você não conseguiu mapear. Adicionar um papel repinta todos os ports que o querem; escrever uma cor num único mapeamento ajuda exatamente um port e esconde a lacuna.\n","externalUrl":null,"permalink":"/docs/sp-night/port-creation/","section":"Documentação","summary":"Um port é um mapeamento, não uma cópia de cores: ele decide qual chave da configuração de um app recebe qual papel, e a ferramenta resolve o resto. Leia …","title":"Criar um port · SP Night","type":"docs"},{"content":"Uma skill é uma pasta com um SKILL.md: instruções que um agente carrega quando a tarefa corresponde à descrição. Cada agente lê skills do próprio diretório, por isso a mesma skill costuma acabar copiada em vários lugares. O lazyagents mantém uma única cópia numa biblioteca central e a disponibiliza aos agentes por links simbólicos. Você instala e atualiza uma vez e escolhe em quais agentes ativar. A aba Skills mostra uma matriz de skill × agente; as mesmas operações estão disponíveis na CLI.\nConceitos # Biblioteca. Pasta das skills gerenciadas pelo lazyagents: ~/.local/share/lazyagents/skills/ por padrão, ou libraryDir em config.yaml (Configuração). Cada skill ocupa uma subpasta com seu nome.\nAtivação por link simbólico. Ativar cria \u0026lt;diretório de skills do agente\u0026gt;/\u0026lt;skill\u0026gt; → \u0026lt;biblioteca\u0026gt;/\u0026lt;skill\u0026gt;. Desativar remove apenas esse link. Como o agente lê a pasta da biblioteca, editar ou atualizar uma skill vale para todos os agentes ao mesmo tempo. Os diretórios lidos por cada agente estão na referência dos agentes.\nSkills locais. Uma pasta real no diretório de um agente, ou um link criado por outra ferramenta, é uma skill local. O lazyagents a mostra, mas nunca a apaga nem desativa. Para gerenciá-la, incorpore-a à biblioteca (Incorporar skills locais).\nDiretórios compartilhados. Codex, Gemini CLI, OpenCode, Pi e Crush leem ~/.agents/skills. Ao ativar uma skill para um só agente, o lazyagents cria o link no diretório próprio dele (~/.codex/skills, ~/.gemini/skills…). Somente quando todos os agentes instalados que leem o diretório compartilhado têm a skill ativada é criado um único link ali. Desativar para um deles move os links de volta aos diretórios próprios dos demais. A exceção é ~/.claude/skills, diretório do Claude Code também lido por OpenCode e Crush: uma skill ativada no Claude Code também aparece neles.\nMarcadores da matriz. Cada célula indica o estado da skill em um agente:\nMarcador Significado ● ativada pelo lazyagents, com link no diretório próprio deste agente ◆ visível pelo diretório de outro agente, como OpenCode lendo ~/.claude/skills; não pode ser alternada apenas neste agente ▪ local: conteúdo real não gerenciado pelo lazyagents ○ não visível para este agente Perfis. Um perfil salva um estado nomeado da matriz: quais skills da biblioteca estão ativadas em quais agentes. Aplicá-lo restaura esse estado, por exemplo para alternar entre conjuntos de trabalho e pessoais.\nBackups. Antes de remover, substituir, restaurar sobre, incorporar ou migrar uma pasta de skill, o lazyagents salva um .tar.gz em ~/.local/share/lazyagents/backups/. São mantidos os 20 backups mais recentes de cada skill.\nNa TUI # A matriz tem uma linha por skill e uma coluna por agente instalado com diretório de skills. ←/→ escolhe a coluna. O detalhe da skill selecionada (descrição, origem, estado por agente e avisos de validação) aparece ao lado ou abaixo da tabela. A lista completa de teclas está na referência de teclas; ? a mostra na TUI.\nNavegar e ler # Percorra a lista e digite / para filtrar por nome. enter abre o SKILL.md renderizado como Markdown; no leitor, e abre o arquivo no editor e esc volta. r verifica novamente a biblioteca e os diretórios dos agentes. O título da aba conta as skills locais ainda fora da biblioteca.\nAtivar e desativar # space alterna a skill selecionada no agente sob o cursor (←/→ escolhe a coluna). a ativa em todos os agentes instalados com diretório de skills; x desativa onde o lazyagents a gerencia. Uma célula ▪ ou ◆ não pode ser alternada pela coluna: o aviso explica o motivo. Incorpore uma skill local com o, ou use x se ela chega ao agente pelo diretório de outro. Só skills da biblioteca podem ser ativadas.\nInstalar do GitHub, de uma pasta ou de um ZIP # Pressione i e informe a origem:\nowner/repo ou uma URL Git (https://…, git@…, ….git): clonada com git clone --depth 1 numa pasta temporária; exige git no PATH. Caminho de um arquivo .zip. Pasta local (~ é expandido). O lazyagents procura pastas com SKILL.md em qualquer profundidade. Se a raiz tiver um, ela própria é a skill. .git, node_modules e vendor são ignorados. Para nomes repetidos, vence a pasta fora de diretórios ocultos e mais próxima da raiz. O seletor mostra as skills encontradas, inicialmente todas marcadas: space alterna uma, a alterna todas, enter instala e esc cancela.\nA instalação só copia para a biblioteca e registra a origem em .origin.json na pasta da skill. Nada é ativado automaticamente. Um nome já existente não é sobrescrito: esse item falha, mas a instalação dos demais continua.\nMarketplaces. Se a origem tiver um manifesto de marketplace do Claude Code (.claude-plugin/marketplace.json) declarando skills, o lazyagents usa o manifesto em vez da varredura. O seletor prefixa cada skill com o nome do plugin. Plugins vindos de outro repositório ou pacote não são buscados; aparecem como notas.\nHooks na mesma origem. Se houver hooks/hooks.json no formato de plugin do Claude Code, os hooks aparecem no mesmo seletor, desmarcados: um hook executa comandos de terceiros a cada evento do agente. Veja o guia de hooks.\nBuscar no GitHub # S busca arquivos SKILL.md com seu termo no código do GitHub e lista os repositórios com descrições. enter inicia a instalação do repositório escolhido. A busca usa gh api, portanto exige a CLI do GitHub instalada e autenticada. Ela só ocorre quando você solicita.\nCriar e editar # n pede um nome em kebab-case (letras minúsculas, dígitos e hífens, até 64 caracteres) e cria \u0026lt;biblioteca\u0026gt;/\u0026lt;nome\u0026gt;/SKILL.md a partir de um modelo com name e description preenchidos. e abre o arquivo da skill selecionada em $EDITOR (vi se não definido), suspendendo a TUI até o editor sair.\nIncorporar skills locais # o incorpora a skill local selecionada: copia a pasta à biblioteca, faz backup da original e a substitui por um link simbólico para a cópia. O agente continua vendo a skill; outros agentes passam a poder ativá-la. A incorpora todas após uma confirmação que as lista.\nNão é possível incorporar um link criado por outra ferramenta: gerencie-o com a ferramenta que o criou. Nomes já presentes na biblioteca também são recusados.\nAtualizar a partir da origem # Skills instaladas de origens Git podem ser atualizadas. Skills de ZIP, pasta ou criadas manualmente não podem.\nu atualiza a selecionada após confirmação: clona novamente o repositório, faz backup da pasta atual e substitui seu conteúdo no mesmo lugar, mantendo os links dos agentes. U verifica todas as skills de origem Git, clonando cada repositório uma vez, e marca a matriz: ↑ atualização disponível, ~ edição local. Se houver atualizações, pede para aplicar todas. Skills editadas localmente são ignoradas para preservar suas mudanças; u permite atualizar uma delas mesmo assim, com backup. As edições locais são detectadas comparando o conteúdo com o hash salvo na instalação ou atualização.\nPerfis # p abre a lista de perfis:\ns salva a matriz atual. Apenas ativações controladas pelo lazyagents são registradas; skills locais e visíveis por diretórios de outros agentes ficam de fora. enter mostra as mudanças da aplicação (+ ativar, − desativar, por skill e agente) e pede confirmação. d apaga o perfil após confirmação. As skills permanecem como estão. Aplicar ativa as skills listadas nos agentes indicados e desativa as outras skills da biblioteca onde o lazyagents as ativou. Skills locais nunca são tocadas. Um perfil que cita uma skill ausente da biblioteca é recusado.\nOs perfis ficam em ~/.local/share/lazyagents/profiles.json.\nBackups e restauração # b lista os backups da skill selecionada, dos mais novos aos mais antigos. enter restaura após confirmação. A pasta atual, se existir, recebe backup antes da substituição, permitindo desfazer a restauração. O backup é extraído e verificado numa pasta temporária antes da troca; um backup corrompido mantém a skill intacta.\nValidação de SKILL.md # Cada skill é validada contra o formato Agent Skills. Problemas aparecem nos detalhes e em lazyagents doctor:\nname deve existir, estar em kebab-case e coincidir com o nome da pasta; description deve ser não vazia e ter até 1024 caracteres; deve haver instruções depois do front matter. Um front matter que não pode ser interpretado torna o SKILL.md inválido.\nPela CLI # A CLI cobre as operações diárias. Cada comando é descrito na referência da CLI; lazyagents help \u0026lt;comando\u0026gt; imprime a ajuda correspondente.\nlazyagents install anthropics/skills # instalar todas as skills do repositório lazyagents install ./my-skills.zip --hooks # instalar também os hooks incluídos lazyagents install anthropics/skills pdf docx # apenas estas skills lazyagents install DietrichGebert/ponytail --all # instalar e ativar em todos os agentes lazyagents list # skills, número de agentes, biblioteca ou local lazyagents enable pdf --agent claude-code # ativar em um agente lazyagents disable pdf --agent codex lazyagents enable pdf # todos os agentes instalados, como a na TUI lazyagents adopt my-notes --agent claude-code # incorporar uma skill local lazyagents remove pdf # remover da biblioteca, com backup lazyagents list --json | jq \u0026#39;.[] | select(.valid | not) | .dir\u0026#39; lazyagents skills \u0026lt;comando\u0026gt; é um alias dos mesmos comandos. Busca, criação, atualização, perfis e restauração ainda estão disponíveis só na TUI.\nConfiguração # # ~/.config/lazyagents/config.yaml libraryDir: ~/.agents/skills libraryDir altera a localização da biblioteca. Defini-lo manualmente só muda onde o lazyagents procura; as skills existentes e os links continuam no lugar antigo. Para movê-los também, use lazyagents migrate-library \u0026lt;dir\u0026gt;: faz backup e copia cada skill, redireciona os links, salva libraryDir e só então remove as cópias antigas. O comando recusa nomes já existentes no destino (incluindo links) ou diretórios contidos um no outro. Resolva o conflito e execute novamente.\nUsar ~/.agents/skills como biblioteca torna todas as skills visíveis para Codex, Gemini CLI, OpenCode, Pi e Crush sem links, pois eles leem essa pasta. Em troca, perde-se a ativação por agente. Outras opções estão no guia de configuração.\nArquivos # Caminho Quando é escrito ~/.local/share/lazyagents/skills/\u0026lt;name\u0026gt;/ instalação, criação, incorporação, atualização, restauração e remoção ~/.local/share/lazyagents/skills/\u0026lt;name\u0026gt;/.origin.json instalação e atualização: tipo de origem, URL ou caminho, subpasta e hash diretório de skills de cada agente ativação e desativação (só links), incorporação (original vira link) e remoção (links à biblioteca) ~/.local/share/lazyagents/backups/\u0026lt;name\u0026gt;.\u0026lt;timestamp\u0026gt;.tar.gz remoção, atualização, incorporação, restauração e migração; modo 0600, 20 por skill ~/.local/share/lazyagents/profiles.json ao salvar um perfil ~/.config/lazyagents/config.yaml migrate-library, no campo libraryDir Clones Git e ZIPs extraídos usam pastas temporárias removidas depois da instalação.\nLimitações # Links simbólicos dentro de uma skill não são copiados na instalação, incorporação ou migração; uma skill não pode importar arquivos externos à própria pasta. Entradas de ZIP que são links ou escapam da raiz são ignoradas. Um ZIP acima dos limites falha antes de chegar à biblioteca: entrada maior que 64 MB, mais de 512 MB descompactados no total ou mais de 10.000 entradas. A ativação usa links simbólicos. No Windows, pode exigir Modo de Desenvolvedor ou direitos de administrador. Os diretórios de skills por projeto do Hermes Agent (\u0026lt;projeto\u0026gt;/.hermes/skills, após hermes skills trust) não são lidos; external_dirs são. Skills incluídas em plugins do Claude Code não são gerenciadas. A TUI não monitora o sistema de arquivos: pressione r após mudanças manuais. ","externalUrl":null,"permalink":"/docs/lazyagents/guide/skills/","section":"Documentação","summary":"Uma skill é uma pasta com um SKILL.md: instruções que um agente carrega quando a tarefa corresponde à descrição. Cada agente lê skills do próprio diretório, por …","title":"Skills · lazyagents","type":"docs"},{"content":"Quando o Claude Code, o Codex, o OpenCode, o Qwen Code ou o Copilot CLI pede permissão para uma chamada de ferramenta, a ilha abre num card que mostra exatamente o que Allow autoriza (o Antigravity, o Cursor, o Factory Droid e o Kimi Code são as exceções, abaixo):\nas próprias palavras do agente sobre ela, quando ele as dá (Run the test suite, then the linter); o comando inteiro, o arquivo ou a URL, não só o nome da ferramenta. Um comando longo aparece completo (até quatro linhas, depois ele rola); numa edição, as linhas que ela adiciona e remove (+12 −3). Patches do Codex também mostram seus arquivos e contagens. O card ocupa toda a largura da ilha até você responder. Depois ele diz o que aconteceu por um instante (Allowed em verde, Denied em vermelho) antes de a próxima coisa aparecer.\nRespondendo # Allow e Deny respondem direto ao agente; ele segue na hora. Embaixo do comando, uma linha diz por que ele pergunta quando há mais a dizer do que \u0026ldquo;nada permite\u0026rdquo;: Destructive: no policy ever allows it ou Your policy asks first for this. Ctrl+Alt+Y e Ctrl+Alt+N fazem o mesmo de qualquer lugar, sem sair da sua janela (atalhos). Os botões mostram as teclas de fato associadas. Um atalho só responde a um card que está na tela; sem nada esperando, ele não faz nada. No Nest, o card é respondido onde você está: enquanto a janela dele tem o foco, a ilha fica de lado e o card da sessão em Flock tem os mesmos botões (e aceita as mesmas teclas). Saia do Nest com um card esperando e a ilha aparece para ele. No modo Panel a ilha fica fora de vista, então um card também aparece como uma notificação do desktop. O Open dela traz a ilha com o card; ela não tem Allow nem Deny (notificações). Enquanto o app está em Paused (presença), nenhum card aparece: o agente pergunta no terminal dele na hora, e nem as regras Always nem as políticas respondem. Always allow permite o pedido e todo pedido idêntico daí em diante: o mesmo agente, a mesma ferramenta e exatamente o mesmo comando, arquivo ou URL, na mesma pasta de projeto. cargo test não cobre cargo test \u0026amp;\u0026amp; rm -rf build, nem o mesmo comando em outro projeto. Esses pedidos são respondidos sem card, e o passo diz always allowed; um pedido idêntico que já espera também é respondido. Settings → Approvals lista todas as regras, e Remove tira uma delas. Um comando com mais de uma linha, ou com mais de 300 caracteres, não oferece Always allow: uma regra só veria o começo dele. Um comando destrutivo (rm -rf, um push forçado) sempre pergunta: o card dele diz isso em laranja, deixa Deny como o botão claro, contorna Allow em vermelho e não oferece Always allow. Nenhuma regra ou política o responde, nem uma regra salva antes. Só você responde: com um clique ou um atalho agora, ou antes com Always allow ou uma política que você aceitou. Nenhum timer ou padrão aprova nada, nunca. Políticas # Uma política responde cards por você: você a escreve em Settings → Approvals → Policies, vê como um diff contra a que está em vigor e aceita com um clique. Uma política por pasta de projeto, mais uma para todo lugar; uma mais nova substitui a mais velha. Revoke desliga na hora, e os cards dela voltam a perguntar. Por enquanto uma política só permite chamadas do Claude Code, o único agente cujos cards mostram a chamada inteira (os shells dos outros rodam numa pasta que o card omite); para Codex, OpenCode, Qwen Code e Copilot CLI ela pode negar ou perguntar. Agentes cujas permissões não viram card (Antigravity, Cursor, Factory Droid, Kimi Code) não são respondidos por ela. O chat do Zeca só as segue quando você escolhe Your policies ou Full access para ele (Quem responde os cards do Zeca).\n# Linhas que começam com # são notas. project ~/Projects/site agents claude codex allow read allow write allow command git status allow command git diff * deny external ask tool WebFetch project define a pasta em que ela vale (e abaixo dela); sem ele, vale em todo lugar. agents limita a alguns agentes; sem ele, todo agente embutido. allow, deny ou ask, depois uma classe (read, read-external, write, external), command e as palavras dele (um * no fim deixa vir mais palavras), ou tool e o nome exato de uma ferramenta (um shell ou uma ferramenta MCP só com deny ou ask). Uma ação destrutiva (rm, um push forçado, um redirecionamento por cima de um arquivo) sempre pergunta: nenhuma linha a responde. Um deny vence um ask, e um ask vence um allow, entre todas as políticas que valem; um deny vence também um Always allow mais antigo. Uma linha deny ou ask cobre o que vier depois das palavras dela, com * ou não, e um comando que tem as duas primeiras palavras dela em qualquer lugar (git --no-pager push, ou um git push sozinho, com deny command git push origin main) nunca é permitido. Ela nomeia um programa: deny command curl não diz nada sobre wget. deny tool Bash vale para o shell de todo agente. Um allow precisa que o Vults saiba o que a ação faz: uma ferramenta MCP, uma ferramenta ou comando desconhecido, um interpretador, um build ou um teste (cargo test roda o código do projeto) sempre perguntam, e também os comandos git que rodam os hooks do repositório (commit, merge, rebase, pull, push, checkout, switch, cherry-pick, revert, am, worktree, clone). Também perguntam um comando com símbolo do shell, aspas, glob ou tab, um comando longo ou de várias linhas, e um card cujo alvo foi cortado. O Always allow continua cobrindo um comando exato. Um allow só alcança a pasta da sessão: aquela em que o Vults a viu começar, nunca / nem a sua pasta pessoal, e nada depois que o agente saiu dela (uma sessão que o Vults viu pela primeira vez depois, após um reinício, não ganha allow). Um caminho fora dela, um que sobe (..), vários caminhos num alvo só ou uma escrita dentro de .git pergunta. As palavras de um comando permitido não nomeiam caminho absoluto, URL, @arquivo, .., .git nem opção grudada num caminho, então um fetch com URL sempre pergunta. Uma linha ampla cobre toda a classe: allow external cobre git push, gh pr merge, gh workflow run, gh gist create e outras ações para fora deste computador que o Vults conhece, inclusive as que mandam um arquivo da pasta para fora; allow write cobre toda escrita conhecida que pode ser desfeita. Prefira linhas command. Uma resposta de uma política não mostra card; o passo diz allowed by your policy, e o log de auditoria nomeia o consentimento da política (Segurança). Editar uma política para que ela nomeie outra pasta revoga a que você editou quando você aceita; a revisão avisa. O que ela não vê: links. Um symlink dentro da pasta que leva para fora dela conta como dentro. E allow write deixa o agente mudar arquivos que rodam depois, quando você ou uma ferramenta os roda (um Makefile, um .envrc, os scripts do package.json). Uma política é uma linha no seu banco de dados local: outro programa rodando como você poderia adicionar uma, como poderia mudar qualquer arquivo seu. Mais de um ao mesmo tempo # Os pedidos esperam em fila, cada um pelo seu agente. O card mostra o primeiro com 1 of 3, embaixo de um ponto por sessão na cor do agente. Responda um e o próximo aparece.\nPara responder primeiro um que está mais atrás, clique em Open na notificação dele (no Panel) ou no pássaro dele no widget do canto: o card dele vai para a frente, mantendo o próprio prazo. Projetos silenciados ou ocultos (por projeto) continuam recebendo seus cards e sons.\nUma pergunta respondida pela metade recomeça quando outro card vem para a frente dela. Um card cujo agente seguiu adiante não vem para a frente, mas um subagente trabalhando em paralelo não tira um card. Quando um agente pede duas chamadas de uma vez, responder a primeira deixa a segunda esperando.\nQuando ninguém responde # Um pedido espera enquanto o agente dele espera (um pouco menos de dois minutos); enquanto isso, o terminal diz Waiting for your answer in Vults. Nos últimos 30 segundos o card faz uma contagem regressiva, Goes back to the terminal in 0:25, e então o terminal pergunta como se o Vults não estivesse ali. Se você responder no terminal, o card avisa e some.\nEnquanto espera, um card sobe uma escada, para que um card que você perdeu chegue até você:\nEle abre a ilha, com o som dele (no Panel, também com uma notificação do desktop, se as notificações estiverem ligadas). O som dele toca de novo aos 45, 75 e 105 segundos. Do not disturb (não perturbe; Settings → General, por 30 minutos, 1 hora ou 4 horas) silencia os sons e as notificações de tudo o que está em repouso, e os lembretes dessa escada, até terminar pelo relógio (uma suspensão não o estica). Uma lua no cabeçalho da ilha diz que ele está ligado; um clique nela o encerra. Um card ainda abre a ilha com o som dele (e, no Panel, a notificação): nada esconde um card pelo qual um agente está esperando.\nSe o app estiver fechado ou sem responder, o hook não responde nada em milissegundos e todo agente pergunta no terminal dele, como de costume.\nO modo automático do Claude Code # No modo automático (auto mode), o classificador libera a maioria dos pedidos num piscar, então a ilha só mostra um card, toca um som ou abre para um pedido que ainda está esperando depois de um instante. O mesmo vale para \u0026ldquo;terminou\u0026rdquo;: só uma sessão que continua pronta é novidade.\nPerguntas # Quando o Claude Code ou o OpenCode pergunta algo a você com opções (a ferramenta AskUserQuestion do Claude Code, a ferramenta question do OpenCode), a ilha abre num card de pergunta:\nUma pergunta por vez, com a etiqueta dela (Theme) e 1 of 2 quando ele faz várias. Um clique numa opção a responde. Quando várias podem ser escolhidas, marque-as e aperte Next (ou Send na última). Other… abre um campo para as suas próprias palavras; Enter o envia, Escape volta. Reply in the terminal devolve a pergunta ao terminal do agente. Até lá, ou até o tempo do card acabar, o Claude Code espera pela ilha. Ctrl+Alt+Y e Ctrl+Alt+N nunca respondem a uma pergunta. Isso precisa do Claude Code 2.1.85 ou mais recente e de hooks instalados por esta versão. Hooks mais antigos mostram Update available em Settings → Agents; até você atualizá-los, a ilha mostra a pergunta e leva você ao terminal, como faz para o Qwen Code.\nOpenCode # As permissões e as perguntas do OpenCode ganham um card pelo plugin que Settings → Agents → OpenCode escreve (conferido com o OpenCode 1.18.35 e 2.0.26). O prompt do próprio OpenCode continua aberto enquanto isso: responda na ilha ou no OpenCode, e vale a primeira resposta; o card some quando você responde no OpenCode.\nAllow é o Allow once do OpenCode; Deny, o Reject dele. Always allow é uma regra do Vults: o Always do próprio OpenCode, que mudaria as configurações dele, nunca é usado. Algumas perguntas ficam no prompt do OpenCode: todas no OpenCode 2, que não deixa um plugin respondê-las, e no OpenCode 1 as com mais de quatro opções ou mais de quatro de uma vez. A ilha mostra que uma espera lá. Sem clique a tempo, com o app fechado ou com um plugin desatualizado (Update plugin… em Settings → Agents), o OpenCode só espera no próprio prompt. Qwen Code # As permissões do Qwen Code ganham um card pelos hooks que Settings → Agents → Qwen Code instala (conferido com o Qwen Code 0.25.0). O Qwen lê a mesma resposta que o Claude Code, então Allow, Deny e Always allow funcionam como lá.\nEnquanto o card está aberto, o Qwen mostra só o spinner; sem clique a tempo, ou com o app fechado, ele pergunta no próprio prompt. As perguntas dele (ask_user_question) ficam no terminal: o Qwen não aceita resposta de um hook para elas. A ilha mostra que ele espera lá. Os cards aparecem no modo de aprovação default do Qwen (Shift+Tab no Qwen, ou qwen --approval-mode default); uma instalação nova começa no auto, em que o próprio classificador dele decide. No yolo o Qwen aprova tudo, então nenhum card aparece. Copilot CLI # As permissões do Copilot CLI ganham um card pelo arquivo de hooks que Settings → Agents → Copilot CLI escreve, ~/.copilot/hooks/vults.json (conferido com o Copilot CLI 1.0.96). O Copilot lê todos os arquivos dessa pasta, então o que o Vults escreve guarda só os hooks dele; um arquivo ali que o Vults não escreveu nunca é tocado.\nAllow e Deny respondem àquela chamada; Always allow é uma regra do Vults. O card de uma edição mostra as linhas que ela adiciona e remove; um arquivo novo aparece como escrita. Sem clique a tempo, ou com o app fechado, o Copilot pergunta no próprio prompt. Ele não tem ferramenta de perguntas, então nenhuma pergunta chega à ilha. Um comando que falhou aparece como falha; o que uma ferramenta imprimiu nunca sai do hook. Agentes que perguntam no próprio prompt # Antigravity, Cursor, Factory Droid e Kimi Code pedem as permissões no próprio terminal ou prompt, e a ilha nunca as responde: os pássaros deles mostram os passos. O que cada agente consegue fazer os resume, e a seção de cada um ali diz por que ele não tem card. Uma tarefa que o Vults roda no Kimi Code pede com um card cada escrita e cada comando, como o agente de qualquer tarefa (Tarefas).\n","externalUrl":null,"permalink":"/docs/vults/guide/approvals/","section":"Documentação","summary":"Quando o Claude Code, o Codex, o OpenCode, o Qwen Code ou o Copilot CLI pede permissão para uma chamada de ferramenta, a ilha abre num card que mostra …","title":"Aprovando pela ilha · Vults","type":"docs"},{"content":"spn \u0026lt;command\u0026gt; [flags] spn sem argumentos, spn help ou spn -h imprime a lista de comandos. As opções podem vir antes ou depois dos argumentos posicionais: spn new eza --out x e spn new --out x eza são o mesmo comando.\nA paleta e o catálogo de ports vêm embutidos no binário. As opções abaixo que recebem um arquivo ou diretório leem essa cópia do disco, e é assim que o contrato é alterado e medido antes de ser publicado.\nComandos que escrevem arquivos # --check em gen, readme e preview não escreve nada e falha quando o que está commitado está desatualizado. É isso que o CI de um port executa.\nspn gen # Renderiza o mapeamento de um port em arquivos de tema prontos.\nspn gen [templates...] Sem argumentos, renderiza todos os *.tmpl do diretório atual, então um repositório de port roda apenas spn gen.\nopção função --check não escreve; falha se algum arquivo em disco estiver desatualizado --stdout escreve na saída padrão em vez de em arquivos --app \u0026lt;slug\u0026gt; slug do catálogo para este port (padrão: inferido do nome do template) --registry \u0026lt;file\u0026gt; lê o catálogo de ports deste arquivo --palette \u0026lt;dir\u0026gt; lê o contrato deste diretório -q imprime só as falhas spn readme # Renderiza o README canônico de um port a partir do catálogo.\nspn readme [slug] opção função --out \u0026lt;file\u0026gt; arquivo a escrever (padrão README.md) --check não escreve; falha se o README estiver desatualizado --stdout escreve na saída padrão em vez de em um arquivo --registry \u0026lt;file\u0026gt; lê o catálogo de ports deste arquivo --copy \u0026lt;file\u0026gt; lê o texto compartilhado dos READMEs deste arquivo --palette \u0026lt;dir\u0026gt; lê o contrato deste diretório spn preview # Desenha a prévia sintética de cada variação. As prévias são SVGs desenhados a partir da paleta, então não têm como mostrar uma cor que o usuário não vai receber.\nspn preview [slug] opção função --out \u0026lt;dir\u0026gt; diretório onde escrever as prévias (padrão assets) --check não escreve; falha se alguma prévia estiver desatualizada --registry \u0026lt;file\u0026gt; lê o catálogo de ports deste arquivo --copy \u0026lt;file\u0026gt; lê o texto compartilhado dos READMEs deste arquivo --palette \u0026lt;dir\u0026gt; lê o contrato deste diretório spn new # Cria a estrutura de um novo repositório de port: o esboço do mapeamento com o cabeçalho canônico, o workflow de seis linhas, a configuração do Renovate e as configurações de editor. O port precisa estar listado no catálogo antes.\nspn new \u0026lt;slug\u0026gt; opção função --out \u0026lt;dir\u0026gt; diretório onde criar a estrutura (padrão: o slug) --force sobrescreve arquivos que a estrutura substituiria --registry \u0026lt;file\u0026gt; lê o catálogo de ports deste arquivo --copy \u0026lt;file\u0026gt; lê o texto compartilhado dos READMEs deste arquivo spn pin # Reescreve a versão do motor que um mapeamento declara no frontmatter. A propagação de release roda esse comando no mesmo pull request que regenera os arquivos de um port.\nspn pin \u0026lt;version\u0026gt; [templates...] opção função --check informa se a versão fixada já corresponde, sem escrever nada Comandos que verificam # spn lint # Verifica se os mapeamentos pedem papéis, nunca cores cruas. Percorre a árvore de parse do template, então um contraexemplo dentro de um comentário não conta como achado.\nspn lint [templates...] spn check # Audita contraste, separação entre acentos e visão de cores em todas as variações. Falha quando um par fica abaixo do seu piso.\nopção função -v lista também os pares aprovados e o resumo de visão de cores --json imprime, como dados, o que a auditoria mede e a política contra a qual mede --palette \u0026lt;dir\u0026gt; lê o contrato deste diretório spn registry # Lista e valida o catálogo de ports.\nopção função --json imprime o catálogo como JSON, usado para montar a matriz de propagação --registry \u0026lt;file\u0026gt; lê o catálogo de ports deste arquivo --copy \u0026lt;file\u0026gt; lê o texto compartilhado dos READMEs deste arquivo Comandos que imprimem # spn entry # Imprime uma entrada inicial de catálogo para um novo port, com todos os campos obrigatórios, uma tabela de mapeamento para completar e uma prévia completa. Ela já é válida do jeito que é impressa.\nspn entry \u0026lt;slug\u0026gt; \u0026gt;\u0026gt; registry/ports.yml spn palette # Imprime a paleta e a camada de papéis resolvida.\nopção função --roles imprime a camada de papéis resolvida em vez das cores --json imprime o contrato como JSON em vez de uma tabela --palette \u0026lt;dir\u0026gt; lê o contrato deste diretório spn version # Imprime a versão da ferramenta. Um build a partir do código-fonte imprime dev.\n","externalUrl":null,"permalink":"/docs/sp-night/reference/cli/","section":"Documentação","summary":"spn \u0026amp;lt;command\u0026amp;gt; [flags] spn sem argumentos, spn help ou spn -h imprime a lista de comandos. As opções podem vir antes ou depois dos argumentos posicionais: …","title":"Referência de comandos · SP Night","type":"docs"},{"content":"A aba Sessions reúne conversas de todos os agentes numa lista, das mais recentes às mais antigas. Você pode retomar na CLI do próprio agente, ler, buscar, exportar, nomear e excluir sessões. O lazyagents apenas lê os arquivos de sessão das CLIs; só os altera ao excluir uma sessão.\nConceitos # Sessão: conversa com um agente, com a primeira mensagem como título, pasta de execução e horário da última atualização. Alias: nome que você dá a uma sessão. O lazyagents o guarda em arquivo próprio, nunca nos dados da CLI. O filtro pesquisa aliases e títulos. Sessão em execução: conversa ainda aberta por um processo do agente. Mostra ● e não pode ser excluída antes de você fechá-la. Índice de conversas: o lazyagents lê cada conversa uma vez e depois apenas o trecho acrescentado. Isso acelera a recarga de históricos grandes. O índice é um cache descartável (Arquivos). Origem das sessões # Agente Leitura Retomada Observações Claude Code ~/.claude/projects/\u0026lt;project\u0026gt;/*.jsonl claude --resume \u0026lt;id\u0026gt; indicador de execução e tokens por sessão; também lê subagentes em \u0026lt;project\u0026gt;/\u0026lt;id\u0026gt;/subagents/ Codex ~/.codex/sessions/**/*.jsonl (rollouts) codex resume \u0026lt;id\u0026gt; Gemini CLI conversas em ~/.gemini/history/\u0026lt;project\u0026gt;/ e ~/.gemini/tmp/\u0026lt;project\u0026gt;/ gemini --resume \u0026lt;id\u0026gt; a pasta vem do mapa de projetos do Gemini OpenCode ~/.local/share/opencode/opencode.db opencode --session \u0026lt;id\u0026gt; usa o binário sqlite3, em modo somente leitura; até 500 sessões principais recentes Crush \u0026lt;project\u0026gt;/.crush/crush.db para cada projeto em ~/.local/share/crush/projects.json crush --session \u0026lt;id\u0026gt;, no projeto usa sqlite3 em modo somente leitura; sessões de subagentes aparecem dentro da sessão que os iniciou Pi ~/.pi/agent/sessions/\u0026lt;project\u0026gt;/*.jsonl pi --session \u0026lt;file\u0026gt; também aceita PI_CODING_AGENT_SESSION_DIR ou sessionDir absoluto em settings.json; título dado por /name ou pela primeira mensagem; mostra só o ramo ativo Esses são os caminhos padrão. Agentes movidos por suas variáveis de configuração, como CLAUDE_CONFIG_DIR, CODEX_HOME, XDG_DATA_HOME ou OPENCODE_DB, são lidos na localização correspondente.\nClaude Desktop e Hermes Agent não têm sessões locais legíveis pelo lazyagents. Outros recursos de cada agente estão na referência dos agentes.\nRequisitos:\nOpenCode: exige sqlite3 no PATH para listar e ler sessões. Sem ele, os demais agentes continuam carregando e o erro identifica o binário ausente. Indicador de execução: no Linux, lê /proc diretamente. Nos demais sistemas, executa lsof uma vez por carga. Sem lsof, nenhuma sessão é marcada como em execução. Na TUI # As teclas estão na referência; ? as mostra na interface. O painel lateral mostra pasta, ID e tokens da sessão quando o agente registra consumo, além do custo estimado para autenticação por chave de API. Custos registrados pelo próprio agente (Pi e Crush) aparecem sem ~. Crush registra custo, mas não os tokens da sessão inteira, então suas sessões não têm a linha de tokens.\nRetomar uma sessão # Pressione enter. O lazyagents suspende a interface, executa a retomada na pasta da sessão e volta quando o agente sai. Se a pasta não existir mais, pede outra. Para escolher a pasta manualmente, use R. O campo aceita ~.\nPara copiar o comando em vez de executá-lo, pressione c: a linha de estado mostra cd \u0026lt;pasta\u0026gt; \u0026amp;\u0026amp; \u0026lt;comando\u0026gt;.\nO binário do agente precisa estar no PATH. Agentes sem retomada pela CLI mostram um erro.\nLer uma conversa # v abre a conversa como registro: cada mensagem sua é um título numerado; cada turno do agente fica atrás de uma barra na cor dele. O turno mostra a resposta e as mensagens após o último comando. O trabalho anterior (progresso, raciocínio e comandos) fica recolhido numa linha ⋯ com contagens.\nPara Claude Code, Codex, Pi, OpenCode e Crush, o leitor mostra o horário das mensagens e a duração do trabalho. Compactações, interrupções, mudanças de modelo e ramos do Pi (branch 2 of 3, seguido dos outros ramos) aparecem entre turnos. Comandos com / aparecem como foram digitados. Falhas recebem ✗; Codex não associa a falha à chamada, então seus comandos não recebem essa marca. Um resumo do Crush aparece como compactação.\nChamadas são mostradas pelo que fizeram: $ comando para shell, ✎ arquivo +3 −1 para edição com linhas adicionadas e removidas, texto discreto para leituras, buscas e consultas web, e ⎇ para subagentes, com contagem de chamadas quando o Claude Code guardou a conversa. A linha ⋯ conta arquivos editados. Planos propostos pelo agente (modo de planejamento do Claude Code) aparecem como documentos; tarefas aparecem como lista com contagem das concluídas. No leitor:\nn/N alternam entre suas mensagens. g/G vão ao começo e ao fim. A partir de 150 colunas, uma faixa à esquerda lista as mensagens com horários e marcas (✎ edição, ✗ falha, ⎇ subagente), destacando a atual. m alterna entre log (registro padrão), conversation (mensagens e respostas, sem etapas) e actions (mensagens e chamadas, sem mensagens de progresso: o que foi feito nos arquivos e shell). ]/[ escolhem o próximo ou anterior turno com etapas recolhidas, subagente ou ramo (▶). enter expande ou recolhe só o turno escolhido, ou abre a conversa do subagente/ramo. esc volta ao ponto anterior. e expande todas as etapas ou as recolhe novamente. t mostra comandos de ferramentas (❯) completos, um por linha, ou resumidos; também expande as etapas. r mostra raciocínio (💭) completo ou só a primeira linha; também expande as etapas. esc volta à lista. Exportar para Markdown # No leitor, x grava em ~/.local/share/lazyagents/exports/ como \u0026lt;agent\u0026gt;-\u0026lt;id\u0026gt;-\u0026lt;timestamp\u0026gt;.md, com modo 0600. O arquivo tem cabeçalho com agente, data e pasta, e uma seção por turno, com comandos em lista e raciocínio em citações. Conversas vazias não são exportadas.\nBuscar em todas as conversas # F pede uma palavra ou frase. A busca ignora diferenças entre maiúsculas e minúsculas e pesquisa, em paralelo, o texto completo de todas as sessões carregadas. Para Claude Code e Codex, arquivos que não podem conter o texto são descartados sem decodificação. A lista mostra só correspondências, com um trecho em torno da primeira ocorrência. esc limpa a busca.\n/ é diferente: filtra a lista por agente, alias, título e nome da pasta sem abrir as conversas.\nNomear uma sessão # m pede um alias. Salvar vazio o remove. O alias aparece antes do título em todos os lugares, inclusive em lazyagents sessions.\nAgrupar e filtrar # g agrupa por projeto (nome da pasta) e agente. f alterna entre todos os agentes e cada agente individualmente. r recarrega do disco. Os arquivos não são monitorados automaticamente. Excluir sessões # d exclui a sessão selecionada. Para várias, marque antes com space; sobre um cabeçalho de grupo, marca o grupo inteiro. A confirmação lista tudo antes da exclusão.\nClaude Code, Codex, Gemini CLI e Pi: o arquivo é copiado para ~/.local/share/lazyagents/backups/ como \u0026lt;file\u0026gt;.\u0026lt;timestamp\u0026gt; antes da remoção. Para restaurar, copie-o à pasta original e retire o sufixo de horário. OpenCode: primeiro salva opencode export \u0026lt;id\u0026gt; em ~/.local/share/lazyagents/backups/opencode-\u0026lt;id\u0026gt;.\u0026lt;timestamp\u0026gt;.json (0600), depois executa opencode session delete \u0026lt;id\u0026gt;. Se a exportação falhar, nada é excluído. Restaure com opencode import \u0026lt;file\u0026gt;. Crush: primeiro salva crush session show \u0026lt;id\u0026gt; --json, com sessão e mensagens, em ~/.local/share/lazyagents/backups/crush-\u0026lt;id\u0026gt;.\u0026lt;timestamp\u0026gt;.json (0600); depois executa crush session delete \u0026lt;id\u0026gt;, ambos com o diretório de dados da sessão. Falha no backup impede a exclusão. Crush não tem importação: o backup é um registro, não um arquivo recarregável. Sessões em execução: são recusadas; feche o agente antes. Pela CLI # lazyagents sessions # todos os agentes, mais recentes primeiro lazyagents sessions --agent codex --limit 20 lazyagents sessions --here # sessões iniciadas nesta pasta lazyagents sessions --json | jq \u0026#39;.[0].id\u0026#39; # id, título, alias, cwd, atualização e consumo --json inclui tokens quando registrados pelo agente e cost_usd apenas para autenticação por chave de API. Retomada, leitura e exclusão são ações da TUI. As opções estão na referência da CLI.\nConfiguração # Sessions não tem seção própria em config.yaml. Para iniciar nessa aba, use startTab: sessions na seção tui: (configuração).\nArquivos # Caminho Conteúdo ~/.local/share/lazyagents/session-aliases.json aliases indexados por \u0026lt;agent\u0026gt;:\u0026lt;session id\u0026gt; ~/.local/share/lazyagents/exports/ conversas exportadas ~/.local/share/lazyagents/backups/ cópias de sessões excluídas e exportações OpenCode (opencode-\u0026lt;id\u0026gt;.\u0026lt;timestamp\u0026gt;.json) ~/.local/share/lazyagents/transcript-index.gob índice descartável; apagar só faz a próxima carga reler tudo Limitações # Custos estimados usam preços de tabela da API Claude (Pi usa seu custo registrado), cobrem apenas modelos Claude conhecidos e aparecem só para chaves de API: assinaturas não pagam por token. Veja as regras no guia de consumo. Formatos de sessão são privados e podem mudar entre versões das CLIs. Arquivos ilegíveis são ignorados, sem impedir os outros de carregar. OpenCode lista até 500 sessões e exclui sessões de subagentes da lista principal. ","externalUrl":null,"permalink":"/docs/lazyagents/guide/sessions/","section":"Documentação","summary":"A aba Sessions reúne conversas de todos os agentes numa lista, das mais recentes às mais antigas. Você pode retomar na CLI do próprio agente, ler, buscar, …","title":"Sessões · lazyagents","type":"docs"},{"content":"A aba Usage responde a duas perguntas por agente: quanto resta da sua assinatura e onde seus tokens foram usados. Os limites vêm da conta de cada agente; os tokens vêm das conversas já no disco. A aba é somente leitura.\nConceitos # Janelas de limite: porcentagem consumida da assinatura em cada janela e horário de renovação. Há janela de sessão (5 horas) e semanal; algumas contas têm limites semanais por modelo. Scripts devem identificar pelo kind (session, weekly, weekly_model). label é texto de apresentação e pode mudar. Autenticação: subscription, API key ou unknown. O lazyagents lê o tipo nos arquivos do agente sem guardar segredos; isso determina se mostra custo em dólares. Eventos de consumo: um por resposta do modelo na conversa, com horário, modelo, pasta e tokens (entrada, saída, leitura e escrita de cache). As tabelas somam esses eventos. Bloco atual: a atividade é dividida em blocos de 5 horas, como a janela de sessão do Claude Code. O bloco começa na primeira resposta após um intervalo e dura 5 horas. O atual contém o momento presente. Os agentes que informam limites e histórico estão na referência.\nNa TUI # Nada é carregado até você abrir a aba pela primeira vez. As teclas estão na referência. Os limites de cada agente são blocos lado a lado conforme a largura disponível. Quando sobra espaço à direita (cerca de 180 colunas), os principais agentes, modelos e projetos aparecem ao lado da tabela. As barras crescem até 40 colunas.\nConsultar limites # O topo mostra uma barra por janela, com porcentagem usada, renovação e plano ou tipo de autenticação. A leitura varia por agente:\nClaude Code: consulta o mesmo endpoint usado por /usage, com a autenticação da CLI. Só acontece ao abrir ou atualizar a aba, nunca na inicialização. Codex: lê os limites registrados nos rollouts das últimas sessões. Sem consulta à rede; a atualização depende da última sessão Codex. Os resultados ficam em cache por 5 minutos. r consulta novamente ignorando o cache. Se falhar, mantém os limites anteriores com aviso. Agentes sem limites a informar (não instalados, não autenticados, com chave de API ou nunca usados) não aparecem nos limites nem nessa parte do doctor.\nFiltrar por período, agente e visualização # p/P avançam e voltam no período: hoje, 7, 30 ou 90 dias, ou todo o histórico. a/A alternam entre todos os agentes e cada agente individualmente. ←/→ ou v alternam dias, agentes, projetos e modelos. Projetos usam o caminho completo; pastas com nomes iguais não se misturam. / filtra linhas pelo nome. Na visualização diária também aceita o dia da semana (Tue). esc limpa o texto; um segundo esc volta a todos os agentes. Mudar filtros não relê as conversas. A visualização diária inclui dias sem consumo, mantendo o gráfico contínuo.\nOs filtros também estão na paleta (:): :usage period 30d, :usage view projects, :usage clear e :usage refresh.\nLer o bloco atual # Abaixo dos limites, o resumo mostra o bloco atual de 5 horas, se houver: início, tempo restante e tokens já usados. Use-o para acompanhar a proximidade do fim da janela.\nCusto # A coluna em dólares só aparece se algum agente filtrado usa chave de API. Assinaturas não pagam por token; a coluna fica oculta. Para contas com chave:\nCada resposta usa o preço do próprio modelo, e as linhas somam as respostas. Sessions usa a mesma regra: mudar de modelo no meio da sessão não faz tudo ser cobrado pelo último modelo. Há preços apenas para modelos Claude, conforme a tabela da API Claude. O programa segue o registro de cobrança do Claude Code: escrita de cache de 1 hora custa 2× a entrada (5 minutos: 1,25×); modo rápido usa preço próprio no Opus 4.8, Opus 5 e Opus 5.5 (outros modelos rápidos ficam sem preço); Batch API custa metade; inferência exclusiva dos EUA (inference_geo: \u0026quot;us\u0026quot;) usa 1,1× no Claude 4.6 ou posterior (versões anteriores sem esse recurso ficam sem preço). Priority Tier e outras regiões sem preço publicado são tratados como sem preço. Se uma resposta não tiver preço, por exemplo de um modelo desconhecido do Codex, a linha mostra — em vez de soma parcial. Respostas sem tokens custam $0 independentemente do modelo; linhas sintéticas de erro de API ou interrupção (\u0026lt;synthetic\u0026gt;) não invalidam a soma. Pi registra o custo por resposta pelo próprio catálogo; o programa usa esse valor para qualquer modelo. Como Pi pode usar vários provedores, cada resposta considera o seu: OAuth por /login (assinatura ChatGPT ou Claude) custa $0.00; chave de API em auth.json ou apiKey de models.json mantém o custo do Pi. O valor é usado como registrado: modelos sem preço no Pi, como locais, mostram $0.00, sem estimativa da tabela. Pi conta como API key se qualquer provedor tiver chave armazenada; a chave fictícia que o lazyagents cria para um perfil sem chave não conta. A tabela oficial é a referência. Trate os valores apresentados como estimativas.\nPela CLI # lazyagents usage # painel: limites, bloco atual e resumo do período lazyagents usage limits # apenas janelas de limite lazyagents usage daily --since 30d # tokens por dia nos últimos 30 dias lazyagents usage projects --limit 0 # todos os projetos, não só os 10 primeiros lazyagents usage models --agent claude-code --since 2026-09-01 lazyagents usage limits --refresh --json --since aceita dias (7d, desde meia-noite), horas (24h) ou data (2026-09-01). usage limits retorna código 1 se nenhum agente informar limites, útil em scripts. As visualizações e opções estão na referência da CLI.\nConfiguração # A seção usage: de config.yaml define os filtros iniciais da aba:\nusage: period: 30d # today | 7d | 30d | 90d | all (padrão: 7d) view: projects # daily | agents | projects | models (padrão: daily) Valores desconhecidos mantêm o padrão. Só a TUI usa essa seção; a CLI usa suas flags. Veja configuração.\nArquivos # Caminho Conteúdo ~/.local/share/lazyagents/usage-cache.json limites consultados nos últimos 5 minutos; pode ser apagado ~/.local/share/lazyagents/transcript-index.gob índice compartilhado com Sessions: tokens por intervalos de 15 minutos; pode ser apagado Esta aba não escreve arquivos dos agentes.\nLimitações # Só contam conversas locais: consumo em outra máquina ou em sessões excluídas não entra. O endpoint de limites do Claude Code não é uma API pública e pode mudar. Nesse caso, a aba mostra erro e mantém o último cache. Os limites do Codex dependem da última sessão nesta máquina. Janelas já vencidas mostram 0% sem horário de renovação, pois o uso registrado era anterior à renovação. Crush registra custo por sessão, mas só tokens da última requisição; não tem histórico aqui. Seu custo aparece em Sessions. Pi não mostra limites de assinatura, apenas tokens e custo. Chaves de provedor vindas só de variáveis de ambiente não são detectadas; essas chamadas mantêm o custo do Pi apenas se outro provedor Pi usar chave armazenada. ","externalUrl":null,"permalink":"/docs/lazyagents/guide/usage/","section":"Documentação","summary":"A aba Usage responde a duas perguntas por agente: quanto resta da sua assinatura e onde seus tokens foram usados. Os limites vêm da conta de cada agente; os …","title":"Consumo · lazyagents","type":"docs"},{"content":"O Nest é a janela do próprio Vults, para quando a ilha fica pequena: o bando inteiro, as suas tarefas, o chat, o que aconteceu e as suas conexões. Abra pelo ícone da bandeja (Nest…) ou pela seta no topo do chat da ilha. Ele é criado quando você abre e some quando você fecha, e abre também com o Zeca desligado, só que sem o Chat. Enquanto ele está aberto a ilha sai, com pílula e aves: uma superfície na tela por vez. O Nest não tem a barra de título do sistema: o cabeçalho dele o move (um clique duplo ocupa a tela) e as bordas e os cantos o redimensionam. Ele abre grande da primeira vez (até 1180 × 820, dentro da tela), e depois no tamanho em que você o deixou. Ela volta quando o Nest fecha ou volta para Quick ou Mini. Um card que espera é respondido onde você está: no Nest enquanto você está nele (a janela dele tem o foco), e na ilha, que aparece para ele, enquanto você está em outro lugar.\nO cabeçalho conta o bando (4 sessions · 1 needs you) e traz a música que o seu player está tocando (com o Now playing ligado; anterior, tocar/pausar e próxima ao lado), a lua enquanto o não perturbe dura (um clique o encerra), o som, a busca (a paleta, como Ctrl+K), o seletor de tamanho e o botão de tela cheia. Embaixo dele, cinco abas com os seus ícones, o número que precisa de você em Flock e as linhas dos conectores em Connections, e Settings à direita, que mostra as Configurações nesta mesma janela, sob as mesmas abas; uma aba traz o Nest de volta. Sobre todas as abas menos Flock, uma etiqueta para cada sessão que precisa de você (ou que falhou); um clique abre Flock com ela na frente (um card que espera vem primeiro ali), onde você o responde. As Configurações continuam uma página própria ali: são a única que muda a config de um agente, uma chave, uma política ou um celular, e nunca mostram texto de agente. O seletor mantém a aba em que você está: Room é a janela, o botão de tela cheia a tela toda (Esc volta para Room), Quick fecha o Nest e abre a ilha, Mini o fecha e deixa a pílula. Alt+1 a Alt+5 escolhem uma aba. Embaixo, Zeca on · optional / Zeca off liga e desliga o Zeca (como Settings → Flock \u0026amp; Zeca → Zeca), Zeca\u0026rsquo;s look abre a página dele nas Configurações, Open terminal traz o terminal da sessão da frente e Back to the island traz a ilha.\nCtrl+K, no Nest ou na ilha aberta (quando ela tem o teclado: aberta com Ctrl+Alt+Space, ou no chat dela), abre a paleta: digite para pular para uma sessão, para começar /task, /delegate, /continue ou /remember no chat (com o Zeca ligado), ou para abrir uma aba. Ela nunca responde um card: uma sessão que espera por você só leva até o card dela.\nFlock # O bando de ponta a ponta da janela, três vezes maior, cada ave sobre um card com o projeto, o estado e o agente da sessão, e ao lado do título quantas estão fora numa saída pela web e quantas estão no fio. Um clique numa ave ou num card (ou ↑ ↓) põe aquela sessão na frente. Um clique direito (ou a tecla de menu, ou Shift+F10) abre as ações rápidas dela, como na ilha: Open terminal, Open folder, Activity, View the last diff, Keep in front (ou Let the flock choose), e silenciar, fixar ou esconder o projeto dela. Enquanto um card espera, só a Activity e o diff daquela sessão podem aparecer. Embaixo, Session details: Needs you deixa só as sessões que esperam por você, e Find a session… lê projetos, repositórios, branches, agentes e o que cada uma faz agora.\nA sessão da frente tem o card dela à esquerda: o estado, o que está fazendo e, numa que espera, o que ela pede (o comando, com Copy, e 1 of 2 quando outras esperam). Uma que trabalha mostra no topo os passos até agora, os subagentes e o custo, o passo que acabou e o que está em andamento (o +N −M de uma edição terminada a abre em Changes) e, quando ela fica quieta, Snooze, Keep going e Dismiss, como na ilha. Uma que terminou ou falhou mostra a última resposta ou o erro. Embaixo do card, o que as edições guardadas mudaram (dos últimos passos dela). À direita, as Changes (o diff de cada edição terminada, escolhida na lista; Focus diff dá ao diff a largura toda), a Activity (os últimos passos, cada um na hora em que começou), o Context (worktree, repositório, branch, pasta, agente, editor, estado e custo) e, com o Zeca ligado, Zeca: Ask Zeca abre o Chat com a pergunta pronta. No Full, o uso dos seus planos fica embaixo, âmbar a partir de 70% e vermelho a partir de 90%.\nUma sessão que espera por você é respondida no card dela, como na ilha (Aprovar pela ilha): Deny, Allow e Always allow para uma permissão (Ctrl+Alt+Y e Ctrl+Alt+N também, enquanto o Nest tem o foco), as escolhas para uma pergunta. Uma sem card aqui (ela pergunta no terminal dela) diz isso. Open terminal aparece onde o Vults consegue trazer o terminal dela para a frente (A ilha).\nTasks # As suas tarefas, sob o roost de cada uma (as sem roost por último): cada uma com o objetivo, os critérios, o dono, o status e o custo, por que o roteador escolheu o agente dela, as rodadas de revisão como marcas (até três, a última na cor do veredito), os botões que a iniciam, revisam ou passam adiante, e o gasto de hoje frente ao seu orçamento diário (definido em Activity → Cost). New task guarda uma sem o chat, que é como você cria uma com o Zeca desligado.\nChat # A conversa da ilha com o Zeca, larga, com respostas em Markdown completo (um link mostra o endereço e nunca é seguido); uma mensagem, New ou outro motor em qualquer um aparece nos dois. Os cards são respondidos aqui também, com Deny, Allow e Always in this chat, como na ilha. A barra de título traz o título da conversa, a pílula do motor (como na ilha: o motor na cor dele e o modelo; o menu dela traz os motores, os modelos e o esforço), a pasta e dois botões de painel. O campo de texto tem um clipe: os arquivos que você escolhe vão para este chat, como soltar na ilha. Numa janela larga ou no Full, o da esquerda mostra Recent: as suas 30 conversas mais novas, a atual marcada, e + New conversation (os dois esperam enquanto o Zeca responde); um clique continua uma delas. O da direita abre Memory, o que o Zeca lembra, ao lado da conversa: o que espera o seu sim, os arquivos e o histórico deles (A memória do Zeca). Antes de qualquer mensagem, o compositor espera no meio com algumas perguntas para começar. Sem o Zeca não há aba Chat.\nActivity # O que este computador guarda, só lido aqui:\nWeek: os quatro números da semana (tempo com os seus agentes, turnos, linhas alteradas, as suas respostas), uma barra por dia (um clique mostra aquele dia), Save as image… com ou sem os nomes dos projetos, e a grade do ano, com os interruptores do histórico (Atividade). By project: o tempo de cada projeto nesta semana em barras (os worktrees de um repositório somam sob ele, com quantos ele tem), uma busca por projeto, branch ou agente, e um card para cada repositório em que uma sessão trabalha: as pastas e os branches, as sessões (um clique põe uma na frente em Flock), os seus pull requests e checks (do card do GitHub; um pull request ou os checks do branch padrão abrem no GitHub), o que o Zeca lembra do projeto e quanto custaram as tarefas dele (A memória do Zeca). Preferences ↗ abre Settings → Projects. History: cada turno terminado dos seus agentes, só contagens. Cost: quanto os agentes custaram hoje e o orçamento diário que você define aqui, as janelas de uso dos seus planos e o que os agentes custaram nas últimas duas semanas, frente a esse orçamento, e por roost (Custo e orçamento diário). Traces: o trabalho do próprio Zeca, cada turno do chat com o modelo, os tokens e o custo, e abaixo dele cada card de ferramenta com quanto tempo esperou por uma resposta; guardado por 30 dias. Audit: quem respondeu cada card e como (você, o seu telefone, uma regra Always ou uma política que você aceitou); guardado por 90 dias e nunca alterado. Connections # Um chip para cada conector que você ligou, com quantas linhas ele tem; + abre Settings → Connectors. Embaixo, o conector escolhido: quando sincronizou pela última vez (ou por que a última consulta falhou), um filtro de repositório (All repos ou um deles) e ↻ Refresh para consultar de novo (no máximo uma vez por minuto). No GitHub, quatro abas com a contagem: Inbox (o que espera por você: revisões pedidas a você, seus pull requests falhando, devolvidos ou prontos para merge, um branch padrão falhando; quantos são novos), Pull requests, Actions (os checks dos seus branches padrão; em vermelho com quantos falham) e Releases (a mais recente de cada repositório). Uma linha escolhida aparece ao lado: o repositório, o branch, o tamanho (+120 −40 · 6 files), quem revisou ou foi chamado, quando mudou pela última vez, cada check um a um (uma barra enquanto rodam), um comando gh para olhar mais de perto com Copy (o Vults nunca o roda), Open in GitHub ↗ e as ações da linha, como na ilha (O card do GitHub); uma linha marcada com ✓ Seen fica esmaecida aqui. Add a connection lista cada conector do Vults que está desligado, com o que ele observa; Turn on in Settings… e Manage connections abrem Settings → Connectors, o único lugar que liga um conector (Conectores).\n","externalUrl":null,"permalink":"/docs/vults/guide/nest/","section":"Documentação","summary":"O Nest é a janela do próprio Vults, para quando a ilha fica pequena: o bando inteiro, as suas tarefas, o chat, o que aconteceu e as suas conexões. Abra pelo …","title":"O Nest · Vults","type":"docs"},{"content":"Um perfil de provedor define endpoint, modelo e token com um nome. O lazyagents escreve esses valores na configuração do agente para alternar Claude Code ou Codex entre API oficial, proxy e modelo local sem editar JSON/TOML manualmente. Funciona como cc-switch: só altera configuração, nunca executa um proxy. Agentes compatíveis e arquivos estão na referência.\nConceitos # Perfil: name, baseUrl, model, token, envKey e wireApi. Precisa definir pelo menos endpoint, modelo ou token. Nomes têm até 40 caracteres. Biblioteca: ~/.config/lazyagents/providers.json, com modo 0600, pois pode conter tokens. Aplicado: estado atual da configuração do agente, lido diretamente do arquivo. Uma configuração manual também aparece como provedor definido fora do lazyagents. A correspondência com a biblioteca usa endpoint e também modelo se dois perfis compartilharem o endpoint. Limpar: remove apenas o que o lazyagents gerencia e restaura o estado anterior. O resto fica intacto. Na TUI # A aba Providers é uma matriz perfil × agente: ● aplicado, ○ padrão do agente e – agente não instalado. O detalhe mostra endpoint, modelo, estado do token (token ✓, nunca o valor) e configuração aplicada por agente. Veja as teclas.\nCriar um perfil # n abre o formulário com nome, endpoint, modelo, token, variável de ambiente e API. tab troca de campo e enter salva. O token fica mascarado. e edita o perfil: deixar o token vazio mantém o salvo, que nunca é carregado no formulário. Renomear também renomeia na biblioteca.\nAplicar ou limpar por agente # Escolha a coluna com ←/→ e pressione space. A confirmação mostra arquivo, endpoint atual e novo (agent default → https://…). Repetir no perfil já aplicado limpa. a aplica em todos os agentes compatíveis e x limpa de todos. d remove da biblioteca, mas não desfaz configurações já aplicadas; use x ou limpe por agente.\nO que é escrito no Claude Code # Três chaves no bloco env de ~/.claude/settings.json:\n{ \u0026#34;theme\u0026#34;: \u0026#34;dark\u0026#34;, \u0026#34;env\u0026#34;: { \u0026#34;ANTHROPIC_AUTH_TOKEN\u0026#34;: \u0026#34;sk-…\u0026#34;, \u0026#34;ANTHROPIC_BASE_URL\u0026#34;: \u0026#34;https://proxy.example.com\u0026#34;, \u0026#34;ANTHROPIC_MODEL\u0026#34;: \u0026#34;my-model\u0026#34; } } Só essas chaves mudam. Outras variáveis e chaves mantêm valor e ordem; novas chaves ficam no fim de env. O lazyagents lembra quais escreveu e só remove as próprias:\nUm campo vazio não muda uma chave definida manualmente. Se foi escrita por um perfil anterior, é removida: trocar para perfil sem modelo retira o modelo antigo. Se substituir endpoint ou modelo manual, limpar restaura o valor anterior. Tokens manuais não são guardados pelo lazyagents; permanecem no backup de settings.json. Chaves editadas por você após a aplicação passam a ser suas e não são removidas. Se o lazyagents criou env e ele ficar vazio, limpar remove também o bloco. Aplicar e limpar devolve o arquivo original. O registro fica em ~/.local/share/lazyagents/claude-provider-state.json (0600) e contém apenas a impressão digital dos valores escritos, nunca o token. Sem registro (nenhuma aplicação ou perfil de v0.2 ou anterior), nenhuma chave é considerada gerenciada: x as preserva, sem apagar configurações manuais de proxy ou Bedrock. Remova manualmente resíduos de versões antigas; os backups preservam o arquivo anterior.\nAo escrever um token, a permissão do arquivo passa a 0600.\nO que é escrito no Codex # Codex mantém estado próprio em ~/.codex/config.toml, como confiança em [projects.*] e hashes de hooks. O lazyagents não interpreta nem reescreve o arquivo inteiro. Só edita blocos entre marcadores # lazyagents — managed block, preservando as outras linhas:\n# lazyagents — managed block start (do not edit by hand) model_provider = \u0026#34;lazyagents\u0026#34; model = \u0026#34;qwen3\u0026#34; # lazyagents: previous model = \u0026#34;gpt-5\u0026#34; # lazyagents — managed block end [projects.\u0026#34;/home/me/app\u0026#34;] trust_level = \u0026#34;trusted\u0026#34; # lazyagents — managed block start (do not edit by hand) [model_providers.lazyagents] name = \u0026#34;local\u0026#34; base_url = \u0026#34;http://localhost:11434/v1\u0026#34; env_key = \u0026#34;OLLAMA_KEY\u0026#34; wire_api = \u0026#34;responses\u0026#34; # lazyagents — managed block end Os comentários do exemplo são marcadores reais do programa e devem permanecer exatamente assim. Chaves globais ficam antes da primeira tabela; a tabela do provedor vai ao fim. Os valores anteriores de model e model_provider são guardados como comentários e restaurados ao limpar. Aplicar e limpar devolve o original.\nPara Codex, o perfil exige endpoint. wireApi só aceita responses, também padrão do Codex.\nPi # Pi guarda provedores personalizados em ~/.pi/agent/models.json. O lazyagents escreve o provedor lazyagents e o define como padrão em ~/.pi/agent/settings.json (defaultProvider e defaultModel). Os demais valores ficam intactos:\n{ \u0026#34;providers\u0026#34;: { \u0026#34;lazyagents\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;lazyagents: local\u0026#34;, \u0026#34;baseUrl\u0026#34;: \u0026#34;http://localhost:11434/v1\u0026#34;, \u0026#34;api\u0026#34;: \u0026#34;openai-completions\u0026#34;, \u0026#34;apiKey\u0026#34;: \u0026#34;$OLLAMA_KEY\u0026#34;, \u0026#34;models\u0026#34;: [{ \u0026#34;id\u0026#34;: \u0026#34;qwen3\u0026#34; }] } } } Pi só disponibiliza modelos declarados pelo provedor; o perfil precisa de endpoint e modelo. wireApi escolhe a API: vazio ou chat para chat compatível com OpenAI, responses para OpenAI Responses, anthropic para Anthropic Messages. Provedor e modelo padrão anteriores ficam nos dados do lazyagents e são restaurados ao limpar, salvo se você já tiver escolhido outro no Pi. Um models.json criado pelo perfil é removido na limpeza.\nCrush # crushrc é um script Bash com comandos como provider add e model large, executado de cima para baixo; linhas posteriores prevalecem. O lazyagents acrescenta um bloco ao fim de ~/.config/crush/crushrc (ou diretório de CRUSH_GLOBAL_CONFIG) sem alterar suas linhas:\n# lazyagents — managed block start: provider (do not edit by hand) provider add lazyagents --name \u0026#39;lazyagents: local\u0026#39; --type openai-compat --base-url \u0026#39;http://localhost:11434/v1\u0026#39; --api-key \u0026#34;$OLLAMA_KEY\u0026#34; model add \u0026#39;lazyagents/qwen3\u0026#39; --name \u0026#39;qwen3\u0026#39; model large \u0026#39;lazyagents/qwen3\u0026#39; # lazyagents — managed block end: provider Os comentários também são marcadores reais, não texto a traduzir na configuração. Como é o último, model large do bloco prevalece. Limpar remove o bloco e volta a usar suas linhas, sem restauração adicional. Valores usam aspas simples para impedir execução como Bash; variáveis usam \u0026quot;$VAR\u0026quot; para o Crush expandir. O perfil exige endpoint e modelo; wireApi aceita vazio, chat (compatível com OpenAI) ou anthropic. Um crushrc criado pelo lazyagents é removido junto com o bloco. Se houver crush.json na mesma pasta, Crush combina os dois, dá preferência ao crushrc e registra um aviso.\nTokens e \u0026ndash;env-key # Claude Code lê o token de settings.json, então ele é escrito ali. Codex só lê a variável indicada por env_key, nunca recebe token em config.toml. Pi aceita os dois: token em models.json com modo 0600, ou \u0026quot;apiKey\u0026quot;: \u0026quot;$VAR\u0026quot;, resolvido pelo próprio Pi. Pi esconde modelos sem credencial, então perfis sem chave, como Ollama local, recebem \u0026quot;apiKey\u0026quot;: \u0026quot;lazyagents-no-key\u0026quot;, conforme a convenção do Pi. No Codex, defina a variável no perfil (--env-key) e exporte no shell:\nexport OLLAMA_KEY=… # no perfil do seu shell Aplicar no Codex um perfil com token, mas sem envKey, falha com explicação em vez de criar configuração sem autenticação.\nPela CLI # # proxy para Claude Code; token pela entrada padrão, fora do histórico do shell pass show work/proxy-token | lazyagents provider add proxy \\ --base-url https://proxy.example.com --model my-model --token - # modelo local para Codex lazyagents provider add local --base-url http://localhost:11434/v1 \\ --model qwen3 --env-key OLLAMA_KEY --wire-api responses lazyagents provider apply proxy --agent claude-code lazyagents provider apply local --agent codex lazyagents provider list # tokens como •••• ou $VAR para envKey lazyagents provider list --json # sem tokens; usa \u0026#34;hasToken\u0026#34;: true lazyagents provider clear # todos os agentes instalados lazyagents provider rm proxy Sem --agent, apply e clear atuam em todos os agentes compatíveis. Falhas de um não impedem os outros; os erros são reunidos. Veja os comandos e flags.\nArquivos # Caminho Conteúdo ~/.config/lazyagents/providers.json biblioteca de perfis, 0600 ~/.local/share/lazyagents/claude-provider-state.json chaves env escritas no Claude Code, só impressões digitais, 0600 ~/.claude/settings.json bloco env do Claude Code ~/.codex/config.toml blocos gerenciados do Codex ~/.local/share/lazyagents/backups/ settings.json.\u0026lt;timestamp\u0026gt; e config.toml.\u0026lt;timestamp\u0026gt;, 20 mais recentes de cada Segurança # Toda aplicação e limpeza copia o arquivo do agente ao backup com as mesmas permissões e grava atomicamente por arquivo temporário e renomeação. Tokens ficam mascarados: token ✓ na TUI, •••• em provider list e campo omitido em JSON. Só provider list --reveal imprime o valor. Toda escrita pela TUI pede confirmação com o arquivo. doctor informa configuração aplicada por agente e aponta provedores em agentes não instalados ou arquivos ilegíveis. Limitações # Apenas Claude Code, Codex, Pi e Crush suportam provedores. Outros só aparecem em provider list quando implementarem o recurso. Strings multilinha (\u0026quot;\u0026quot;\u0026quot; ou ''') e arrays multilinha em TOML são preservados: linhas internas não são tratadas como chaves, tabelas ou marcadores. Strings/arrays não terminados, blocos quebrados ou aninhados e [model_providers.lazyagents] manual fora do bloco gerenciado são recusados, sem alterar o arquivo. Perfis aplicados são identificados por endpoint e modelo. Dois com os mesmos valores são indistinguíveis. ","externalUrl":null,"permalink":"/docs/lazyagents/guide/providers/","section":"Documentação","summary":"Um perfil de provedor define endpoint, modelo e token com um nome. O lazyagents escreve esses valores na configuração do agente para alternar Claude Code ou …","title":"Provedores · lazyagents","type":"docs"},{"content":"Uma tarefa é um objetivo com os critérios que dizem que ela está pronta, guardada neste computador, que o Vults pode passar para um agente trabalhando num clone só dele. A aba Tasks do Nest as lista (O Nest).\nGuardando uma tarefa # /task no chat guarda uma tarefa numa mensagem só, mandada para nenhum modelo: o objetivo na primeira linha, e depois uma linha para cada critério que diz que ela está pronta, começando com -:\n/task Fix the flaky login test - passes 20 runs in a row - no sleep added Numa linha só, done when: começa os critérios, separados por ;. O roost dela é o repositório da pasta da conversa. A aba Tasks do Nest lista as tarefas, as que faltam primeiro, com cada critério para marcar, quem trabalha nela (você, o Zeca ou um agente), em que pé está (To do, Doing, Blocked, Done, Dropped) e quanto custou depois que o Vults começar sessões para ela. New task cria uma lá também. Com o conector do GitHub ligado, uma tarefa num repositório do GitHub ganha Open an issue: no seu clique, o seu gh abre uma issue com o objetivo e os critérios, e a tarefa fica ligada a ela. Qualquer tarefa pode se ligar a uma issue que você já tem: #12 (no repositório do GitHub dela) ou o endereço da issue, e depois Link. As tarefas ficam no vults.sqlite, neste computador.\nDelegando # /delegate cria uma tarefa do mesmo jeito e a começa na hora no agente que o roteador escolhe, e o card da tarefa diz por quê. A regra do próprio projeto escolhe primeiro (/delegate default codex, ou claude, digitado numa conversa nesse projeto; /delegate default none a apaga); sem ela, o Claude Code. Se o plano desse agente passa de 85% e o do outro está, que se saiba, abaixo disso, a tarefa vai para o outro. Quando um projeto tem 10 tarefas terminadas de um tipo (uma correção, testes, docs, uma funcionalidade), o agente que mais terminou delas ali substitui a regra para esse tipo, mas os 85% continuam valendo. Uma tarefa conta para o agente dono dela quando é marcada como feita ou abandonada.\nComeçando um agente numa tarefa # Start with Claude Code trabalha numa tarefa que está num repositório. O Vults faz para a tarefa um clone próprio, num branch só dela (vults/task-12), dentro da pasta de dados do Vults: um clone --shared, que lê os objetos do seu repositório mas nunca os escreve. Ele começa o Claude Code ali com o objetivo e os critérios da tarefa, orientado a fazer commit nesse branch e nunca dar push. Ele roda no sandbox do Claude Code (bubblewrap): não começa sem ele, todo comando continua perguntando, e ele só escreve no clone dele e nas pastas temporárias, nunca no seu repositório, nos branches, nos hooks ou na config dele. Comandos que você tirou do sandbox nas suas próprias configurações do Claude Code continuam rodando fora dele, cada um perguntando antes. Ele lê as suas próprias configurações, então aparece no bando como qualquer sessão e as permissões dele são cards da ilha, respondidos por você, pelas suas regras ou pelas suas políticas. Duas tarefas rodam lado a lado sem mexer nos arquivos uma da outra. Quando o turno acaba, o Vults traz o branch da tarefa, e só ele, para o seu repositório, sem rodar nada do clone; What it said last embaixo da tarefa guarda o fim da resposta, e Go on continua a mesma sessão. Start fresh passa a tarefa para uma sessão nova, quando a antiga já cresceu demais: a sessão antiga escreve um pacote de contexto (Objective, Constraints, Done, In progress, Decisions, Files, Failures, Next), o Vults põe o que sabe com certeza (o objetivo, quais critérios estão marcados, os arquivos mudados no branch), e a sessão nova começa só desse pacote. O pacote fica embaixo da tarefa como Handoff notes; se a sessão antiga não escreve nenhum, nada é passado adiante e ela mantém a sessão. Stop pede para o turno parar, espera e então o encerra; só uma sessão que o Vults começou pode ser parada, e uma tarefa rodando não pode ser apagada. O que ela custou entra na tarefa. Remove its folder traz o branch de volta e remove o clone; trabalho que nunca teve commit nele vai junto, então pergunta duas vezes.\nCodex # Start with Codex faz o mesmo com o Codex, no sandbox dele (workspace-write: o clone dele e as pastas temporárias). O Codex pede aprovações pelo próprio canal: o Vults transforma cada uma no card da ilha que o hook dele mandaria (o comando inteiro, ou os arquivos e a contagem de linhas de uma edição; uma chamada que ele não consegue nomear inteira é um não), então as suas regras, políticas e o telefone respondem do mesmo jeito, e uma execução parada tira o card que esperava. Numa tarefa com sessão, Hand off to Codex (ou Hand off to Claude Code) é o Start fresh no outro agente: a sessão escreve o pacote, e o outro começa dele.\nOutros agentes # Start with another agent… lista os agentes instalados aqui que falam o Agent Client Protocol: OpenCode, Qwen Code, Copilot CLI e Kimi Code. Um deles trabalha no clone da tarefa do mesmo jeito, logado com a própria conta. O Vults não oferece arquivos nem terminal próprios: ele usa as ferramentas dele e pede antes de cada uma que escreve, roda ou busca algo, e cada pedido é um card da ilha, respondido só daquela vez, nunca com o \u0026ldquo;sempre\u0026rdquo; do próprio agente. Uma mudança num arquivo fora do clone, ou no .git dele, um comando rodado em outro lugar, uma movimentação ou uma exclusão é um não sem card, assim como um arquivo alcançado por um link que aponta para fora do clone. O OpenCode roda toda ferramenta sem perguntar por padrão, e o Qwen Code e o Kimi Code podem rodar, pelas suas próprias configurações: o Vults inicia cada um com uma configuração, só para aquele processo ou sessão, que o faz perguntar (nunca escrita na config dele), e uma escrita ou um comando que ainda assim roda sem perguntar para o turno. Os hooks deles não perguntam nada nessas sessões, então uma chamada nunca mostra dois cards. Stop, Go on, Start fresh e Review funcionam como com o Codex; a revisão é do Codex. Testado com o OpenCode, e com o Kimi Code 2.1.1 contra um modelo de mentira; o Qwen Code e o Copilot CLI seguem o mesmo protocolo, mas ainda não foram testados com uma conta real.\nRevisão # Review with Codex (ou with Claude Code) faz o outro agente revisar o trabalho de uma tarefa, no clone dela, como um revisor que não escreveu nada daquilo, num sandbox em que não escreve nada: ele roda os testes, lê o diff contra onde o branch começou, confere cada critério e lista o que está errado. O Codex usa o revisor próprio dele. Quando a revisão pede mudanças, os achados vão para a sessão da tarefa, que os corrige e faz commit, e a rodada seguinte revisa de novo, até três rodadas. Uma aprovação encerra; uma revisão sem veredito, ou uma terceira rodada que ainda pede mudanças, fica para você ler. A última revisão fica embaixo da tarefa, e quem marca a tarefa como feita continua sendo você.\nCusto e um orçamento diário # O Vults conta o que os agentes dizem que custaram: cada turno de uma sessão que ele iniciou para uma tarefa ou um /continue (os dólares do Claude Code; o Codex informa só tokens, então as tarefas dele mostram os tokens) e cada sessão do Claude Code que ele acompanha, pela status line, contada a partir da primeira vez que o Vults a vê (o que ela custou antes fica fora do dia). Nada é estimado por tabela de preços. O chat do próprio Zeca, os resumos e o sono não entram nessa conta, e o orçamento não os para. Numa assinatura, os dólares são o que os tokens custariam a preços de API, que o seu plano não cobra; o Vults diz isso quando consegue saber (um plano que informa as janelas de uso). Cada tarefa mostra custo e tokens, cada roost em Activity → By project do Nest o custo de hoje e o total, e o topo da aba Tasks o de hoje.\nActivity → Cost, no Nest, define um orçamento diário em dólares. Em 80% uma notificação avisa; quando ele acaba, outra avisa, e o Vults não inicia nenhuma sessão nova até o dia seguinte: nada de Start, handoff, review, /delegate ou /continue. É só isso. Ele nunca para uma sessão que está rodando, e nunca bloqueia nem atrasa um agente que você mesmo iniciou. Os custos ficam em vults.sqlite, neste computador; o Clear history não os apaga.\n","externalUrl":null,"permalink":"/docs/vults/guide/tasks/","section":"Documentação","summary":"Uma tarefa é um objetivo com os critérios que dizem que ela está pronta, guardada neste computador, que o Vults pode passar para um agente trabalhando num clone …","title":"Tarefas · Vults","type":"docs"},{"content":"Abra a aba Chat, escolha Chat… no ícone da bandeja ou solte um arquivo na ilha. O Zeca fica no começo da conversa (pequeno no topo do chat da ilha, grande no do Nest): ele pensa enquanto a resposta vem, inclina a cabeça quando pergunta algo a você e engole os arquivos que você dá a ele. Escolha Claude ou Codex no topo (ou o provedor de API que você configurou, veja abaixo); na ilha é um botão só, ● Claude Code · Default model ▾, cujo menu traz o motor, o modelo e o esforço. Os motores vêm em dois grupos, Your setup (os CLIs do Claude Code e do Codex, cada um Signed in, Installed ou Not installed: o Vults só olha se o CLI e o arquivo de login dele estão lá, nunca os lê) e Vults harness (a API, Ready com uma chave ou um modelo local), com Engines in Settings › embaixo. New (+ na ilha) começa uma conversa nova, e trocar de provedor também; a anterior fica na lista (veja Conversas). Esc fecha o chat de qualquer ponto dele; a conversa continua lá quando você volta.\nO chat é do Zeca: com ele desligado (Settings → Flock \u0026amp; Zeca → Zeca) não há chat nem microfone, o atalho de fala não faz nada e os arquivos soltos na ilha não são aceitos. Veja Sem o Zeca. No KDE Plasma, o desktop continua reservando Ctrl+Alt+V para o app enquanto isso; para usar a tecla em outra coisa, limpe Hold to speak to the chat em Configurações do Sistema → Atalhos; a tecla de fala então fica desligada até você dar uma tecla a ela de novo ali.\nOnde ele trabalha # Antes da primeira mensagem, a pasta (in vults ▾, no topo no Nest, embaixo do campo na ilha) diz onde a conversa vai trabalhar: a pasta da sessão em primeiro plano, a menos que você escolha outra das sessões no fio, ou uma pasta vazia só dela. Depois que a conversa começa, ela fica lá até New.\nModelo e esforço # Ao lado da pasta (na ilha, no botão do topo), Default model ▾ escolhe o modelo e o quanto ele pensa, para o Claude e para o Codex. O Claude oferece Opus, Sonnet e Haiku (os nomes do Claude Code para o mais recente de cada um); o Codex lista os modelos que o seu próprio codex oferece, perguntados na primeira vez que você abre o seletor com o Codex. O esforço vai de Low a Max, só com os que o modelo escolhido aceita. Default deixa cada um para a CLI, como as suas configurações definem.\nA escolha é lembrada por pasta e por motor: uma conversa nova naquela pasta começa com ela. Como a pasta, ela fica fixa quando a conversa começa, então uma resposta nunca troca de modelo no meio; New começa outra. O modelo do chat por API é escolhido em Settings → Chat \u0026amp; voice.\nO Nest # A seta no topo do chat da ilha abre o Nest, a janela do próprio Vults. A aba Chat dele é a mesma conversa, larga, com respostas em Markdown completo; os cards dela são respondidos ali também. Memory, ao lado, mostra o que o Zeca lembra.\nContinuando uma sessão # /continue \u0026lt;palavras\u0026gt; entrega as suas palavras a uma sessão do Claude Code ou do Codex na pasta da conversa que parou nos últimos dez minutos, como o próximo turno dela: o Vults a retoma aqui, com as configurações dela, no sandbox dela, e ela volta a aparecer no bando com os cards dela. Só uma sessão cujo processo acabou: uma que ainda está aberta no terminal é recusada, então você fala com ela lá. Uma por vez; /continue stop encerra. Como o /task, não vai para nenhum modelo do Zeca.\nTarefas # /task guarda uma tarefa e /delegate começa uma num agente, as duas mandadas para nenhum modelo: veja Tarefas.\nConversas # Toda conversa é salva neste computador enquanto acontece, e o botão de lista no topo do chat mostra todas, a usada por último primeiro, com o motor e a pasta de cada uma. Clique numa para continuar de onde parou, mesmo depois de reiniciar: ela mantém o motor, a pasta, o modelo e o esforço, e a CLI dela retoma a própria sessão (a sessão do Claude Code, a thread do Codex; o chat por API reenvia o que foi dito, com cada arquivo mandado guardado só como um rótulo: um arquivo de texto pelo nome, um documento pelo título, uma imagem como \u0026ldquo;uma imagem\u0026rdquo;, nunca pelo conteúdo). O lápis renomeia; o xis apaga depois de um segundo clique, com tudo o que foi dito nela.\nO que é salvo é o que o chat mostra: suas mensagens e os nomes dos arquivos que você mandou, as respostas do Zeca, erros e paradas; nunca a resposta a um card (o log de auditoria guarda essas) e nunca uma regra Always in this chat, então uma conversa aberta de novo pergunta como uma nova perguntaria. As 200 mais recentes ficam guardadas, no mesmo vults.sqlite local do histórico de atividade; Settings → Activity → Clear history apaga todas. Uma conversa cuja pasta sumiu não pode ser aberta de novo.\nO que o Zeca sabe # Cada mensagem leva, antes das suas palavras, um bloco \u0026lt;today\u0026gt; com a data e a hora deste computador e um bloco \u0026lt;flock\u0026gt; com uma linha para cada sessão que a ilha mostra (até 12, depois \u0026ldquo;and N more\u0026rdquo;): o agente, o projeto, o estado e o passo em que está (segredos redigidos), nunca o comando sobre o qual um card pergunta. Isso vai para quem roda o chat, o provedor da CLI ou o da API, junto com a mensagem.\nCom a memória ligada, o que o Zeca lembra e o que ele recupera também entram: veja A memória do Zeca.\nEscrevendo e lendo # Enter envia, Shift+Enter começa uma nova linha. Você pode digitar a próxima mensagem enquanto uma resposta chega, e enviá-la quando a resposta terminar. ↑ com o campo vazio traz de volta a sua última mensagem, para mudá-la ou enviá-la de novo. Enquanto o Zeca responde, o botão de enviar vira Stop: ele encerra o turno ali, e tudo o que o turno estava esperando vira um não. A resposta chega à medida que é escrita. Role para cima para ler e ela fica onde você está, com um botão ↓ new text para voltar ao fim. Copy embaixo da última resposta copia ela inteira, no Markdown em que foi escrita; uma resposta mais antiga mostra o botão quando o ponteiro passa sobre ela. Um bloco de código tem o seu próprio Copy. Um turno que falha diz por quê, com Try again: ele envia as mesmas palavras e arquivos mais uma vez. Enquanto um turno roda, Thinking… avisa, com os segundos depois que ele passa de três. No Nest a conversa é lida em uma coluna da largura do campo de texto, por mais larga que seja a janela. Cada resposta vem assinada pelo Zeca e pelo motor que a escreveu, e um bloco de código diz a sua linguagem. Falando em vez de digitar # Ligue uma vez em Settings → Chat \u0026amp; voice → Voice: baixe um modelo (Base tem 60 MB e é rápido; Small e Large v3 Turbo entendem melhor sotaques e nomes). Um microfone aparece no campo (ao lado do botão de enviar no Nest, ao lado do clipe na ilha).\nClique no microfone e fale. Ele para sozinho depois de cerca de 1,5 s de silêncio após as suas palavras, ou quando você clica de novo; as palavras caem no campo de entrada para você ler e corrigir, e aí Enter as envia. O silêncio antes de você começar nunca o interrompe; se uma pausa o interromper, clique de novo para continuar. Ou segure Ctrl+Alt+V de qualquer lugar: o chat abre e o Zeca escuta enquanto você segura (pausas nunca o interrompem); soltar transforma tudo em texto. A tecla pode ser trocada em Configurações do Sistema → Atalhos. Esc enquanto ele escuta descarta a gravação. Uma gravação para sozinha depois de um minuto. Language you speak (idioma que você fala) segue o do seu sistema; escolha outro, ou Detect it each time. Um idioma fixo é muito mais confiável em frases curtas. O Base é fraco fora do inglês: em português use o Small, ou o Large v3 Turbo com uma GPU. Só a sua fala vai para o whisper: um pequeno detector de fala (Silero VAD, menos de 1 MB) corta o silêncio em volta dela, para o whisper não inventar palavras ali. Ele é baixado sozinho enquanto a voz está ligada e ele falta; até lá, o microfone só para com um clique. Com uma GPU (Vulkan: AMD, Intel ou NVIDIA) uma frase leva uma fração de segundo e uma prévia esmaecida das suas palavras aparece enquanto você fala; no processador, escolha o Base.\nTudo acontece neste computador: o whisper.cpp transcreve o áudio na memória, e o áudio nunca é salvo nem enviado para lugar nenhum. Os modelos e o detector são conferidos contra o SHA-256 conhecido deles antes de serem usados.\nO que ele pode fazer # Ele lê arquivos daquela pasta livremente. Todo comando e toda edição aparecem na conversa como um card igual ao da própria ilha: o que o Zeca pretende fazer, o comando inteiro ou o arquivo com suas linhas +/−, e Deny e Allow lado a lado com suas teclas (Ctrl+Alt+N / Ctrl+Alt+Y respondem de qualquer lugar). Nada roda até você responder, e um card que ninguém responde é um não. Depois que a conversa lê conteúdo de fora (uma página ou busca na web, um comando que rodou curl, git pull ou gh, uma ferramenta MCP que não seja as do vults-zeca, o servidor que o Vults entrega ao Claude Code do chat), todo card seguinte avisa em vermelho: uma página pode trazer palavras escritas para conduzir o Zeca, então leia com cuidado o que o card pede. Só conta uma chamada que rodou (um fetch negado não leu nada), compilar e testar nunca contam, e o aviso vale pelo resto daquela conversa, também quando ela é aberta de novo pela lista. Uma conversa nova começa limpa. Always in this chat permite aquela chamada exata de novo (o comando e a entrada inteiros, não o texto do card) sem card, até a conversa acabar: New, outro motor, ou o Zeca desligado. Um card que não consegue nomear a chamada inteira não tem esse botão. Toda vez que a regra responde, o chat mostra Allowed for this conversation e o log de auditoria guarda. As regras nunca são salvas. Quem responde os cards do Zeca # Settings → Chat \u0026amp; voice → Who answers Zeca\u0026rsquo;s cards escolhe, para toda conversa, na hora:\nAsks first (o padrão): um card para cada chamada, como acima. Your policies: as políticas que você aceitou respondem as chamadas do chat como respondem as do Claude Code na ilha. Um deny nega, um allow permite (chamadas do Claude Code, dentro da pasta da conversa), o resto pergunta. Full access: tudo roda sem card, mas um comando destrutivo (rm, um push forçado) ainda pergunta, o que uma política nega é negado e o que uma política manda perguntar ainda pergunta. Depois que a conversa lê conteúdo de fora (uma página web, um fetch, uma ferramenta MCP), os cards dela voltam a perguntar até ela acabar: as palavras de uma página podem estar conduzindo a conversa. Adicione linhas deny a uma política para o que nunca deve rodar. O chat diz cada resposta dada assim (Allowed by your policy, Denied by your policy, Ran with full access), e o log de auditoria guarda. O chip dele, ao lado do modelo (vermelho com acesso total), mostra a escolha; dali você só pode devolver acesso. Mais acesso é dado em Settings.\nArquivos # Clique no clipe do chat para escolher arquivos, ou arraste um sobre a ilha e solte na área onde o Zeca espera de bico aberto. Nos dois casos ele engole o arquivo, um urubu o leva até o outro lado enquanto uma barra enche, e ele entra na sua próxima mensagem: um chip sobre o campo (× o retira). Clique no campo para escrever sobre ele. Você pode enviá-lo sem texto para perguntar o que ele é. Imagens, PDFs, código e texto funcionam melhor. Os arquivos são copiados para a caixa de entrada do app (até 20 MB cada) e apagados depois de uma semana; uma pasta, ou um arquivo com mais de 20 MB, é recusado com uma linha dizendo por quê.\nSua assinatura, seu login # O chat roda o comando claude ou codex em que você já fez login, então ele usa a sua própria assinatura e o Vults nunca lê suas credenciais. Os dois transmitem a resposta à medida que ela é escrita: o Claude por claude -p, o Codex por um único codex app-server de longa duração.\nSua configuração # O chat lê a sua própria configuração do Claude Code e do Codex, como no seu terminal: seu CLAUDE.md, skills, servidores MCP, hooks e regras de permissão (um ícone de pessoa no topo avisa). As configurações e os servidores do .mcp.json de um projeto só entram numa pasta em que você já confiou no Claude Code; o CLAUDE.md dele é lido de qualquer jeito. As suas regras de permissão valem em qualquer pasta. Os cards continuam perguntando o que suas regras não liberam, seja qual for o defaultMode das suas configurações, e os seus hooks nunca fazem o chat aparecer como uma sessão de agente.\nDesligue em Settings → Chat \u0026amp; voice → Your Claude Code and Codex setup, e o Claude não lê nada disso; o Codex então só deixa de fora os seus hooks. O interruptor vale para a próxima conversa. Bom saber:\nclaude -p pula a pergunta de confiança, então um repositório que você acabou de clonar não consegue trazer regras ou hooks próprios. Uma regra de permissão como Bash(npm test:*) roda o script de teste de um projeto clonado sem card. Com o interruptor desligado, o Claude não recebe servidores MCP além do próprio Vults, e nenhuma regra salva pula um card. O config.toml do Codex ainda traz os servidores MCP dele, e o AGENTS.md dele ainda é lido. Uma conversa já em andamento mantém o que leu. Veja Segurança para o resto.\nSem uma CLI: uma chave de API, ou um modelo local # O chat também pode usar a API de um provedor com a sua própria chave, ou um modelo rodando na sua máquina. Em Settings → Chat \u0026amp; voice, escolha o Provider, cole a chave dele e escolha um Model; o nome do provedor então aparece no topo do chat, ao lado de Claude e Codex.\nProvedor Chave Observações Anthropic sk-ant-… Claude Opus 5.5 até você escolher outro modelo OpenAI sk-… Google Gemini AIza… (Google AI Studio) OpenRouter sk-or-… Uma chave para centenas de modelos Groq, DeepSeek, Mistral, xAI a de cada um Ollama nenhuma Precisa estar rodando em 127.0.0.1:11434 LM Studio nenhuma O servidor dele precisa estar ligado, em 127.0.0.1:1234 Os modelos são listados ao vivo pelo provedor. Cada provedor guarda o modelo que você escolheu para ele. Uma chave fica no chaveiro do sistema, nunca é mostrada de novo, e só é enviada para o próprio provedor; Remove a apaga. O uso é cobrado na sua conta com aquele provedor. Este chat não pode rodar comandos, editar arquivos nem olhar seu projeto. Ele lê o que você digita e os arquivos que você solta (imagens, texto até 512 KB, e PDFs com a Anthropic), e chama ferramentas quando uma pergunta precisa: as do bando (suas sessões, os cards esperando, o uso dos seus planos, seu card do GitHub), recall e memory_propose com a memória ligada, e as da web com a web ligada. O que uma ferramenta devolve vai para o provedor (comandos com os segredos redigidos); ele nunca responde um card. Modelos de raciocínio que pensam em voz alta só mostram a resposta: a parte \u0026lt;think\u0026gt; fica oculta e nunca é enviada de volta. Uma conversa mantém o provedor e o modelo com que começou. Com a Anthropic, um pedido que o Claude recusa por motivos de segurança é tentado de novo com outro modelo Claude na mesma chamada; se esse também recusar, o balão avisa. A web # Com Settings → Chat \u0026amp; voice → Web for Zeca ligado, o chat por API pode buscar na web e ler páginas. As buscas vão para o Brave Search ou o Tavily com a sua própria chave (guardada no chaveiro), ou para um SearXNG que você roda. Desligado, o modelo nunca recebe nenhum dos dois.\nUma página não é confiável, então o modelo do chat nunca a vê: uma chamada separada ao seu provedor de API, sem ferramentas e avisada de que a página é dado, a lê para a pergunta, e só essa resposta volta. Os títulos e trechos de uma busca chegam ao modelo, marcados como não confiáveis. Páginas só são lidas de endereços públicos. Cada busca e cada página é uma requisição em seu nome com um limite diário (Segurança), e a conversa então conta como tendo lido de fora.\n","externalUrl":null,"permalink":"/docs/vults/guide/chat/","section":"Documentação","summary":"Abra a aba Chat, escolha Chat… no ícone da bandeja ou solte um arquivo na ilha. O Zeca fica no começo da conversa (pequeno no topo do chat da ilha, grande no do …","title":"Conversando com o Zeca · Vults","type":"docs"},{"content":"Um hook é um comando de shell executado por um agente quando algo acontece: começa uma sessão, uma ferramenta está prestes a executar ou termina um turno. O lazyagents mantém hooks numa biblioteca e os instala nos agentes compatíveis. Você pode escrevê-los ou importar de repositórios com hooks de plugins do Claude Code. Agentes e eventos disponíveis estão na referência.\nConceitos # Biblioteca: ~/.local/share/lazyagents/hooks/, um JSON \u0026lt;name\u0026gt;.json por hook, editável manualmente. Entrada: contém nome e um ou mais comandos, cada um com event, matcher opcional e command. Um pacote importado pode reunir muitos comandos e eventos e ser instalado como unidade. Comandos individuais ainda podem ser desativados. Identidade: um hook instalado é reconhecido pela combinação de evento, filtro e comando. O lazyagents não adiciona marcador no arquivo do agente. Hooks sem correspondência na biblioteca são externos: apenas contados, nunca editados ou removidos. Alcance: cada comando é instalado apenas nos agentes que emitem seu evento. Em pacotes com vários eventos, cada agente recebe os comandos compatíveis. Exemplo de entrada na biblioteca:\n{ \u0026#34;name\u0026#34;: \u0026#34;notify\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;notificação na área de trabalho\u0026#34;, \u0026#34;hooks\u0026#34;: [ { \u0026#34;event\u0026#34;: \u0026#34;Stop\u0026#34;, \u0026#34;command\u0026#34;: \u0026#34;notify-send \\\u0026#34;Claude terminou\\\u0026#34;\u0026#34; } ] } Outros campos: matcher filtra, por exemplo, uma ferramenta em PreToolUse; timeout define segundos; async: true executa sem bloquear o turno; off lista índices dos comandos desativados. Entradas importadas incluem source e files, com origem e pasta de scripts. O nome deve coincidir com o arquivo e usar letras, dígitos, - ou _, até 40 caracteres.\nNa TUI # A aba Hooks é uma matriz hook × agente: ● instalado, ◐ parcial (faltam comandos), ○ não instalado, – agente sem nenhum dos eventos. As teclas estão na referência.\nInstalar ou desinstalar por agente # Escolha a coluna com ←/→ e pressione space. A confirmação mostra evento → comando, arquivo a reescrever e avisos do agente. Pressionar novamente desinstala. a instala em todos os agentes compatíveis e x desinstala de todos. d apaga da biblioteca, mas mantém os hooks já instalados: desinstale primeiro para removê-los de todos os lugares. Scripts importados são apagados junto com o hook, salvo se outra entrada ainda os usar.\nAlternar comandos individuais de um pacote # enter abre a lista da entrada selecionada. space ou enter ativa/desativa um comando; esc volta. Se instalada em agentes, a mudança é aplicada neles após confirmação. Caso contrário, só a biblioteca muda.\nLer e editar comandos e scripts # v abre um leitor em tela cheia com o comando e os scripts referenciados (.sh, .py, .js e similares). ←/→ alterna e e edita em $EDITOR. Antes de salvar, a confirmação compara o texto antigo e novo. Salvar um comando atualiza todos os agentes onde está instalado e desfaz se algum falhar. Salvar um script faz backup e recusa se o arquivo mudou no disco desde a abertura.\nImportar hooks de um repositório # Plugins do Claude Code declaram hooks em \u0026lt;plugin\u0026gt;/hooks/hooks.json. Na instalação com i em Skills, aparecem junto com as skills, inicialmente desmarcados, porque executam comandos de terceiros a cada evento.\nNa importação:\nPastas referenciadas por ${CLAUDE_PLUGIN_ROOT} são copiadas com a estrutura original, junto com hooks/. Outras pastas do plugin não são copiadas. Cada comando recebe export CLAUDE_PLUGIN_ROOT='\u0026lt;cópia\u0026gt;'; antes do original, e ${CLAUDE_PLUGIN_ROOT} vira $CLAUDE_PLUGIN_ROOT, pois Claude Code recusa a forma com chaves fora dos próprios plugins. As aspas originais são mantidas. Uma entrada reúne todos os comandos de cada plugin. A importação é integral ou não acontece; nomes já existentes são recusados. Comandos importados usam o protocolo do Claude Code. Outros agentes podem fornecer dados diferentes pela entrada padrão; a confirmação lembra a origem do hook.\nCodex: ativação de hooks e confiança # Codex guarda hooks em ~/.codex/hooks.json e mais dois itens em config.toml: [features] hooks = true e trusted_hash por comando. O hash registra seu consentimento. O lazyagents instala o hook, mas nunca escreve esses itens, pois isso aprovaria execução em seu nome. Em vez disso, avisa na confirmação, em hooks list e doctor:\nHooks estão desligados no Codex: defina hooks = true em [features] de config.toml. Um novo hook só executa depois de você confirmar a confiança no próprio Codex. Claude Code não tem essa etapa: o que estiver em settings.json executa.\nCrush # Crush executa apenas PreToolUse e lê respostas no formato do Claude Code. O lazyagents cria linhas hook add num bloco ao fim de ~/.config/crush/crushrc, com nome lazyagents-\u0026lt;id\u0026gt; por hook, permitindo removê-los separadamente. O resto permanece intacto. hooks list também mostra hooks de crush.json, que nunca é editado; a desinstalação informa essa limitação. Hooks definidos fora do bloco no crushrc são Bash que só a execução revelaria, então não são listados. Comandos ou filtros multilinha não podem ser instalados: coloque-os num script e instale o script.\nPela CLI # lazyagents hooks add notify --event Stop --command \u0026#39;notify-send \u0026#34;Claude terminou\u0026#34;\u0026#39; --desc \u0026#34;notificação na área de trabalho\u0026#34; lazyagents hooks add guard --event PreToolUse --matcher Bash --command ~/bin/check-bash.sh --timeout 10 lazyagents hooks enable notify # todos os agentes que emitem Stop lazyagents hooks enable guard --agent codex lazyagents hooks list # instalações e contagem de hooks externos lazyagents hooks list --json lazyagents hooks disable guard lazyagents hooks rm guard lazyagents install owner/repo --hooks # importar também hooks de plugins hooks add avisa se o executável estiver ausente do PATH ou sem permissão, evitando falha silenciosa quando o evento ocorrer. Comandos e flags estão na referência. A importação faz parte de install.\nArquivos # Caminho Conteúdo ~/.local/share/lazyagents/hooks/\u0026lt;name\u0026gt;.json entradas da biblioteca, modo 0600 ~/.local/share/lazyagents/hooks/\u0026lt;plugin\u0026gt;/ scripts de um plugin importado ~/.claude/settings.json chave hooks do Claude Code ~/.codex/hooks.json hooks do Codex ~/.local/share/lazyagents/backups/ cópia antes de cada escrita; 20 mais recentes por arquivo Segurança # Toda instalação, remoção e edição faz backup do arquivo do agente e grava atomicamente. Grupos não gerenciados são preservados byte a byte, inclusive campos desconhecidos. Exceção: se um grupo misturar comandos seus e da biblioteca, a desinstalação reescreve o grupo sem o comando da biblioteca. Escritas na TUI exigem confirmação mostrando comando e arquivo. Apagar um hook só remove scripts dentro da biblioteca de hooks, nunca arquivos externos. doctor informa executáveis ausentes, arquivos inválidos ou nomes inconsistentes, contagens por agente (gerenciados, externos e parciais) e avisos específicos. Limitações # Apenas Claude Code, Codex e Crush têm hooks; Codex emite menos eventos e Crush só PreToolUse. Veja a tabela de eventos. Apenas hooks command são gerenciados; outros tipos permanecem intactos. Scripts importados podem exigir shell POSIX ou ferramentas do autor. doctor verifica o executável, não todas as dependências do script. ","externalUrl":null,"permalink":"/docs/lazyagents/guide/hooks/","section":"Documentação","summary":"Um hook é um comando de shell executado por um agente quando algo acontece: começa uma sessão, uma ferramenta está prestes a executar ou termina um turno. O …","title":"Hooks · lazyagents","type":"docs"},{"content":"O Zeca pode lembrar de você, dos seus projetos e do que os seus agentes fizeram. Essa memória fica desligada até você ligá-la, é guardada neste computador, e só você a escreve.\nLigando # Ligue em Settings → Chat \u0026amp; voice → Memory → Zeca\u0026rsquo;s memory. O app então mantém um diário no vults.sqlite local por 90 dias: o tempo, os passos e as mudanças de cada turno dos agentes, a resposta de cada card com o comando ou caminho, e as linhas do chat do Zeca, com os segredos redigidos antes de qualquer coisa ser escrita. Os outros interruptores da seção aparecem quando este está ligado.\nDesligada, nada da memória chega a um modelo (nenhum fato, nenhuma lembrança, nenhum diário): a Memory ao lado do Chat do Nest mostra só Zeca\u0026rsquo;s memory is off…, By project não mostra fatos da memória, e o /remember é recusado. Desligá-la para a escrita e mantém o que já foi escrito.\nO que o Zeca lembra é um repositório git de pequenos arquivos Markdown em ~/.local/share/vults/memory/, cada mudança um commit. Settings → Activity → Clear history apaga o diário e o que vem dele, mas não essa pasta (o que ele apaga): para apagar os fatos dele, apague-a.\nO que entra numa conversa # Quando uma conversa começa, a memória dele entra nela depois das instruções dele: quem você é, o que ele aprendeu, como falar com você, e a memória do projeto em que ela trabalha. Ela fica fixa a conversa toda; um fato adicionado nesse meio-tempo entra na próxima. Desligar a memória não a tira de uma conversa já em andamento; reaberta depois pela lista, ela começa sem os fatos dele.\nAntes de cada mensagem, o app procura no diário e nos resumos dos dias o que as suas palavras tratam, neste computador, e até três trechos entram na mensagem como o bloco \u0026lt;memories\u0026gt;, contexto e nunca instruções. O chat de hoje fica de fora, e também tudo o que uma conversa disse depois de ler conteúdo de fora. Os trechos vão para o provedor do chat junto com a sua mensagem. O chat por API também pode pedir mais com a ferramenta recall, e sugerir um fato com o memory_propose, que só escreve uma proposta.\nEscrevendo a memória dele # /remember \u0026lt;fato\u0026gt; no chat, com a memória ligada, guarda um fato no que o Zeca aprendeu; /remember project: \u0026lt;fato\u0026gt; no projeto em que a conversa está. /forget \u0026lt;palavras\u0026gt; remove o único fato que as contém (com vários, ele os lista). O que o Zeca propõe espera na Memory ao lado do Chat do Nest, com para onde vai (um projeto pelo nome e pela pasta) e a mudança como um diff: Remember guarda, Turn down descarta. A Memory também lista o que ele lembra, arquivo por arquivo com o quanto cada um está cheio, e o histórico: quem escreveu cada mudança (você, ou o Zeca com o seu sim) e Undo, que a desfaz numa mudança nova (recusado quando uma mudança depois mexeu no mesmo arquivo; nunca oferecido numa que o Vults não escreveu). Um fato nunca entra duas vezes: o /remember e toda proposta são recusados quando outro fato já diz isso, sem contar maiúsculas, espaços e o ponto final, e o mesmo fato decidido no último mês não é proposto de novo. Uma proposta passa pela verificação da memória (nada de caracteres escondidos, palavras que falam com um modelo ou formatos de chave).\nO que ele faz sozinho # Cada um é um interruptor em Settings → Chat \u0026amp; voice → Memory, desligado até você ligá-lo. O Haiku é o menor modelo do Claude Code, pelo seu claude e pela sua assinatura, sem ferramentas e sem nenhuma das suas configurações; cada chamada passa pelo portão de rede e pelo rastro local (Segurança).\nRecurso Interruptor O que lê Modelo Requisições por dia Um resumo de cada dia passado (no máximo 2.000 bytes) A summary of each day Um dia do diário, só os dias desde que você ligou Haiku 8 Até três fatos para lembrar, quando você começa ou abre outra conversa Suggest what to remember A conversa que você deixou, redigida, com pelo menos 2 mensagens suas e nenhum conteúdo de fora Haiku 20 Junções, e um resumo da volta mostrado como While you were away Let Zeca sleep on it O que ele lembra sobre você e entre projetos, e os resumos dos últimos 7 dias Haiku 4 Lembrar pelo sentido, não só pelas palavras Recall by meaning Cada resumo, e cada mensagem que você manda nomic-embed-text num Ollama em 127.0.0.1 nenhuma sai do computador O resumo roda numa passada de hora em hora: cada dia passado sem resumo, até três por passada (ele alcança o atraso depois de dias fora), três tentativas por dia enquanto o app roda. Os embeddings rodam nessa passada, para cada resumo sem um, e antes de cada mensagem do chat (rode antes ollama pull nomic-embed-text).\nO sono vem uma vez por dia, a partir das duas da manhã e enquanto nada está trabalhando. Mesmo sem o interruptor dele, ele propõe remover um fato que repete outro na mesma seção, sem modelo. Com ele, também propõe junções e escreve o resumo da volta, no seu idioma, marcado como a leitura dele dos resumos. Toda mudança espera o seu sim.\nMemória de projeto # Activity → By project do Nest tem um card para cada repositório em que uma sessão trabalha: as pastas e os branches dele, as sessões, os seus pull requests e checks (do card do GitHub), e o que o Zeca lembra do projeto. Ele só lê este computador. Uma conversa que começa num repositório leva essa memória junto.\nCompartilhando o AGENTS.md com o Claude # Quando um repositório tem um AGENTS.md (a memória de projeto que o Codex lê) que o CLAUDE.md dele não importa, o card dele oferece Share it with Claude…. Ele mostra a mudança (@AGENTS.md adicionado no fim do CLAUDE.md, @../AGENTS.md no fim do .claude/CLAUDE.md, ou um CLAUDE.md novo) e só a escreve quando você clica em Apply, sobre o mesmo arquivo que você viu, depois de um backup datado em ~/.local/share/vults/backups/. Aí o Claude Code e o Codex leem a mesma memória de projeto.\nPelo Claude Code # O chat entrega ao Claude Code o próprio servidor MCP do Zeca, vults-zeca, com --mcp-config (a sua configuração do Claude nunca é tocada): flock_list (as suas sessões agora), recall e journal_day (o diário dele), roost_memory (a memória do projeto) e memory_propose; só o flock_list com a memória desligada. O Claude Code pergunta com um card antes de cada chamada que as suas regras não permitem, e uma proposta ainda espera na aba Memory. Essas chamadas não marcam a conversa como tendo lido conteúdo de fora. O servidor é este app rodando de novo (vults --zeca-mcp), e não envia nada a lugar nenhum: o flock_list lê um retrato redigido das sessões da ilha que o app mantém enquanto roda e apaga quando fecha, e as chamadas do diário leem o vults.sqlite sem nunca atualizá-lo. O Codex só lê servidores MCP da própria configuração, então não os recebe.\n","externalUrl":null,"permalink":"/docs/vults/guide/memory/","section":"Documentação","summary":"O Zeca pode lembrar de você, dos seus projetos e do que os seus agentes fizeram. Essa memória fica desligada até você ligá-la, é guardada neste computador, e só …","title":"A memória do Zeca · Vults","type":"docs"},{"content":"A aba Agents oferece uma visão somente leitura de todos os agentes conhecidos: se estão instalados, qual a versão e o que o lazyagents pode gerenciar. Use-a para entender por que um agente não aparece em outra aba ou onde ficam suas skills.\nO suporte de cada agente (diretórios, provedores, hooks, limites e eventos) é gerado do código na referência dos agentes. Aqui você encontra a explicação da aba.\nA tabela # Uma linha por agente, com os instalados primeiro:\nColuna na interface Significado agent nome na cor do agente; ○ e texto discreto se não instalado version primeira linha de \u0026lt;cli\u0026gt; --version skills skills ativadas; — se não houver diretório local de skills sessions sessões do agente encontradas no disco hooks · provider · usage ✓ quando é possível gerenciar hooks, aplicar perfil de provedor ou ler consumo O contador da aba é o número de agentes instalados. Em terminais com menos de 75 colunas, as três colunas de recursos passam para uma linha manages no detalhe. Em terminais largos, o detalhe fica ao lado da tabela.\nPainel de detalhes # Para o agente selecionado:\nskills in: diretório onde o lazyagents cria os links de skills. reads too: outros diretórios lidos pelo agente. Uma skill ali aparece mesmo sem ativação pelo lazyagents. detection: caminho do binário, ou diretório de configuração se o binário não estiver no PATH. (shared): diretório compartilhado, como ~/.agents/skills. O link fica ali só enquanto a skill estiver ativada para todos os agentes instalados que o leem; veja diretórios compartilhados. Um agente não instalado mostra apenas a orientação de instalar sua CLI e reabrir o lazyagents.\nComo funciona a detecção # O agente conta como instalado se o binário estiver no PATH ou seu diretório de configuração existir, como ~/.claude ou ~/.codex. Com apenas o diretório, o detalhe avisa que o binário não está no PATH: skills e sessões ainda funcionam, mas retomar exige a CLI. A versão vem de \u0026lt;cli\u0026gt; --version, executado uma vez em segundo plano ao iniciar a TUI, com até 6 segundos por CLI. Na CLI do lazyagents, só comandos que precisam da versão, como doctor, fazem essa consulta. Claude Desktop é detectado apenas pelo diretório de configuração. Skills e conversas ficam na conta claude.ai; não há conteúdo local para gerenciar. Hermes Agent ativa skills em ~/.hermes/skills (%LOCALAPPDATA%\\hermes\\skills no Windows), no perfil de hermes profile use ou em HERMES_HOME. Também lê skills.create_dir e skills.external_dirs de config.yaml, resolvendo ~, ${VAR} e caminhos relativos como o Hermes. Diretórios inexistentes ficam de fora. Incluir ~/.agents/skills torna Hermes participante desse compartilhamento. Pi usa ~/.pi/agent ou PI_CODING_AGENT_DIR. Como outras ferramentas também têm um binário pi, sem esse diretório o binário só conta se pi --version imprimir apenas uma versão. Agentes movidos por suas variáveis (CLAUDE_CONFIG_DIR, CODEX_HOME, XDG_DATA_HOME para OpenCode…) são encontrados ali se o lazyagents executar com o mesmo ambiente. Veja a referência de variáveis. Crush conta como instalado pelo binário, ~/.config/crush ou ~/.local/share/crush. Lê skills em ~/.config/crush/skills (onde são ativadas), ~/.config/agents/skills, ~/.claude/skills e ~/.agents/skills. Se houver CRUSH_SKILLS_DIR, usa somente esse diretório, onde o lazyagents também ativa as skills. A detecção ocorre uma vez por execução. Reabra o lazyagents após instalar uma CLI.\nNa CLI, lazyagents doctor mostra a mesma detecção na primeira seção; --json inclui a versão.\nTeclas # ↑/↓ seleciona o agente e shift+↑/↓ rola os detalhes. Veja a referência completa.\nSolicitar um novo agente # O suporte usa um adaptador em internal/agent, único lugar que conhece caminhos e formatos dos agentes. Para solicitar um, abra uma issue com nome, locais de skills, sessões e configuração, e links da documentação. Para implementar, veja Adicionar um agente.\n","externalUrl":null,"permalink":"/docs/lazyagents/guide/agents/","section":"Documentação","summary":"A aba Agents oferece uma visão somente leitura de todos os agentes conhecidos: se estão instalados, qual a versão e o que o lazyagents pode gerenciar. Use-a …","title":"Agentes · lazyagents","type":"docs"},{"content":"Os conectores trazem novidades de serviços externos para a ilha. Cada um fica desligado até você ligá-lo em Settings → Connectors.\nGitHub # Ele verifica a cada cinco minutos, e a cada minuto enquanto houver checks de CI rodando:\nseus pull requests abertos: checks que falharam ou passaram, aprovado, mudanças solicitadas; pull requests em que sua revisão foi solicitada; os checks na branch padrão dos dez repositórios seus (de que você é dono) com push mais recente, e a release mais recente de cada um. A mesma consulta única também traz o que a aba Connections do Room mostra de cada linha: o branch de um pull request, o tamanho, os revisores e a última atualização, e cada check pelo nome (O Nest). As releases só aparecem lá: nunca viram alerta, nunca vão para a ilha.\nEle usa o GitHub CLI em que você já está logado (gh auth login), então o Vults nunca vê um token. A primeira verificação só aprende como as coisas estão; os alertas começam na próxima mudança. Clique em um alerta para abri-lo no GitHub, ou no × para dispensá-lo. Checks que passam substituem uma falha, e uma decisão de revisão mais nova substitui a mais antiga.\nDepois de um erro ele tenta de novo em 15 minutos se for um limite de requisições do GitHub, em 10 quando o gh não está instalado ou está deslogado, e de 4 a 15 (dobrando) nos outros casos. Abrir a ilha ou o card verifica antes quando a última verificação tem mais de um minuto, exceto sob um limite de requisições. O GitHub é verificado no máximo 3.000 vezes por dia; passado isso, Settings → Connectors mostra Budget spent. Um repositório sobre o qual o GitHub não consegue responder (por exemplo, um que exige login via SAML) não impede o resto de aparecer.\nO card do GitHub # Depois que o GitHub responde, a aba Connections da ilha aberta mostra o card dele, com um chip para o GitHub e um card por linha:\nYour pull requests (seus pull requests), do atualizado mais recentemente para o mais antigo: um ponto para os checks (verde passando, âmbar rodando, vermelho falhando) e a revisão (Approved ou Changes requested); Waiting for your review (esperando sua revisão); Default branches (branches padrão): o último commit em cada uma, com o resultado dos checks. Repositórios sem checks ficam de fora. Clique em uma linha para abri-la no GitHub. Quando um pull request é mergeado ou fechado, ou uma solicitação de revisão é retirada, os alertas dele vão junto.\nCom o Zeca ligado, uma linha pode perguntar a ele sobre ela:\nReview with Zeca (revisar com o Zeca), numa revisão que espera por você: ele lê o diff e diz os riscos antes de você aprovar; Ask Zeca why (perguntar ao Zeca por quê), em checks falhando: ele lê só o log da etapa que falhou e diz o que quebrou e onde. Cada um abre o chat com a pergunta escrita no campo de texto. Nada é perguntado até você enviar, então dá para mudá-la antes.\nSquash and merge aparece no seu próprio pull request quando ele está aprovado e com os checks passando. O primeiro clique só pergunta, embaixo da linha, o que o segundo vai fazer; Merge então faz o squash na branch base e apaga a branch dele, pelo seu login do gh, e o card pergunta ao GitHub de novo, então ela sai com a próxima resposta. Só o commit que o card mostrou verde é mergeado: se alguém deu push depois, o GitHub recusa. Se o GitHub recusar (uma regra de branch, um conflito), a linha diz por quê. Cada merge escreve uma linha no rastro local, e nada é mergeado por conta própria.\n✓ marca uma linha como vista: ela sai da ilha, e da contagem da aba, até mudar (os checks, a revisão ou o último commit de uma branch), e continua nas Connections do Nest. Mark all seen (marcar todos como vistos) limpa o card de uma vez. Quais linhas você marcou fica guardado só neste computador; o GitHub nunca fica sabendo.\nQuando uma verificação falha, o card mantém o que viu por último e mostra quando foi atualizado pela última vez, e o erro. Enquanto um card de permissão espera, a aba Connections fica esmaecida até ele ser respondido.\nO que a última verificação viu (os títulos, links e estados de checks que o card mostra, e nada mais) fica guardado em connectors/github.json na pasta de dados do app (~/.local/share/vults/ no Linux), para que uma reinicialização não gere alertas de novo sobre novidades antigas.\nQuer outro serviço? Veja Como adicionar um conector.\n","externalUrl":null,"permalink":"/docs/vults/guide/connectors/","section":"Documentação","summary":"Os conectores trazem novidades de serviços externos para a ilha. Cada um fica desligado até você ligá-lo em Settings → Connectors.\nGitHub # Ele verifica a cada …","title":"Conectores · Vults","type":"docs"},{"content":"Um plugin acrescenta sua própria aba, comandos e diagnósticos ao lazyagents sem alterar o código. É um executável em qualquer linguagem que usa JSON Lines pela entrada/saída padrão. Esta página explica instalação, uso e criação; o contrato completo está no protocolo de plugins.\nInstalar um plugin # Coloque o arquivo no diretório de plugins e dê permissão de execução:\nmkdir -p ~/.config/lazyagents/plugins cp my-plugin ~/.config/lazyagents/plugins/ chmod +x ~/.config/lazyagents/plugins/my-plugin Se XDG_CONFIG_HOME estiver definida, use $XDG_CONFIG_HOME/lazyagents/plugins/. Veja os caminhos de macOS/Windows em configuração. No Windows, arquivos .exe contam como executáveis.\nO nome sem extensão é o ID. Deve:\nseguir ^[a-z0-9][a-z0-9_-]{0,31}$ (minúsculas, dígitos, - e _, até 32 caracteres); não repetir aba ou comando interno (skills, sessions, list, doctor, help…); ser único: hello e hello.sh na mesma pasta colidem. Arquivos inválidos são ignorados com aviso (ao sair da TUI ou antes da saída da CLI) e aparecem em lazyagents doctor.\nO que o plugin acrescenta # Local Recurso TUI aba com título definido pelo plugin, após as abas de trabalho e antes de Usage/Agents Paleta comandos :\u0026lt;id\u0026gt; \u0026lt;comando\u0026gt; Ajuda (?) lista própria de teclas CLI lazyagents \u0026lt;id\u0026gt; [args…] executa o arquivo com argumentos, fluxos de entrada/saída e código de saída repassados doctor resultado da negociação inicial na seção plugins e, se solicitado, diagnóstico próprio O processo da aba inicia com a TUI e termina com ela, junto dos processos filhos.\nConfigurar um plugin # A seção com o ID em config.yaml é entregue inteira ao plugin ao iniciar:\nhello: greeting: hi Para mover ou ocultar, use tui: como nas outras abas (configuração). Um plugin oculto nem inicia, mas lazyagents \u0026lt;id\u0026gt; continua funcionando:\ntui: hidden: [hello] Confiança e segurança # Plugins executam com as permissões do seu usuário, como qualquer programa instalado. O lazyagents não oferece sandbox; instale apenas plugins confiáveis.\nA proteção oferecida é contra falhas na TUI:\nMensagens são não confiáveis. O texto mantém cores, mas perde outros controles de terminal (cursor, limpeza, títulos) e é recortado ao tamanho da aba. Títulos, ajuda e nomes de comandos também são reduzidos e limpos. Falta de resposta em 3 segundos, saída inválida ou encerramento deixa a aba em erro, mostrando motivo e final de stderr. r ou :reload reinicia. O resto do programa continua. Se o plugin parar de ler a entrada, é encerrado. Escrever um plugin # O exemplo mínimo funcional é o script examples/plugins/hello. Ele mostra os três modos:\n\u0026lt;bin\u0026gt; serve executa a aba. Lê init (tamanho, caminhos, cores, configuração), responde manifest (título, ajuda, comandos, diagnóstico) e envia frame com o texto completo quando mudar. Teclas, redimensionamentos e comandos chegam por novas linhas na entrada. Ao fechar a entrada, termina. \u0026lt;bin\u0026gt; doctor só executa se o manifesto tiver \u0026quot;doctor\u0026quot;: true. Imprima os resultados; código diferente de zero indica problema. Não usa terminal; a saída aparece ao terminar. Após 30 segundos, falha e encerra plugin e filhos. \u0026lt;bin\u0026gt; \u0026lt;qualquer outra coisa\u0026gt; recebe os argumentos de lazyagents \u0026lt;id\u0026gt; … diretamente. Experimente:\ncp examples/plugins/hello ~/.config/lazyagents/plugins/hello chmod +x ~/.config/lazyagents/plugins/hello lazyagents doctor # negociação inicial e diagnóstico do hello lazyagents hello a b # argumentos repassados lazyagents # aba Hello repete cada tecla Dicas:\nstdout é exclusivo do protocolo. Logs vão para stderr; o programa guarda os últimos 4 KiB para exibir em falhas. Toda execução recebe LAZYAGENTS_HOME, LAZYAGENTS_CONFIG_DIR, LAZYAGENTS_DATA_DIR, LAZYAGENTS_LIBRARY_DIR e LAZYAGENTS_PROTOCOL. Para abrir editor ou CLI de agente, peça ao hospedeiro com exec em vez de iniciar sozinho: ele suspende a TUI e entrega o terminal. Para depurar sem TUI, envie linhas manualmente: printf '{\u0026quot;type\u0026quot;:\u0026quot;init\u0026quot;,\u0026quot;protocol\u0026quot;:1,\u0026quot;width\u0026quot;:80,\u0026quot;height\u0026quot;:24}\\n' | ./my-plugin serve. Campos, limites e ciclo de vida estão no protocolo. Mudanças incompatíveis incrementam protocol em init.\n","externalUrl":null,"permalink":"/docs/lazyagents/guide/plugins/","section":"Documentação","summary":"Um plugin acrescenta sua própria aba, comandos e diagnósticos ao lazyagents sem alterar o código. É um executável em qualquer linguagem que usa JSON Lines pela …","title":"Plugins · lazyagents","type":"docs"},{"content":"Activity → Week do Nest mostra o que os seus agentes fizeram: o resumo de uma semana e o último ano numa grade; Settings → Activity mostra a mesma página. Tudo é contado neste computador, a partir de um histórico local que o Vults guarda enquanto os seus agentes trabalham.\nO que é um turno # Um turno é o que um prompt pôs para andar, até o agente parar. Para cada um o Vults guarda quando ele rodou, o agente, o nome da pasta do projeto e contagens (passos, comandos, linhas mudadas, as suas respostas). Nunca um prompt, uma resposta, um comando, um nome de arquivo ou um caminho, e nada sai deste computador (Segurança).\nA semana # O card mostra uma semana, de segunda a domingo, pelos seus dias locais: esta semana primeiro, e ‹ › para passar pelas semanas que o histórico guarda (12).\nTempo com os seus agentes: turnos rodando lado a lado contam uma vez só. Turnos e os passos deles, linhas adicionadas e removidas e os arquivos mexidos, comandos, respostas (permitidas, negadas, perguntas respondidas), e turnos que falharam. O tempo por dia em barras, o agente e o projeto com mais turnos, o dia mais movimentado e o turno mais longo. Compartilhando a semana # Save as image… embaixo da semana a desenha como uma imagem (1080 × 1350), com o Zeca no fio dele. Hide project names tira o projeto dela. O diálogo Salvar como do desktop pergunta onde (no Windows ela vai para a sua pasta Imagens), e nada é enviado.\nNa segunda de manhã # A partir das 08:00 de segunda, a ilha conta a semana passada numa linha (Last week: 41 turns, 6 h 20 min with your agents, most on site.), uma vez, se os seus agentes tiveram algum turno naquela semana. Ela aparece em cada preset como a linha que vem depois de uma tela bloqueada (A ilha), nunca no Paused. Open Activity mostra a semana inteira no Settings; ele e o × a marcam como lida.\nA grade # O último ano, uma coluna por semana e uma linha por dia, com a segunda em cima. O tom de um dia segue o tempo com os seus agentes, em quatro degraus pelos quartis dos seus dias ativos. Passe o mouse num dia para ver os turnos e o tempo.\nA aba GitHub mostra o seu calendário de contribuições do GitHub, com os níveis do próprio GitHub e as semanas começando no domingo, como no seu perfil. Ela precisa do conector GitHub ligado (Settings → Connectors) e é pedida pelo gh uma vez quando a aba abre, depois guardada por uma hora na memória, nunca em disco.\nO histórico # Keep a history vem ligado. Desligado, nada novo é guardado e o que existe fica. Clear history… pergunta uma vez, depois apaga os turnos e dias, o log de auditoria das suas respostas, o trace local de pedidos (os turnos do Zeca e cada pedido feito em seu nome), as conversas salvas do Zeca, o diário dele, os resumos dos dias e os dados de lembrança deles, as propostas de memória, as execuções do sono e o retrato do bando guardado para o servidor MCP do Zeca, tudo de uma vez, deixando uma linha no log de auditoria: que você o limpou, e quando. O que fica: o que o Zeca lembra (os arquivos de memória dele, Settings → Chat \u0026amp; voice → Memory), as políticas que você aceitou, os seus telefones pareados, as suas tarefas e o que os agentes custaram (Segurança). O histórico fica num banco local, vults.sqlite (cada turno por 12 semanas, os totais de cada dia por um ano), em ~/.local/share/vults/ (%LOCALAPPDATA%\\Vults\\ no Windows). Veja Configurações e arquivos. ","externalUrl":null,"permalink":"/docs/vults/guide/activity/","section":"Documentação","summary":"Activity → Week do Nest mostra o que os seus agentes fizeram: o resumo de uma semana e o último ano numa grade; Settings → Activity mostra a mesma página. Tudo …","title":"Atividade · Vults","type":"docs"},{"content":"Tudo é opcional: o lazyagents funciona sem configuração. Para personalizar, crie config.yaml no diretório de configuração.\nOnde ficam os arquivos # Diretório Linux macOS Windows Configuração $XDG_CONFIG_HOME/lazyagents, padrão ~/.config/lazyagents ~/Library/Application Support/lazyagents %AppData%\\lazyagents Dados $XDG_DATA_HOME/lazyagents, padrão ~/.local/share/lazyagents igual ao Linux igual ao Linux O restante da documentação usa os caminhos do Linux.\nCaminho Conteúdo ~/.config/lazyagents/config.yaml esta configuração ~/.config/lazyagents/providers.json perfis de provedores, modo 0600, podem conter tokens ~/.config/lazyagents/plugins/ plugins externos, um executável por plugin (guia) ~/.config/lazyagents/themes/ temas personalizados \u0026lt;id\u0026gt;.yaml (temas) ~/.local/share/lazyagents/skills/ biblioteca de skills, movível por libraryDir ~/.local/share/lazyagents/profiles.json perfis de ativação de skills ~/.local/share/lazyagents/hooks/ biblioteca de hooks, JSON por hook e scripts importados ~/.local/share/lazyagents/session-aliases.json aliases de sessões ~/.local/share/lazyagents/usage-cache.json cache de limites ~/.local/share/lazyagents/claude-provider-state.json chaves env escritas no Claude Code; só impressões digitais, nunca os valores ~/.local/share/lazyagents/pi-provider-state.json provedor/modelo padrão anterior do Pi, restaurado na limpeza; sem segredo ~/.local/share/lazyagents/transcript-index.gob índice descartável; apagar só faz a próxima carga reler tudo ~/.local/share/lazyagents/backups/ backups de skills, sessões e configurações dos agentes ~/.local/share/lazyagents/exports/ conversas exportadas As escritas fora desses diretórios estão em Segurança e dados.\nconfig.yaml # theme: sp-night-garoa # tema incluído ou personalizado libraryDir: ~/.agents/skills # localização da biblioteca tui: splash: true # false pula a tela inicial splashSeconds: 2 # duração; 0 pula, máximo 10 startTab: sessions # aba inicial tabs: [sessions, skills, usage] # ordem; não listadas vêm depois hidden: [hooks, providers] # ocultas da barra e da paleta usage: period: 30d # today | 7d | 30d | 90d | all view: projects # daily | agents | projects | models hello: # seção de plugin, identificada por seu id greeting: hi O lazyagents só reescreve o arquivo quando um comando altera uma configuração que ele gerencia; atualmente migrate-library define libraryDir. Comentários, ordem das chaves e seções desconhecidas são preservados.\nChaves globais # Chave Padrão Efeito theme sp-night tema da TUI: ID incluído ou arquivo em themes/; lido na inicialização. ID desconhecido usa sp-night com aviso. IDs anteriores à v0.3 (noite, garoa, jaragua) ainda funcionam libraryDir ~/.local/share/lazyagents/skills biblioteca. Prefira lazyagents migrate-library \u0026lt;dir\u0026gt;, que move skills e recria links (guia) Apenas essas duas chaves são globais. As outras são seções de módulos/plugins, nomeadas pelo ID.\ntui: disposição das abas # Chave Efeito splash false pula a tela inicial splashSeconds duração da tela, até 10 segundos; 0 pula startTab aba inicial tabs ordem das abas; omitidas vêm depois na ordem padrão hidden remove abas da barra e da paleta Os IDs são os da paleta: skills, sessions, providers, hooks, usage, agents e os plugins. Abas internas ocultas continuam carregando, pois Usage e Agents dependem dos demais módulos. Plugins ocultos não iniciam, mas seu comando de CLI continua disponível.\nusage # Filtros iniciais: period e view. Veja o guia de consumo.\nSeções de plugins # Ao iniciar, o plugin recebe a seção inteira com seu ID. O conteúdo é definido por ele.\nValores inválidos não impedem a inicialização # Um config.yaml ilegível é ignorado: o programa usa padrões e emite aviso. IDs desconhecidos de aba, tema ou filtro recebem aviso e usam o padrão. Avisos aparecem na saída de erro ao sair da TUI. Configuração, temas e plugins também avisam antes da saída de comandos. Avisos de tui: só aparecem na TUI, pois a CLI não tem abas. Migrar de config.json # Versões de desenvolvimento anteriores à v0.1.0 usavam config.json. Na primeira execução, ele é migrado para config.yaml e preservado como config.json.migrated.\n","externalUrl":null,"permalink":"/docs/lazyagents/configuration/","section":"Documentação","summary":"Tudo é opcional: o lazyagents funciona sem configuração. Para personalizar, crie config.yaml no diretório de configuração.\nOnde ficam os arquivos # Diretório …","title":"Configuração · lazyagents","type":"docs"},{"content":"Claude Code, Codex, Antigravity, OpenCode, Qwen Code, Copilot CLI, Cursor, Factory Droid e Kimi Code já vêm integrados (Settings → Agents). Qualquer outra ferramenta também pode colocar suas sessões no fio, se ela rodar um comando nos seus eventos e mandar o JSON de hook do Claude Code pelo stdin (o formato que a maioria das ferramentas de agente copia). Para ferramentas que rodam plugins em vez disso (Pi), um plugin curto faz o mesmo; as receitas estão mais abaixo.\nAponte os hooks da ferramenta para o relay, com um nome à sua escolha (no Windows o relay fica em %LOCALAPPDATA%\\Vults\\bin\\):\n~/.local/share/vults/bin/vults-hook --agent my-tool SessionStart O nome tem de 1 a 24 caracteres de a-z, 0-9 e -, e não pode ser um para o qual o fio tem um tipo (claude, codex, copilot, opencode, qwen e other), nem gemini: o fio não tem mais um tipo para ele, mas os hooks antigos do Gemini CLI podem continuar instalados, então o nome segue reservado e eles não mandam nada. Os integrados que o Vults manda por nome (antigravity, cursor, droid, kimi) usam esses nomes eles mesmos, então não ficam reservados; uma ferramenta com qualquer nome não ganha card, inclusive um integrado mandado por nome. Com um nome que quebra essas regras, o hook não manda nada e sai na hora. O nome do evento vem de hook_event_name no JSON, ou do último argumento. Os nomes de evento do Claude Code são lidos, e os do Cursor também. Cada sessão precisa de um id: session_id, ou conversation_id, sessionId ou conversationId. Um evento sem id é descartado. As sessões aparecem com o nome da ferramenta, em violeta. Os campos que ela lê estão em Protocolo do hook. Para essas ferramentas, o relay sempre sai com 0 e não imprime nada, mas um relay ausente faz o comando falhar: termine todo comando de hook em || exit 0, ou uma ferramenta que trata um hook com falha como um \u0026ldquo;não\u0026rdquo; para de funcionar quando o app não está instalado.\nO que cada agente consegue fazer # Settings → Agents, em What each agent can do, mostra cada agente embutido: se a CLI dele está no PATH e a versão, se os hooks estão instalados e atualizados (e, no Codex, confiáveis), e o que ele consegue fazer com o Vults. Check again pergunta de novo; a resposta fica guardada por dez minutos.\nPermissões Perguntas Diffs Parar um turno Sandbox Iniciado pelo Vults Claude Code um card um card linhas, numeradas na hora, quando o Vults o iniciou bubblewrap, se ligado sim Codex um card o terminal dele linhas na hora, quando o Vults o iniciou o modo de sandbox dele sim Antigravity o terminal dele o terminal dele nenhum pelo Vults, ainda não nenhum ainda não OpenCode um card um card (OpenCode 1) linhas na hora, quando o Vults o iniciou nenhum uma tarefa, por ACP Qwen Code um card o terminal dele linhas na hora, quando o Vults o iniciou um contêiner, se ligado uma tarefa, por ACP Copilot CLI um card nenhuma linhas na hora, quando o Vults o iniciou nenhum uma tarefa, por ACP Cursor o terminal dele o terminal dele nenhum não pelo Vults nenhum não Factory Droid o terminal dele o terminal dele linhas não pelo Vults nenhum não Kimi Code o terminal dele; um card numa tarefa o terminal dele linhas na hora, quando o Vults o iniciou nenhum uma tarefa, por ACP O Vults para um turno, e mantém a sessão, só numa sessão que ele iniciou (a do chat, ou a de uma tarefa): nenhum sinal faz isso, um sinal encerra a sessão inteira. OpenCode, Qwen Code e Copilot CLI pegam tarefas pelo Agent Client Protocol (Start with another agent… na aba Tasks, quando o agente está instalado); veja Tarefas. O sandbox do Codex depende do modo: workspace-write escreve só na pasta dele, nas pastas temporárias e nas pastas que recebe. Se ligado: o sandbox fica desligado até você ligar nesse agente. Nenhum desses sandboxes foi testado com o Vults ainda.\nPermissões # A ilha nunca responde à permissão de uma ferramenta que não vem integrada: ela não tem como saber o que essa ferramenta espera de volta. Um PermissionRequest aparece como uma pergunta esperando no terminal, o hook não espera, e a ferramenta pergunta a você lá, como de costume.\nAntigravity # Settings → Agents → Antigravity instala um hook chamado vults em ~/.gemini/config/hooks.json, o arquivo que o CLI agy, o app Antigravity e a IDE compartilham (testado com o agy 1.2.16). Os outros hooks dali nunca são tocados; se um hook seu já se chamar vults, o instalador não escreve nada. As sessões dele aparecem como antigravity.\nA ilha mostra o Antigravity pensando, cada passo (view_file, run_command…) e quando ele para. O Antigravity não manda a resposta dele, então uma sessão terminada não tem linha de resumo, e não há início nem fim de sessão: uma sessão sai do fio depois de um tempo em silêncio (10 minutos depois de terminar, 30 nos outros casos). O hook dele roda antes de toda ferramenta e não diz se o Antigravity teria perguntado, então o Antigravity pede as permissões ele mesmo (Aprovando).\nCursor # Settings → Agents → Cursor adiciona os hooks dele a ~/.cursor/hooks.json, o arquivo que o editor e o cursor-agent compartilham; os hooks de outras ferramentas nele ficam, e Remove hooks… tira só os do Vults. Reinicie o Cursor depois. As sessões dele aparecem como cursor, no projeto em que o Cursor trabalha.\nA ilha mostra cada passo terminado, falhas incluídas, e quando um turno para. Os hooks dele que rodam antes de um passo (preToolUse, beforeSubmitPrompt, beforeShellExecution…) ficam de fora: o Cursor lê o que eles imprimem como uma decisão, então o Cursor pergunta as permissões ele mesmo (Aprovando). O que uma ferramenta imprimiu e o email da conta nunca saem do hook.\nO Cursor também roda os hooks do Claude Code (os hooks third-party dele, ligados por padrão). O relay ignora os eventos do Cursor ali, então uma sessão nunca aparece duas vezes, uma como Claude Code.\nFactory Droid # Settings → Agents → Factory Droid adiciona os hooks dele a ~/.factory/settings.json (o Droid lê os hooks do Claude Code; o resto do arquivo e os hooks de outras ferramentas ficam). Reinicie o Droid depois. As sessões dele aparecem como droid (conferido com o droid 0.239.0).\nA ilha mostra cada passo quando começa e termina, as linhas de uma edição e quando um turno para. Um comando que falha não manda evento próprio: o passo dele termina com o turno. O Droid não tem evento de permissão, e o PreToolUse dele roda antes de toda ferramenta, pedisse ele ou não, então o Droid pergunta as permissões ele mesmo (Aprovando).\nKimi Code # Settings → Agents → Kimi Code adiciona os hooks dele a ~/.kimi-code/config.toml (KIMI_CODE_HOME o move), como tabelas [[hooks]] ao lado das suas configurações: seus comentários e a formatação ficam, e os hooks de outras ferramentas também. Reinicie o Kimi depois. As sessões dele aparecem como kimi (conferido com o Kimi Code 2.1.1).\nA ilha mostra cada passo, as linhas de uma edição, um comando que falhou e quando um turno para. O Kimi avisa o hook PermissionRequest sobre uma permissão sem esperar resposta, então a ilha mostra que ela espera no terminal do Kimi e o Kimi pergunta ele mesmo (Aprovando).\nO Kimi também pega tarefas por ACP (kimi acp), e ali cada escrita e cada comando é um card da ilha. A sessão dele é posta no modo do Kimi que pergunta quando começa: o seu default_permission_mode na config dele, senão, rodaria toda ferramenta sem perguntar, enquanto a sessão ainda diz que pergunta.\nOpenCode # Settings → Agents → OpenCode escreve um plugin em ~/.config/opencode/plugins/vults.js, com o mesmo diff, backup e clique dos hooks; reinicie o OpenCode depois. Ele informa cada passo e coloca as permissões e as perguntas do OpenCode na ilha (Aprovando). Um arquivo ali sem a primeira linha Generated by Vults é seu, e o instalador não mexe nele. O OpenCode não tem um evento para quando ele fecha, então os pássaros dele saem do fio depois de um tempo em silêncio.\nReceitas # Estas receitas foram conferidas com a documentação e a cópia instalada de cada ferramenta (versões abaixo), inclusive com o relay ausente; nenhuma foi rodada dentro de uma sessão real da ferramenta. Cada uma só informa: nunca responde a uma permissão.\nPi # O Pi (1.0) carrega extensões de ~/.pi/agent/extensions/. Salve isto como ~/.pi/agent/extensions/vults.ts. Ele escuta tool_execution_start e _end, nunca tool_call: um handler de tool_call que falha para a ferramenta.\nimport { spawn } from \u0026#34;node:child_process\u0026#34;; import { homedir } from \u0026#34;node:os\u0026#34;; import { join } from \u0026#34;node:path\u0026#34;; const RELAY = join(homedir(), \u0026#34;.local/share/vults/bin/vults-hook\u0026#34;); function toolInput(args: any): Record\u0026lt;string, unknown\u0026gt; { const a = args ?? {}; const out: Record\u0026lt;string, unknown\u0026gt; = {}; if (typeof a.command === \u0026#34;string\u0026#34;) out.command = a.command; if (typeof a.path === \u0026#34;string\u0026#34;) out[a.pattern === undefined ? \u0026#34;file_path\u0026#34; : \u0026#34;path\u0026#34;] = a.path; if (typeof a.pattern === \u0026#34;string\u0026#34;) out.pattern = a.pattern; return out; } let queue: Promise\u0026lt;void\u0026gt; = Promise.resolve(); function run(event: string, payload: string): Promise\u0026lt;void\u0026gt; { return new Promise((done) =\u0026gt; { try { const child = spawn(RELAY, [\u0026#34;--agent\u0026#34;, \u0026#34;pi\u0026#34;, event], { stdio: [\u0026#34;pipe\u0026#34;, \u0026#34;ignore\u0026#34;, \u0026#34;ignore\u0026#34;], detached: true }); setTimeout(done, 2000).unref(); child.on(\u0026#34;error\u0026#34;, () =\u0026gt; done()); child.on(\u0026#34;exit\u0026#34;, () =\u0026gt; done()); child.stdin?.on(\u0026#34;error\u0026#34;, () =\u0026gt; {}); child.stdin?.end(payload); child.unref(); } catch { done(); } }); } function send(event: string, ctx: any, extra: Record\u0026lt;string, unknown\u0026gt; = {}): void { try { const payload = JSON.stringify({ hook_event_name: event, session_id: ctx.sessionManager.getSessionId(), cwd: ctx.cwd, ...extra }); queue = queue.then(() =\u0026gt; run(event, payload)); } catch {} } function text(content: any): string | undefined { if (!Array.isArray(content)) return undefined; const s = content.filter((c) =\u0026gt; c?.type === \u0026#34;text\u0026#34;).map((c) =\u0026gt; c.text).join(\u0026#34;\\n\u0026#34;).trim(); return s || undefined; } export default function (pi: any) { let last: string | undefined; let failed = false; pi.on(\u0026#34;session_start\u0026#34;, (_e: any, ctx: any) =\u0026gt; send(\u0026#34;SessionStart\u0026#34;, ctx)); pi.on(\u0026#34;session_shutdown\u0026#34;, (_e: any, ctx: any) =\u0026gt; send(\u0026#34;SessionEnd\u0026#34;, ctx)); pi.on(\u0026#34;before_agent_start\u0026#34;, (_e: any, ctx: any) =\u0026gt; { last = undefined; failed = false; send(\u0026#34;UserPromptSubmit\u0026#34;, ctx); }); pi.on(\u0026#34;tool_execution_start\u0026#34;, (e: any, ctx: any) =\u0026gt; send(\u0026#34;PreToolUse\u0026#34;, ctx, { tool_name: e.toolName, tool_input: toolInput(e.args) })); pi.on(\u0026#34;tool_execution_end\u0026#34;, (e: any, ctx: any) =\u0026gt; send(e.isError ? \u0026#34;PostToolUseFailure\u0026#34; : \u0026#34;PostToolUse\u0026#34;, ctx, { tool_name: e.toolName })); pi.on(\u0026#34;agent_end\u0026#34;, (e: any, ctx: any) =\u0026gt; { try { const reply = [...(e.messages ?? [])].reverse().find((m: any) =\u0026gt; m?.role === \u0026#34;assistant\u0026#34;); if (reply?.stopReason === \u0026#34;error\u0026#34;) { failed = true; send(\u0026#34;StopFailure\u0026#34;, ctx, { error: reply.errorMessage }); } else last = text(reply?.content) ?? last; } catch {} }); pi.on(\u0026#34;agent_settled\u0026#34;, (_e: any, ctx: any) =\u0026gt; { if (!failed) send(\u0026#34;Stop\u0026#34;, ctx, { last_assistant_message: last }); }); } ctx.sessionManager.getSessionId() existe no Pi, mas não está na documentação dele; se um Pi futuro o remover, a extensão não manda nada em vez de falhar.\nTestando # echo \u0026#39;{\u0026#34;hook_event_name\u0026#34;:\u0026#34;SessionStart\u0026#34;,\u0026#34;session_id\u0026#34;:\u0026#34;s1\u0026#34;,\u0026#34;cwd\u0026#34;:\u0026#34;\u0026#39;$PWD\u0026#39;\u0026#34;}\u0026#39; \\ | ~/.local/share/vults/bin/vults-hook --agent my-tool echo \u0026#39;{\u0026#34;hook_event_name\u0026#34;:\u0026#34;PreToolUse\u0026#34;,\u0026#34;session_id\u0026#34;:\u0026#34;s1\u0026#34;,\u0026#34;tool_name\u0026#34;:\u0026#34;Bash\u0026#34;,\u0026#34;tool_input\u0026#34;:{\u0026#34;command\u0026#34;:\u0026#34;make\u0026#34;}}\u0026#39; \\ | ~/.local/share/vults/bin/vults-hook --agent my-tool echo \u0026#39;{\u0026#34;hook_event_name\u0026#34;:\u0026#34;SessionEnd\u0026#34;,\u0026#34;session_id\u0026#34;:\u0026#34;s1\u0026#34;}\u0026#39; \\ | ~/.local/share/vults/bin/vults-hook --agent my-tool O protocolo por trás disso está em Protocolo do hook.\n","externalUrl":null,"permalink":"/docs/vults/guide/other-agents/","section":"Documentação","summary":"Claude Code, Codex, Antigravity, OpenCode, Qwen Code, Copilot CLI, Cursor, Factory Droid e Kimi Code já vêm integrados (Settings → Agents). Qualquer outra …","title":"Outros agentes · Vults","type":"docs"},{"content":"As cores da TUI vêm do tema escolhido em theme: de config.yaml, aplicado na inicialização. Os temas incluídos e seus IDs estão na referência.\nTemas incluídos # A família padrão é SP Night, inspirada em São Paulo. As variantes sp-night, sp-night-garoa e sp-night-jaragua incluem toda a paleta original e todos os papéis semânticos, sem adaptação. IDs usados até v0.2 (noite, garoa, jaragua) continuam funcionando em theme: e extends:.\nTambém há temas da comunidade com paletas oficiais: Tokyo Night, Dracula, Gruvbox, Nord, Rosé Pine, Kanagawa, Everforest e One Dark. Se uma cor original tornar texto ilegível (contraste abaixo de 3:1 contra fundo ou seleção), o papel usa outra da mesma paleta. Se nenhuma passar, o arquivo acrescenta uma cor derivada com comentário.\nPara combinar terminal e editor, o SP Night tem versões para outras ferramentas em sp-night.github.io.\nSeu próprio tema # Crie ~/.config/lazyagents/themes/\u0026lt;id\u0026gt;.yaml e use theme: \u0026lt;id\u0026gt;. Escreva só as mudanças: o restante vem de extends, cujo padrão é sp-night.\n# ~/.config/lazyagents/themes/my-dracula.yaml label: Meu Dracula extends: dracula palette: purple: \u0026#34;#caa9fa\u0026#34; # muda papéis herdados que usam purple ui: accent: \u0026#34;#ff79c6\u0026#34; # destaque: aba ativa e bordas focadas bg: \u0026#34;#1e1f29\u0026#34; diagnostic: ok: \u0026#34;#50fa7b\u0026#34; Formato:\nCampo Significado id opcional; se presente, deve coincidir com o nome do arquivo label, description nome do tema e descrição curta appearance dark ou light; informativo, não muda a renderização extends tema herdado; padrão sp-night palette cores nomeadas, name: \u0026quot;#rrggbb\u0026quot; ui, diagnostic, git, syntax, ansi grupos de papéis; cada valor é hexadecimal entre aspas ou nome da paleta Os nomes são resolvidos após a herança: mudar uma cor nomeada altera todos os papéis herdados que a usam.\nA lista completa de papéis e o que desenham está em internal/tui/theme/README.md. Os arquivos incluídos são exemplos completos.\nRegras # Não reutilize o ID de um tema incluído; use extends para modificá-lo. Arquivos inválidos (hexadecimal incorreto, papel desconhecido, ciclo de herança) são ignorados com aviso; os demais carregam. Avisos aparecem na saída de erro ao sair da TUI ou antes da saída de um comando. Plugins e temas # Plugins recebem o tema ativo ao iniciar, com tokens e papéis em hexadecimal, para combinar sua aba. Veja o protocolo.\nContribuir um tema # Um novo tema incluído é um YAML completo em internal/tui/theme/themes/: paleta e todos os papéis, sem extends. Papéis de texto devem ter contraste de ao menos 3:1 sobre ui.bg e ui.selection; go test ./internal/tui/theme/ verifica. Acrescente a licença da paleta em LICENSES-themes.md e execute go test ./docs -update para atualizar a referência.\nLicenças # As paletas são MIT, exceto Tokyo Night (Apache-2.0). Avisos: LICENSE-SP-Night e LICENSES-themes.md.\n","externalUrl":null,"permalink":"/docs/lazyagents/themes/","section":"Documentação","summary":"As cores da TUI vêm do tema escolhido em theme: de config.yaml, aplicado na inicialização. Os temas incluídos e seus IDs estão na referência.\nTemas incluídos # …","title":"Temas · lazyagents","type":"docs"},{"content":"Um telefone que você pareia pode responder aos cards que esperam por você enquanto está longe da mesa. Ele só decide: este computador continua fazendo o que você escolheu, e a ilha também mantém todos os cards. O app de telefone do Vults ainda não saiu; até lá, o cliente de teste de linha de comando de O relay do telefone pareia e responde como um telefone.\nComo ligar # Em Settings → Phone, ligue Answer cards from a phone, depois escolha uma opção em How the phone reaches this computer e preencha o campo abaixo dela:\nThrough a relay: um servidor pequeno que guarda mensagens seladas até o outro lado lê-las. Rode o seu (O relay do telefone) e informe o endereço dele em Relay. Straight (LAN or tailnet): este computador roda o próprio relay no endereço que você informa em Listen on, como o endereço dele na tailnet e uma porta (100.64.0.2:8787). O telefone precisa conseguir alcançá-lo. Cada pedido ao relay é um pedido em seu nome: desligado até você ligar, no máximo 10.000 por dia, cada um guardado no trace local (Segurança).\nPareamento # Aperte Pair: um QR aparece por dois minutos. Escaneie com o telefone. O QR leva a chave pública deste computador, o endereço do relay e um segredo de uso único; só um telefone que o viu consegue parear, e ele pareia um telefone. Abaixo do QR, The code\u0026rsquo;s text, for the command-line test client dá o mesmo código em texto. O telefone então aparece em Paired phones.\nComo responder # Cada card esperando na ilha vai para todos os telefones pareados, e sai deles quando o card sai da fila. No preset Paused nenhum card existe, então nada chega ao telefone. No telefone:\nDeny e Dismiss (mandar para o terminal) não pedem biometria. Allow, Always e responder a uma pergunta pedem a sua digital ou o seu rosto, para aquela resposta. Uma resposta só vale se a chave daquele telefone a assinou para aquele card exato, a tempo, e ela nunca foi usada antes. Um relay que perde, atrasa ou repete mensagens pode fazer um card esperar, nunca respondê-lo (O que ele vê). Se este computador não conseguir guardar que uma resposta foi usada, a resposta é descartada e o card continua esperando. Always pelo telefone cria a mesma regra que na ilha (Aprovando).\nComo revogar # Revoke ao lado de um telefone e nada do que ele assinar vale a partir dali. Um telefone revogado fica na lista e não consegue parear de novo com as mesmas chaves.\n","externalUrl":null,"permalink":"/docs/vults/guide/phone/","section":"Documentação","summary":"Um telefone que você pareia pode responder aos cards que esperam por você enquanto está longe da mesa. Ele só decide: este computador continua fazendo o que …","title":"O telefone · Vults","type":"docs"},{"content":"O lazyagents edita arquivos dos quais seus agentes dependem. Esta página informa exatamente o que muda, como desfazer e como segredos são tratados. Os guias de módulos detalham cada assunto.\nPrincípios # Nada muda sem uma ação sua. Navegar, abrir a TUI ou consultar informações nunca escreve arquivos dos agentes. Configurações são confirmadas. Na TUI, aplicar provedor ou instalar hook mostra arquivo e mudanças antes de escrever. Skills só adicionam/removem links, por isso a ativação é imediata. Backup antes de sobrescrever. Configurações são copiadas antes de cada escrita; skills removidas e sessões excluídas são preservadas antes da remoção. Só conteúdo gerenciado é alterado. Chaves, hooks e seções TOML não escritos pelo lazyagents ficam intactos e na mesma ordem. No env do Claude Code, aplicação/limpeza só remove chaves próprias e restaura endpoint/modelo substituídos. Escrita atômica. Usa arquivo temporário e renomeação sobre o original, evitando arquivo parcial após falha. Escritas concorrentes não são sobrescritas. A configuração só é substituída se ainda corresponder à leitura. Se outro processo mudar, Codex (config.toml) e Pi (models.json, settings.json) são relidos e editados novamente, até três tentativas com um backup. Claude Code e hooks são deixados como o outro programa escreveu, com aviso. Remover arquivos criados pelo lazyagents segue a mesma regra. O que o lazyagents escreve # Nos próprios diretórios (caminhos): bibliotecas de skills/hooks, perfis, aliases, caches, exportações e backups.\nNos diretórios dos agentes, apenas por sua ação:\nAção Mudança Como desfazer Ativar skill link simbólico no diretório do agente para a biblioteca desativar remove o link Desativar skill remove o link, nunca uma pasta real local ou de outra ferramenta ativar novamente Incorporar skill pasta local vai à biblioteca; link toma seu lugar copiar a pasta da biblioteca de volta Aplicar provedor Claude Code: env em ~/.claude/settings.json. Codex: model_provider e bloco [model_providers.lazyagents] em ~/.codex/config.toml. Pi: provedor lazyagents em ~/.pi/agent/models.json e defaultProvider/defaultModel em settings.json. Crush: bloco delimitado ao fim de ~/.config/crush/crushrc, com valores entre aspas simples limpar o provedor ou restaurar backup Instalar hook entrada em ~/.claude/settings.json ou ~/.codex/hooks.json, ou linha hook add no bloco do crushrc desinstalar ou restaurar backup Excluir sessão arquivo removido após cópia ao backup. OpenCode exporta com opencode export antes de opencode session delete; Crush salva com crush session show --json antes de crush session delete. Falha no backup impede exclusão copiar backup de volta; OpenCode usa opencode import \u0026lt;file\u0026gt;; Crush não tem importação, backup é só registro migrate-library move skills, recria links e salva libraryDir em config.yaml executar de volta ao diretório antigo Arquivos por agente estão na referência.\nBackups # Tudo fica em ~/.local/share/lazyagents/backups/, como \u0026lt;file\u0026gt;.\u0026lt;timestamp\u0026gt;:\nConteúdo Retenção configurações (settings.json, config.toml, hooks.json, models.json) 20 mais recentes por arquivo skills removidas/atualizadas (\u0026lt;skill\u0026gt;.\u0026lt;timestamp\u0026gt;.tar.gz) 20 mais recentes por skill sessões excluídas (\u0026lt;transcript file\u0026gt;.\u0026lt;timestamp\u0026gt;, opencode-\u0026lt;id\u0026gt;.\u0026lt;timestamp\u0026gt;.json, crush-\u0026lt;id\u0026gt;.\u0026lt;timestamp\u0026gt;.json) todas Skills são restauradas pela TUI: b na aba Skills (guia). Backups de configuração são cópias comuns: para restaurar, copie sobre o arquivo atual.\nls -t ~/.local/share/lazyagents/backups/settings.json.* | head -1 # backup mais recente Segredos # Tokens de provedores: ficam em ~/.config/lazyagents/providers.json, modo 0600, preservado nos backups. TUI e --json só indicam presença; texto puro exige lazyagents provider list --reveal. Use --token - para ler da entrada padrão, fora do histórico do shell. Codex: prefira --env-key VAR; config.toml guarda apenas o nome da variável. Claude Code: token precisa estar em settings.json, onde o agente o lê. O lazyagents usa modo 0600 ao escrevê-lo. Pi: --env-key VAR evita token no arquivo (\u0026quot;apiKey\u0026quot;: \u0026quot;$VAR\u0026quot;); caso contrário fica em models.json, modo 0600. Credenciais dos agentes: por exemplo a autenticação do Claude Code, só são lidas para a consulta que exige isso (limites), nunca guardadas, registradas ou exibidas. Para identificar o tipo, o programa lê apenas existência e tipo (oauth/api_key no auth.json do Pi, presença de chave em models.json do Pi ou crush.json), nunca o valor. Rede # O lazyagents funciona offline. Só usa a rede quando você pede um recurso que depende dela:\nQuando Consulta abre Usage, executa lazyagents usage ou doctor limites Claude Code, no endpoint de /usage, cache de 5 minutos; Codex usa arquivos locais instala do GitHub git clone --depth 1 do repositório busca no GitHub (S) gh api com sua autenticação do gh verifica atualizações de skills repositório de origem Nada disso executa na inicialização, e não há telemetria.\nO consentimento pertence ao agente # Alguns agentes exigem sua aprovação para executar comandos. O lazyagents nunca responde em seu nome. Codex registra a aprovação de hooks em trusted_hash e exige [features] hooks ativado: o lazyagents instala e avisa da pendência, mas não grava o hash nem ativa a função. Você aprova no Codex.\nConteúdo de terceiros # Hooks executam comandos. Um hook de repositório executa a cada evento correspondente com suas permissões. Hooks encontrados na instalação vêm desmarcados; leia primeiro com v em Hooks. Skills são instruções que seus agentes seguirão. Leia o SKILL.md (enter) antes de ativar de uma origem desconhecida. Plugins são programas instalados por você. O lazyagents trata mensagens como não confiáveis, remove controles de terminal e isola falhas da aba, mas o plugin executa com suas permissões. Veja o guia. Relatar uma vulnerabilidade # Veja SECURITY.md.\n","externalUrl":null,"permalink":"/docs/lazyagents/safety/","section":"Documentação","summary":"O lazyagents edita arquivos dos quais seus agentes dependem. Esta página informa exatamente o que muda, como desfazer e como segredos são tratados. Os guias de …","title":"Segurança e dados · lazyagents","type":"docs"},{"content":"O que o Vults promete:\nEle nunca bloqueia seu agente. Se o app estiver fechado, lento ou quebrado, o hook sai em milissegundos sem imprimir nada, e seu agente pergunta no terminal como sempre. Só você responde a uma permissão. Nenhum timer ou padrão responde a uma. Além do seu clique, só estes respondem: uma regra exata que você criou com Always, para aquele comando ou arquivo; uma política que você escreveu, viu como diff e aceitou com um clique (um deny vence um allow); um telefone que você pareou, quando a resposta dele é assinada pela chave dele para aquele card exato, no prazo, e nunca vista antes (aprovar pede a sua biometria no telefone, negar não; veja O telefone); e, só no chat do Zeca, o acesso que você escolheu para os cards dele (Quem responde os cards do Zeca); no acesso total, a negação ou o perguntar de uma política continuam valendo, e conteúdo de fora traz os cards de volta. Uma chamada destrutiva (rm -rf, um push forçado) sempre pergunta: o card dela não oferece Always, e nenhuma regra, política ou acesso total a responde. Uma pergunta do Claude Code só é respondida com a escolha ou as palavras que você deu no card dela. Só a sua conta de usuário fala com ele. O socket fica na sua pasta de runtime privada, com modo 0600, e os dois lados verificam se o outro processo roda como você (no Windows, pelo SID). Ele nunca edita a configuração de um agente pelas suas costas. Toda mudança ganha um backup datado e um diff que você aprova; os hooks de outras ferramentas são mantidos, uma status line do Claude Code que seja sua continua rodando (como), e o trusted_hash do Codex nunca é escrito (você mesmo confia nos nossos hooks, no /hooks do Codex). O uso do plano vem só das CLIs. A entrada da status line do Claude Code é reduzida no hook aos rate_limits dela e ao custo da sessão antes de qualquer coisa sair dele; o Codex é consultado com uma chamada só de leitura, só enquanto Settings → General → Codex usage estiver ligado. O chat usa as CLIs em que você fez login (claude, codex), e o Vults nunca lê as credenciais delas; todo comando e toda edição que suas próprias regras não liberam esperam o seu Allow (veja Sua configuração). As chaves de API ficam no chaveiro do sistema. Se você der ao chat a chave de API de um provedor, ela é gravada só no chaveiro (Secret Service no Linux), nunca em um arquivo ou log, nunca devolvida a uma janela, e só é enviada para aquele provedor. Modelos locais (Ollama, LM Studio) são acessados só em 127.0.0.1. O chat pela API não executa comandos nem edita arquivos. As ferramentas dele leem o que a ilha mostra (sessões, cards esperando, uso, seu card do GitHub); com a memória ligada, o recall lê o diário e o memory_propose só escreve uma proposta; com a web ligada, ele recebe as ferramentas da web. O que elas devolvem vai para aquele provedor junto com a conversa, comandos com os segredos redigidos. Cada mensagem do chat diz o que a ilha mostra. Por uma CLI ou por uma API, uma mensagem ao Zeca leva a data e a hora e uma linha para cada sessão (agente, projeto, estado, o passo dela com os segredos redigidos), nunca o comando de um card. Com a memória ligada, o que o Zeca lembra entra quando uma conversa começa, e até 3 trechos lembrados vão com cada mensagem. O microfone só escuta enquanto você segura uma gravação. A voz fica desligada até você baixar um modelo; depois o mic grava só na memória enquanto o botão dele está vermelho (no máximo um minuto), e o whisper.cpp transcreve neste computador. O áudio nunca é salvo nem enviado para lugar nenhum. O Now playing fica desligado até você ligar. Aí o app lê seus players de mídia pelo session bus (MPRIS no Linux) para mostrar a música; isso nunca é guardado nem enviado para lugar nenhum. O que o app pede por conta própria passa por um portão só. Uma requisição feita sem um clique naquele momento (a verificação de um conector, a leitura de uso do Codex, os cards e as respostas de um telefone pareado, as ferramentas da web, o resumo do diário, as sugestões de memória e o sono do Zeca) pergunta antes ao portão de rede do app: só um recurso que você ligou, cada um com o próprio limite diário (veja a tabela), cada requisição guardada como uma linha no vults.sqlite (quando, qual recurso, se respondeu; 30 dias). Um conector que passa do limite espera e diz isso em Settings → Connectors. O que ele guarda fica neste computador, nunca é enviado para lugar nenhum e está listado em Configurações e arquivos; o Clear history apaga quase tudo:\nAs edições que ele mostra ficam na memória: as linhas alteradas de uma edição concluída (no máximo 400), dos últimos passos da sessão, nunca gravadas em um arquivo ou log. Os conectores guardam só a última resposta, para que um reinício não repita notícias antigas (Conectores). O histórico de atividade é só contagem: nunca um prompt, uma resposta, um comando, um nome de arquivo ou um caminho (Atividade). Os turnos do Zeca ficam registrados por 30 dias: motor, modelo, tokens, custo e o alvo redigido de cada ferramenta, nunca um prompt ou uma resposta (O Nest). As conversas do Zeca ficam guardadas, as 200 mais recentes, nunca a resposta a um card nem uma regra Always in this chat (Conversas). A memória do Zeca fica desligada até você ligá-la, e só você a escreve: o que o Zeca, um modelo ou o servidor MCP dele adicionariam espera o seu sim, e o CLAUDE.md de um projeto só muda sobre o arquivo que você viu, depois de um backup datado (A memória do Zeca). Toda resposta fica registrada. Um log de auditoria guarda, por 90 dias, cada resposta a um card, do bando e do chat do Zeca: quem a deu (você, o seu telefone pareado, uma regra Always, o Always in this chat do chat, uma política com o consentimento dela, o acesso total do chat, ou o app quando o tempo de um card acabou ou o Paused o mandou para o terminal), o que ela fez (permitir, negar, sempre permitir, permitir nesta conversa, responder, mandar para o terminal, ou o tempo acabou), o agente, o nome da pasta do projeto, a ferramenta e o comando ou caminho exato, com tokens e valores NOME=segredo redigidos antes. Uma resposta dada no próprio terminal do agente não entra. Cada configuração de agente que o instalador escreve também fica. Uma linha nunca é alterada e nenhuma sai antes de 90 dias, exceto pelo Clear history, que deixa uma linha: que você o limpou, e quando. Fica sempre ligado. O que você aceita fica guardado para sempre. Cada política que você aceita é uma linha nos consentimentos do vults.sqlite: quando, sobre o que é, as palavras que você aceitou e um SHA-256 do diff que você viu. Uma linha nunca é alterada nem apagada, e o Clear history não mexe nela: uma política nunca pode perder a prova de que você disse sim. Revogar desliga a política na hora; a linha fica, marcada como revogada. As palavras da linha são a própria política, e uma cujo diff não termina nessas palavras nunca responde. Os segredos ficam no chaveiro do sistema, e não há telemetria. Toda requisição que o Vults faz # Nada mais chega à rede. O CI confere: o scripts/check-network.sh falha num crate que depende de um cliente HTTP, ou num arquivo que nomeia um ou inicia um comando de rede, fora do scripts/network-allowlist.txt, que nomeia cada um e o motivo; e num webview que possa se conectar a qualquer lugar além do próprio app.\nRequisição Quem inicia O que a liga Onde Um turno do chat por uma API (Anthropic, OpenAI, Gemini, OpenRouter, Groq, DeepSeek, Mistral, xAI; Ollama e LM Studio em 127.0.0.1) Você, a cada mensagem O provedor e a chave que você escolheu; enviado só a esse provedor crates/chat/src/api.rs, openai.rs, providers.rs A lista de modelos de um provedor Você, ao abrir Settings → Chat \u0026amp; voice com uma chave salva (ou um Ollama ou LM Studio local), ou com Try again O provedor e a chave que você escolheu crates/chat/src/providers.rs Uma busca na web (a web do Zeca, Settings → Chat \u0026amp; voice, desligada até você ligar) O modelo do chat por API, num turno que você mandou; pelo portão de rede (200 por dia, com as leituras de página) Brave Search ou Tavily com a sua chave, ou o seu SearXNG crates/chat/src/web.rs, app/src/web_tools.rs A leitura de uma página (o mesmo interruptor) O modelo do chat por API, num turno que você mandou; pelo portão de rede (os mesmos 200) O site da página, só endereços públicos; o texto dela então vai para o seu provedor de API numa chamada própria, sem ferramentas crates/chat/src/web.rs, app/src/web_tools.rs Os cards e as respostas de um telefone pareado (Settings → Phone, desligado até você ligar) O app: cada card que ele manda, e uma leitura da caixa de cada telefone a cada 25 s; pelo portão de rede (10.000 por dia) O relay que você escolheu, que só vê mensagens seladas; em Direto, este computador escuta no endereço que você deu crates/relay/src/client.rs, app/src/phone.rs A lista de modelos do Codex Você, abrindo o seletor de modelo do chat com o Codex (uma vez por execução) O codex em que você fez login, pelo model/list do codex app-server crates/chat/src/codex_server.rs Um turno do chat pelo claude ou pelo codex Você, a cada mensagem O motor que você escolheu; a CLI fala com o próprio serviço no seu login crates/chat/src/claude.rs, codex.rs, codex_server.rs A sessão de uma tarefa (o claude ou o codex app-server na worktree da tarefa) Você, ao clicar em Start with Claude Code ou Start with Codex numa tarefa; o turno dela roda até acabar ou você dar Stop A CLI fala com o próprio serviço no seu login, no sandbox dela, cada comando perguntando antes app/src/runs.rs, crates/chat/src/claude.rs, codex_server.rs A leitura de uso do Codex (account/rateLimits/read, pelo codex app-server) O app, a cada 5 minutos e meio minuto depois que uma janela reinicia, nunca com a tela bloqueada Settings → General → Codex usage, pelo portão de rede (400 por dia) app/src/usage.rs Um dia passado do diário do Zeca resumido (Settings → Chat \u0026amp; voice → Memory → A summary of each day, desligado até você ligar) O app, numa passada de hora em hora: cada dia passado sem resumo desde que você ligou, até 3 por passada; pelo portão de rede (8 por dia) O claude em que você entrou, o menor modelo dele, sem ferramentas e sem nenhuma das suas configurações crates/chat/src/summary.rs, app/src/journal.rs Um embedding de um resumo do diário ou da sua mensagem, para lembrar (Recall by meaning, desligado até você ligar) O app, na passada de hora em hora do diário para cada resumo sem um, e antes de cada mensagem do chat Um Ollama em 127.0.0.1 com o nomic-embed-text, nunca por um proxy; nada sai do computador crates/chat/src/embed.rs, app/src/recall.rs Sugestões de memória de uma conversa que você deixou (Suggest what to remember, desligado até você ligar) O app, quando você começa uma conversa nova ou abre outra; pelo portão de rede (20 por dia), só com pelo menos 2 mensagens suas, nunca para uma que leu conteúdo de fora O claude em que você entrou, o menor modelo dele, sem ferramentas e sem nenhuma das suas configurações; o que ele propõe espera o seu sim crates/chat/src/summary.rs, app/src/memory.rs O sono do Zeca (Let Zeca sleep on it, desligado até você ligar): o que ele lembra sobre você e entre projetos, e os resumos dos últimos 7 dias O app, uma vez por dia a partir das 2h enquanto nada trabalha; pelo portão de rede (4 por dia) O claude em que você entrou, o menor modelo dele, sem ferramentas e sem nenhuma das suas configurações; as junções dele esperam o seu sim app/src/sleep.rs, crates/chat/src/summary.rs A verificação de um conector (GitHub, pelo gh) O app, no seu próprio ritmo O interruptor de cada conector em Settings → Connectors, pelo portão de rede (3.000 por dia) crates/connectors/src/github.rs O seu calendário de contribuições do GitHub (pelo gh) Você, ao abrir a aba GitHub de Settings → Activity O conector do GitHub ligado crates/connectors/src/github.rs Uma issue a partir de uma tarefa (pelo gh) Você, ao clicar em Open an issue numa tarefa do Nest O conector do GitHub ligado crates/connectors/src/github.rs Um squash merge do seu pull request (pelo gh), com uma linha no rastro local Você, ao clicar em Squash and merge na linha dele nas Connections da ilha, e depois em Merge O conector do GitHub ligado; só o seu próprio pull request, aprovado, com os checks passando crates/connectors/src/github.rs, app/src/connectors.rs O download de um modelo de voz Você, com um clique em Settings → Chat \u0026amp; voice → Voice Nada até você clicar; do Hugging Face (ggerganov/whisper.cpp), conferido pelo SHA-256 crates/voice/src/models.rs O download do detector de fala (Silero VAD, menos de 1 MB) O app, sozinho, fora do portão, enquanto a voz está ligada e ele falta Um modelo de voz que você escolheu; do Hugging Face (ggml-org/whisper-vad), conferido pelo SHA-256 crates/voice/src/models.rs, app/src/voice.rs O uso do plano do Claude Code O Claude Code, que o entrega à nossa status line Nenhuma requisição nossa o hook A checagem de atualização Ainda não existe (ADR 0019) Vai ficar desligada até você ligar, pelo portão — ","externalUrl":null,"permalink":"/docs/vults/safety/","section":"Documentação","summary":"O que o Vults promete:\nEle nunca bloqueia seu agente. Se o app estiver fechado, lento ou quebrado, o hook sai em milissegundos sem imprimir nada, e seu agente …","title":"Segurança · Vults","type":"docs"},{"content":"\nComece com lazyagents doctor # lazyagents doctor # relatório legível; código 1 se houver problema lazyagents doctor --json # mesmas informações para scripts e relatos de bugs O comando lista agentes e verifica skills, links quebrados, provedores, hooks, limites e plugins. A maioria dos problemas abaixo corresponde ao relatório. Inclua-o ao abrir uma issue (referência).\nAvisos de configuração, temas e plugins aparecem em stderr, antes da saída da CLI ou depois de sair da TUI. As mensagens entre crases abaixo são textos reais do programa, cuja interface continua em inglês; as explicações e soluções estão traduzidas.\nAgentes # Agente aparece como não instalado # Causa: não foi encontrado binário no PATH nem diretório de configuração (~/.claude, ~/.codex, ~/.gemini, ~/.config/opencode, ~/.hermes ou %LOCALAPPDATA%\\hermes no Windows, ~/.pi/agent, ~/.config/crush), nem a localização da variável do agente, como CODEX_HOME. O ambiente usado é o da inicialização: execute no mesmo shell do agente.\nSolução: instale a CLI ou inclua o binário no PATH e reabra o lazyagents. A detecção ocorre uma vez por execução; veja o guia.\nAgente detectado sem versão ou retomada informa que a CLI não está no PATH # Causa: a configuração existe, mas o binário não está no PATH. Skills/sessões funcionam, porém retomar exige a CLI.\nSolução: inclua o diretório do binário no PATH. O detalhe de Agents mostra config in … (binary not in PATH).\nSkills # Falta Git para instalar do GitHub # Mensagem: installing from GitHub requires git in PATH. Instale git. Pasta local e ZIP funcionam sem ele.\ngit clone falha # A mensagem contém o erro do próprio Git. Confira nome/URL do repositório, rede e credenciais para repositórios privados.\nNenhum SKILL.md encontrado # Mensagem: no SKILL.md found in …. A origem não contém SKILL.md em nenhuma profundidade. Confira o repositório ou pasta: cada skill deve conter esse arquivo.\nFalta autenticação ou CLI do GitHub para buscar # Mensagem: searching requires the GitHub CLI (gh) in PATH, logged in. A busca S usa gh api. Instale a CLI e execute gh auth login. Outros erros aparecem como GitHub search: ….\nSkill local não gerenciada # Mensagem: … is local (unmanaged) — o to adopt.\nCausa: pasta real ou link de outra ferramenta no diretório do agente, não link da biblioteca. O lazyagents não apaga conteúdo real.\nSolução: incorpore com o, A para todas ou lazyagents adopt \u0026lt;skill\u0026gt; --agent \u0026lt;id\u0026gt;. A pasta vai à biblioteca e recebe um link em seu lugar. Links de terceiros não são incorporáveis: use a ferramenta original.\nNome já existente ao ativar # Mensagem: a skill with this name already exists. O diretório do agente já contém esse nome; a mensagem informa o caminho. Remova, renomeie ou incorpore se for a mesma skill.\nSkill mostra ◆ ou aparece em agentes não selecionados # OpenCode e Crush também leem ~/.claude/skills, então skills ativadas no Claude Code aparecem neles com ◆. Uma skill colocada manualmente em ~/.agents/skills, ou por versão antiga, é visível a Codex, Gemini CLI, OpenCode, Pi e Crush. Desative nos agentes que não devem vê-la; o lazyagents move para os diretórios próprios dos demais. Veja a referência.\ndoctor informa link quebrado # Mensagem: broken symlink. O link aponta para pasta inexistente, geralmente após mover/apagar a biblioteca manualmente. Remova o link ou reinstale e ative a skill. Remoções pelo lazyagents têm backup .tar.gz, restaurável por b em Skills.\nmigrate-library recusa a execução # Mensagem Significado e solução destination already exists or is inaccessible: \u0026lt;path\u0026gt; skill ou link com mesmo nome já existe no destino; nada é presumido migrado. Mova/remova o conflito e tente novamente libraries cannot contain each other / libraries overlap after resolving symlinks um diretório contém o outro; escolha locais separados Se a migração falhar parcialmente, as cópias são desfeitas e a origem permanece.\nSessões # Sessões OpenCode não aparecem # Mensagem: opencode sessions live in SQLite: install sqlite3 to list them. As sessões ficam em opencode.db; instale a ferramenta sqlite3.\nProvedores # String ou array TOML sem fechamento # Mensagem: TOML config has an unterminated string or array; file left untouched. O lazyagents edita Codex linha a linha, acompanhando strings/arrays multilinha. Sem fechamento, não conhece a estrutura e não altera o arquivo. Codex também não conseguiria carregá-lo: feche a string/array e aplique novamente.\nTabela de provedor fora do bloco gerenciado # Mensagem: table model_providers.lazyagents already exists outside the managed block. Há uma tabela [model_providers.lazyagents] manual fora do bloco. Remova ou renomeie e aplique novamente.\nArquivo mudou durante a edição # Mensagem: it changed while lazyagents was editing it … try again. O agente ou outro lazyagents escreveu no mesmo arquivo (settings.json, hooks, config.toml, models.json/settings.json do Pi). O lazyagents preserva a escrita concorrente; sua mudança não é aplicada. Codex/Pi já tentam automaticamente antes do aviso. Repita o comando; se persistir, feche o agente. Veja segurança.\nProvedor aplicado em agente não instalado # Mensagem no doctor: provider applied to an agent that is not installed. A configuração continua, mas o agente foi removido. Limpe com x em Providers ou lazyagents provider clear --agent \u0026lt;id\u0026gt;, ou reinstale o agente.\nHooks # Hook do Codex não executa # Codex exige duas aprovações que o lazyagents deliberadamente não escreve:\nhooks are off in Codex: set hooks = true under [features] in config.toml: acrescente em ~/.codex/config.toml. a new hook only runs after you confirm trust in Codex itself: aprove cada novo comando no próprio Codex. Só você pode dar esse consentimento. Veja segurança.\nComando de hook ausente ou sem permissão # Mensagens: \u0026lt;command\u0026gt;: not in PATH, not found, not executable. Corrija caminho/permissões do script ou edite o hook em ~/.local/share/lazyagents/hooks/.\nConsumo # Limites de assinatura não aparecem # Agentes sem dados ficam de fora dos limites e do doctor, sem aviso:\nClaude Code: não instalado, não autenticado (execute /login) ou com chave de API, que não tem limite de assinatura; mostra custo em vez disso. Codex: nunca usado nesta máquina ou ainda sem limites registrados. Use uma vez e atualize: os limites vêm das sessões. Mensagem Solução Claude Code session expired: open the CLI to renew it abrir Claude Code uma vez Cache dura 5 minutos. Use r em Usage ou lazyagents usage limits --refresh. Claude Code exige rede; Codex lê arquivos locais.\nNúmeros antigos ou incorretos após atualizar # O cache fica em ~/.local/share/lazyagents/transcript-index.gob. Índices de outra versão ou danificados são reconstruídos automaticamente. Pode apagar: a próxima execução relê todas as conversas, o que pode demorar.\nConfiguração e temas # Configuração YAML inválida # Mensagem: parsing config: …; using defaults. O programa usa padrões e preserva o arquivo. Corrija a sintaxe; veja as chaves.\nAviso de configuração da TUI # Mensagem: config tui: …. ID ou valor desconhecido em tui:; é só aviso, o restante da disposição se aplica.\nTema desconhecido # Mensagem: unknown theme: \u0026lt;id\u0026gt; in \u0026lt;config path\u0026gt;; using \u0026quot;sp-night\u0026quot;. theme: não corresponde a tema incluído nem arquivo em ~/.config/lazyagents/themes/. Confira os IDs. Arquivo personalizado inválido informa a causa, como papel ausente ou cor inválida.\nPlugins # Plugin ignorado # Mensagem: plugin \u0026lt;file\u0026gt; ignored: ….\nMotivo literal Solução not executable executar chmod +x no arquivo name must match … renomear com minúsculas, dígitos, - e _, até 32 caracteres duplicate id dois arquivos com mesmo nome sem extensão; manter um id reserved by a built-in tab or command renomear para não colidir com skills, list, doctor… Aba de plugin em erro # O plugin não respondeu em 3 s, escreveu fora do protocolo ou terminou. A aba mostra causa e final de stderr. Corrija e pressione r ou :reload. lazyagents doctor mostra a negociação inicial fora da TUI. Veja as dicas.\nAinda precisa de ajuda? # Abra uma issue com lazyagents doctor --json, sistema operacional, agentes e versões. Remova dados privados como caminhos e URLs de provedores antes de publicar.\n","externalUrl":null,"permalink":"/docs/lazyagents/troubleshooting/","section":"Documentação","summary":"\nComece com lazyagents doctor # lazyagents doctor # relatório legível; código 1 se houver problema lazyagents doctor --json # mesmas informações para scripts e …","title":"Solução de problemas · lazyagents","type":"docs"},{"content":"\nOnde cada coisa fica (Linux) # Caminho O quê ~/.config/vults/settings.json As configurações do app. Um campo que ele não consegue ler (tipo errado) volta ao padrão e o resto é mantido; antes, o arquivo como estava é copiado para settings.json.bad-\u0026lt;time\u0026gt;. Um arquivo de uma release mais nova é lido até onde esta entende, e antes é copiado para settings.json.v\u0026lt;version\u0026gt;-\u0026lt;time\u0026gt; (veja version abaixo) ~/.local/share/vults/bin/vults-hook O relay de hook que seus agentes executam ~/.local/share/vults/bin/statusline-previous.json O seu próprio statusLine do Claude Code, salvo quando os hooks foram instalados; o hook o executa, e remover os hooks o coloca de volta ~/.local/share/vults/inbox/ Cópias dos arquivos soltos na ilha, apagadas depois de uma semana ~/.local/share/vults/chat/ A pasta vazia que os chats usam quando não há sessão em primeiro plano ~/.local/share/vults/connectors/ O que cada conector viu por último ~/.local/share/vults/vults.sqlite O banco local: o histórico dos turnos dos agentes (só contagens), para Settings → Activity, o log de auditoria das respostas aos cards (90 dias), as políticas que você aceitou (guardadas até você revogá-las, e depois), os telefones que você pareou (as chaves públicas deles e o último contador com que cada um assinou; os revogados ficam, para que um telefone revogado nunca volte), os traces do Zeca (30 dias), as conversas dele (as 200 mais recentes), o diário e os resumos dos dias (90 dias), os vetores do recall, as propostas de memória (as decididas ficam 90 dias), as rodadas de sono, as suas tarefas e o que os agentes custaram por dia e por roost (veja Segurança). O Clear history esvazia quase tudo (o que ele remove e o que fica). O history.jsonl e o days.json das versões anteriores entram nele na primeira abertura ~/.local/share/vults/memory/ A memória do Zeca: um repositório git de pequenos arquivos Markdown, cada mudança um commit (modo da pasta conforme o seu umask). O Clear history não mexe nela; apague a pasta para apagar os fatos dele (A memória do Zeca) ~/.local/share/vults/voice/ Os modelos de voz que você baixou e o detector de fala ~/.local/share/vults/backups/ Backups datados dos arquivos que o Vults edita dentro de um projeto, como um CLAUDE.md que ele fez ler o AGENTS.md (nunca guardados no repositório) ~/.local/share/vults/zeca-mcp.json A configuração de MCP que o Claude Code do chat recebe com --mcp-config: este app rodando como o servidor do Zeca (vults --zeca-mcp); modo 0600 ~/.local/share/vults/zeca-flock.json As sessões da ilha (redigidas) para o flock_list desse servidor, reescrito quando mudam e apagado quando o app fecha; modo 0600 $XDG_RUNTIME_DIR/vults.sock O socket com que o hook conversa (modo 0600) ~/.config/autostart/ A entrada que Start with the desktop adiciona Chaveiro do sistema, serviço io.github.rogeriojunior31.vults, conta \u0026lt;provider\u0026gt;-api-key (anthropic-api-key, openai-api-key, …) As chaves de API do chat, uma por provedor para o qual você deu uma (nunca em arquivo) ~/.local/state/vults/logs/ O log: um arquivo por dia, os últimos cinco são mantidos. Ele registra o que aconteceu (nomes de eventos, decisões, erros), nunca comandos, caminhos ou texto do chat $XDG_CONFIG_HOME e $XDG_DATA_HOME substituem ~/.config e ~/.local/share quando estão definidas. Settings → About mostra a versão do app e os caminhos reais.\nsettings.json # { \u0026#34;version\u0026#34;: 22, \u0026#34;connectors\u0026#34;: { \u0026#34;github\u0026#34;: true }, \u0026#34;sounds\u0026#34;: true, \u0026#34;volume\u0026#34;: 50, \u0026#34;fold_after\u0026#34;: 15, \u0026#34;api_provider\u0026#34;: \u0026#34;openrouter\u0026#34;, \u0026#34;api_models\u0026#34;: { \u0026#34;openrouter\u0026#34;: \u0026#34;anthropic/claude-opus-5.5\u0026#34; } } Chave Padrão Significado version 22 Versão do esquema, para que releases futuras possam migrar o arquivo. Se for mais nova que a do app (você voltou para uma release mais antiga), o app (a partir da 0.1.1) usa as chaves que conhece, guarda o arquivo como estava em settings.json.v\u0026lt;version\u0026gt;-\u0026lt;time\u0026gt; e avisa no log; a próxima mudança que você fizer salva só as chaves que ele conhece, na versão dele. Até lá, cada início guarda mais uma cópia. Se nenhuma cópia puder ser guardada, as mudanças não são salvas. Para voltar às configurações da release mais nova, restaure essa cópia. Um arquivo mais antigo é lido com os padrões para as chaves que faltam nele, e é salvo na versão do app connectors {} Id do conector → ligado sounds true Sons 8-bit volume 50 O volume dos sons, em porcentagem (0 a 100); 50 é o volume em que a 0.1.0 os tocava voice_model ausente O modelo de voz do chat (base, small, turbo), baixado em ~/.local/share/vults/voice/ (junto com o detector de fala, ggml-silero-v6.2.0.bin); ausente deixa a voz desligada voice_language ausente O idioma que o usuário fala para a voz: um código (pt, en), auto para detectar a cada vez, ausente para seguir o idioma do sistema now_playing false Mostra na ilha a música que seus players estão tocando (MPRIS no Linux), com tocar, pausar e pular codex_usage false Lê o uso do plano do Codex para a ilha a cada 5 minutos (e meio minuto depois que uma janela reinicia), pelo codex em que você fez login (cada leitura chega à OpenAI, pelo portão de rede do app). Desligado numa instalação nova; um arquivo de antes da versão 16 o recebe ligado quando há um codex no PATH, para que uma atualização mantenha os medidores que mostrava (a partir da versão 16) web false As ferramentas de web do Zeca no chat por API: uma busca e a leitura de uma página que o modelo pode pedir, cada uma uma requisição pelo portão de rede. Desligado, elas nunca são oferecidas web_engine \u0026quot;brave\u0026quot; Para onde as buscas vão: brave, tavily (cada um com a chave no chaveiro) ou searxng searxng_url ausente O endereço do seu próprio SearXNG (https://…), quando ele é o serviço phone false Responder aos cards por um telefone pareado: cada card vai para ele e as respostas dele são lidas de volta, pelo portão de rede. Definido em Settings → Phone (a partir da versão 17) phone_transport \u0026quot;relay\u0026quot; Como o telefone chega a este computador: relay (por phone_relay) ou direct (este computador escuta em phone_listen) phone_relay ausente O endereço do relay (https://…; http:// só numa rede em que você confia) phone_listen ausente Em direct, o endereço deste computador na sua rede local ou tailnet e uma porta (100.64.0.2:8787) chat_picks ausente O modelo e o esforço do chat por pasta (\u0026quot;\u0026quot; para a pasta vazia dele), depois por motor: { \u0026quot;/home/me/site\u0026quot;: { \u0026quot;claude\u0026quot;: { \u0026quot;model\u0026quot;: \u0026quot;sonnet\u0026quot;, \u0026quot;effort\u0026quot;: \u0026quot;high\u0026quot; } } }. model é um nome que a CLI aceita (opus, gpt-6.1-sol), effort um de low, medium, high, xhigh, max; qualquer um ausente é o padrão da CLI. Definido pelo seletor do chat; uma conversa nova naquela pasta começa com ele native_chat true O claude e o codex do chat leem a sua própria configuração: seu CLAUDE.md, skills, servidores MCP, hooks e regras de permissão; as configurações de um projeto só numa pasta em que você já confiou no Claude Code. Os cards ainda perguntam o que suas regras não liberam. Desligado, o Claude não lê nada disso e o Codex deixa de fora os seus hooks (ele sempre lê o próprio config.toml). Vale a partir da próxima conversa chat_access \u0026quot;ask\u0026quot; Quem responde os cards do Zeca (ADR 0004): ask (um card toda vez), policies (as políticas que você aceitou respondem o que cobrem) ou full (tudo roda sem card, menos comandos destrutivos e o que uma política nega ou manda perguntar; os cards voltam depois que uma conversa lê algo de fora). Muda em Settings → Chat \u0026amp; voice; um valor que ele não consegue ler pergunta. Vale na hora memory false A memória e o diário do Zeca; desligada, nada dela chega a um modelo (A memória do Zeca) (a partir da versão 18) journal_summary false Com memory ligada, A summary of each day do diário, pelo menor modelo do Claude Code (A memória do Zeca) (a partir da versão 18) local_embeddings false Com memory ligada, Recall by meaning, por um Ollama em 127.0.0.1 (A memória do Zeca) (a partir da versão 18) memory_suggest false Com memory ligada, Suggest what to remember a partir da conversa que você deixou (A memória do Zeca) (a partir da versão 18) sleep false Com memory ligada, Let Zeca sleep on it: o sono noturno dele também pede a um modelo junções e um resumo da volta (A memória do Zeca) (a partir da versão 18) journal_summary_since ausente O dia em que journal_summary foi ligado (YYYY-MM-DD): o diário guardado antes nunca vai para o modelo (a partir da versão 18) fold_after 15 Segundos que a ilha aberta espera, depois que o ponteiro sai, antes de se recolher (5 a 120) open_on_hover false Deixar o ponteiro parado sobre a pílula abre a ilha, sem clique; aberta assim, ela se recolhe assim que o ponteiro sai, a não ser que você tenha clicado nela. Não vale no painel. Definido em Settings → General (a partir da versão 11) monitor ausente A tela em que a ilha fica, como fabricante e modelo (\u0026quot;Samsung Electric Company LS27AG32x\u0026quot;); ausente deixa o desktop escolher. Duas telas idênticas têm o mesmo nome, e a primeira vence nest_size ausente A janela do Nest como você a deixou por último, [largura, altura] em pixels lógicos; ausente, ela abre no tamanho padrão (a partir da versão 21) rules [] Regras de permitir sempre: { \u0026quot;agent\u0026quot;, \u0026quot;cwd\u0026quot;, \u0026quot;tool\u0026quot;, \u0026quot;target\u0026quot; }, cada uma comparada exatamente zeca_species \u0026quot;atratus\u0026quot; A espécie do Zeca, pelo id (atratus é o urubu-de-cabeça-preta; os ids estão em ui/src/character/flock/species.ts); um desconhecido desenha o urubu-de-cabeça-preta zeca_look \u0026quot;auto\u0026quot; O que o Zeca usa: auto (o visual do calendário: witch-hat de 1º de outubro a 1º de novembro, santa-hat de 1º a 26 de dezembro, party-hat de 31 de dezembro a 2 de janeiro, bunny-ears da Sexta-feira Santa à segunda-feira depois da Páscoa), none, ou um desses ou um visual do ano todo (sunglasses, west-coast, fitted-cap, mountain-hat, headband, dreads, front-knot, durag, crown, bucket-hat, clock-chain, headphones, shutter-shades, chrome-chain, eye-patch). Um desconhecido vira auto flock \u0026quot;brazil\u0026quot; De onde vêm as aves das outras sessões: brazil (os urubus do Brasil), americas (com os dois condores) ou world (todos os urubus). Cada projeto sorteia a espécie dele daqui, a mesma a cada início; mudar isto sorteia todos os projetos de novo. O urubu-rei vem pelo papel de qualquer jeito presence \u0026quot;island\u0026quot; A predefinição de presença: island (o bando no topo da tela), panel (o Zeca na bandeja do painel; a ilha abre perto do painel quando você clica nele ou quando um card precisa de você), quiet (nada em repouso; um card ainda abre a ilha com o seu som) ou paused (os cards vão na hora para os terminais dos agentes, os conectores param, sem notificações). Arquivos da versão 4 guardam island ou panel e são lidos como estão. Um valor desconhecido vira island zeca true O Zeca, o companheiro: desligado, sem chat, microfone ou atalho de fala, e a bandeja fica sem Chat…; o bando, os cards, as notificações e os conectores funcionam como sempre widget ausente O canto do widget de canto: top-left, top-right, bottom-left ou bottom-right; ausente (o padrão) para nenhum widget. Um valor desconhecido é nenhum widget projects ausente Escolhas por pasta de projeto, definidas pelas ações rápidas de uma sessão ou em Settings → Projects: { \u0026quot;/home/me/site\u0026quot;: { \u0026quot;pin\u0026quot;: true }, \u0026quot;/home/me/x\u0026quot;: { \u0026quot;mute\u0026quot;: true, \u0026quot;hide\u0026quot;: true } }. mute: sem sons nem notificações das suas sessões em repouso (um card mantém os dois); pin: as suas sessões primeiro; hide: as suas sessões fora da ilha, da bandeja e do widget, exceto enquanto uma delas tem um card esperando; species: a ave das suas sessões, um id de espécie do renderer (\u0026quot;vultur\u0026quot;), qualquer uma menos a do urubu-rei (\u0026quot;papa\u0026quot;), ignorada como uma desconhecida (a partir da versão 12). Só as escolhas ligadas são escritas, e um projeto sem nenhuma é removido (a partir da versão 8) delegate ausente Em qual agente as tarefas delegadas de um projeto começam, pelo roost dele ({ \u0026quot;github:me/site\u0026quot;: \u0026quot;codex\u0026quot; }, claude ou codex), definido com /delegate default no chat; quando o projeto tem 10 tarefas terminadas de um tipo, as notas delas escolhem (a partir da versão 19) budget_daily_cents ausente O orçamento diário, em centavos de dólar (500 é $5,00), definido em Activity → Cost, no Nest: em 80% uma notificação, e quando acaba outra, e o Vults não inicia nenhuma sessão nova naquele dia. Nunca para nem bloqueia um agente. Ausente, sem orçamento (a partir da versão 20) budget_told ausente O passo do orçamento já avisado hoje (2026-10-11:1 para 80%, :2 quando acabou), para que um reinício não avise de novo (a partir da versão 20) dnd_until ausente Não perturbe até esse momento, em segundos desde a época Unix: sem sons e sem notificações em repouso, sem lembretes; um card ainda abre a ilha com o seu som (e, no Panel, a sua notificação). Definido em Settings → General; um horário que já passou significa desligado (a partir da versão 9) history true Guardar um histórico local dos turnos dos agentes para Settings → Activity: as contagens de cada turno terminado (12 semanas) e os totais de cada dia (um ano), no vults.sqlite da pasta de dados. Desligado, nada novo é guardado e o que existe fica; Clear history apaga tudo (a partir da versão 13), e o log de auditoria junto recap_shown_week ausente A segunda-feira da última semana cujo card de resumo você leu na ilha, para que ele venha uma vez só (a partir da versão 14) language ausente O idioma do app: en, pt-BR, es ou zh (chinês simplificado), definido em Settings → General. Ausente segue o sistema (LC_ALL, LC_MESSAGES ou LANG; o locale do usuário no Windows), e um idioma que o Vults não fala vira inglês (a partir da versão 15) notifications true Notificações do desktop, só em Panel (no topo da tela a ilha já mostra tudo): uma sessão terminou, falhou ou ficou quieta, e um card esperando, na hora. A única ação delas abre a ilha visitors true De vez em quando, enquanto há sessões abertas, um urubu de fora do bando cruza o céu uma vez, sem nunca pousar api_provider \u0026quot;anthropic\u0026quot; O provedor do chat por API: anthropic, openai, google, openrouter, groq, deepseek, mistral, xai, ollama, lmstudio api_models {} Provedor → o modelo escolhido para ele (as chaves nunca ficam aqui) Configurações de agentes que o Vults edita # Só quando você clica em Write the file, depois de um backup datado e de um diff que você revisou:\nAgente Arquivo O que é adicionado Claude Code ~/.claude/settings.json Uma entrada de hook por evento, executando vults-hook --agent claude, e um statusLine executando vults-hook --agent claude --statusline (se você tem um seu, só o command dele muda, e o hook continua executando o seu) Codex ~/.codex/hooks.json Uma entrada de hook por evento, executando vults-hook --agent codex Antigravity ~/.gemini/config/hooks.json Um hook de nível superior chamado vults, com um handler por evento executando vults-hook --agent antigravity \u0026lt;Event\u0026gt; || exit 0 (timeouts em segundos). Os outros hooks nomeados no arquivo nunca são tocados, Remove hooks… apaga só a chave vults, com tudo o que estiver dentro dela, e desligá-lo com \u0026quot;enabled\u0026quot;: false no Antigravity é respeitado. Um hook vults seu que não executa o nosso nunca é sobrescrito: a instalação é recusada OpenCode ~/.config/opencode/plugins/vults.js (sob $XDG_CONFIG_HOME quando definido) Um plugin nosso, o arquivo inteiro, que repassa os passos, as permissões e as perguntas do OpenCode pelo vults-hook --agent opencode. Um arquivo ali sem a primeira linha Generated by Vults é seu e nunca é escrito Qwen Code ~/.qwen/settings.json Uma entrada de hook por evento, executando vults-hook --agent qwen Copilot CLI ~/.copilot/hooks/vults.json Um arquivo nosso, um hook por evento executando vults-hook --agent copilot. O Copilot lê todos os arquivos dessa pasta; os outros nunca são tocados Cursor ~/.cursor/hooks.json Um hook por evento, executando vults-hook --agent cursor \u0026lt;event\u0026gt; || exit 0; nenhum dos hooks que rodam antes de um passo, cuja saída o Cursor lê como uma decisão Factory Droid ~/.factory/settings.json Uma entrada de hook por evento, executando vults-hook --agent droid Kimi Code ~/.kimi-code/config.toml Uma tabela [[hooks]] por evento, executando vults-hook --agent kimi; os seus comentários e o seu layout ficam O Vults não suporta mais o Gemini CLI. Enquanto os hooks que um Vults anterior instalou em ~/.gemini/settings.json continuarem lá, eles não mandam nada, e Settings → Agents mostra um card do Gemini CLI cujo único botão é Remove hooks… (o mesmo diff, backup datado e clique).\nA variável de pasta de cada agente move o arquivo dele, lida do jeito que o agente a lê: CLAUDE_CONFIG_DIR (Claude Code, no lugar de ~/.claude), CODEX_HOME (Codex, no lugar de ~/.codex, o config.toml também), QWEN_HOME (Qwen Code, no lugar de ~/.qwen), COPILOT_HOME (Copilot CLI, no lugar de ~/.copilot), FACTORY_HOME_OVERRIDE (Factory Droid, no lugar da home: a .factory dele fica dentro), KIMI_CODE_HOME (Kimi Code, no lugar de ~/.kimi-code) e GEMINI_CLI_HOME (o Gemini CLI guarda a sua .gemini dentro dela; lida só para achar os hooks antigos a remover). Aberto pelo desktop, o app não vê o que os arquivos de inicialização do seu shell exportam, então ele pergunta ao seu shell de login uma vez, quando abre, e guarda só essas sete; um shell que leva mais de dois segundos é deixado de lado, e valem as pastas de sempre. O Claude Code e o Codex que o próprio app abre (o chat, a leitura de uso do Codex) também as recebem, então usam as mesmas pastas que no seu terminal. Cada card em Settings → Agents mostra o arquivo que ele edita. O OPENCODE_CONFIG_DIR do OpenCode ainda não é seguido.\nUma escrita nunca deixa meio arquivo: o texto novo vai para um arquivo próprio ao lado, é gravado no disco e só então toma o lugar do antigo. Um arquivo com outros nomes (um hard link, como fazem alguns gerenciadores de dotfiles e ferramentas de backup) é escrito no próprio lugar, então todos os nomes veem a mudança. Um arquivo salvo com marca de ordem de bytes (BOM) ou com quebras de linha do Windows (CRLF) continua com elas.\nEntradas de outras ferramentas são mantidas, e Remove hooks… tira só as nossas. Se você colocar o hook de outra ferramenta no mesmo grupo que o nosso, esse grupo fica: uma atualização muda só o nosso hook nele, e Remove tira só o nosso hook. No Codex, um hook ou grupo que vinha depois de um dos nossos que removemos sobe uma posição, então o Codex pode pedir que você confie nele de novo em /hooks. Uma atualização muda as nossas entradas onde elas estão: o arquivo mantém a ordem das chaves, então o diff mostra só o que mudou. Hooks que executam outra cópia do vults-hook (de outra pasta de dados) avisam isso em Settings → Agents, e Update hooks… os aponta para o deste app (se o seu próprio status line estiver salvo ao lado daquele outro hook, o card não oferece atualização e avisa: remova os hooks primeiro, veja abaixo).\nUma configuração tem um único statusLine, e o Claude Code informa o uso do plano só para ele. Se você tem um seu, a instalação salva o objeto inteiro dele em statusline-previous.json ao lado do hook e muda só o command dele para o nosso (o seu padding e os outros campos ficam); o diff mostra os dois arquivos. O nosso então entrega o uso ao app, executa o seu comando com a mesma entrada (via sh -c, por até 10 segundos) e imprime exatamente o que ele imprime (até 64 KiB), cores incluídas. Se o seu comando sumiu, não consegue iniciar ou demora mais, o status line fica em branco daquela vez, o que ele tiver iniciado em segundo plano também é parado, e o Claude Code segue em frente. Remove hooks… devolve o seu objeto como estava; um statusLine que você mudou desde então não é mais nosso e fica como está. Hooks instalados por outra pasta de dados mantêm a sua linha ao lado do hook deles: remova-os antes de instalar a partir desta.\nAmbiente # Variável Efeito VULTS_NO_LAYER_SHELL Usa uma janela comum sempre no topo mesmo onde existe layer-shell VULTS_LOG Filtro do log, por exemplo debug (padrão info) VULTS_LEAN Renderiza a ilha em software (WebKit sem compositing): cerca de 44 MB a menos, mas o WebKitGTK 2.54 e mais novos deixam partes da ilha sem pintar. Desligado por padrão ","externalUrl":null,"permalink":"/docs/vults/reference/settings/","section":"Documentação","summary":"\nOnde cada coisa fica (Linux) # Caminho O quê ~/.config/vults/settings.json As configurações do app. Um campo que ele não consegue ler (tipo errado) volta ao …","title":"Configurações e arquivos · Vults","type":"docs"},{"content":"Cada comando imprime ajuda com lazyagents help \u0026lt;comando\u0026gt;. Sem argumentos, lazyagents abre a TUI. Plugins externos acrescentam comandos com seus IDs, descritos na ajuda após a instalação (guia). Esta página traduz a referência: comandos, opções, nomes de campos e colunas permanecem literais; a saída do programa continua em inglês.\nCódigo de saída 0 indica sucesso; códigos diferentes de zero indicam falha.\nComando Função list listar skills e quantos agentes as veem enable ativar skill da biblioteca por link simbólico disable desativar removendo o link install instalar do GitHub, ZIP ou pasta remove remover da biblioteca adopt incorporar skill local de agente migrate-library mover biblioteca skills agrupar comandos de skills (skills list = list) sessions listar sessões, recentes primeiro provider gerenciar perfis de endpoint e autenticação hooks listar, instalar e desinstalar hooks usage limites de assinatura, tokens e custo por dia/agente/projeto/modelo doctor diagnosticar agentes, skills, hooks, provedores, consumo e plugins list # lazyagents list [--json] Lista skills da biblioteca e skills locais encontradas nos diretórios dos agentes, com a quantidade de agentes que as veem. ENABLED IN conta os agentes; LIBRARY indica gerenciamento pelo lazyagents.\nOpção Efeito --json cada skill com origem, estado da validação e estado por agente enable # lazyagents enable \u0026lt;skill\u0026gt; [--agent id|--all] Ativa uma skill da biblioteca criando link no diretório do agente. \u0026lt;skill\u0026gt; aceita nome da pasta ou do front matter. Agentes que já a veem ficam como estão. Skills locais precisam ser incorporadas antes.\nOpção Efeito --agent id só esse agente (claude-code, codex, gemini-cli…) --all todos os instalados com diretório de skills; padrão disable # lazyagents disable \u0026lt;skill\u0026gt; [--agent id|--all] Remove o link do agente, mantendo a skill na biblioteca e nos demais. Links únicos em ~/.agents/skills são movidos aos diretórios próprios dos agentes que mantêm a ativação. Skills locais (pastas reais ou links de outra ferramenta) nunca são apagadas; o comando falha para elas.\nOpção Efeito --agent id só esse agente --all todos onde o lazyagents ativou; padrão install # lazyagents install \u0026lt;source\u0026gt; [skill...] [--all] [--hooks] Instala na biblioteca pastas com SKILL.md encontradas em qualquer profundidade. Marketplaces Claude Code (.claude-plugin/marketplace.json) são lidos pelo manifesto. Nomes após a origem restringem a instalação; nome desconhecido instala nada e lista as opções. Nomes já na biblioteca são ignorados com aviso. Sem --all, não ativa: use enable. Sem --hooks, apenas conta hooks, pois executam comandos de terceiros a cada evento.\nOrigem Significado owner/repo repositório GitHub, exige git no PATH https://…, git@…, *.git URL Git, clonada com --depth 1 ./skills.zip arquivo ZIP ~/some/folder pasta local Opção Efeito --all ativar skills instaladas em todos os agentes com diretório, como enable --all --hooks instalar também hooks de plugins em hooks/hooks.json remove # lazyagents remove \u0026lt;skill\u0026gt; Remove da biblioteca e apaga links criados pelo lazyagents que apontam para ela. Antes, faz backup .tar.gz; b em Skills restaura. Skills locais não estão na biblioteca e não podem ser removidas aqui.\nadopt # lazyagents adopt \u0026lt;skill\u0026gt; --agent \u0026lt;id\u0026gt; Copia a pasta local à biblioteca, faz backup da original e a substitui por link. O agente continua vendo a skill e outros podem ativá-la. Links de outras ferramentas são recusados; gerencie-os na ferramenta original.\nOpção Efeito --agent id agente com a cópia local; obrigatória migrate-library # lazyagents migrate-library \u0026lt;dir\u0026gt; Copia todas as skills para \u0026lt;dir\u0026gt;, redireciona links dos agentes, salva libraryDir em config.yaml e só depois remove cópias antigas, com backup prévio de cada skill. Recusa nomes já existentes no destino ou diretórios contidos um no outro. Em falha, links e configuração permanecem como antes.\nExemplo: lazyagents migrate-library ~/.agents/skills.\nskills # lazyagents skills list|enable|disable|install|remove|adopt|migrate-library … Agrupa os comandos acima. lazyagents skills \u0026lt;sub\u0026gt; equivale a lazyagents \u0026lt;sub\u0026gt;, com as mesmas opções. Sem subcomando, executa list. A organização acompanha hooks e provider.\nsessions # lazyagents sessions [--agent id] [--here] [--limit n] [--json] Lista sessões, recentes primeiro. Saída textual usa AGENT, TITLE, CWD e UPDATED; aliases aparecem como alias (title). JSON acrescenta ID e, quando registrado, consumo (input, output, cache_read, cache_write, model). Para chave de API, inclui cost_usd em modelos conhecidos; assinaturas não pagam por token. Para retomar, abra a TUI.\nOpção Efeito --agent id só esse agente; ID desconhecido lista os válidos --here sessões iniciadas no diretório atual --limit n no máximo n; padrão 0, todas --json saída JSON provider # lazyagents provider list|apply \u0026lt;profile\u0026gt;|clear|add \u0026lt;profile\u0026gt;|rm \u0026lt;profile\u0026gt; [--agent id] [--json] [--reveal] Gerencia perfis de endpoint, modelo e autenticação.\nSubcomando Efeito list perfis e configuração aplicada por agente; padrão apply \u0026lt;profile\u0026gt; escrever perfil na configuração dos agentes clear remover o aplicado, preservando o restante add \u0026lt;profile\u0026gt; criar ou substituir perfil rm \u0026lt;profile\u0026gt; apagar da biblioteca; agentes mantêm o aplicado Opção Efeito --agent id limitar aplicação/limpeza; padrão é todos os instalados compatíveis --json listagem JSON --reveal mostrar tokens em texto puro na listagem Opções de add:\nOpção Efeito --base-url url endpoint compatível HTTP/HTTPS --model m modelo; vazio usa padrão do agente --token - ler da entrada padrão; valor literal funciona, mas fica no histórico do shell --env-key VAR variável com token para Codex, Pi e Crush --wire-api api Codex: só responses; Pi: chat padrão, responses ou anthropic; Crush: chat padrão ou anthropic Perfis ficam em providers.json, modo 0600. Tokens são mascarados em texto/JSON salvo --reveal. Aplicar/limpar faz backup do arquivo do agente. Codex nunca recebe token no arquivo: defina --env-key e exporte a variável. Pi/Crush exigem --base-url e --model.\nhooks # lazyagents hooks list|enable \u0026lt;name\u0026gt;|disable \u0026lt;name\u0026gt;|add \u0026lt;name\u0026gt;|rm \u0026lt;name\u0026gt; [--agent id] [--json] Lista hooks da biblioteca e instala/desinstala nos agentes.\nSubcomando Efeito list biblioteca e locais de instalação; padrão enable \u0026lt;name\u0026gt; instalar em agentes com os eventos necessários disable \u0026lt;name\u0026gt; desinstalar add \u0026lt;name\u0026gt; criar entrada com um comando rm \u0026lt;name\u0026gt; apagar da biblioteca; instalações existentes permanecem Opção Efeito --agent id limitar ativação/desativação; padrão todos os instalados compatíveis --json listagem JSON Opções de add:\nOpção Efeito --event name evento, como SessionStart, PreToolUse, Stop --command text comando shell --matcher re filtro de evento, como ferramenta em PreToolUse; vazio aceita todos --timeout n segundos; 0 usa padrão do agente --desc text descrição na aba Hooks executam a cada evento; instalar faz backup primeiro, e hooks externos não são tocados. Codex só executa novo hook após confiança aprovada no próprio Codex; o lazyagents não a escreve. Importe hooks com lazyagents install \u0026lt;source\u0026gt; --hooks.\nusage # lazyagents usage [limits|daily|agents|projects|models] [--agent id] [--since 7d] [--limit n] [--refresh] [--json] Mostra limites, tokens e custo por período/agente/projeto/modelo.\nVisualização Conteúdo sem subcomando painel de limites, bloco atual de 5 horas e resumo do período limits janelas de sessão/semana com consumo e renovação daily tokens por dia agents tokens por agente projects tokens por projeto, usando pasta da sessão models tokens por modelo Opção Efeito --agent id só esse agente --since period início do período: 7d, 24h ou 2026-09-01; padrão 7d --limit n linhas de agentes/projetos/modelos no texto; padrão 10, 0 todas --refresh ignorar cache de 5 minutos e consultar limites novamente --json JSON, não limitado por --limit Tokens vêm das conversas locais; limites vêm das contas dos agentes. Custos em USD só aparecem para chaves de API; assinaturas não pagam por token.\ndoctor # lazyagents doctor [--json] Diagnostica agentes, skills, hooks, provedores, consumo e plugins.\nSeção na saída Verificação detected agents ID e instalação de cada agente skills SKILL.md inválido/incompleto na biblioteca e agentes symlinks links quebrados nos diretórios lidos pelos agentes providers provedor aplicado; configuração em agente não instalado é problema hooks arquivos inválidos, executáveis ausentes/sem permissão e avisos por agente usage autenticação e limites; usa cache recente ou consulta novamente plugins arquivos ignorados, negociação inicial e diagnóstico próprio se declarado --json retorna {ok, agents, sections[{title, report, problems}]}. Sai com 1 se alguma seção reportar problema, 0 se tudo estiver correto.\n","externalUrl":null,"permalink":"/docs/lazyagents/reference/cli/","section":"Documentação","summary":"Cada comando imprime ajuda com lazyagents help \u0026amp;lt;comando\u0026amp;gt;. Sem argumentos, lazyagents abre a TUI. Plugins externos acrescentam comandos com seus IDs, …","title":"Referência da CLI · lazyagents","type":"docs"},{"content":"O vults-hook e o app trocam um objeto JSON por linha através de um socket local.\nTransporte # Plataforma Endpoint Controle de acesso Linux $XDG_RUNTIME_DIR/vults.sock (alternativa /tmp/vults-\u0026lt;uid\u0026gt;/, pasta 0700) socket 0600, SO_PEERCRED Windows \\\\.\\pipe\\vults-\u0026lt;SID\u0026gt; as duas pontas verificam o SID do outro processo macOS planejado getpeereid Mensagens # Do hook para o app, versão 8:\n{ \u0026#34;kind\u0026#34;: \u0026#34;event\u0026#34;, \u0026#34;v\u0026#34;: 8, \u0026#34;id\u0026#34;: \u0026#34;18f…-1a2b\u0026#34;, \u0026#34;agent\u0026#34;: \u0026#34;claude\u0026#34;, \u0026#34;event\u0026#34;: \u0026#34;PermissionRequest\u0026#34;, \u0026#34;wants_reply\u0026#34;: true, \u0026#34;terminal\u0026#34;: { \u0026#34;cwd\u0026#34;: \u0026#34;/home/me/project\u0026#34;, \u0026#34;pid\u0026#34;: 4242, \u0026#34;env\u0026#34;: { \u0026#34;TERM_PROGRAM\u0026#34;: \u0026#34;kitty\u0026#34; } }, \u0026#34;payload\u0026#34;: { \u0026#34;tool_name\u0026#34;: \u0026#34;Bash\u0026#34;, \u0026#34;tool_input\u0026#34;: { \u0026#34;command\u0026#34;: \u0026#34;cargo test\u0026#34; } } } agent: claude, codex, opencode (o nosso plugin), qwen, copilot, ou other para qualquer outra ferramenta (veja Outros agentes). Antigravity, Cursor, Factory Droid e Kimi Code são nativos, mas vão como other, com agent_name antigravity, cursor, droid e kimi. agent_name: só com other, o nome da ferramenta: de 1 a 24 caracteres entre a-z, 0-9 e -. São recusados os nomes para os quais o fio tem um tipo (claude, codex, copilot, opencode, qwen e other) e gemini, que não tem tipo desde a versão 7 mas segue reservado porque os hooks antigos do Gemini CLI podem continuar instalados. Qualquer outro nome, inclusive os desses quatro nativos, é um other com nome, e um other nunca ganha card. Ausente nos outros casos. id: único por mensagem, opaco. zeca: true só num evento do próprio claude ou codex do chat (o hook vê VULTS_ZECA=1 no ambiente dele), ausente nos outros. Um evento assim é trabalho do Zeca: o app nunca o transforma em sessão, card ou pássaro, e ele nunca tem wants_reply, já que o chat pergunta os próprios cards. Definir a variável em outro lugar só esconde aquele agente da ilha; o terminal dele continua perguntando. Todo processo que a CLI do chat inicia a herda: um claude que o chat abre por um comando também fica escondido. terminal: todos os campos são opcionais. env lista só as variáveis definidas entre as que identificam o terminal, mais VULTS_TASK numa sessão que uma tarefa sua começou (a ave dela decola do Zeca). cwd é o cwd do payload, senão a primeira entrada de workspacePaths (Antigravity) ou workspace_roots (Cursor), senão a pasta de trabalho do próprio hook. payload: o JSON de hook do agente sem tool_response, transcript_path (e os transcriptPath e artifactDirectoryPath do Antigravity); as strings são limitadas a 2000 bytes. Duas coisas sobrevivem em tool_response: o error de uma ferramenta e, num PostToolUse, o structuredPatch do Claude Code, cortado nas primeiras 400 linhas (com \u0026quot;cut\u0026quot;: true quando linhas ficaram de fora). Num PostToolUse do apply_patch do Codex, tool_input.command (o patch) guarda até 64 KiB. Os campos são opcionais e o envelope não mudou, então isso não precisou de uma versão nova. Um evento que ainda passaria do tamanho de mensagem de 1 MiB tem as strings cortadas mais curtas e depois fica só com os campos que dizem o que aconteceu (hook_event_name, session_id, cwd, tool_name…): o app descarta uma linha maior sem ler. Um evento assim nunca espera resposta (wants_reply é falso): o card dele não conseguiria mostrar tudo o que o Allow autorizaria, então o próprio terminal do agente pergunta. Um evento espera uma resposta (wants_reply) quando é um PermissionRequest do Claude Code, do Codex, do OpenCode, do Qwen Code ou do Copilot CLI, ou um PreToolUse para AskUserQuestion do Claude Code ou do OpenCode enviado por uma entrada instalada com --ask (vults-hook --agent claude --ask PreToolUse, com um timeout de 120 segundos; o plugin do OpenCode roda o relay do mesmo jeito para a ferramenta question dele, nas palavras do Claude Code). Uma entrada sem a flag tem o timeout curto de todos os outros eventos, então ela nunca espera.\nDo app para o hook, só quando wants_reply é true:\n{ \u0026#34;kind\u0026#34;: \u0026#34;waiting\u0026#34;, \u0026#34;v\u0026#34;: 8, \u0026#34;id\u0026#34;: \u0026#34;18f…-1a2b\u0026#34; } { \u0026#34;kind\u0026#34;: \u0026#34;decision\u0026#34;, \u0026#34;v\u0026#34;: 8, \u0026#34;id\u0026#34;: \u0026#34;18f…-1a2b\u0026#34;, \u0026#34;decision\u0026#34;: \u0026#34;allow\u0026#34; } { \u0026#34;kind\u0026#34;: \u0026#34;answer\u0026#34;, \u0026#34;v\u0026#34;: 8, \u0026#34;id\u0026#34;: \u0026#34;18f…-1a2b\u0026#34;, \u0026#34;answers\u0026#34;: [\u0026#34;Blue\u0026#34;, [\u0026#34;S\u0026#34;, \u0026#34;M\u0026#34;]] } { \u0026#34;kind\u0026#34;: \u0026#34;unsupported\u0026#34;, \u0026#34;v\u0026#34;: 8, \u0026#34;id\u0026#34;: \u0026#34;18f…-1a2b\u0026#34; } waiting vem primeiro, assim que o card está na tela: um humano está sendo consultado, e a decisão pode demorar. Um hook que não ouve nem waiting nem a resposta em 2 s desiste, então um app parado ou congelado (cujo socket o kernel ainda aceita) segura um agente por 2 s, não pelo prazo inteiro de decisão. Uma decisão que chega antes do card (uma regra Always) vem sem ele.\nanswers tem uma entrada por pergunta, na ordem de tool_input.questions: uma string (o rótulo de uma opção, ou as palavras do próprio usuário) ou, numa seleção múltipla, uma lista delas. Vai por posição porque o app só viu as perguntas com as strings limitadas; o hook associa as respostas às perguntas que ele leu.\nUm evento de other nunca tem wants_reply: nada no app responde à permissão de outra ferramenta.\nStatusLine é a entrada de statusLine do Claude Code, enviada por vults-hook --agent claude --statusline. O payload dele é só rate_limits (as janelas de 5 horas e semanal do plano), cost.total_cost_usd (o que os tokens da sessão custariam em preço de API, para o card dela) e session_id; os caminhos, os outros números de custo e o modelo da sessão nunca saem do hook. Antes da primeira resposta da sessão não há rate_limits, e sem custo também nada é enviado. O hook imprime só o que o status line do próprio usuário imprime (salvo na instalação, veja configurações), ou nada quando não há nenhum, então o status line do Claude Code fica como era antes.\nA versão 2 adicionou other e agent_name, depois gemini. A versão 3 adicionou answer. A versão 4 adicionou opencode, que um hook mais antigo mandava como other. A versão 5 adicionou waiting, depois qwen, que um hook mais antigo manda como other (o app o lê como o de qualquer outra ferramenta, sem card). A versão 6 adicionou zeca. A versão 7 removeu gemini: os hooks que sobraram do Gemini CLI não mandam nada. A versão 8 adicionou copilot. O app instala o próprio hook quando inicia, então os dois sempre falam a mesma versão; um evento de outra versão recebe unsupported.\nUma conexão que não recebe resposta, uma resposta para outro id, ou unsupported fazem o hook não imprimir nada.\nLimites # Limite Valor Tamanho da mensagem 1 MiB Hook: conectar 300 ms Hook: evento sem resposta 2 s no total Hook: ouvindo waiting 2 s Hook: esperando uma decisão 110 s App: confirmação de um card pela UI 800 ms App: decisão 108 s App: resposta de um card aceita 107 s a partir de quando a linha do hook foi lida (1 s para a resposta voltar) App: leitura de uma mensagem 5 s App: conexões simultâneas 32 Saída para o agente # O hook transforma uma decisão no formato que cada agente espera. O Claude Code e o Codex leem a mesma saída de PermissionRequest:\n{\u0026#34;hookSpecificOutput\u0026#34;:{\u0026#34;hookEventName\u0026#34;:\u0026#34;PermissionRequest\u0026#34;,\u0026#34;decision\u0026#34;:{\u0026#34;behavior\u0026#34;:\u0026#34;allow\u0026#34;}}} {\u0026#34;hookSpecificOutput\u0026#34;:{\u0026#34;hookEventName\u0026#34;:\u0026#34;PermissionRequest\u0026#34;,\u0026#34;decision\u0026#34;:{\u0026#34;behavior\u0026#34;:\u0026#34;deny\u0026#34;,\u0026#34;message\u0026#34;:\u0026#34;Denied from Vults\u0026#34;}}} O Copilot CLI lê a decisão sozinha:\n{\u0026#34;behavior\u0026#34;:\u0026#34;allow\u0026#34;} {\u0026#34;behavior\u0026#34;:\u0026#34;deny\u0026#34;,\u0026#34;message\u0026#34;:\u0026#34;Denied from Vults\u0026#34;} O plugin do OpenCode lê a resposta que ele entrega ao endpoint de permissão do OpenCode, once ou reject (nunca o always do OpenCode: um Always allow é uma regra do próprio app):\n{\u0026#34;reply\u0026#34;:\u0026#34;once\u0026#34;} {\u0026#34;reply\u0026#34;:\u0026#34;reject\u0026#34;} e, para respostas, uma lista de rótulos (ou as palavras do próprio usuário) por pergunta, em ordem, que ele entrega ao endpoint de perguntas do OpenCode:\n{\u0026#34;answers\u0026#34;:[[\u0026#34;Blue\u0026#34;],[\u0026#34;S\u0026#34;,\u0026#34;M\u0026#34;]]} Uma resposta vira a saída de PreToolUse do Claude Code: a ferramenta roda com as respostas adicionadas à própria entrada, associadas ao texto de cada pergunta (verificado com o Claude Code 2.1.286):\n{\u0026#34;hookSpecificOutput\u0026#34;:{\u0026#34;hookEventName\u0026#34;:\u0026#34;PreToolUse\u0026#34;,\u0026#34;permissionDecision\u0026#34;:\u0026#34;allow\u0026#34;, \u0026#34;updatedInput\u0026#34;:{\u0026#34;questions\u0026#34;:[…],\u0026#34;answers\u0026#34;:{\u0026#34;Which color?\u0026#34;:\u0026#34;Blue\u0026#34;,\u0026#34;Which sizes?\u0026#34;:[\u0026#34;S\u0026#34;,\u0026#34;M\u0026#34;]}}}} Quando o número de respostas não bate com o de perguntas, o hook não imprime nada e o Claude Code pergunta no terminal dele.\n","externalUrl":null,"permalink":"/docs/vults/reference/protocol/","section":"Documentação","summary":"O vults-hook e o app trocam um objeto JSON por linha através de um socket local.\nTransporte # Plataforma Endpoint Controle de acesso Linux …","title":"Protocolo do hook · Vults","type":"docs"},{"content":"As mesmas listas aparecem na TUI: ? abre a ajuda da aba atual e : abre a paleta, que aceita parte do nome dos comandos abaixo. Esta referência traduz as ações; os nomes de comandos e teclas permanecem iguais aos da interface.\nEnquanto um campo, filtro ou confirmação estiver aberto, ele recebe o teclado: esc fecha e enter confirma.\nNavegação # Tecla Ação tab próxima aba shift+tab aba anterior 1-9 ir à aba correspondente : paleta de comandos ? abrir/fechar ajuda q sair Aba Skills # Skills # Tecla Ação enter ler SKILL.md e editar em $EDITOR n criar skill o incorporar à biblioteca A incorporar todas as skills locais d remover com backup i instalar do GitHub/pasta/ZIP S buscar no GitHub Ativação # Tecla Ação ←/→ escolher coluna do agente space alternar no agente escolhido a ativar em todos x desativar em todos Perfis e atualizações # Tecla Ação p perfis: enter aplica, s salva matriz, d apaga u atualizar esta skill U verificar atualizações b backups Lista # Tecla Ação shift+↑/↓ rolar detalhes / filtrar r recarregar Aba Sessions # Sessões # Tecla Ação enter retomar v ler conversa R retomar em outra pasta c mostrar comando m definir alias; vazio remove d excluir com backup Lista # Tecla Ação shift+↑/↓ rolar detalhes pgup/pgdn paginar lista space selecionar em lote/grupo g agrupar por projeto e agente f alternar filtro de agente F buscar nas conversas / filtrar r recarregar Leitor de conversa (v) # Tecla Ação n · N sua próxima mensagem · anterior g · G início · fim m visualização: registro / conversa / ações ] · [ próximo turno/subagente · anterior enter expandir turno escolhido · abrir subagente e etapas (⋯): todas / apenas resposta t comandos (❯): um por linha / resumidos r raciocínio (💭): completo / primeira linha x exportar para Markdown esc voltar à lista Aba Providers # Provedores # Tecla Ação ↑/↓ · j/k selecionar perfil ←/→ selecionar coluna do agente space aplicar no agente; repetir limpa a aplicar em todos os agentes instalados shift+↑/↓ · ctrl+u/d rolar detalhes x limpar provedor de todos n criar perfil no formulário e editar perfil; token vazio mantém o salvo d apagar perfil da biblioteca r recarregar Criar perfil # Comando/opção Ação lazyagents provider add criar pela CLI --token - ler token da entrada padrão Aba Hooks # Hooks # Tecla Ação ↑/↓ · j/k selecionar hook ←/→ selecionar coluna do agente space instalar no selecionado; repetir desinstala a instalar em todos os agentes compatíveis com seus eventos enter escolher comandos do pacote; space alterna, esc volta x desinstalar de todos d apagar da biblioteca pgup/pgdn · ctrl+u/d ler detalhes e comandos longos, inclusive durante seleção shift+↑/↓ rolar detalhes uma linha v leitor completo: ←→ alterna comando/scripts, e edita r recarregar Criar hook # Comando/caminho Ação lazyagents hooks add criar pela CLI ~/.local/share/lazyagents/hooks JSON por hook, editável manualmente Aba Usage # Filtros # Tecla Ação p / P período: hoje · 7 · 30 · 90 dias · tudo a / A todos os agentes ou só um ←/→ · v visualização por dia · agente · projeto · modelo / filtrar linhas por nome esc limpar texto; repetir volta a todos os agentes Consumo # Tecla Ação r atualizar limites, consultando a API ↑/↓ · j/k rolar pgup/pgdn · space rolar uma página g / home voltar ao início Aba Agents # Agentes # Tecla Ação ↑/↓ · j/k selecionar agente shift+↑/↓ · ctrl+u/d rolar detalhes g · G primeiro · último Paleta de comandos # Digite : e parte de um nome. Comandos de abas executam dentro delas.\nEntrada Ação skills abrir Skills sessions abrir Sessions providers abrir Providers hooks abrir Hooks usage abrir Usage agents abrir Agents providers new criar perfil de provedor providers clear limpar provedor de todos usage refresh atualizar limites usage period today período de hoje usage period 7d últimos 7 dias usage period 30d últimos 30 dias usage period 90d últimos 90 dias usage period all todo o histórico usage view daily consumo por dia usage view agents consumo por agente usage view projects consumo por projeto usage view models consumo por modelo usage clear limpar filtros de agente e texto help ajuda da aba atual reload recarregar aba quit sair do lazyagents ","externalUrl":null,"permalink":"/docs/lazyagents/reference/keys/","section":"Documentação","summary":"As mesmas listas aparecem na TUI: ? abre a ajuda da aba atual e : abre a paleta, que aceita parte do nome dos comandos abaixo. Esta referência traduz as ações; …","title":"Referência de teclas · lazyagents","type":"docs"},{"content":"Um telefone pareado recebe os seus cards e envia as suas respostas por um relay: um servidor pequeno que guarda mensagens seladas até o outro lado lê-las. Esta página serve para rodar um, ou para conferir o que ele consegue ver; o pareamento e as respostas estão em O telefone.\nO que ele vê # Cada direção entre o desktop e um telefone tem a sua própria caixa, endereçada por 32 bytes de aparência aleatória que só os dois conseguem derivar das suas chaves. Uma mensagem é selada (XChaCha20-Poly1305, com uma chave vinda do X25519) antes de sair de qualquer uma das pontas e não nomeia aparelho nenhum, então o relay guarda só endereços e texto cifrado: nenhum comando, nenhum projeto, nenhum nome. Ele ainda vê de onde os pedidos vêm e quando, o que pode lhe dizer que duas caixas andam juntas. Uma mensagem fica até a próxima leitura de quem a lê dizer que já a tem, e é descartada depois de 10 minutos mesmo que ninguém a tenha lido. Não há contas e o relay não grava nada em disco.\nO endereço de uma caixa é a sua única chave: quem o descobre pode ler o texto cifrado, ou dizer que já o leu para o relay descartá-lo. Acesse o relay por HTTPS ou por uma tailnet, e mantenha os caminhos dos pedidos fora dos logs de um proxy reverso.\nUma resposta do telefone só vale se estiver assinada pela chave daquele telefone, feita para aquele card exato, no prazo, e nunca vista antes. Um relay que perde, atrasa ou repete mensagens pode fazer um card esperar ou ir para o terminal; nunca consegue respondê-lo.\nComo rodar # A partir da raiz do repositório:\ndocker build -f packaging/relay/Dockerfile -t vults-relay . docker run -p 8787:8787 vults-relay ou sem contêiner:\ncargo run --release -p vults-relay --bin vults-relay VULTS_RELAY_ADDR diz onde ele escuta (0.0.0.0:8787 por padrão). Ele fala HTTP puro: coloque um proxy reverso com TLS na frente, ou acesse-o só por uma tailnet ou pela sua rede local. Um proxy na frente também deve limitar as conexões por endereço: os limites do próprio relay valem para o servidor inteiro.\nLimites # O quê Limite Uma mensagem 64 KiB Mensagens esperando numa caixa 64 Caixas ao mesmo tempo 10.000 Mensagens guardadas no total 256 MiB Uma mensagem não lida 10 minutos Uma leitura esperando uma mensagem 25 segundos Um pedido, com o corpo 35 segundos Conexões ao mesmo tempo (as outras esperam a vez) 1.000 Uma conexão que não envia nada 60 segundos HTTP # Pedido Faz POST /v1/boxes/{box} Guarda o corpo (uma mensagem selada). 202; 400 o corpo não é UTF-8; 404 um endereço que não tem 64 caracteres hexadecimais minúsculos; 413 grande demais; 429 a caixa está cheia; 503 caixas demais, ou bytes demais guardados GET /v1/boxes/{box}?after=n\u0026amp;wait=s Descarta as mensagens até n (quem lê já as tem) e entrega o resto como um array JSON de {\u0026quot;seq\u0026quot;, \u0026quot;msg\u0026quot;}; sem nada lá, espera até s segundos (25 no máximo) por algo chegar. 400 uma query que não são dois números; 404 um endereço que não é um GET /health ok Como testar # Dois substitutos de linha de comando fazem o papel do desktop e do telefone:\ncargo run -p vults-relay --bin vults-relay cargo run -p vults-relay --example desk -- http://127.0.0.1:8787 cargo run -p vults-relay --example phone -- \u0026#39;\u0026lt;o texto do QR que o desk mostrou\u0026gt;\u0026#39; O desk mostra o texto do QR, espera o telefone e manda um card para ele; o phone pareia, mostra o card e envia a sua resposta, assinada; o desk mostra o que o Vults faria com ela.\n","externalUrl":null,"permalink":"/docs/vults/reference/relay/","section":"Documentação","summary":"Um telefone pareado recebe os seus cards e envia as suas respostas por um relay: um servidor pequeno que guarda mensagens seladas até o outro lado lê-las. Esta …","title":"O relay do telefone · Vults","type":"docs"},{"content":"Esta é a tradução da referência gerada dos adaptadores em internal/agent: o que o lazyagents faz com cada agente. Os caminhos são padrões de Linux/macOS. A leitura de sessões está no guia de sessões.\nSkills # Um diretório compartilhado é lido por vários agentes. O lazyagents só coloca o link ali quando a skill está ativada para todos os agentes instalados que o leem; caso contrário, usa o diretório próprio de cada agente.\nAgente ID Ativa skills em Também lê Claude Code claude-code ~/.claude/skills — Codex codex ~/.codex/skills ~/.agents/skills (compartilhado) Gemini CLI gemini-cli ~/.gemini/skills ~/.agents/skills (compartilhado) OpenCode opencode ~/.config/opencode/skills ~/.claude/skills, ~/.agents/skills (compartilhado) Claude Desktop claude-desktop — (não gerenciado localmente) — Hermes Agent hermes-agent ~/.hermes/skills — Pi pi ~/.pi/agent/skills ~/.agents/skills (compartilhado) Crush crush ~/.config/crush/skills ~/.config/agents/skills, ~/.claude/skills, ~/.agents/skills (compartilhado) Recursos # Agente Provedores (escrita) Hooks (escrita) Limites de assinatura Histórico de consumo Indicador de sessão em execução Claude Code ~/.claude/settings.json ~/.claude/settings.json sim sim sim Codex ~/.codex/config.toml ~/.codex/hooks.json sim sim — Gemini CLI — — — — — OpenCode — — — — — Claude Desktop — — — — — Hermes Agent — — — — — Pi ~/.pi/agent/models.json — — sim — Crush ~/.config/crush/crushrc ~/.config/crush/crushrc — — — Variáveis de configuração # As variáveis abaixo movem arquivos dos agentes. O lazyagents usa as mesmas para procurar onde a CLI procura; valores relativos são ignorados.\nAgente Variável O que move Claude Code CLAUDE_CONFIG_DIR ~/.claude: sessões, skills, configurações, hooks e autenticação Codex CODEX_HOME ~/.codex: sessões, skills, config.toml e hooks OpenCode XDG_CONFIG_HOME ~/.config: configuração e skills de opencode/ OpenCode XDG_DATA_HOME ~/.local/share: opencode/opencode.db OpenCode OPENCODE_DB arquivo do banco de sessões Hermes Agent HERMES_HOME ~/.hermes ou perfil de hermes profile use: skills e config.yaml Hermes Agent LOCALAPPDATA só Windows: padrão %LOCALAPPDATA%\\hermes no lugar de ~/.hermes Crush XDG_CONFIG_HOME ~/.config: configurações/skills de crush/ e agents/skills Crush XDG_DATA_HOME ~/.local/share: índice de sessões crush/projects.json Crush CRUSH_GLOBAL_CONFIG pasta de crushrc e crush.json; não muda skills em ~/.config/crush/skills Crush CRUSH_GLOBAL_DATA o próprio ~/.local/share/crush Crush CRUSH_SKILLS_DIR substitui todos os diretórios globais de skills; só esse é lido Pi PI_CODING_AGENT_DIR tudo em ~/.pi/agent Pi PI_CODING_AGENT_SESSION_DIR \u0026lt;diretório do agente\u0026gt;/sessions Eventos de hooks # Um hook só instala em agentes que emitem seu evento; os demais recebem – na TUI. Os identificadores dos eventos permanecem literais.\nEvento Claude Code Codex Crush SessionStart sim sim — UserPromptSubmit sim sim — PreToolUse sim sim sim PostToolUse sim sim — Notification sim — — Stop sim — — SubagentStop sim — — PreCompact sim sim — SessionEnd sim sim — ","externalUrl":null,"permalink":"/docs/lazyagents/reference/agents/","section":"Documentação","summary":"Esta é a tradução da referência gerada dos adaptadores em internal/agent: o que o lazyagents faz com cada agente. Os caminhos são padrões de Linux/macOS. A …","title":"Suporte dos agentes · lazyagents","type":"docs"},{"content":"O Zeca e os vults são urubus-de-cabeça-preta (Coragyps atratus). Cada clipe nasce de algo que um urubu-de-cabeça-preta de verdade faz, para que a ave seja lida como urubu antes de ser lida como luz de status.\nComo é um urubu-de-cabeça-preta # Plumagem preta fosca com um leve brilho azulado; cauda curta e quadrada. Cabeça nua, enrugada e cinza-escura num pescoço curto; olho castanho-escuro sob uma sobrancelha; bico fino e escuro, com a ponta de chifre clara curvada para baixo bem no fim. Pernas cinza-claras. Em voo, asas largas e curtas cujas primárias são branco-prateadas por baixo, abertas como dedos. Como ele se move # Comportamento Como parece Voo batido Três ou quatro batidas rápidas, curtas e rígidas, depois um planeio curto de asas retas (sem \u0026ldquo;V\u0026rdquo;, ao contrário do urubu-de-cabeça-vermelha) Voo planado Círculos largos numa térmica, planando, subindo aos poucos Decolagem Um agachamento e um pulo, depois batidas fundas e pesadas para baixo Pouso Asas para cima e para a frente para frear, pés para fora, asas fechadas só depois de tocar o chão Pousado Ombros curvados, cabeça para a frente; vira a cabeça para observar e inclina para examinar Banho de sol Asas bem abertas, de frente para o sol: os pulsos no alto, a mão pendendo com as primárias abertas, o corpo redondo entre elas Ameaça Penas eriçadas, um chiado de bico aberto Sono Todo afofado, a cabeça virada para trás e deitada nas costas, sob as penas Clipes # Clipe Atividade ou estado Comportamento que ele empresta idle ocioso Observando, piscando, uma respiração de vez em quando, um ajeitar dos pés, uma olhada para trás por cima do ombro think pensando Cabeça erguida e parada, piscadas lentas read lendo Cabeça baixa, varrendo uma linha e descendo para a próxima search buscando Pescoço esticado, viradas rápidas de cabeça, uma inclinada para olhar mais de perto edit editando O movimento de comer: inclina, bica, puxa para trás run executando Puxões rápidos no fio, pés se ajeitando para firmar approval aprovação Pose de banho de sol: olha para você quase o tempo todo, vira a cabeça para um lado e para o outro entre um olhar e outro, e as asas abertas baixam e sobem de novo question pergunta A inclinada curiosa de cabeça, mantida done concluído Um pulo que pousa com um leve achatamento, um alongamento de asa e perna, se acomoda, depois a assinatura da espécie (veja abaixo) fail falha Penas eriçadas, um chiado, uma sacudida; depois abatido, cabeça pendurada e uma asa caída listen o mic do chat está aberto A cabeça inclinada na sua direção, pequenos acenos enquanto você fala dance música tocando (Now playing ligado), o Zeca sozinho Um balanço a cada batida, gingando, um pé batendo sleep dormindo Todo afofado, a cabeça virada para trás sobre as costas, só o alto dela aparecendo por cima dos ombros swallow um arquivo solto em cima dele Desce até o fio, pega, joga a cabeça para trás e engole gape um arquivo arrastado sobre a ilha Cabeça para cima, bico aberto, esperando ele cair dentro preen o ponteiro parado sobre o Zeca Uma sessão de limpeza das penas, cabeça na asa startle um clique no Zeca Um pulo com as asas jogadas para cima, cabeça erguida hello o app abrindo Um pouso com achatamento, um quique para cima bem esticado e um pouso mais suave; depois ele vira a cabeça para você e acena com uma asa speak Sem uso: o Zeca responde só em texto, e nada no app o toca. Ele fica no sprite e no lab, onde os testes visuais o desenham De frente para o chat, o bico abrindo e fechando num ritmo irregular, uma piscada entre as frases fly web Uma saída completa: decola, bate-bate-bate-plana para longe, plana de volta, freia, pousa, vira; cada batida para baixo levanta o corpo uma linha O clipe idle inclui uma sessão de limpeza das penas (cabeça na asa, mordiscadas rápidas), e o done estica uma asa para baixo e para trás, com a perna do mesmo lado, antes da assinatura da espécie: o alongamento que as aves fazem quando terminam algo.\nMais quatro clipes são montados para cada espécie com os quadros dela: doze (a cabeça pesa duas vezes, um tranco que o acorda, então ela vira para as costas e a ave dorme), wake (um olho abre com a cabeça nas costas, a cabeça volta, o alongamento de asa e perna (o urubu-rei, cujo done estica as duas asas, pula essa parte) e uma sacudida nas penas), court (asas meio abertas, cabeça baixa, um pulinho a cada dois tempos e uma olhada para cada lado; os dois condores abrem as asas inteiras, mantêm a cabeça alta e fazem uma reverência) e fed (depois de engolir, o papo estufa sob a faixa e esvazia em três tamanhos, na plumagem da própria ave, só no poleiro).\nA ilha os toca assim:\ndoze: uma ave descansando num poleiro onde ela não plana cochila com ele depois de 90 segundos, ±12% conforme a sessão, e então dorme: o Zeca no fio vazio da ilha e no chat, o bando do Nest e o widget do canto (o bando ocioso da própria ilha plana em vez disso). Com movimento reduzido ela dorme direto. wake: o trabalho acorda uma ave dormindo, que se alonga antes do clipe de trabalho (ou antes de decolar, no trabalho na web). Uma permissão, uma pergunta ou uma falha entra direto, sem alongamento. court: com uma música tocando (Now playing), as aves ociosas do bando fazem o cortejo no fio em vez de planar, e voltam a subir quando ela para. O Zeca sozinho continua dançando. fed: quando o Zeca engole um arquivo no chat, o engolir segue para o papo cheio, que esvazia enquanto ele descansa; pensar, ouvir ou outro arquivo interrompe. O Zeca percebe você # No card de foco e no chat, um Zeca em repouso olha para o ponteiro: por cima do ombro quando ele está atrás, para você (com uma piscada) quando está em cima dele. Deixe o ponteiro parado nele e ele limpa as penas; clique nele e ele se assusta; três cliques seguidos e ele se estufa e chia. Quando o app abre, ele cai direto no fio, pousa com um achatamento (afofado, afundado sobre as pernas dobradas) e um quique, e acena um olá; a ilha recolhe quando ele termina. O achatamento é desenhado com as próprias partes dele, então toda espécie e todo visual sazonal pousa do mesmo jeito. Com movimento reduzido não há olá.\nMarcas sobre a cabeça # Uma pequena marca de pixel sobre a cabeça de uma ave diz o estado dela de relance, nas cores de estado da ilha. Ela fica sobre qualquer pose de cabeça em que a ave esteja, e se repete sozinha.\nMarca Estado Movimento Um balão de pensamento pensando os pontinhos se preenchem um por um ! em âmbar uma permissão espera ele pula ? em ciano uma pergunta ele balança Brilhos verdes concluído eles cintilam e trocam de lugar # em vermelho falhou ele treme Uma gota de suor limite de uso atingido ela escorre z dormindo eles sobem flutuando Elas aparecem no card de foco e no chat (o Zeca em 3x) e no habitat (1x); a pílula compacta não tem espaço sobre as cabeças e mantém os selos dela.\nO bando no fio # O Zeca nunca é a ave de uma sessão: ele fica no fio vazio e no chat. A sessão da frente (a que precisa de você, a que você escolheu ou a primeira a chegar) ocupa o lugar dele com a própria ave; toda outra sessão é um vult. Com o Zeca desligado (Settings → Flock \u0026amp; Zeca), um fio vazio fica vazio: nada de Zeca ocioso, nada da assinatura dele. O vult de uma sessão nova chega planando pela direita e pousa; uma sessão que termina decola e vai embora voando. Cada subagente em execução manda um batedor: um Cathartes (os urubus que acham comida pelo olfato) decola do poleiro da sua sessão e circula baixo ao lado dela, e vai embora quando o subagente termina. No máximo três por sessão, seis no total; só na ilha aberta (a pílula recolhida não tem espaço), nenhum com movimento reduzido. O bando e seus batedores passam por trás do card de um conector (o card do GitHub), nunca por cima do texto dele. Visitantes raros: a cada dez a vinte minutos com sessões abertas, um urubu que não é nenhum dos do fio (um abutre do Velho Mundo ou um condor) chega planando pela direita, sobe uma vez na térmica da ilha e segue o caminho, sem nunca pousar; ele passa por trás dos cards e das linhas, nunca por cima do texto deles. Desligue em Settings → Flock \u0026amp; Zeca; nenhum com movimento reduzido ou enquanto a ilha está escondida. O lab traz um na hora: /lab/?visitor=1. Depois de dois segundos ociosa, a ave de uma sessão decola para o céu compartilhado abaixo da ilha. Uma sessão concluída (o agente esperando o próximo prompt) toca primeiro o clipe de concluído, depois decola quando esse clipe e a assinatura da espécie acabam (seis a oito segundos depois que o estado de concluído aparece); o selo \u0026ldquo;done\u0026rdquo; dela fica até você dispensá-lo. Cada sessão mantém a sua ave nas transições entre compacto e aberto, na própria fase e velocidade de volta. O bando circula sem parar enquanto está ocioso, de dia. Trabalho traz para baixo só a ave daquela sessão; abrir a ilha deixa as outras aves voando. Sem sessões, não há bando decorativo. O dia de um urubu, pelo relógio local: sem sol, sem térmica. Ao amanhecer (6 às 9) as aves ociosas ficam no fio com as asas abertas ao sol (a pose de asas abertas como um clipe sun próprio, sem marca em cima, para nunca agir como um card); das 9 às 17 elas planam; ao entardecer (17 às 19) descem, e à noite dormem no fio, cochilando poucos segundos depois de parar. O Zeca sozinho também toma sol ao amanhecer. Os visitantes raros só vêm de dia, acima dos mais altos do bando. Cada espécie na sua altura: os Cathartes circulam baixo, o urubu-preto no meio, os condores, o urubu-rei e os do Velho Mundo no alto, na pílula como na ilha aberta. Os voos atualizam a 30 fps usando o timer compatível com o desktop. Subidas e retornos em curva preservam a velocidade orbital, com inclinação sutil. Na térmica cada espécie bate as asas como o próprio clipe fly dela (os Cathartes seguem balançando no V entre as rajadas), e quanto mais larga a asa, mais raras as rajadas: a cada 3,6 s no urubu-preto, por volta de 10 s num condor. Uma ave que se inclina na curva é desenhada, não girada: em cinco passos a asa de cima sobe e a de baixo desce e perde algumas colunas, em células inteiras do mesmo tamanho do voo reto. Os quadros de voo usam o cache de bitmaps existente e renderização nearest-neighbor. O céu é um canvas transparente e sem ponteiro dentro da superfície de desktop existente de 720 por 640; ele não aumenta a região de entrada nem remapeia a janela layer-shell do Linux. Com movimento reduzido (inclusive mudanças durante o voo), as aves voltam às suas cenas estáticas. Uma ave ociosa no poleiro cochila depois de 90 segundos, e uma ave ociosa decola depois de 2, cada uma ±12% conforme a sessão, para o bando nunca se mexer no mesmo passo. Cenas escondidas param os timers de desenho. O agente aparece como uma pequena faixa na base do pescoço (laranja Claude, verde-azulado Codex, rosa OpenCode, índigo Qwen, azul Copilot, violeta para qualquer outra ferramenta, o Antigravity incluído), nunca como a cor da ave. Um clipe toca pelo menos 600 ms antes que um mais calmo o substitua; aprovação, pergunta e falha entram na hora. Um voo sempre pousa antes de o próximo clipe começar. As espécies # O Zeca é um urubu-de-cabeça-preta, a menos que você escolha outra espécie para ele em Settings → Flock \u0026amp; Zeca. O bando vem dos urubus do Brasil por padrão; a mesma página amplia para as Américas (com os dois condores) ou para todos os urubus e abutres do mundo. Toda espécie é construída a partir do rig do Zeca em ui/src/character/flock/ (uma paleta, um tamanho a partir das medidas da ave real, alguns detalhes de pixel, e só os clipes em que a ave real se comporta diferente), então todos os clipes do Zeca funcionam em todas as aves.\nTamanho: a envergadura segue a média real (as 37 células do Zeca são 150 cm, então um condor tem 73). A envergadura extra se espalha por igual ao longo do braço e da mão de cada asa, então uma ave grande mantém o pulso, a curva e os dedos em vez de uma barra reta esticada. A pose de banho de sol é desenhada no tamanho de cada espécie, com linhas e colunas acrescentadas dentro da asa e o contorno do corpo redesenhado, então uma ave grande é maior por inteiro, nunca um tronco mais comprido; a asa erguida e o alongamento também crescem com a ave. As pontas das penas da mão só são claras onde as da ave real são (as primárias brancas do urubu-de-cabeça-preta, o prateado dos Cathartes), com as asas abertas, erguidas ou em voo, e o condor-dos-andes mostra o seu painel branco. O comprimento do corpo é comprimido para que as maiores aves ainda caibam na ilha. Os grifos, os condores, o abutre-preto, o abutre-orelhudo e o quebra-ossos têm um corpo alto próprio, com ombros e um pescoço longo que afunda no colar de penas em repouso e se estica quando alerta. Cabeças: toda espécie usa a cabeça do Zeca com a sua pele, o seu olho e o seu bico. De frente, os olhos ficam nas bordas do rosto, com o bico entre eles. As oito maiores (poleiro de 26 linhas ou mais: os dois condores, o quebra-ossos, o grifo, o grifo-do-cabo, o grifo-do-himalaia, o abutre-preto e o abutre-orelhudo) ganham uma cabeça uma linha mais funda e, de perfil, uma coluna mais longa, ou de frente uma coluna de bochecha a mais de cada lado, crescida para cima e para trás, então a ponta do bico e o pescoço ficam no lugar: a cabeça do Zeca num corpo de condor parecia a de uma ave pequena. A sobrancelha entra depois que a espécie pinta a sua pele, então uma testa de penas ou uma cabeça vermelha mantém a sua cor sobre o olho. Asas em voo: uma asa é desenhada no planeio, e as batidas para cima e para baixo a dobram no ombro, mais na mão que no braço, então as batidas são lidas como uma única asa se movendo. Vista de baixo, a borda de ataque é iluminada, as penas de voo atrás dela formam uma faixa mais clara (prateada no urubu-de-cabeça-vermelha e nos urubus-de-cabeça-amarela), a borda de fuga é serrilhada e as primárias se abrem em dedos. Onde as penas de voo da ave de verdade são escuras sob coberteiras claras (o abutre-do-egito, o abutre-das-palmeiras e todos os grifos), a parte de trás da asa é escura; o branco do condor-da-califórnia é um triângulo nas coberteiras, e o quebra-ossos voa com a barriga laranja e a cauda longa em losango. Cada parte de voo também tem uma cópia :molt com uma pena de voo faltando em cada asa, que o voo mostra de dezembro a março (a muda de verão, pelo calendário local). Plumagem em repouso: o urubu-de-cabeça-vermelha é o mais marrom dos três Cathartes, o urubu-de-cabeça-amarela o mais pálido, com as hastes claras das primárias riscando a asa dobrada, e o urubu-da-mata o mais preto, com brilho azul-esverdeado. A cauda branca do abutre-do-egito é uma cunha curta, e o abutre-de-dorso-branco e o abutre-de-dorso-branco-asiático mostram o uropígio branco só como uma faixa na borda das costas, sob a asa dobrada. Quem é quem: o Zeca é a espécie que você escolheu. O core (crates/core/src/flock.rs) dá a cada outra sessão uma espécie do grupo que você escolheu, por um hash do id dela e da estação, um número que o app sorteia ao abrir: uma sessão mantém a sua ave enquanto vive, e o bando muda cada vez que o app abre. Um projeto com três ou mais sessões coroa rei a sessão mais antiga (o urubu-rei), e a coroa fica lá enquanto o foco muda. O rei nunca é sorteado, então continua raro. Assinaturas: toda espécie tem um clipe próprio, a partir de algo que a ave real faz. A ave de uma sessão concluída toca a dela logo depois do clipe de concluído, antes de decolar; o Zeca sozinho num fio vazio (fora do chat) toca a dele vinte segundos depois de se acomodar, e depois uma vez por minuto até cochilar. Uma assinatura que sai do poleiro (urubu-de-cabeça-amarela, grifo-de-rüppell, abutre-de-dorso-branco e abutre-de-rabadilha-branca) acontece no céu: uma vez por volta, enquanto a ave plana, ela toca os quadros de voo dela no seu próprio ponto da volta (crescendo a partir do planeio e voltando a ele, sem passar do topo da ilha), e o urubu-de-cabeça-amarela desce rasante até perto do chão da ilha. O lab também mostra cada uma (/lab/?species=\u0026lt;id\u0026gt;). Com movimento reduzido, o Zeca não toca a dele por conta própria. Espécie Assinatura Urubu-de-cabeça-preta (Coragyps atratus) Se refresca: urohidrose, por isso as pernas parecem brancas Urubu-de-cabeça-vermelha (Cathartes aura) Banho de sol, asas abertas (a pose horáltica); em voo, um V que balança Urubu-de-cabeça-amarela (Cathartes burrovianus) Baixo sobre o capim, balançando rápido Urubu-da-mata (Cathartes melambrotus) Espera o rei abrir a carcaça Urubu-rei (Sarcoramphus papa) Abre a carcaça com o bico mais forte Condor-dos-andes (Vultur gryphus) A cabeça fica vermelha: dominância Condor-da-califórnia (Gymnogyps californianus) Corte: cabeça vermelha, asas abertas, uma reverência Abutre-do-egito (Neophron percnopterus) Joga uma pedra num ovo Quebra-ossos (Gypaetus barbatus) Solta um osso para quebrá-lo Abutre-das-palmeiras (Gypohierax angolensis) Anda pela praia Abutre-de-capuz (Necrosyrtes monachus) O rosto fica vermelho quando agitado Grifo (Gyps fulvus) Estica o pescoço para fora do colar de penas Grifo-de-rüppell (Gyps rueppelli) Sobe mais alto: o voo de ave mais alto já registrado Grifo-do-cabo (Gyps coprotheres) Sente o calor com as manchas azuis do pescoço Grifo-do-himalaia (Gyps himalayensis) Sacode a neve Abutre-de-dorso-branco (Gyps africanus) Pousa no meio de um bando, freando com as asas Abutre-indiano (Gyps indicus) Enfia o pescoço nu na carcaça Abutre-de-bico-fino (Gyps tenuirostris) Sonda com o bico longo e fino Abutre-de-rabadilha-branca (Gyps bengalensis) Decola, mostrando as costas brancas Abutre-preto (Aegypius monachus) Se agiganta sobre os rivais Abutre-orelhudo (Torgos tracheliotos) Investe Abutre-real (Sarcogyps calvus) Sacode a cabeça e as barbelas Abutre-de-cabeça-branca (Trigonoceps occipitalis) Caça presas vivas Visuais # Só o Zeca usa um visual, da estação ou para sempre; os vults mantêm as penas da sua espécie. O core escolhe o visual a partir da data do usuário e da configuração (crates/core/src/looks.rs), e a view o carrega.\nVisual Quando (Auto) witch-hat 1º de outubro a 1º de novembro santa-hat 1º a 26 de dezembro party-hat 31 de dezembro a 2 de janeiro bunny-ears Sexta-feira Santa à segunda-feira de Páscoa (Páscoa pelo cômputo de Meeus/Jones/Butcher) sunglasses Nunca: só quando escolhido nas configurações west-coast Nunca: uma bandana azul de paisley amarrada atrás, com as pontas descendo pela nuca, e óculos envolventes fitted-cap Nunca: um boné fechado preto, aba para a frente, uma logo escrita em branco na frente, e óculos envolventes mountain-hat Nunca: o chapéu alto de feltro com a copa amassada, uma fita escura e aba larga headband Nunca: uma faixa branca na cabeça e um curativo embaixo de um olho dreads Nunca: dreads torcidos descendo pela nuca e ao lado do rosto, até abaixo do queixo, com ponteiras de ouro, e um grill de ouro front-knot Nunca: uma bandana vermelha com nó na testa e as pontas para cima, e uma cruz de ouro numa corrente fina durag Nunca: um durag de seda branco com a cauda descendo pelas costas, um grill de ouro, uma corrente com medalhão crown Nunca: uma coroa de ouro com pedras vermelhas, meio inclinada, e uma corrente com medalhão bucket-hat Nunca: um chapéu bucket vermelho de aba mole, e uma corrente grossa de ouro trançada clock-chain Nunca: óculos grandes de armação branca e um relógio numa corrente, que balança quando ele dança headphones Nunca: fones grandes prateados, a concha sobre o ouvido, e uma corrente de ouro shutter-shades Nunca: óculos brancos de persiana e um medalhão chrome-chain Nunca: uma corrente grossa cromada com um medalhão quadrado grande eye-patch Nunca: um tapa-olho com tira dourada, e uma pilha de correntes de ouro Um visual sazonal é desenhado duas vezes no zeca.py, de perfil e de frente, com onde ele fica na cabeça em repouso e na cabeça de frente. As outras poses seguem de onde a copa e o olho delas se moveram; a olhada para trás usa o perfil espelhado, e em voo ele fica na pequena cabeça de voo. Os outros visuais são compostos de peças (HATS, EYES, GRILL, NECK no zeca.py): uma combinação é uma linha que nomeia um chapéu, óculos, um grill e o que pende do pescoço, e looks() carimba as peças da cabeça numa grade por pose (o grill fica no bico de baixo, que se move mais que a copa), então o renderizador as lê como qualquer visual. Nenhum visual sobe mais de 5 linhas acima da cabeça; o zeca.py recusa um que suba.\nO espaço do pescoço é do corpo: uma corrente pende de baixo da faixa do agente (a faixa, a marca do agente, fica inteira) e uma cabeça abaixada a cobre como cobriria de verdade. Um pingente pende do fio e fica uma célula para trás quando o corpo balança para a frente (a dança, a sacudida de uma falha); o peito o segura na volta. A pose de banho de sol usa a vista de frente; o voo não tem faixa, então nada pende ali. Dormindo, a cabeça virada para trás sob as penas usa o que cobre o alto da cabeça (um chapéu, uma bandana, os dreads, os fones) e nada do que fica no rosto; a corrente pende no peito afofado.\nui/src/character/looks.ts grava um visual numa cópia das cabeças e dos quadros de voo do conjunto: toda cabeça cresce as mesmas linhas em cima e suas camadas sobem o mesmo tanto, então uma troca de pose no meio de um clipe mantém o chapéu no lugar e todo clipe, espécie e cache de quadros funciona sem mudanças. Um visual também pode passar da última linha da cabeça (os dreads descem abaixo do queixo): a grade cresce para baixo, o que não move nenhuma camada. Em outra espécie, o visual segue o olho dela (a crista do condor-dos-andes o desce uma linha). O lab mostra a prévia de cada um (/lab/?look=\u0026lt;id\u0026gt;).\nUm clique com o botão direito no Zeca abre os visuais dele na ilha (ui/src/island/looks.ts), agrupados como acima: os quatro sazonais, os só de cabeça (os óculos de sol e os cinco estilosos sem nada no pescoço) e os nove com corrente. Cada quadradinho é o quadro ocioso dele usando o visual; o que está sob o ponteiro vai para o poleiro como prévia ao vivo. Os grupos ficam em LOOK_GROUPS (ui/src/character/looks.ts), compartilhados com Settings; um teste do core verifica que cada visual tem um lugar ali.\nO Zeca na bandeja # No modo Panel (Settings), o Zeca mora no ícone da bandeja em vez da ilha no topo. O ícone tem dois quadros por estado, escolhidos pela atenção do core: ocioso, trabalhando, precisa de você (o mais chamativo: um card espera), concluído e falhou. Cada quadro é desenhado em 22, 24 e 32 px, e o ícone carrega os três, então o painel escolhe o mais próximo do seu tamanho (22 px no padrão do Plasma) e o mostra sem escala. Em 32 px ele é o próprio quadro da ilha (quando precisa de você, asas abertas mais estreitas que as da ilha, largas demais para o ícone); em 22 e 24, um Zeca menor desenhado para eles: pousado, de cabeça baixa enquanto trabalha, estufado e chiando quando falhou, asas abertas quando precisa de você. Todo estado menos o ocioso também tem um selo redondo no canto superior direito com um glifo escuro: pontinhos de trabalho no branco (o último pisca), precisa de você um ponto de exclamação no âmbar que pisca escuro e volta, concluído um check no verde, falhou um X no vermelho. Os quadros mudam devagar (uma piscada de 0,2 s, fora isso pausas de 0,5 a 4 s), nenhum com movimento reduzido. Um clique abre a ilha junto ao painel; o ícone só chama atenção, nunca responde a um card. Os quadros são desenhados pelo zeca.py em app/icons/tray/\u0026lt;size\u0026gt;/, nunca em tempo de execução.\nOnde a arte fica # design/mascots/zeca/zeca.py é a fonte: paleta, partes (corpo, poses de cabeça, quadros de voo) e clipes, os visuais sazonais e as peças de que os outros visuais são feitos. Rode-o depois de uma mudança; ele escreve ui/src/character/zeca/zeca.json, os quadros da bandeja em app/icons/tray/ e as folhas de revisão design/mascots/zeca/clips.png e design/mascots/zeca/looks.png. Um quadro empilha partes em deslocamentos inteiros, então uma pose de cabeça ou uma piscada é desenhada uma vez e reaproveitada. ui/src/character/flock/ transforma o rig do Zeca em cada outra espécie em tempo de execução (rig.ts guarda as transformações, species.ts as 23 espécies); nada é gerado nem versionado para elas. ui/src/character/sprites.ts desenha os quadros e escolhe um pelo tempo; ele não sabe nada de urubus. O lab (npm run dev, depois /lab/) repete cada clipe em loop e faz uma saída completa: decolagem, cruzeiro batendo asas, uma térmica, um planeio de volta, o pouso. ","externalUrl":null,"permalink":"/docs/vults/animations/","section":"Documentação","summary":"O Zeca e os vults são urubus-de-cabeça-preta (Coragyps atratus). Cada clipe nasce de algo que um urubu-de-cabeça-preta de verdade faz, para que a ave seja lida …","title":"Animações · Vults","type":"docs"},{"content":"Defina theme: \u0026lt;id\u0026gt; em config.yaml. Para criar um tema, veja o guia de temas. Os IDs e nomes próprios permanecem iguais aos do programa.\nID Nome Aparência Descrição sp-night SP Night escuro A cidade às 3 da manhã: fundo azul-violeta do tokyodark com a luz quente dos postes de sódio. sp-night-garoa SP Night Garoa escuro A mesma janela vista pela garoa. Cinza plano: a garoa não esfria a cidade, ela a apaga. sp-night-jaragua SP Night Jaraguá escuro A mesma noite do ponto mais alto da cidade: escuridão voltada ao verde da mata densa, com a torre vermelha e branca iluminada no topo. dracula Dracula escuro Tema escuro de vampiro: roxo, rosa e verde neon sobre cinza-azulado. everforest-dark Everforest Dark escuro Floresta verde confortável: fundo de musgo e tons suaves para os olhos. gruvbox-dark Gruvbox Dark escuro Retrô e quente: marrons terrosos, laranja e amarelo queimado, contraste médio. kanagawa Kanagawa Wave escuro A Grande Onda de Hokusai: tinta sumi, azul de ondas e branco Fuji do papel. nord Nord escuro Ártico e limpo: Polar Night, Snow Storm, Frost e Aurora. onedark One Dark escuro Clássico do Atom: cinza grafite com azul, roxo, verde e laranja equilibrados. rose-pine Rosé Pine escuro Pinheiro natural, pele sintética e um toque de Soho: tons suaves sobre roxo quase preto. rose-pine-dawn Rosé Pine Dawn claro Rosé Pine ao amanhecer: papel creme e tinta roxa. rose-pine-moon Rosé Pine Moon escuro Rosé Pine sob o luar: a mesma atmosfera num fundo um pouco mais claro. tokyonight Tokyo Night escuro Luzes noturnas do centro de Tóquio: fundo azul escuro, azul neon e magenta. tokyonight-storm Tokyo Night Storm escuro Tokyo Night sob tempestade: o mesmo neon sobre azul ardósia mais claro. ","externalUrl":null,"permalink":"/docs/lazyagents/reference/themes/","section":"Documentação","summary":"Defina theme: \u0026amp;lt;id\u0026amp;gt; em config.yaml. Para criar um tema, veja o guia de temas. Os IDs e nomes próprios permanecem iguais aos do programa.\nID Nome Aparência …","title":"Temas incluídos · lazyagents","type":"docs"},{"content":"Tudo flui num só sentido, por um único loop:\nagent ──hook JSON──▶ vults-hook ──protocol line──▶ ipc ──┐ GitHub (gh) ─────────────▶ connectors runtime ─────────────────┤ island clicks (Allow, open, jump…) ────────────────────────────┤ ▼ core::reduce(state, input, now) ──▶ effects │ (answer the hook, State::view ▼ open a URL, jump) island renders Camadas # Os crates formam três camadas sobre uma pequena base. Um crate depende só da própria camada ou de uma mais baixa; scripts/check-layers.sh verifica isso na CI (os testes podem ir além).\nCamada Crates Do que ela cuida Experience app, platform, ui/ Todas as superfícies: a ilha, o widget, as configurações, a bandeja, o Zeca e o bando Connect connectors, chat, voice, media, zeca, link, relay, evals, spike O que vai além dos agentes: GitHub, as CLIs e APIs do chat, o microfone, o que está tocando, um telefone pareado Core core, protocol, peer, ipc, hook, agents, agent-config, store Sessões, eventos, aprovações e decisões: o que os agentes estão fazendo e o que o humano disse base brand, secrets O nome, o chaveiro do sistema Só o app liga as camadas entre si: Connect nunca chama Experience, e Core não conhece nenhuma das duas. Isso mantém barata uma superfície nova (ela desenha State::view e envia intents, ADR 0021) e mantém o Zeca opcional (ADR 0018): ele usa Chat, Voice e Connect, e nenhum deles sabe que ele existe. O corpo dele fica em Experience; o cérebro é o crate zeca em Connect, que lê o bando mas nunca responde a uma permissão (ADR 0018).\nCrate Papel Não pode usar brand O nome, o slug e o bundle id do app; gera ui/src/brand.ts nada protocol Mensagens versionadas hook ↔ app, limites, nomes de socket e pipe tokio, Tauri peer Verificações de mesmo usuário nas duas pontas da conexão tokio, Tauri hook Lê o JSON de hook do agente, o encaminha, imprime a decisão no formato do agente tokio, HTTP ipc Servidor assíncrono: limites de conexão, confirmar-e-depois-decidir, roteamento para o app Tauri core Domínio puro: sessões, aprovações (cada card uma oferta no ledger: presa ao pedido exato, respondida uma vez, só no prazo), classes de ação, as linhas de auditoria, alertas, a view, cujos tipos TypeScript ele gera em ui/src/view.gen.ts (um teste verifica que está atualizado); relógio injetado IO, async, Tauri agents O registro de todos os agentes (id, nome, forma no fio, instalação, como roda, o que consegue fazer; ui/src/agents.gen.ts é o gêmeo dele) e, por agente (Claude Code, Codex, Antigravity, OpenCode, Qwen Code, Copilot CLI, Cursor, Factory Droid, Kimi Code, qualquer outro): nomes de eventos, ferramenta → atividade, entradas de instalação, confiança do Codex; o trait AgentDriver para um agente que o próprio app roda (sem runtime) Tauri, tokio agent-config Edições seguras das configurações dos agentes (JSON, TOML com os comentários mantidos, arquivos de plugin inteiros): leitura estrita, diff, fingerprint, backup, escrita atômica Tauri store O banco local: um vults.sqlite (SQLite embutido), migrações numeradas, o histórico de turnos, o log de auditoria só de acréscimo, os consentimentos (nunca apagados), traces, as conversas do Zeca (com o que cada uma leu de fora e o seu contexto congelado), os telefones pareados e o maior contador com que cada um assinou, o diário do Zeca e os resumos diários com a busca de texto e por vetor, as propostas de memória esperando um sim, as noites dele, as tarefas do usuário e o que os agentes custaram por dia e por roost Tauri, async, a rede chat Chat pelas CLIs claude e codex, com pedidos de permissão, ou por uma API: Anthropic ou uma nuvem compatível com OpenAI com a chave do usuário, ou um Ollama / LM Studio local Tauri zeca O cérebro do Zeca (ADR 0018): uma visão só de leitura do bando, a memória dele como um repositório git de pequenos arquivos Markdown de fatos, cada um com um limite rígido (cada escrita um commit) core (então nada nele consegue construir um Intent), Tauri link O elo com um telefone pareado (ADR 0004): pareamento por QR, envelopes selados com X25519 e XChaCha20-Poly1305 (um relay só vê texto cifrado), respostas assinadas pelas chaves do Keystore do telefone e verificadas antes que o ledger do core as resgate IO, a rede, Tauri relay O relay do telefone (ADR 0004): um servidor axum que guarda e repassa envelopes selados por caixa, com limites e descartados depois de 10 minutos, e o cliente que as duas pontas usam, cada pedido pelo gate de rede do app; depende só do link Tauri, core evals Evals com cassettes (só para desenvolvimento, nunca no app): classes de política, redação, os prompts enviados aos modelos, streams gravados repetidos para injeção ser ligado ao app spike O kit de spike (só para desenvolvimento, nunca no app): um modelo falso, um app falso no socket do hook e um terminal para as TUIs, para gravar os hooks de um agente de verdade sem conta; o scripts/spike.sh roda o kit para cada agente ser ligado ao app secrets O chaveiro do sistema (Secret Service, Credential Manager), indexado pelo bundle id Tauri, arquivos connectors Vults Connect: o trait Connector, o runtime de polling, GitHub Tauri, core voice Apertar para falar: o microfone para a memória (cpal), whisper.cpp neste computador, downloads de modelos verificados por SHA-256 Tauri, core media O que está tocando (MPRIS pelo session bus, pelos sinais dele) e tocar/pausar/pular Tauri, core platform Posicionamento das superfícies no Linux (layer-shell, uma região de entrada por janela), o item da bandeja (um StatusNotifierItem), atalhos globais (o portal do desktop) e pular para o terminal Tauri, core app O shell Tauri: o loop do runtime, effects, comandos, bandeja, configurações — A UI (ui/) é TypeScript sem framework. src/bridge.ts é o único arquivo que fala com o Tauri; src/island/ renderiza a ilha a partir da view, src/character/ desenha as aves a partir dos dados de sprite, e src/surfaces/ guarda todas as outras superfícies, uma pasta cada (widget/, settings/, nest/) com a sua entrada main.ts e a sua folha de estilo. O código usado por mais de uma superfície fica na raiz de src/; as exceções são o painel do chat (src/island/chat.ts, com o Markdown e os ícones dele) e o card do GitHub (src/island/board.ts), que o Nest também desenha, e o visual das páginas das configurações (surfaces/settings/pages.css), que a Week do Nest usa dentro de uma shadow root.\nSignificado no core, aparência na superfície # A view diz o que as coisas significam, para que todas as superfícies concordem (ADR 0021). Cada sessão carrega a sua attention, um nível ordenado (quiet \u0026lt; info \u0026lt; done \u0026lt; failed \u0026lt; needs-you), e a view carrega o maior deles; card marca a sessão cujo card é o primeiro da fila e ainda espera por ele. A ilha só escolhe a aparência: que som cada nível faz, e quanto tempo um estado precisa durar (1,5 s, 3 s para done) antes de virar novidade.\nO runtime transmite a view, quando ela muda, para todas as janelas de uma vez (publish_view), e guarda a última para uma página que carregue depois (current_view). Eventos destinados só à ilha (ponteiro, atalhos, chat) são enviados para o label dela. Um listen comum ouve todos os alvos, então uma superfície nova assina esses eventos pelos helpers com escopo de janela em bridge.ts (getCurrentWebviewWindow().listen) para ficar fora deles.\nA janela do Nest tem dois webviews, o do Nest e o das Configurações, um visível por vez sob o mesmo cabeçalho (ADR 0021). Os comandos conferem o label do webview que chamou: as chamadas que só as Configurações podem fazer são recusadas vindas do webview do Nest, que mostra texto de agente.\nended lista os cards que saíram da fila mais recentemente, cada um com o seu outcome: respondido aqui (allowed, denied, answered), released (enviado daqui para o terminal), terminal (o agente seguiu em frente), expired ou rule (um Always num card idêntico). A ilha lê isso para dizer o que aconteceu com o card que ela mostrou. Um outcome é só informação: ele é registrado onde um card sai da fila e nunca responde a um.\nfront é a sessão em primeiro plano, por uma única regra: a sessão cujo card espera, senão a que o usuário pôs em primeiro plano (focus, definida por Intent::Focus a partir de um clique na linha dela, esquecida quando a sessão sai), senão a primeira. O trabalho sozinho nunca a muda. As sessões vêm na ordem em que chegaram, a ordem em que todas as superfícies as desenham, e a que Intent::FocusNext e FocusPrevious (atalhos globais) percorrem, dando a volta. O chat trabalha na pasta da sessão em primeiro plano.\nPor que o hook espera uma confirmação # Um pedido de permissão mantém a conexão aberta. O servidor só espera por um humano depois que o loop do app pegou o pedido e o core enfileirou o card dele (Effect::AckPermission). Se o app estiver travado ou não estiver escutando, o agente recebe a resposta (silêncio, então ele pergunta no terminal) em 800 ms em vez de dois minutos. A ilha abre num card enfileirado e fica aberta até ele ser respondido; nenhum modo de presença pode escondê-lo depois de confirmado (ADR 0021).\nPor que só o core produz uma decisão # core::reduce transforma um evento PermissionRequested em estado pendente, e só o clique de um humano transforma estado pendente num effect RespondPermission: Intent::Decide (Allow, Deny) ou Intent::DecideAlways, que também salva uma regra. Uma regra salva só responde a um pedido que bate com ela exatamente: o mesmo agente, pasta, ferramenta e alvo (ADR 0004). Uma pergunta (QuestionAsked) espera do mesmo jeito, e só um Intent::Answer que se encaixe nas perguntas dela a transforma num effect AnswerQuestion. Um teste alimenta todas as outras entradas em todas as ordens e verifica que nenhuma delas responde.\nA ilha no Wayland # A ilha é uma superfície layer-shell mapeada uma vez, num tamanho fixo, e nunca redimensionada nem escondida: o KWin deixa de mostrar uma layer surface redimensionada a partir do webview. A UI desenha a ilha dentro dela e informa o retângulo dela, que vira a única parte que recebe o mouse (a região de entrada); todo o resto passa para as janelas abaixo. O WebKit pausa requestAnimationFrame enquanto acha que a página está escondida, então a UI mede o DOM de forma síncrona e anima com timers.\nO código de plataforma é por janela: cada superfície tem um LayerSpec (namespace, tamanho fixo, as bordas de que ela pende, margem, teclado) e a própria região de entrada, guardados pelo label da janela. Os pedidos de layout e de teclado de uma página agem na janela que os enviou, e só se ela for uma superfície (SURFACES em app/src/lib.rs). Uma superfície nova ganha um spec, o seu label em windows de app/capabilities/default.json e, para a própria página, uma entrada no Vite.\nTestando a ilha sem um agente # cargo run -p vults-hook --example replay envia uma sessão gravada pelo hook de verdade para o app em execução: leitura, busca, a web, uma edição, uma permissão (ela espera a sua resposta, como um agente faria), um comando e o fim. Passe o seu próprio arquivo JSONL (um JSON de hook por linha) e --delay-ms ou --agent codex para mudá-la. ui/lab/ (npm run dev, depois /lab/) mostra todos os clipes e a ilha com estados inventados, sem o app.\nDecisões # Por que o app é construído assim (só Rust, as regras de segurança, um core para todas as superfícies, Zeca opcional, regras antes de modelos) está nos registros de decisão.\nDocumentação # docs/ é a fonte da documentação no site (rogeriojunior31.github.io/en/docs/vults), publicada a cada tag de release; docs/site.json guarda o nome e o resumo que o site mostra. As páginas começam com um # H1, usam links relativos e guardam as imagens em docs/assets/. docs/adr/ guarda os registros de decisão. docs/dev/ é interno e não é publicado; docs/pt-br/ guarda a tradução em português do Brasil (veja o CONTRIBUTING). node tests/visual/docs-shots.mjs refaz as imagens da ilha do README e dos guias a partir do lab; rode antes de cada release.\n","externalUrl":null,"permalink":"/docs/vults/architecture/","section":"Documentação","summary":"Tudo flui num só sentido, por um único loop:\nagent ──hook JSON──▶ vults-hook ──protocol line──▶ ipc ──┐ GitHub (gh) ─────────────▶ connectors runtime …","title":"Arquitetura · Vults","type":"docs"},{"content":"Um plugin é um executável em ~/.config/lazyagents/plugins/ ou $XDG_CONFIG_HOME/lazyagents/plugins/. O nome sem extensão é o ID: vira aba da TUI, subcomando lazyagents \u0026lt;id\u0026gt; e seção \u0026lt;id\u0026gt;: de config.yaml. IDs seguem ^[a-z0-9][a-z0-9_-]{0,31}$ e não podem repetir abas internas (skills, sessions, agents, providers, hooks, usage, plugins) nem comandos da CLI.\nQualquer linguagem serve: o contrato usa JSON Lines na entrada/saída padrão. Há um exemplo shell completo em examples/plugins/hello.\nModos de execução # Comando Quando Contrato \u0026lt;bin\u0026gt; serve abre a TUI protocolo abaixo, processo vivo até fechar a TUI \u0026lt;bin\u0026gt; \u0026lt;args…\u0026gt; lazyagents \u0026lt;id\u0026gt; \u0026lt;args…\u0026gt; repassa stdin/stdout/stderr e código de saída \u0026lt;bin\u0026gt; doctor doctor, se o manifesto tiver doctor: true problemas em stdout; código diferente de zero indica problema; sem terminal, mostra saída ao terminar; após 30 s falha e encerra árvore de processos Comandos solicitados por exec recebem o ambiente do plugin e são cancelados ao fechar o aplicativo. No Windows, aceita executáveis .exe; o exemplo shell exige ambiente POSIX.\nTodos os modos recebem LAZYAGENTS_HOME, LAZYAGENTS_CONFIG_DIR, LAZYAGENTS_DATA_DIR, LAZYAGENTS_LIBRARY_DIR e LAZYAGENTS_PROTOCOL.\nProtocolo v1 (serve) # Uma mensagem JSON por linha, UTF-8, até 1 MiB. type identifica a mensagem. O hospedeiro é o lazyagents; o plugin lê stdin e escreve stdout. stdout é exclusivo do protocolo: logs vão para stderr, capturado pelo hospedeiro; os últimos 4 KiB aparecem na aba se houver falha.\nHospedeiro → plugin # type Campos Quando init protocol (1), id, home, configDir, dataDir, libraryDir, theme{id, colors{role: \u0026quot;#hex\u0026quot;}} (tokens Primary/Bg/Info e papéis ui.accent/ansi.red; veja internal/tui/theme/README.md), config (seção \u0026lt;id\u0026gt;: de config.yaml em JSON, omitida se ausente), width, height primeira linha após iniciar resize width, height área útil mudou, já descontando cabeçalho, abas e margens key key, text tecla pressionada com aba ativa; nomes Bubble Tea: a, enter, space, esc, ctrl+x, shift+tab paste text texto colado mouse mouse{kind: \u0026quot;wheel\u0026quot;|\u0026quot;click\u0026quot;, x, y, button} coordenadas relativas ao corpo da aba command name escolha de \u0026lt;id\u0026gt; \u0026lt;name\u0026gt; na paleta (:) reload — :reload ou tecla de recarga agents agents[{id, name, installed, version, managedDir, readDirs}] após detecção dos agentes e novamente após reiniciar o plugin exec_result execId, code, stdout, stderr, error exec terminou; stdout/stderr só em execução não interativa, até 1 MiB Teclas globais (q, ?, :, tab, shift+tab, 1–9) não chegam ao plugin, salvo se o último quadro tiver capturing: true, usado enquanto um campo tem foco.\nPlugin → hospedeiro # type Campos Regras manifest title, help[{title, keys[[key, description]]}], commands[{name, desc}], doctor primeira linha, em até 3 s de init; título até 40 caracteres; nomes de comandos seguem ^[a-z0-9][a-z0-9_-]*$, mostrados como \u0026lt;id\u0026gt; \u0026lt;name\u0026gt; frame view, count, capturing estado completo da aba, a qualquer momento; último prevalece; count é o contador da aba, omitido para ocultar exec execId, argv, dir, interactive pede execução ao hospedeiro; interativa suspende a TUI e entrega o terminal (editor/CLI), não interativa executa em segundo plano e retorna saída em exec_result view é texto com \\n. Caracteres de controle usam escapes JSON (\\u001b[1m para ESC). Cores SGR (ESC[…m) são mantidas; outros controles (cursor, limpeza, OSC) são removidos. O hospedeiro recorta ao tamanho da aba e repinta o fundo após cada ESC[0m.\nCiclo de vida e falhas # Ao fechar stdin (EOF), o plugin deve sair. O hospedeiro envia SIGTERM e, 2 s depois, SIGKILL. No Linux/macOS, há um grupo próprio e os sinais atingem todo o grupo; processos restantes são encerrados após a saída. No Windows, o plugin inicia suspenso, entra num Job Object com encerramento ao fechar e só então executa: nada escapa. A parada encerra a árvore (taskkill /T durante execução); restos do job são encerrados após sair, inclusive se o lazyagents morrer. O mesmo vale para exec não interativo; o interativo mantém o terminal e executa como filho comum. Sem manifesto, linha não JSON, type vazio, linha maior que 1 MiB ou processo morto: a aba mostra erro e stderr; :reload reinicia. A TUI continua funcionando. Se o plugin parar de ler stdin e a fila de 256 mensagens encher, o hospedeiro o encerra. Configuração # Crie uma seção com o ID em config.yaml; ela chega inteira em init.config:\nhello: greeting: hi Testes # mkdir -p ~/.config/lazyagents/plugins cp examples/plugins/hello ~/.config/lazyagents/plugins/hello chmod +x ~/.config/lazyagents/plugins/hello lazyagents doctor # negociação inicial e `hello doctor` lazyagents hello a b # argumentos repassados lazyagents # aba Hello Para depurar manualmente: printf '{\u0026quot;type\u0026quot;:\u0026quot;init\u0026quot;,\u0026quot;protocol\u0026quot;:1,\u0026quot;width\u0026quot;:80,\u0026quot;height\u0026quot;:24}\\n{\u0026quot;type\u0026quot;:\u0026quot;key\u0026quot;,\u0026quot;key\u0026quot;:\u0026quot;x\u0026quot;}\\n' | ./hello serve.\n","externalUrl":null,"permalink":"/docs/lazyagents/plugins/","section":"Documentação","summary":"Um plugin é um executável em ~/.config/lazyagents/plugins/ ou $XDG_CONFIG_HOME/lazyagents/plugins/. O nome sem extensão é o ID: vira aba da TUI, subcomando …","title":"Plugins externos · lazyagents","type":"docs"},{"content":"Como o código é organizado e onde cada mudança entra. A versão curta com regras para assistentes de IA é CLAUDE.md; esta página é para pessoas.\nVisão geral # O lazyagents é um único binário Go. Sem argumentos, abre uma TUI Bubble Tea v2; com subcomando, executa sem interface. Ambos usam os mesmos módulos: cada módulo reúne domínio, aba, comandos CLI e verificações de doctor em um pacote.\nmain.go apenas despacho: --version, CLI ou TUI internal/ ├── app/ composição: inicialização, migrações e registro (features.go) ├── feature/ contrato entre módulo e raiz: Feature e Deps ├── core/ caminhos XDG e config.yaml; base da pilha ├── fsutil/ escritas atômicas, backups e rotação ├── agent/ adaptador por agente e interfaces opcionais de recursos ├── cli/ estrutura sem interface: despacho, ajuda, flags e doctor ├── tui/ estrutura TUI: raiz, abas, ajuda, paleta, componentes e temas └── modules/ pacote por módulo ├── skills/ sessions/ providers/ hooks/ usage/ agents/ └── plugins/ plugins externos: processo, protocolo e aba intermediária Dependências apontam em uma direção:\nfsutil ← core ← agent ← {cli, tui/*} ← feature ← modules/* ← app ← main cli e tui não conhecem módulos. O módulo os importa, nunca o contrário.\nMódulos # Um módulo ocupa internal/modules/\u0026lt;name\u0026gt;/:\nArquivo Conteúdo service.go e um por assunto domínio: Service, tipos e entrada/saída; nunca importa tui/ tab.go, view.go, help.go, msgs.go aba; modelo Tab construído por newTab cli.go commands(svc) e checks(svc), não exportados feature.go Feature() feature.Feature, único ponto exportado Quando aba e domínio tratam do mesmo assunto, o arquivo da aba recebe _ui (install.go/install_ui.go).\nA aba não realiza entrada/saída diretamente: chama o serviço em tea.Cmd e recebe uma mensagem. Erros viram avisos, nunca panics.\nAbas se comunicam por internal/tui/events, com dados agregados (map[agent]int), nunca tipos de um módulo.\nAdicionar um módulo # Crie internal/modules/\u0026lt;name\u0026gt;/ com os arquivos acima. Registre em uma linha de features() em internal/app/features.go. A ordem define as abas; Last: true coloca uma aba somente leitura no fim. Leia configurações na seção própria por d.Config.Section(\u0026quot;\u0026lt;name\u0026gt;\u0026quot;, \u0026amp;cfg). Não acrescente chave global. Para arquivos de agentes, acrescente um recurso opcional, conforme a próxima seção. Documente em docs/guide/\u0026lt;name\u0026gt;.md e ligue no índice. Um teste exige o guia (Documentação). Não edite app/app.go, tui/app.go ou cli/cli.go para registrar um módulo.\nAgentes # Só internal/agent conhece caminhos e formatos dos agentes. Todos implementam Adapter (detecção, sessões, retomada, leitura e exclusão). Recursos adicionais são interfaces opcionais verificadas por asserção de tipo:\nInterface Usada por Recurso ProviderHost provedores aplicar/limpar perfil na configuração atual HooksHost hooks ler, acrescentar e remover hooks e eventos RateLimitReader consumo janelas de limite de assinatura UsageEventReader, UsageReader, AuthModeReader consumo e sessões tokens por resposta/sessão e autenticação por token LiveChecker sessões detectar execução atual TranscriptProber sessões pré-verificação rápida de busca textual Adapter não cresce: novo recurso usa nova interface, implementada apenas onde houver suporte.\nConversas chegam como []agent.Entry, com o mesmo formato por agente: papel (mensagem, resposta, raciocínio, ferramenta, evento), horário, tipo de chamada (agent/toolkind.go: shell, edição, leitura, agente, plano, tarefa), linhas adicionadas/removidas, falha e Sub para conversa de subagente ou outro ramo, lida pelo mesmo adaptador como Session.Path. Cada adaptador preenche o que seu formato registra e deixa o restante vazio; o leitor exibe o disponível.\nAdicionar um agente # Implemente internal/agent/\u0026lt;agent\u0026gt;.go: Detect (binário no PATH ou configuração; --version só aqui), sessões e conversas. Confirme formatos na documentação/código da CLI; não adivinhe. Registre em AllWithIndex de internal/agent/registry.go. A ordem define colunas. Implemente recursos compatíveis. Extração de tokens/prévias deve usar lineScanner e índice compartilhado (internal/agent/index.go) para ler cada arquivo uma vez. Dê uma cor por theme.AgentColor. Testes usam casas temporárias (core.PathsIn(t.TempDir())), nunca seu ~. Variáveis que movem arquivos entram em agent.ConfigOverrides após confirmação na CLI. Pacotes que constroem adaptadores chamam agenttest.ClearOverrides() no TestMain. Registre formatos reais: acrescente um gravador em scripts/record-fixtures.go e execute go test ./internal/agent -run TestRecordedFixtures -update. Veja Fixtures gravadas. Execute go test ./docs -update para atualizar a referência. Se houver sessões, mencione no guia. Fixtures gravadas das CLIs # Agentes mudam formatos privados entre versões. internal/agent/testdata/fixtures/\u0026lt;agent\u0026gt;/\u0026lt;version\u0026gt;/ guarda sessões produzidas pelas CLIs reais, por versão; TestRecordedFixtures compara cada adaptador com golden.json. A matriz lista versões e origens.\ngo run scripts/record-fixtures.go grava CLIs instaladas: cada uma usa casa temporária e fakellm, servidor local determinístico dentro do script (OpenAI Chat Completions/Responses e Anthropic Messages), sem conta nem rede. Caminhos viram /work/proj e /home/user; prompts de sistema são removidos. Dados identificando a máquina (usuário, hostname, kernel) fazem a gravação falhar. Nova versão ganha novo diretório; preserve os anteriores como matriz. go test ./internal/agent -run TestRecordedFixtures -update gera os resultados esperados; revise diferenças, pois revelam mudanças de formato. Limites Codex não vêm de modelo falso. -codex-limits-from ~/.codex/sessions copia o formato de rate_limits do rollout mais recente substituindo valores que descrevam a conta. Limites Claude Code vêm da rede. -claude-limits faz a mesma consulta da aba Usage, pela autenticação do Claude Code e Claude.RateLimits; preserva só campos lidos (limits, five_hour, seven_day), substitui valores e nunca grava a autenticação. O teste serve limits.json com credencial fictícia. Regras de proteção dos dados # São válidas em todo o código e verificadas na revisão:\nConfiguração usa fsutil.WriteAtomic. Arquivo do agente recebe fsutil.Backup antes; chaves desconhecidas são preservadas. JSON dos agentes usa a primitiva settings (internal/agent/settings.go), alterando apenas a chave alvo e preservando ordem. TOML do Codex nunca é reserializado. Só blocos entre comentários # lazyagents — … são editados; o resto é copiado literalmente. Ativação de skills usa links. Desativar remove o link, nunca pasta real. Segredos ficam em arquivos 0600, mascarados na TUI/JSON, fora de logs, erros e estruturas exportadas. Sem rede na inicialização. Consultas apenas sob demanda. Consentimento nunca é forjado. Aprovações do agente, como trusted_hash do Codex, ficam com o usuário. Plugins não são confiáveis. Mensagens são sanitizadas; falha deixa apenas a aba em erro. A versão para usuários está em Segurança e dados.\nTemas # Cores existem só em internal/tui/theme. A UI usa tokens (theme.Primary, theme.AgentColor(id)) resolvidos durante renderização; não renderize estilos na inicialização do pacote. Veja internal/tui/theme/README.md e Contribuir um tema.\nDocumentação # Listas existentes no código são geradas dele; o restante é escrito e verificado por testes.\nTipo Local Fonte Como manter Referência docs/reference/ cli.Command Usage/Summary/Help, Help() e Commands() das abas, adaptadores e temas go test ./docs detecta diferenças; go test ./docs -update regenera Guias docs/guide/\u0026lt;module\u0026gt;.md escrita manual, por módulo teste exige guia e link no índice Tópicos docs/*.md escrita manual teste de links Protocolo docs/plugins.md escrita manual muda com versão do protocolo Traduções docs/pt-br/\u0026lt;mesmo caminho\u0026gt; tradução da página inglesa workflow compara marca do original go test ./docs verifica links relativos e âncoras de todos os Markdown do repositório. Renomear título/arquivo pode quebrar o teste antes de quebrar os docs.\nO site rogeriojunior31.github.io/docs/lazyagents publica os docs. .github/workflows/docs.yml chama o workflow compartilhado: em PR, valida título # H1 e links; em tag v*, avisa o site para publicar a release. Use Markdown comum de GitHub: primeiro H1 vira título, docs/README.md é o índice e a ordem dos links define o menu; links relativos são convertidos para páginas do site. docs/dev/ não é público.\nTraduções ficam em docs/pt-br/, com o mesmo caminho relativo do original. Cada uma registra a marca da revisão traduzida abaixo do título:\n# Skills Obtenha a marca com sha256sum docs/guide/skills.md | cut -c1-12. Se o original mudar, o workflow detecta e o site indica desatualização. Só atualize a marca após revisar a tradução. O verificador de inglês ignora docs/pt-br/ e os metadados localizados de docs/site.json.\nIntegração com o site # docs/site.json define nome e descrições por idioma, com schema: 1, name e summary contendo en e pt-br. O site lê a mesma revisão dos docs e metadados. Novos repositórios ainda precisam de cadastro inicial e montagem de módulo no site; não são descobertos arbitrariamente.\nrequiredTranslations: [\u0026quot;pt-br\u0026quot;] torna obrigatória a documentação completa e atualizada em português. Cada Markdown público em inglês deve ter tradução correspondente com a marca atual do original. Traduções ausentes ou antigas fazem os testes, workflow compartilhado e build do site falharem. Revise e traduza mudanças antes de atualizar a marca. Comandos, identificadores e mensagens literais permanecem iguais. Âncoras HTML id preservam os links de seções no GitHub e no site.\nOriginais ficam em docs/; traduções em docs/pt-br/\u0026lt;mesmo caminho\u0026gt;. Use links relativos para as traduções correspondentes. Metadados descrevem o projeto, não produzem traduções. O estado das traduções lista cobertura e marcas atuais.\nPara repetir em outro projeto, copie a estrutura de docs/site.json, escreva docs/README.md, crie as traduções correspondentes com marcas revisadas e reutilize .github/workflows/docs.yml. go test ./docs valida referências, links e metadados; o workflow compartilhado valida metadados, títulos, links e atualização das traduções. Sem SITE_DISPATCH_TOKEN, o site procura docs publicados no build diário.\nO que atualizar por mudança:\nMudança Atualização comando ou flag Help em cli.go, depois go test ./docs -update tecla ou paleta Help()/Commands() da aba e regeneração agente, recurso ou evento de hook adaptador e regeneração tema YAML e regeneração módulo docs/guide/\u0026lt;name\u0026gt;.md e link no índice comportamento visível guia do módulo e CHANGELOG.md arquivo em disco, consulta de rede ou escrita em agente Configuração e Segurança Guias explicam tarefas/conceitos e citam teclas/flags necessárias, ligando à referência completa sem copiar tabelas que ficariam desatualizadas.\nVerificações # test -z \u0026#34;$(gofmt -l .)\u0026#34; \u0026amp;\u0026amp; go vet ./... \u0026amp;\u0026amp; go test -race ./... \u0026amp;\u0026amp; go build ./... scripts/check-english.sh A CI executa os mesmos passos; go test ./... inclui os testes dos docs.\n","externalUrl":null,"permalink":"/docs/lazyagents/architecture/","section":"Documentação","summary":"Como o código é organizado e onde cada mudança entra. A versão curta com regras para assistentes de IA é CLAUDE.md; esta página é para pessoas.\nVisão geral # O …","title":"Arquitetura · lazyagents","type":"docs"},{"content":"Registros de decisão de arquitetura (ADRs): um arquivo por tema que molda o projeto, com a regra em vigor, o contexto em que foi feita e o que ela custa. O código e os guias dizem o que o app faz; estes registros dizem por quê.\nTema Registro Status Incorporados Como decidimos 0001 Registrar decisões como ADRs Aceita Stack 0002 Rust em todo o backend; nenhum sidecar em Python Aceita O hook 0003 O hook nunca bloqueia um agente Aceita Permissões 0004 Quem responde a uma permissão Aceita 0014, 0017, 0025, 0026 Permissões 0027 Uma resposta aberta para qualquer ferramenta que peça uma Proposta Configurações dos agentes 0005 As configurações dos agentes, e os agentes que suportamos Aceita 0029 Ações 0011 Oferecer só as ações que os agentes permitem Aceita Zeca 0018 Zeca: opcional, separado do bando, regras antes de modelos Aceita 0010, 0012 Rede e segredos 0019 Rede, segredos e telemetria Aceita 0006, 0016 Releases 0020 Releases: pequenas e frequentes, a 0.2.0 no portão de Operations Aceita 0007, 0015 Superfícies 0021 Superfícies: um núcleo, quatro tamanhos, um card respondido onde você está Aceita 0008, 0009, 0022, 0023, 0024, 0030 Voz 0028 Voz: escuta local, respostas faladas opcionais Aceita 0013 Um número da última coluna foi um registro próprio até 2026-10-12; um commit ou PR antigo que o cita quer dizer o registro em que ele foi incorporado. Números nunca são reusados: o próximo tema é o 0031.\nComo escrever um # Uma decisão sobre um tema que já tem registro é uma edição desse registro, num PR próprio, com uma linha datada no seu Histórico. Só um tema novo ganha número novo: copie o formato de um registro existente (Status, Contexto, Decisão, Consequências), dê a ele o próximo número e acrescente-o à tabela. Escreva ou edite um quando uma escolha muda uma regra do CLAUDE.md, a arquitetura, o plano de releases ou o que o app promete aos usuários (0001).\n","externalUrl":null,"permalink":"/docs/vults/adr/","section":"Documentação","summary":"Registros de decisão de arquitetura (ADRs): um arquivo por tema que molda o projeto, com a regra em vigor, o contexto em que foi feita e o que ela custa. O …","title":"Decisões · Vults","type":"docs"},{"content":"Um conector observa um serviço externo e põe as novidades dele na ilha: uma verificação que falhou, um pull request aprovado, uma review esperando por você. O GitHub é o primeiro; adicionar outro leva um arquivo Rust, uma linha no registro e uma entrada na UI de configurações.\nO que você escreve # pub trait Connector: Send + Sync { fn id(\u0026amp;self) -\u0026gt; \u0026amp;\u0026#39;static str; // \u0026#34;github\u0026#34; fn interval(\u0026amp;self, last: \u0026amp;Snapshot) -\u0026gt; Duration; // espera após um poll bom, pelo que ele viu fn poll(\u0026amp;self) -\u0026gt; Poll\u0026lt;\u0026#39;_\u0026gt;; // o estado atual do serviço, como um Snapshot fn diff(\u0026amp;self, before: \u0026amp;Snapshot, after: \u0026amp;Snapshot) -\u0026gt; Vec\u0026lt;Event\u0026gt;; // novidades entre dois estados fn board(\u0026amp;self, snapshot: \u0026amp;Snapshot) -\u0026gt; Option\u0026lt;Vec\u0026lt;Row\u0026gt;\u0026gt; { None } // opcional: o card dele } Um Snapshot é um mapa de uma chave estável (pr:owner/repo#12) para qualquer JSON de que você precise para saber o que mudou. Você nunca decide quando algo é novidade pelo relógio: você compara dois snapshots. É isso que torna o resto automático.\nO que o runtime faz por você # Faz poll só enquanto o usuário está com o conector ligado, e para na hora quando ele é desligado. Salva o último snapshot no disco, para que um reinício não repita novidades antigas. No primeiríssimo poll, só registra uma linha de base: nada de uma enxurrada de alertas sobre coisas que já eram verdade. Recua em caso de erro (a partir de 4 minutos, dobrando, até 15, seja qual for o seu interval), espera o fim de Error::RateLimited { retry_after }, e verifica só a cada 10 minutos quando o usuário precisa agir (Error::Unavailable, Error::Auth). Espera interval(\u0026amp;last_snapshot) depois de um poll bom, para que um conector possa fazer poll mais cedo enquanto algo está rodando (GitHub: 60 s enquanto as verificações rodam, senão 300 s). Faz poll antes quando a ilha abre e o último poll, bom ou com falha, tem mais de um minuto (Runtime::refresh_if_stale): novidades frescas, ou uma nova tentativa depois de um erro que o usuário pode ter corrigido. Nunca enquanto desligado, já fazendo poll, ou com limite de taxa. Não envia eventos de um poll que termina depois que o usuário desligou o conector; o snapshot dele ainda é salvo como linha de base. Envia o card (board, quando o conector tem um) depois de cada poll bom, depois dos eventos dele, e o retira quando o conector é desligado. O item de uma linha é a chave dela no snapshot: quando um item sai do card, o core descarta os alertas cujas chaves começam com \u0026lt;item\u0026gt;:. Pergunta ao portão de rede do app (ADR 0019) antes de cada poll: só enquanto ligado, no máximo 3.000 em quaisquer 24 horas, um span request por poll no vults.sqlite. Uma recusa espera 10 minutos e mostra Budget spent. O Runtime::start recebe o portão; não há como fazer poll por fora dele. Informa o status (ligado, último poll bem-sucedido, erro, itens observados, orçamento esgotado) para as Configurações. Passos # crates/connectors/src/\u0026lt;id\u0026gt;.rs: implemente Connector. Mantenha o poll em uma requisição quando o serviço permitir, e transforme a resposta dele num Snapshot numa função pura que você consiga testar. crates/connectors/src/lib.rs: adicione pub mod \u0026lt;id\u0026gt;; e o conector em all(). ui/src/connectors.ts: adicione { id, name, about }. about diz, em uma frase, o que ele observa e como ele faz login. Links: a url de um evento só é mostrada se core::SafeUrl aceitá-la (https, host permitido). Adicione o host do serviço a HOSTS em crates/core/src/safe_url.rs. Testes: alimente a sua função de snapshot com respostas gravadas e verifique o diff para cada tipo de novidade, e para \u0026ldquo;nada mudou significa nenhuma novidade\u0026rdquo;. Credenciais # Prefira a CLI do próprio serviço em que o usuário já está logado, como o GitHub faz com o gh: o app nunca lida com um token. Quando não há uma CLI assim, o token vai para o chaveiro do sistema (Secret Service, Credential Manager), nunca para um arquivo, e nunca para um log.\nChaves de evento # Event::key identifica a novidade, não só a coisa: pr:owner/repo#12:ci-failed. A ilha substitui um alerta com a mesma chave em vez de empilhar duplicatas, e uma nova falha em outro commit (branch:owner/repo:ci-failed:\u0026lt;sha\u0026gt;) é um alerta novo.\nEvent::topic nomeia a história a que uma novidade pertence (pr:owner/repo#12:ci): um evento mais novo do mesmo tópico aposenta os alertas mais antigos, para que checks passed não fique ao lado da falha que ele corrigiu. Deixe None para novidades que se sustentam sozinhas. Todo evento é novidade para a ilha, mesmo com uma chave que ela já mostrou: uma review pedida de novo toca de novo.\n","externalUrl":null,"permalink":"/docs/vults/contributing/connectors/","section":"Documentação","summary":"Um conector observa um serviço externo e põe as novidades dele na ilha: uma verificação que falhou, um pull request aprovado, uma review esperando por você. O …","title":"Adicionando um conector · Vults","type":"docs"},{"content":"O Vults mostra as sessões de um agente de código pelos hooks que o agente roda nos próprios eventos. A maioria dos agentes cabe em poucas centenas de linhas: um arquivo em crates/agents, uma linha no registro, uma sessão gravada e as docs. Esta página é o checklist, na ordem em que o trabalho anda.\nObservar ou responder # Decida isso primeiro, a partir de uma execução real do agente, nunca só pela documentação dele: o Gemini CLI, o Antigravity e o Cursor pareciam respondíveis no papel e não são.\nSó observar (Antigravity, Cursor, Factory Droid, Kimi Code): a ilha mostra os passos; o agente pergunta as permissões no próprio prompt. Esse é o padrão, e o primeiro PR certo. Responder (Claude Code, Codex, Qwen Code, Copilot CLI): o agente tem um evento enviado só quando perguntaria ao usuário (um PermissionRequest), aceita um allow ou um deny do hook e, com uma resposta vazia, pergunta no próprio prompt. Um hook que roda antes de toda ferramenta (PreToolUse) não basta: ele não diz se o agente teria perguntado. Silêncio nunca é aprovação: sem clique, vale o prompt do próprio agente, nunca allow, nunca deny.\n1. Grave uma sessão # O kit de spike roda o CLI de verdade contra um modelo falso e um app falso, sem conta e sem tocar em nada fora de uma pasta de rascunho:\nscripts/spike.sh \u0026lt;agent\u0026gt; [allow|deny|none] [script.json] Adicione uma receita para o agente em scripts/spike.sh: aponte as configurações de modelo dele (a maioria aceita uma URL base própria da OpenAI ou da Anthropic) para $base. Se o modelo falso não conhece os nomes das ferramentas do agente, ensine crates/spike/src/model.rs (plain()), com um teste. A execução deixa events.jsonl (o que o hook mandou), replay.txt (o que a ilha faz disso) e fixture.jsonl. Um agente que precisa dos servidores do fornecedor não pode ser gravado assim: diga isso no PR e no plano.\n2. Escreva o agente # Um arquivo, crates/agents/src/\u0026lt;agent\u0026gt;.rs, implementando a trait Agent:\nparse: os eventos do agente nas palavras do Claude Code. A maioria dos agentes copiou o JSON de hooks do Claude Code; mapeie o que difere (nomes de eventos, nomes de ferramentas como Execute → Bash, nomes de argumentos como old_str → old_string) e passe para other::as_claude. Eventos e ferramentas desconhecidos falham com suavidade: um passo genérico, nunca um crash. config_file, hook_entries, e install / uninstall / installed / up_to_date quando o arquivo não tem o formato do Claude Code. O vults-agent-config tem os escritores: hooks JSON no estilo do Claude Code, chaves com nome (named), listas planas por evento (flat), TOML (toml, instalado com Setup::Toml; o Kimi Code é o exemplo) e arquivos de plugin inteiros (plugin). Os hooks de outras ferramentas num arquivo compartilhado sempre ficam. Uma variável de pasta que move os arquivos do agente vai em dirs.rs (DIR_VARS), lida do jeito que o agente a lê. Se um hook que falha para o agente, termine todo comando em || exit 0. Se o agente lê qualquer saída de um hook como decisão, não registre esse hook. Campos que levam a saída de uma ferramenta ou uma conta (tool_output, user_email) são descartados no hook (DROPPED_FIELDS em crates/hook/src/lib.rs); só um erro ou um código de saída fica. Teste contra a fixture gravada (crates/agents/tests/fixtures/\u0026lt;agent\u0026gt;-session.jsonl, com os caminhos reescritos para /home/me), mais uma instalação e uma remoção que mantêm o resto do arquivo.\n3. Adicione a linha no registro # crates/agents/src/registry.rs guarda uma Entry por agente: o id, o nome, o comando, como ele vai no fio (Wire::Named para um agente só observado, enviado como other com o nome dele), a instalação, como o Vults o roda, e as Caps dele (o que Settings → Agents mostra). Atualize os testes do registro e depois regenere o gêmeo da UI:\nVULTS_REGEN=1 cargo test -p vults-agents agents_ts Um agente respondível também precisa do próprio AgentKind (um aumento do VERSION do protocolo), o formato da resposta dele em crates/hook/src/output.rs, o nome dele em crates/core/src/notify.rs, o gêmeo da view (VULTS_REGEN=1 cargo test -p vults-core view_ts), a cor dele na UI e as listas de agentes dos alvos de fuzz. O PR do Copilot CLI é o exemplo.\n4. Settings e docs # Uma nota sob o card dele em Settings → Agents (ui/src/surfaces/settings/main.ts), com as traduções em ui/src/i18n/{pt-BR,es,zh}.ts. Em inglês e em português do Brasil: a seção dele em Outros agentes (e a linha em O que cada agente consegue fazer; ele sai das receitas), Aprovando, a tabela em Primeiros passos, as listas de agentes nos READMEs, docs/README.md e architecture.md. Uma linha no CHANGELOG.md, e o passo dele marcado como feito em docs/dev/plan-every-agent.md com o que o spike mostrou. Depois, as verificações em CONTRIBUTING.md; um agente novo alarga um select ou dois, então os testes visuais podem precisar de baselines novas de propósito.\n","externalUrl":null,"permalink":"/docs/vults/contributing/agents/","section":"Documentação","summary":"O Vults mostra as sessões de um agente de código pelos hooks que o agente roda nos próprios eventos. A maioria dos agentes cabe em poucas centenas de linhas: um …","title":"Adicionando um agente · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-04. Emendada em 2026-10-12: registros de um mesmo tema podem ser consolidados.\nContexto # As escolhas estavam espalhadas pelo CLAUDE.md, pelos planos internos em docs/dev/ e por threads de pull request. Os planos são apagados quando terminam, então os motivos iam junto. Depois, registros que emendavam uns aos outros se acumularam no mesmo tema, e achar a regra em vigor significava ler quatro deles.\nDecisão # Toda escolha que molda o projeto ganha um registro curto em docs/adr/, numerado, com status, contexto, decisão e consequências. Os planos em docs/dev/ apontam para os registros; os registros duram mais que os planos.\nRegistros de um mesmo tema podem ser consolidados num registro vivo: a regra atual, inteira, com um Histórico curto dos registros incorporados a ele. Uma consolidação não decide nada novo e só descarta o que um registro posterior já tinha substituído. Os registros incorporados são apagados, e todo link para eles aponta para o registro vivo; o índice lista os números antigos que cada um guarda, e o histórico do git guarda o texto deles. Números nunca são reusados.\nDaí em diante um tema cresce no lugar: uma nova decisão sobre um tema que já tem registro vivo é uma edição desse registro, feita num PR próprio com uma linha datada no seu Histórico. Um número novo é só para um tema novo.\nConsequências # Quem contribui pode entender por que o app funciona assim sem conhecer o histórico. Uma mudança numa regra começa no registro dela (o registro vivo do tema, ou um novo registro para um tema novo), não com uma edição só no CLAUDE.md. Um tema, um lugar para ler a regra em vigor. ","externalUrl":null,"permalink":"/docs/vults/adr/0001-record-decisions/","section":"Documentação","summary":"Status: Aceita, 2026-10-04. Emendada em 2026-10-12: registros de um mesmo tema podem ser consolidados.\nContexto # As escolhas estavam espalhadas pelo CLAUDE.md, …","title":"0001. Registrar decisões como ADRs · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-04 (a regra existe desde o início do projeto).\nContexto # O app roda o dia todo ao lado dos agentes do usuário. Cada runtime a mais é memória, tempo de inicialização, um problema de empacotamento e mais uma coisa para manter segura. Ferramentas como pequenos modelos de decisão costumam ser distribuídas como serviços em Python.\nDecisão # Todo crate e ferramenta do backend é em Rust. TypeScript só renderiza a UI. Nada de Swift, nada de Go, e nenhum processo Python iniciado pelo app. Um modelo que o próprio app roda passa por um binding em Rust (whisper.cpp via whisper-rs; ONNX via ort, se um dia for preciso). Um servidor de modelos que o usuário já roda (Ollama, LM Studio) é acessado pela API HTTP local dele.\nConsequências # Uma toolchain, um binário, pacotes sem interpretador. Uma biblioteca que só existe em Python fica de fora até ter um caminho em Rust, por melhor que seja. ","externalUrl":null,"permalink":"/docs/vults/adr/0002-rust-backend-no-sidecars/","section":"Documentação","summary":"Status: Aceita, 2026-10-04 (a regra existe desde o início do projeto).\nContexto # O app roda o dia todo ao lado dos agentes do usuário. Cada runtime a mais é …","title":"0002. Rust em todo o backend; nenhum sidecar em Python · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-04 (a regra existe desde o início do projeto).\nContexto # O hook roda em cada evento de cada agente. Se ele travar ou imprimir a coisa errada, o trabalho do usuário para, e ele não pediu para a gente estar nesse caminho.\nDecisão # Em qualquer falha (app fechado, lento, uma mensagem ruim), o hook sai com código 0 e stdout vazio, e o agente segue como se não estivéssemos lá. Um pedido de permissão espera a confirmação do app por no máximo 800 ms; um humano, no máximo pelo prazo de decisão (110 s), e depois o agente pergunta no próprio terminal.\nConsequências # O hook usa só std e serde_json: inicia rápido e tem pouco para quebrar. Recursos que precisariam que o agente esperasse por nós (parar, pausar) não podem ser feitos só com o hook. Veja 0011. ","externalUrl":null,"permalink":"/docs/vults/adr/0003-never-block-an-agent/","section":"Documentação","summary":"Status: Aceita, 2026-10-04 (a regra existe desde o início do projeto).\nContexto # O hook roda em cada evento de cada agente. Se ele travar ou imprimir a coisa …","title":"0003. O hook nunca bloqueia um agente · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-04. Consolidada em 2026-10-12 a partir da 0014, da 0017, da 0025 e da 0026.\nContexto # Permitir um comando é a única coisa que o app faz que pode causar dano. Isso nunca pode vir de um timer, de um palpite, de um modelo ou de outro programa, nem de uma mensagem que apenas diz ser o usuário.\nDecisão # O core transforma uma permissão pendente em resposta a partir apenas destas entradas, cada uma uma escolha de um humano:\nUm clique: Intent::Decide (Allow ou Deny, ou Ctrl+Alt+Y/N com o card visível), ou Intent::DecideAlways (Always: permite este pedido e salva uma regra). Uma regra exata que o usuário salvou: o mesmo agente, pasta, ferramenta e alvo. cargo test não permite cargo test \u0026amp;\u0026amp; rm -rf build. Uma política que o usuário escreveu, viu como diff e aceitou com um clique, como uma config de agente (0005). As políticas classificam as ações como leitura, leitura externa, escrita, destrutiva, gasto ou externa (core::policy), e um deny vence um allow. A resposta de um celular Android pareado, que vale como clique só quando passa por estas verificações: O pareamento é um QR mostrado no desktop: a chave pública do celular, a URL do relay e um segredo de uso único que vive 2 minutos. O usuário pode revogar um celular no Settings. Toda resposta é assinada pela chave do aparelho pareado. Aprovar, responder, passar adiante, aceitar uma tarefa e uma ação de serviço também pedem uma chave guardada no Android Keystore com BIOMETRIC_STRONG, desbloqueada pela biometria do usuário para aquele único uso; negar e dispensar não pedem. Enviar mensagem ou mover dinheiro não existe no protocolo. Toda resposta passa pelo ledger do core: presa a um hash do pedido inteiro, usada uma vez, recusada depois de min(120 s, limits::SERVER_DECISION_TIMEOUT), com um contador por aparelho. O desktop continua a fonte da verdade e o único que age; o celular só decide. Um relay vê só envelopes cifrados; ligar o celular é uma requisição em nome do usuário (0019). No desktop, a ilha continua o único lugar dos cards (0021). Kotlin é permitido só para a casca Android; a lógica dela é o núcleo Rust via UniFFI. O Android é a única exceção a \u0026ldquo;Linux primeiro e só Linux\u0026rdquo;; iOS e macOS vêm depois, no mesmo protocolo. Só no chat do Zeca, o que o usuário escolheu em Settings → Chat \u0026amp; voice → Who answers Zeca\u0026rsquo;s cards: Asks first (o padrão): um card para cada chamada que nenhuma regra Always cobre (o Always in this chat é um comando exato, até a conversa acabar). Your policies: as políticas aceitas respondem as chamadas do chat exatamente como respondem as do Claude Code na ilha: um deny nega, um allow permite (só chamadas do Claude Code, dentro da pasta da conversa), o resto pergunta. Full access: toda chamada roda sem card, exceto que o que uma política nega é negado, o que uma política manda perguntar ainda pergunta, e depois que a conversa leu conteúdo de fora (uma página web, um fetch, uma ferramenta MCP) os cards dela voltam a perguntar pelo resto da conversa. Mais acesso só se dá no Settings; o seletor do chat mostra a escolha e só pode devolver parte dela. O chat diz o que rodou com a palavra de quem, e a CLI dele continua rodando com --permission-mode default, para que as respostas venham do Vults. As sessões do bando não mudam. Acima de tudo isso:\nUma chamada destrutiva sempre pergunta: nenhuma política, nenhuma regra Always (inclusive uma salva antes desta regra) e nenhuma configuração do chat a responde. O card dela não oferece Always allow; se o core receber um mesmo assim, ele vale como um Allow simples para aquele card, auditado como tal, e nenhuma regra é salva. Toda resposta (de um humano, de uma regra, de uma política com o consentimento dela, do celular, o full-access do chat) vai para um log de auditoria só de acréscimo que o usuário pode ler. O \u0026ldquo;hard stop\u0026rdquo; de um orçamento só impede novas sessões que o app iniciaria; ele nunca bloqueia nem mata um agente que o app só observa. Nada mais responde. Um teste alimenta todas as outras entradas e verifica que nenhuma responde; todo novo Intent entra nele, com um caso para cada decisão do celular, válida e forjada (sem assinatura, aparelho revogado, oferta expirada ou reusada, binding divergente). Consequências # Nenhuma notificação, item da bandeja, paleta, modelo, voz ou assistente pode permitir nada; eles só podem trazer o card à tona. Um celular perdido sem a biometria do dono não aprova nada; com ela, aprova até ser revogado. O acesso total confia no modelo dentro da pasta do chat: uma edição errada ou um git push roda. A configuração diz isso, o chip no chat fica vermelho, e as linhas de deny de uma política mantêm ações fora de alcance. Um teste fixa cada metade da regra destrutiva: Always num card destrutivo não salva regra, e uma regra antiga não responde a um. Histórico # 0014, 2026-10-10: políticas aceitas podem responder; um deny vence um allow, o destrutivo sempre pergunta, o log de auditoria, o hard stop do orçamento. 0017, 2026-10-10: a resposta assinada de um celular pareado vale como clique; Kotlin e o Android como a única exceção. 0025, 2026-10-12: nenhuma regra Always responde a uma chamada destrutiva. 0026, 2026-10-12: quem responde os cards do chat do Zeca é escolha do usuário. ","externalUrl":null,"permalink":"/docs/vults/adr/0004-a-human-answers-permissions/","section":"Documentação","summary":"Status: Aceita, 2026-10-04. Consolidada em 2026-10-12 a partir da 0014, da 0017, da 0025 e da 0026.\nContexto # Permitir um comando é a única coisa que o app faz …","title":"0004. Quem responde a uma permissão · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-04 (a regra existe desde o início do projeto). Consolidada em 2026-10-12 a partir da 0029.\nContexto # Instalar o nosso hook significa editar arquivos que pertencem ao usuário e a outras ferramentas: a configuração de cada agente suportado. Os agentes também vêm e vão (o Antigravity tomou o lugar do Gemini CLI), e quem instalou os nossos hooks num agente que deixamos de suportar ainda precisa conseguir removê-los.\nDecisão # Antes de qualquer escrita: uma leitura estrita, um diff que o usuário vê, um clique, depois um backup datado e uma escrita atômica. Os hooks de outras ferramentas ficam. O trusted_hash do Codex nunca é escrito: o próprio usuário confia nos nossos hooks no Codex. Tudo o que injeta configuração nossa num agente (skills, servidores MCP) passa pela mesma tela, ou não acontece. Os agentes suportados são Claude Code, Codex, Antigravity, OpenCode, Qwen Code, Copilot CLI, Cursor, Factory Droid e Kimi Code, cada um um driver em crates/agents. Acrescentar um é um driver, uma entrada no instalador e a documentação. Aposentar um agente é uma lista de passos, não uma exclusão: a versão do protocolo sobe; um instalador que só remove continua: o Settings ainda acha os hooks que um Vults anterior escreveu e oferece removê-los (diff, backup datado, clique), e nunca os instala de novo; o nome dele continua reservado (valid_agent_name em crates/protocol), então os hooks antigos não mandam nada e nenhuma outra ferramenta pode tomar o nome; os turnos antigos dele ficam fora do histórico, e uma política que o nomeia é ignorada inteira: nada do que ele deixou amplia o acesso. Consequências # Instalar leva uma tela a mais que uma configuração silenciosa. O Gemini CLI foi aposentado assim (versão 7 do protocolo): crates/agents/src/gemini.rs só remove os hooks dele. Histórico # 0029, 2026-10-12: a lista dos agentes suportados, e como aposentar um. ","externalUrl":null,"permalink":"/docs/vults/adr/0005-agent-configs-backup-diff-click/","section":"Documentação","summary":"Status: Aceita, 2026-10-04 (a regra existe desde o início do projeto). Consolidada em 2026-10-12 a partir da 0029.\nContexto # Instalar o nosso hook significa …","title":"0005. As configurações dos agentes, e os agentes que suportamos · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-04.\nContexto # Foram propostas ações rápidas em um pássaro: abrir terminal, ver diff, aprovar, parar, renomear. Mas o app só alcança um agente enquanto um hook de permissão ou de pergunta espera uma resposta, e ele não é dono do processo do agente. Pular para um terminal traz a janela para a frente no KDE e foca painéis do tmux, kitty, wezterm e herdr; em outros lugares, ele não consegue trazer uma janela para a frente.\nDecisão # Um menu mostra só o que funciona hoje, e avisa quando não dá (Open terminal em uma área de trabalho onde não conseguimos trazer janelas para a frente). Stop não é oferecido até que um agente dê uma forma suportada de pará-lo de fora; até lá, é pesquisa. Preferências como silenciar, fixar e esconder ficam guardadas por projeto, porque as sessões saem depois de 10 a 30 minutos e não são salvas.\nConsequências # Menos botões do que nos mock-ups, mas nenhum que mente. Sessões que o próprio app inicia (0.2.0) podem ser paradas, porque aí somos donos do processo. ","externalUrl":null,"permalink":"/docs/vults/adr/0011-only-actions-that-work/","section":"Documentação","summary":"Status: Aceita, 2026-10-04.\nContexto # Foram propostas ações rápidas em um pássaro: abrir terminal, ver diff, aprovar, parar, renomear. Mas o app só alcança um …","title":"0011. Oferecer só as ações que os agentes permitem · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-10. Consolidada em 2026-10-12 a partir da 0010 e da 0012.\nContexto # O app faz dois trabalhos: mostra o que os agentes do usuário estão fazendo (o bando) e oferece um companheiro que conversa, escuta, lê o bando, lembra, cria tarefas e as passa para os agentes do usuário (o Zeca). Alguns usuários querem só o primeiro, e o poder do segundo não pode vazar para ele. Também foi proposto um pequeno modelo local de decisão para as escolhas do próprio app, mas os eventos que ele recebe já vêm tipados, e modelos assim sem fine-tuning acertam menos que chutar a classe majoritária, com uma confiança que não conseguimos calibrar sem coletar dados (0019).\nDecisão # Opcional. Tudo sobre o bando funciona com o Zeca desligado: sessões, cards, notificações, conectores, o Nest com as tarefas e os registros (0021). Com ele desligado: nada de chat, de microfone, de atalho de fala, de Chat… na bandeja, de aba Chat ou de Ask Zeca; a ilha tem a sua própria aparência ociosa, e o zeca não inicia processo, não escreve arquivo e não faz requisição. Onde: o cérebro dele é um crate zeca na camada Connect, ao lado do chat; o corpo dele (sprites, a ilha, o Nest) fica em Experience. Nenhum crate abaixo do zeca sabe que ele existe; o app o conecta. O que ele lê: o bando, por um FlockReader construído a partir da view, sem caminho até um Intent. O conteúdo do bando é entrada não confiável: pode trazer uma injeção. O que ele faz: ações tipadas próprias; o zeca não depende do vults-core, então o app mapeia cada uma para as classes de política do core (leitura, leitura externa, escrita, destrutiva, gasto, externa) e para o ledger, como as de qualquer agente. Ele nunca constrói Decide nem DecideAlways, por tipo, e nunca responde a uma permissão, sua ou de outro agente (0004). O que ele lembra: um repositório git próprio (via gix): toda escrita é um commit, desfeita por um revert. Código é trabalho dos agentes: no harness (uma chave de API ou um modelo local) ele nunca roda código por conta própria; ele transforma isso numa tarefa para um agente, que pergunta ao usuário como sempre. Os comandos e edições dele no chat perguntam ao usuário como em qualquer chat. O trabalho dele nunca é uma sessão: os processos de CLI dele levam VULTS_ZECA=1; o hook marca os eventos deles e o core os manda para o estado do chat (taint e atividade), nunca para o bando. Qualquer processo poderia definir essa variável, então um evento marcado nunca esconde nem descarta um pedido de permissão: ele continua sendo perguntado ao usuário, pelo approver do chat. Regras antes de modelos nas decisões do próprio app: O que pode ser decidido a partir de estado tipado é decidido por regras simples no core, com testes: notificações, atenção, a aparência do Zeca, qual agente está instalado e tem cota. Escolher para qual agente vai uma tarefa é preferência do usuário mais disponibilidade, não um palpite. Texto livre do usuário (o que ele pede ao Zeca) vai para o modelo do chat. Um classificador treinado pode vir depois só atrás da mesma interface, só para texto livre, só local, e só se um conjunto de avaliação neste repositório mostrar que as regras não bastam. Nenhum modelo responde a uma permissão. Consequências # O crescimento do companheiro nunca muda quem responde a uma permissão; as decisões continuam exatas, testáveis e explicáveis. O scripts/check-layers.sh põe o zeca em Connect; um teste de falha de compilação garante que o FlockReader não alcança um Intent. O protocolo ganhou um campo para o evento marcado (versão 6). Histórico # 0010, 2026-10-04: o Zeca é opcional e fica separado do bando; o handle dele não consegue construir uma decisão. 0012, 2026-10-04: regras antes de modelos nas decisões do próprio app. ","externalUrl":null,"permalink":"/docs/vults/adr/0018-zeca-as-an-agent/","section":"Documentação","summary":"Status: Aceita, 2026-10-10. Consolidada em 2026-10-12 a partir da 0010 e da 0012.\nContexto # O app faz dois trabalhos: mostra o que os agentes do usuário estão …","title":"0018. Zeca: opcional, separado do bando, regras antes de modelos · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-10. Consolidada em 2026-10-12 a partir da 0006 e da 0016.\nContexto # O app vê comandos, nomes de arquivo, diffs e chaves de API, ao lado de trabalho privado. Alguns recursos ainda precisam da rede enquanto o usuário não está pedindo naquele momento: conectores, busca e fetch na web durante um turno do chat, o sono do Zeca, rotinas, o relay e o push do celular, respostas faladas, a checagem de atualização. Cada um manda para fora da máquina algo que importa ao usuário, custa dinheiro ou cota, e poderia virar telemetria por acidente.\nDecisão # Segredos só no chaveiro do sistema, nunca num arquivo ou num log. Nunca telemetria. O app não manda nada sobre o próprio uso; nenhuma requisição leva uso, um id ou qualquer coisa sobre o usuário além do que o recurso precisa para fazer o seu trabalho. Uma requisição que o usuário inicia com um clique ou uma mensagem (um turno do chat, um chat por API) é escolha explícita dele, dita onde ela é ligada. Uma requisição em nome do usuário (uma que sai da máquina sem um clique naquele momento, inclusive uma busca ou fetch na web que o modelo faz durante um turno que o usuário começou) é um recurso com: um interruptor próprio no Settings, desligado por padrão; ligá-lo diz o que manda, para onde, e quanto custa; um orçamento (requisições, tokens ou dinheiro por dia), e ele para quando acaba; um registro local que o usuário pode ler (o quê, para onde, quando, custo), mandado para nenhum outro lugar; um único portão de rede, do app (app/src/gate.rs), que confere o interruptor e o orçamento. Nenhum crate abre uma conexão para um recurso desses por fora dele. Os conectores (o GitHub pelo gh, hoje) são recursos assim: cada um fica desligado até o usuário conectá-lo, e o polling dele passa pelo portão. As atualizações são pedidas e assinadas: A checagem fica desligada até o usuário ligá-la (no Settings, e oferecida uma vez na primeira execução). Ligada, ela busca um manifesto estático do GitHub Releases no máximo uma vez por dia e não manda nada além da requisição: nenhum id, nenhum uso, nenhuma versão numa query string. Uma atualização só é instalada depois de um clique que mostra a versão e as notas dela. Um agente rodando nunca é interrompido: o reinício espera até o usuário escolher. Três canais, cada um com a própria URL de manifesto: stable (o padrão), beta (release candidates) e nightly (commits selecionados). Um build sabe o seu canal em tempo de compilação, então um build stable nunca lê o manifesto nightly; trocar de canal é reinstalar. Toda atualização é assinada. A chave privada vive só nos segredos do job de release; a chave pública vem embutida no app. Um manifesto ou pacote que falha na verificação é ignorado e registrado no log. Pacotes que uma distribuição atualiza (AUR, um futuro Flatpak) saem com o atualizador fora da compilação. Consequências # Um teste roda um dia com todos os recursos desligados e conta zero requisições. Nenhum número de uso guia o roadmap: aprendemos com as issues e usando o app nós mesmos. Tudo o que aprenderia com os dados dos usuários tem de aprender na máquina do usuário, ou não aprender. O atualizador chega depois da 0.2.0 (0020). O release.yml vai assinar os pacotes e publicar um manifesto por canal; a chave é criada uma vez e guardada offline (perdê-la significa que os usuários reinstalam à mão). Os builds nightly e beta ganham um sufixo próprio no bundle id, para instalar ao lado do stable sem dividir configurações nem o chaveiro. Histórico # 0006, 2026-10-04: segredos só no chaveiro; sem telemetria; sair da máquina é escolha do usuário. 0016, 2026-10-08: a checagem de atualização, pedida, assinada, um canal por vez. ","externalUrl":null,"permalink":"/docs/vults/adr/0019-requests-on-the-users-behalf/","section":"Documentação","summary":"Status: Aceita, 2026-10-10. Consolidada em 2026-10-12 a partir da 0006 e da 0016.\nContexto # O app vê comandos, nomes de arquivo, diffs e chaves de API, ao lado …","title":"0019. Rede, segredos e telemetria · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-10. Consolidada em 2026-10-12 a partir da 0007 e da 0015.\nContexto # O primeiro plano dava a cada versão até a 0.5 um tema, o que deixava os usuários esperando meses por trabalho pronto em dias e fazia um número de versão prometer um tema inteiro. O plano seguinte (docs/dev/plan-zeca.md) cresceu: a memória e o trabalho do Zeca, um companheiro que fala quando deve, um celular Android, e o que sobrou. Segurar a 0.2.0 até tudo isso ficar pronto deixaria o marco de Operations esperando por trabalho de que ele não precisa.\nDecisão # A primeira release é a 0.1.0. As releases continuam pequenas e frequentes: uma 0.1.x sai sempre que um ou dois passos são integrados e o teste rápido R3 passa; correções urgentes também são a próxima. Um número de patch não quer dizer \u0026ldquo;só correções\u0026rdquo;, e pode passar de 9. A 0.2.0 recebe a tag no portão da onda 4 do plan-zeca.md: o Nest, as políticas (0004), as tarefas, iniciar agentes pelo app e a revisão deles. Ela sai com o layout Living Flock (0021); o portão é o teste R3 nesse layout, uma vez depois do U1 e de novo depois do U13, e a tag vem depois do segundo. Depois dela, as ondas 5 a 7 (o companheiro, o celular, o que sobrou) saem como releases 0.2.x pela mesma regra. Linux primeiro durante toda a 0.2.x, com o Android como a única exceção (0004). Betas de Windows e macOS podem chegar no fim da 0.2.x (plan-zeca X7); o suporte completo vem depois. A 1.0 quer dizer \u0026ldquo;pronto para Linux\u0026rdquo;. Consequências # Os usuários recebem cada recurso quando ele fica pronto; o changelog é por release. Os passos antes prometidos até a 0.2.0 que o plano põe depois (a paleta de comandos, a voz de microfone aberto, o painel lateral, o pássaro na área de trabalho, Vercel, o dicionário de voz) chegam na 0.2.x. O plan-zeca.md, Waves, aponta para este registro. Histórico # 0007, 2026-10-04: a primeira release é a 0.1.0; um tema por versão até a 0.5 (abandonado pela 0015). 0015, 2026-10-04: pequenas releases 0.1.x, com tudo o que estava planejado até a 0.2.0 (reduzido aqui ao portão da onda 4). ","externalUrl":null,"permalink":"/docs/vults/adr/0020-0.2.0-at-wave-4-then-0.2.x/","section":"Documentação","summary":"Status: Aceita, 2026-10-10. Consolidada em 2026-10-12 a partir da 0007 e da 0015.\nContexto # O primeiro plano dava a cada versão até a 0.5 um tema, o que …","title":"0020. Releases: pequenas e frequentes, a 0.2.0 no portão de Operations · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-11. Consolidada em 2026-10-12 a partir da 0008, da 0009, da 0022, da 0023, da 0024 e da 0030.\nContexto # Os usuários querem vários níveis de presença: a ilha, um ícone na bandeja, um widget de canto, notificações, uma paleta, um app completo. Feita de forma ingênua, cada uma reimplementaria quem precisa de atenção, qual sessão está na frente e como um card terminou. O protótipo Living Flock do dono (design/explorations/08-living-flock.html) desenha o app como uma identidade em quatro distâncias, com o bando num céu compartilhado em todos os tamanhos. Algumas superfícies mostram texto dos agentes, que pode trazer palavras feitas para conduzir quem as lê.\nDecisão # Significado no core, aparência na superfície. O core diz quem precisa do usuário (um nível de atenção ordenado), qual sessão está em foco e como cada card terminou (aqui, no terminal, expirado, por uma regra). As superfícies escolhem clipes, ícones, cores e sons, a partir de um único view model pequeno (uma projeção por superfície só quando um payload cresce), e falam só em Intents, pelos mesmos comandos. Quatro tamanhos: Mini é a pílula (340 x 38, o bando e nenhum texto: novidades chegam a ela só como corpo, cor ou movimento). Quick é a ilha (440 px de largura) dentro da superfície de camada fixa. Room é a janela do Nest, redimensionável a partir de 480 x 360 px, sem máximo, que na primeira vez abre grande dentro da tela. Full é o Nest maximizado ou em tela cheia; Esc volta ao tamanho anterior. A sobreposição de layer-shell nunca passa do seu tamanho fixo. As superfícies em repouso são superfícies de camada mapeadas uma vez num tamanho fixo, cada uma com a sua região de entrada; o widget de canto fica num canto que o usuário escolhe e não é uma janela para arrastar. Em repouso vive uma webview (a ilha, mais o widget se escolhido); o Nest é criado quando aberto. A paleta não é uma superfície: ela abre dentro da página da ilha ou do Nest. Um card é respondido onde o usuário está: na ilha ou no Nest. A ilha guarda os cards de permissão e de pergunta e o Ctrl+Alt+Y/N (no modo painel ela se ancora pela bandeja, a mesma janela). O Nest responde os cards do bando (Allow, Deny, Always allow, as escolhas de uma pergunta, Reply in the terminal) no card do Flock da sessão da frente, e os cards do Chat dele no Chat, com os botões e as regras da ilha: uma ação destrutiva mantém o Deny em destaque e não oferece Always (0004). O usuário está no Nest quando a janela dele tem o foco e mostra o Nest, não as Configurações; aí um card não abre a ilha, a faixa de quem precisa de você e o som do Nest dizem que ele espera, e o Ctrl+Alt+Y/N responde o card na tela de lá. Em qualquer outro lugar um card abre a ilha, para que um agente nunca espere sem ser visto. Entrar no Nest recolhe uma ilha que segura um card; sair dele traz a ilha de volta. Só esses dois respondem: o app confere a webview por trás de cada resposta, e as Configurações, o widget e a paleta nunca respondem. Toda resposta continua sendo um clique (ou a tecla dele) do usuário, e é auditada. Um celular pareado também pode responder (0004). Nenhum modo de presença deixa um card confirmado sem ser visto. Em Island, Panel e Quiet, um card pendente abre a ilha e toca o seu som, ou, no Nest em que o usuário está, aparece na faixa de quem precisa de você com o seu som (o Quiet só silencia o que acontece em repouso). Em Paused, o core não confirma cards e os libera na hora, então o agente pergunta no terminal sem esperar, e os conectores param o polling. O Nest tem cinco abas, Flock, Tasks, Chat, Activity (Week com By project, History, Cost, Traces, Audit) e Connections, com Memory num painel lateral do Chat, as Configurações atrás de uma engrenagem e a tabela de capacidades dos agentes em Configurações › Agents. Trocar de tamanho mantém a seleção: a sessão é o focus do core; a aba, os filtros e a conexão escolhida são aparência que o app entrega ao Nest. O Nest abre com o Zeca desligado, sem a aba Chat e sem Ask Zeca. Uma superfície por vez (a ilha e o Nest continuam duas superfícies por baixo). Enquanto o Nest está aberto e à vista (Room ou Full), a ilha fica escondida, pílula, céu e tudo, sem nenhuma região que pegue o mouse. Ela volta quando o Nest fecha ou volta para Quick ou Mini (ou é minimizado, onde o sistema diz isso); o Back to the island do rodapé é o Quick. Nada mais a acorda, a não ser um card enquanto o usuário está fora do Nest; respondido, ela se recolhe depois do atraso de sempre e volta a ficar escondida. A janela do Nest (nest-window) se move, se redimensiona e aparece no Alt+Tab, sem a barra de título do sistema: a moldura arredondada do protótipo, um cabeçalho que a move, bordas que a redimensionam. Ela tem duas webviews sob um único cabeçalho, a do Nest (nest) e a das Configurações (settings), uma visível por vez. A engrenagem mostra as Configurações; uma aba mostra o Nest; open_settings(section) abre a janela nas Configurações, numa página quando pedida. Só a webview das Configurações tem os poderes: escrever a config de um agente (0005), salvar ou apagar uma chave, criar ou retirar uma política, parear, revogar ou alcançar um celular (0004), e ligar uma requisição em nome do usuário (0019). Os comandos conferem o label da webview que chamou, nunca o da janela (settings_page, policies::from_settings). As duas webviews dividem o armazenamento da origem, que as Configurações nunca leem. As Configurações não mostram texto de nenhum agente: a moldura delas tem nomes e contagens das abas, a troca de tamanho, som, tela cheia, e um rodapé que liga e desliga o Zeca e traz à frente o terminal da sessão da frente (ela guarda só quem é essa sessão). As páginas são General, Agents, Chat \u0026amp; voice, Approvals, Projects, Activity, Connectors, Phone, Flock \u0026amp; Zeca, About. Consequências # Um teste confere cada preset: um card confirmado sempre aparece, na ilha ou no Nest em que o usuário está, e o Paused nunca confirma um. Enquanto um card espera, o terminal do agente diz Waiting for your answer in Vults; o Review its card da paleta o abre no Nest ou na ilha. O Nest aberto vale, para a ilha, como o repouso do preset Panel. Uma página futura escolhe a sua webview pelo que mostra: texto de agentes vai na do Nest, poderes na das Configurações. Uma superfície que precise de um poder abre as Configurações na página dele. Webviews filhas precisam da feature unstable do Tauri. No Linux, as webviews de uma janela dividem a caixa dela, então são trocadas, nunca sobrepostas, e a escondida fica fora do show-all do GTK. Abrir nas Configurações carrega também a página do Nest, escondida e em repouso. Um evento que o app manda chega aos listeners de todas as webviews; uma página continua desenhando só o que pediu. No Wayland, o compositor posiciona a janela do Nest; ela não pode ser presa embaixo do lugar da ilha. Histórico # 0008, 2026-10-04: um núcleo, várias superfícies; a ilha é o único lugar dos cards. 0009, 2026-10-04: nenhum modo de presença esconde um card confirmado. 0022, 2026-10-12: só as Configurações têm os poderes (então numa janela própria). 0023, 2026-10-12: as Configurações viram uma webview da janela do Nest; as verificações vão pelo label da webview. 0024, 2026-10-12: a ilha sai enquanto o Nest está aberto. 0030, 2026-10-12: o Nest também responde um card, enquanto o usuário está nele. ","externalUrl":null,"permalink":"/docs/vults/adr/0021-four-sizes-one-nest/","section":"Documentação","summary":"Status: Aceita, 2026-10-11. Consolidada em 2026-10-12 a partir da 0008, da 0009, da 0022, da 0023, da 0024 e da 0030.\nContexto # Os usuários querem vários …","title":"0021. Superfícies: um núcleo, quatro tamanhos, um card respondido onde você está · Vults","type":"docs"},{"content":"Status: Proposta, 2026-10-12. Emenda a 0004, dentro da 0003.\nContexto # O Vults responde a uma permissão só para os agentes que conhece: cada um lê o próprio formato de resposta (o hookSpecificOutput do Claude Code, o behavior puro do Copilot CLI), então cada um foi adicionado à mão depois de uma sessão gravada. Qualquer outra ferramenta já pode pôr as sessões dela no fio com vults-hook --agent \u0026lt;name\u0026gt; e o JSON de hooks do Claude Code, mas o PermissionRequest dela aparece como uma pergunta esperando no terminal e o hook nunca espera: nada no app sabe o que essa ferramenta leria de volta (veja Permissões em Outros agentes).\nIsso deixa a porta fechada para as ferramentas que as pessoas constroem (scripts, agentes internos, orquestradores que rodam vários agentes), que são justamente para o que o bando e os cards servem. Uma ferramenta que quer um card deveria poder pedir um, se aceitar uma resposta fixa e a honrar.\nDecisão # A ferramenta pede a resposta. O comando de hook dela adiciona --reply vults: vults-hook --agent \u0026lt;name\u0026gt; --reply vults PermissionRequest. Sem isso nada muda: o hook nunca espera por uma ferramenta com nome, como hoje. Os nomes integrados (claude, codex, copilot, gemini, opencode, qwen, other, e todo agente que o registro lista, como cursor ou kimi) não podem usá-lo. Ela manda o JSON de hooks do Claude Code, o formato que a maioria das ferramentas já copia: um PermissionRequest com session_id, cwd, tool_name e tool_input. O card é montado a partir dele como para qualquer agente: o comando, o arquivo ou a URL inteiros, nunca um resumo que a ferramenta escreveu. Ela lê uma resposta fixa no stdout, uma linha JSON: {\u0026quot;decision\u0026quot;:\u0026quot;allow\u0026quot;} ou {\u0026quot;decision\u0026quot;:\u0026quot;deny\u0026quot;,\u0026quot;reason\u0026quot;:\u0026quot;Denied from Vults\u0026quot;}. Qualquer outra coisa, stdout vazio incluído, significa pergunte ao usuário você mesma: nenhum clique a tempo, o app fechado ou pausado, uma versão de protocolo não suportada, qualquer falha. O hook continua saindo com 0 e nunca bloqueia a ferramenta (0003); silêncio nunca é um allow. Quem responde é quem responde hoje (0004): um clique, uma resposta assinada de um celular pareado (0004), ou uma regra Always exata que o usuário fez no card daquela ferramenta. As regras são guardadas pelo nome da ferramenta, a pasta dela, a ferramenta chamada e o alvo: uma regra feita para uma ferramenta com nome nunca responde a outra, nem a um agente integrado. As políticas (0004) alcançam uma ferramenta com nome só quando a nomeiam (agents my-tool), e então só para negar ou perguntar: uma política nunca libera a chamada de uma ferramenta com nome, assim como hoje não libera a de nenhum agente além do Claude Code. Uma chamada destrutiva sempre pergunta (0004). Toda resposta é auditada com o nome da ferramenta. Uma ferramenta com nome não ganha nada que o card de um agente integrado não mostraria. Ela chega ao mesmo socket que qualquer processo do usuário já alcança (mesmo usuário, verificado pelo peer); o card dela mostra exatamente o que ela mandou; um Allow volta só para a chamada que pediu. O Vults não pode obrigar uma ferramenta a honrar a resposta, assim como não pode obrigar nenhum agente: uma ferramenta que a ignora é uma que nunca pediu. Um nome que vira agente integrado depois perde as regras dele: elas não passam para um agente que lê outra resposta. Consequências # O G2 constrói isso: a flag e a resposta do hook, um aumento do VERSION do protocolo (um app antigo responde unsupported, então a ferramenta pergunta ela mesma), regras e políticas indexadas pelo nome no core, as ferramentas com nome em Settings → Agents com as regras delas, e o Protocolo de hooks escrito como uma especificação, com uma ferramenta de exemplo em shell e em TypeScript. A regra 2 do CLAUDE.md, a página Segurança e Outros agentes dizem que uma ferramenta que pede com --reply vults ganha um card, e como ele é respondido. Uma ferramenta de teste em shell ganha um card, um allow e um deny, e pergunta ela mesma quando o app está fechado; um hook antigo fica em silêncio. ","externalUrl":null,"permalink":"/docs/vults/adr/0027-an-open-reply-for-any-tool/","section":"Documentação","summary":"Status: Proposta, 2026-10-12. Emenda a 0004, dentro da 0003.\nContexto # O Vults responde a uma permissão só para os agentes que conhece: cada um lê o próprio …","title":"0027. Uma resposta aberta para qualquer ferramenta que peça uma · Vults","type":"docs"},{"content":"Status: Aceita, 2026-10-12. Consolidada em 2026-10-12 a partir da 0013.\nContexto # A voz é como muitos usuários querem falar com o Zeca, e ouvi-lo. Áudio é pessoal, e os melhores motores são serviços na nuvem ou modelos locais grandes. O push-to-talk saiu no #15. A voz local que saiu para as respostas faladas (Kokoro, com fonemas do espeak-ng) foi removida em 2026-10-07: soava ruim demais para ficar, sobretudo em português. A transcrição na nuvem nunca foi feita, e o usuário a tirou do plano em 2026-10-12.\nDecisão # A fala vira texto neste computador: whisper.cpp via whisper-rs, na GPU via Vulkan quando há uma; modelos baixados pelo Settings e conferidos por SHA-256. O áudio fica na memória e nunca é salvo. Sem transcrição na nuvem. Sem palavra de ativação e sem microfone sempre ligado: o microfone só abre quando o usuário pede. As respostas faladas vêm de um modelo em tempo real que o usuário liga. É uma requisição em nome do usuário (0019): desligada por padrão, com interruptor, orçamento e registro próprios, pelo portão de rede do app. A chave dela vive só no chaveiro do sistema. Ligá-la diz que o áudio sai da máquina e para onde vai. Nenhum código GPL no nosso binário: o Piper (GPL-3.0) fica de fora, e também o build padrão do crate sherpa-onnx, que liga o espeak-ng (GPL-3.0). Uma ferramenta GPL que o usuário instalou pode rodar como um processo separado. Cada motor ou modelo que roda localmente tem a licença conferida (código e modelo) antes de entrar. A voz nunca responde a um card (0004), diga o modelo o que disser. Consequências # Com o recurso desligado, o Zeca não fala; nada sobre voz sai da máquina. Nenhum motor de fala nem voz vai no nosso binário, então as checagens de licença valem para o whisper.cpp e os modelos dele. Downloads maiores e um caminho de GPU para manter funcionando. Histórico # 0013, 2026-10-04: fala para texto local, nada de microfone sempre ligado, nada de GPL no binário, a voz nunca responde a um card. As respostas faladas locais e a transcrição opcional na nuvem dela foram substituídas aqui. ","externalUrl":null,"permalink":"/docs/vults/adr/0028-spoken-replies-through-a-realtime-model/","section":"Documentação","summary":"Status: Aceita, 2026-10-12. Consolidada em 2026-10-12 a partir da 0013.\nContexto # A voz é como muitos usuários querem falar com o Zeca, e ouvi-lo. Áudio é …","title":"0028. Voz: escuta local, respostas faladas opcionais · Vults","type":"docs"},{"content":"O lazyagents é o lazygit dos agentes de código com IA: uma TUI e uma CLI que gerenciam, num lugar só, o que os seus agentes usam: skills, sessões, consumo, providers e hooks. Primeira vez aqui? Comece pelo Primeiros passos.\nTodos os guias, tópicos e referências deste índice têm tradução para português. Comandos, opções, identificadores e mensagens literais do programa mantêm sua forma original para que os exemplos funcionem e os erros possam ser reconhecidos.\nGuias # Uma página por módulo, organizada por tarefa.\nGuia O que cobre Skills A biblioteca de skills, ativar skills por agente, instalar do GitHub, de pastas e de zips, perfis, atualizações e backups Sessões Um histórico só para todos os agentes: retomar, ler e exportar conversas, buscar, apelidos, limpeza Consumo Limites da assinatura, consumo de tokens por dia, agente, projeto e modelo, estimativa de custo Provedores Perfis de endpoint e modelo aplicados na configuração de cada agente Hooks Uma biblioteca de hooks instalada por agente, e hooks importados de repositórios Agentes Quais agentes são detectados e o que cada um suporta Plugins Novas abas e comandos com executáveis externos, em qualquer linguagem Tópicos # Configuração: config.yaml, disposição das abas, onde cada arquivo fica. Temas: temas incluídos e como criar o seu. Segurança e dados: o que o lazyagents escreve, backups e restauração, segredos, consentimento. Solução de problemas: problemas comuns e como resolver. Referência # Traduzida da referência gerada a partir do código. As marcas de revisão são verificadas para impedir a publicação quando o original muda sem revisão da tradução.\nCLI: todos os comandos e opções. Teclas: todas as teclas de todas as abas e a paleta de comandos. Suporte por agente: pastas de skills, recursos e eventos de hook por agente. Temas incluídos. Protocolo de plugins: o contrato JSON Lines que os plugins externos implementam. Contribuir # Arquitetura: como o código é organizado e como adicionar um módulo, um agente ou um tema. CONTRIBUTING, SECURITY e o Código de Conduta. ","externalUrl":null,"permalink":"/docs/lazyagents/","section":"Documentação","summary":"O lazyagents é o lazygit dos agentes de código com IA: uma TUI e uma CLI que gerenciam, num lugar só, o que os seus agentes usam: skills, sessões, consumo, …","title":"Documentação do lazyagents","type":"docs"},{"content":"A lâmpada de sódio pinta a cidade inteira desta cor. SP Night é um esquema de cores escuro que tem São Paulo como referência: a lâmpada de sódio dos postes, o concreto aparente, o vão livre do MASP, a garoa antes da chuva.\nEste repositório é o contrato e a ferramenta. O contrato é uma paleta e uma camada de papéis que diz qual cor significa o quê. A ferramenta, spn, transforma o mapeamento de um port em arquivos de tema prontos, mede a paleta contra pisos de contraste e se recusa a gerar quando ela não os atinge.\nPor onde começar # Primeiros passos: escolha uma variação, instale um port ou compile o spn você mesmo. A especificação: a paleta, os papéis e a regra de qual cor vai onde. Leia antes de mexer em um mapeamento. Criar um port: de uma entrada no catálogo a um repositório publicado, passo a passo. Referência de comandos: todos os comandos e opções do spn. As três variações # As três são escuras, por decisão: três jeitos de olhar a mesma cidade.\nid nome ideia noite Noite Paulista a cidade às 3 da manhã; escuro azul-violeta, a lâmpada de sódio acesa e quente por cima garoa Garoa a mesma janela através da garoa; cinza chapado, croma quase zero jaragua Pico do Jaraguá a mesma noite vista do ponto mais alto; o escuro puxado para a mata Links # Site, com a paleta e uma página por port: sp-night.github.io Guias de instalação de todos os ports: sp-night.github.io/ports Código-fonte: github.com/sp-night/sp-night Licença: MIT ","externalUrl":null,"permalink":"/docs/sp-night/","section":"Documentação","summary":"A lâmpada de sódio pinta a cidade inteira desta cor. SP Night é um esquema de cores escuro que tem São Paulo como referência: a lâmpada de sódio dos postes, o …","title":"SP Night","type":"docs"},{"content":"O Vults mostra seus agentes de código na sua área de trabalho e te dá um companheiro para trabalhar junto. O bando: cada sessão do Claude Code, Codex, Antigravity, OpenCode, Qwen Code, Copilot CLI, Cursor, Factory Droid e Kimi Code é um urubu que mostra o que está fazendo; aprove ou negue as permissões dele com um clique, responda às perguntas dele, pule para o terminal dele e receba novidades do GitHub. Zeca: um urubu-de-cabeça-preta que conversa com você pelas CLIs que você já usa e escuta a sua voz. Ele é opcional: desligue-o e o bando funciona sem ele.\nVersão 0.1, inicial. Os pacotes estão na release mais recente; veja Primeiros passos.\nPrimeiros passos A ilha Aprovando pela ilha O Nest Tarefas Conversando com o Zeca A memória do Zeca Conectores Atividade Outros agentes O telefone Segurança Configurações e arquivos Protocolo do hook O relay do telefone Animações Arquitetura Decisões (ADRs) Adicionando um conector Adicionando um agente ","externalUrl":null,"permalink":"/docs/vults/","section":"Documentação","summary":"O Vults mostra seus agentes de código na sua área de trabalho e te dá um companheiro para trabalhar junto. O bando: cada sessão do Claude Code, Codex, …","title":"Vults","type":"docs"},{"content":"","date":"out. 5, 2026","externalUrl":null,"permalink":"/en/tags/ai/","section":"Tags","summary":"","title":"AI","type":"tags"},{"content":"","date":"5 out. 2026","externalUrl":null,"permalink":"/tags/desktop/","section":"Tags","summary":"","title":"Desktop","type":"tags"},{"content":"","date":"5 out. 2026","externalUrl":null,"permalink":"/tags/ia/","section":"Tags","summary":"","title":"IA","type":"tags"},{"content":"Ferramentas de terminal, open source e experimentos com IA.\nExplorar projetos · Documentação · Currículo · Fale comigo\nOPEN SOURCE / RUST / TAURI / LINUXVults_ Seus agentes de código, vivos no desktop.\nCada sessão de agente é um urubu 8-bit no topo da tela, fazendo o que a sessão faz. Aprove, responda e pule para o terminal certo com um clique. O Zeca, o companheiro, conversa pelos CLIs que você já usa.\nClaude Code · Codex · Gemini CLI · Antigravity\nExplorar as docs → Baixar ↗ GitHub ↗ Sobre o projeto a ilhaKDE Plasma Ilha → Card → TerminalScreenshot das docs, nesta versão OPEN SOURCE / GO / TUIlazyagents_ Seus agentes. Um terminal.\nAtive skills, encontre conversas e acompanhe o consumo dos seus agentes de código com IA. Tudo no mesmo lugar.\nClaude Code · Codex · Gemini CLI · OpenCode · Hermes\nExplorar as docs → GitHub ↗ Sobre o projeto ~/lazyagents13s Baixar demonstração Skills → Sessões → ConsumoGravado com dados fictícios · sem áudio OPEN SOURCE / GO / TEMA DE CORESSP Night_ O poste de sódio deixa a cidade inteira desta cor.\nUm tema escuro com São Paulo como referência. Cada cor tem o contraste medido antes de ser publicada, e todo port é gerado da mesma paleta.\nGhostty · Kitty · Alacritty · Eza · Helix · Herdr · Foot\nExplorar as docs → Instalar um port ↗ GitHub ↗ ~/sp-nightspn palette noite Noite Paulista\nA cidade às 3h. O escuro azul-violeta do tokyodark, e o poste de sódio queimando quente por cima.\ngaroa Garoa\nA mesma janela, vista através do chuvisco. Cinza chapado — a garoa não esfria a cidade, ela desbota.\njaragua Pico do Jaraguá\nA mesma noite, vista do ponto mais alto da cidade. O escuro do noite girado para o verde da mata fechada — e a torre vermelha e branca acesa no topo.\n23 cores · 3 variaçõesLido de palette/sp_night.json ","date":"5 out. 2026","externalUrl":null,"permalink":"/","section":"Início","summary":"Site pessoal de Rogerio de Queiroz Junior: projetos, posts e currículo.","title":"Início","type":"page"},{"content":"","date":"5 out. 2026","externalUrl":null,"permalink":"/tags/open-source/","section":"Tags","summary":"","title":"Open Source","type":"tags"},{"content":"","date":"5 out. 2026","externalUrl":null,"permalink":"/projects/","section":"Projetos","summary":"Coisas que construí.","title":"Projetos","type":"projects"},{"content":"","date":"5 out. 2026","externalUrl":null,"permalink":"/tags/rust/","section":"Tags","summary":"","title":"Rust","type":"tags"},{"content":"","date":"5 out. 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"5 out. 2026","externalUrl":null,"permalink":"/tags/tauri/","section":"Tags","summary":"","title":"Tauri","type":"tags"},{"content":" OPEN SOURCE / RUST / TAURI / LINUXVults_ Seus agentes de código, vivos no desktop.\nCada sessão de agente é um urubu 8-bit no topo da tela, fazendo o que a sessão faz. Aprove, responda e pule para o terminal certo com um clique. O Zeca, o companheiro, conversa pelos CLIs que você já usa.\nClaude Code · Codex · Gemini CLI · Antigravity\nExplorar as docs → Baixar ↗ GitHub ↗ a ilhaKDE Plasma Ilha → Card → TerminalScreenshot das docs, nesta versão Quem roda vários agentes de código ao mesmo tempo perde a conta: um terminou, outro falhou, outro está há dez minutos esperando uma permissão num terminal que você não acha. O Vults coloca todos no seu desktop. Cada sessão do Claude Code, Codex, Gemini CLI ou Antigravity vira um vult, um urubu 8-bit numa ilha no topo da tela, fazendo o que a sessão está fazendo.\nFunciona com: Claude Code, Codex, Gemini CLI e Antigravity, no Linux (primeiro KDE Plasma e outros compositores com layer-shell).\nAprovações num lugar só: o card mostra o comando, o arquivo ou o diff inteiro; Permitir, Negar ou um atalho global. Nada é aprovado sem o seu clique. Diffs ao vivo e pulo para o terminal: cada edição mostra as linhas adicionadas e removidas, e um clique foca o painel do tmux, kitty, wezterm ou herdr da sessão. Novidades do GitHub e consumo do plano: checks com falha, reviews e os limites do Claude e do Codex, pelos CLIs que você já usa. Zeca, o companheiro: um urubu-de-cabeça-preta que conversa pelo CLI claude ou codex, escuta quando você segura uma tecla e fala (whisper.cpp, no seu computador) e recebe os arquivos que você solta nele. Um botão desliga ele. Seguro por padrão: o hook nunca trava o agente, a configuração dos agentes só muda depois de um backup e de um diff que você aprova, segredos ficam no chaveiro do sistema, sem telemetria. Baixe o .deb ou o .rpm da última release, ou gere o pacote do Arch com makepkg.\nDocumentação Baixar github.com/rogeriojunior31/Vults ","date":"5 out. 2026","externalUrl":null,"permalink":"/projects/vults/","section":"Projetos","summary":"Um app de desktop em Rust e Tauri para quem roda vários agentes de código ao mesmo tempo: cada sessão é um urubu 8-bit no topo da tela, com aprovações, chat e um companheiro chamado Zeca.","title":"Vults","type":"projects"},{"content":"","date":"28 set. 2026","externalUrl":null,"permalink":"/tags/cli/","section":"Tags","summary":"","title":"CLI","type":"tags"},{"content":"","date":"28 set. 2026","externalUrl":null,"permalink":"/tags/go/","section":"Tags","summary":"","title":"Go","type":"tags"},{"content":" OPEN SOURCE / GO / TUIlazyagents_ Seus agentes. Um terminal.\nAtive skills, encontre conversas e acompanhe o consumo dos seus agentes de código com IA. Tudo no mesmo lugar.\nClaude Code · Codex · Gemini CLI · OpenCode · Hermes\nExplorar as docs → GitHub ↗ ~/lazyagents13s Baixar demonstração Skills → Sessões → ConsumoGravado com dados fictícios · sem áudio Cada agente de código guarda as próprias skills, sessões e configuração numa pasta diferente, num formato diferente. O lazyagents junta tudo num terminal só, no espírito do lazygit: uma biblioteca de skills que você liga por agente com uma tecla, o histórico de sessões de todos os agentes num lugar, e o consumo da assinatura sempre à vista.\nFunciona com: Claude Code, Codex, Gemini CLI, OpenCode e Hermes Agent.\nSkills: instala de um repositório do GitHub, pasta ou zip, e ativa por agente com um symlink, sem copiar nada. Sessões: retoma qualquer conversa no próprio CLI e na pasta certa, lê o transcript e busca em todos os agentes. Consumo: limites da assinatura (janela de sessão e semanal) e tokens por dia, agente, projeto e modelo. Providers e hooks: perfis de endpoint e hooks aplicados na configuração de cada agente, com confirmação e backup antes de escrever. Plugins: qualquer executável vira uma aba e um comando novo, em qualquer linguagem. go install github.com/rogeriojunior31/lazyagents@latest Também há binários para Linux, macOS e Windows na página de releases.\nDocumentação github.com/rogeriojunior31/lazyagents A TUI usa a paleta do SP Night.\n","date":"28 set. 2026","externalUrl":null,"permalink":"/projects/lazyagents/","section":"Projetos","summary":"Uma TUI em Go para gerenciar, num lugar só, o que seus agentes de código com IA usam: skills, sessões, consumo, providers e hooks.","title":"lazyagents","type":"projects"},{"content":"","date":"28 set. 2026","externalUrl":null,"permalink":"/tags/tui/","section":"Tags","summary":"","title":"TUI","type":"tags"},{"content":"","date":"2 ago. 2026","externalUrl":null,"permalink":"/tags/astro/","section":"Tags","summary":"","title":"Astro","type":"tags"},{"content":" OPEN SOURCE / GO / TEMA DE CORESSP Night_ O poste de sódio deixa a cidade inteira desta cor.\nUm tema escuro com São Paulo como referência. Cada cor tem o contraste medido antes de ser publicada, e todo port é gerado da mesma paleta.\nGhostty · Kitty · Alacritty · Eza · Helix · Herdr · Foot\nExplorar as docs → Instalar um port ↗ GitHub ↗ ~/sp-nightspn palette noite Noite Paulista\nA cidade às 3h. O escuro azul-violeta do tokyodark, e o poste de sódio queimando quente por cima.\ngaroa Garoa\nA mesma janela, vista através do chuvisco. Cinza chapado — a garoa não esfria a cidade, ela desbota.\njaragua Pico do Jaraguá\nA mesma noite, vista do ponto mais alto da cidade. O escuro do noite girado para o verde da mata fechada — e a torre vermelha e branca acesa no topo.\n23 cores · 3 variaçõesLido de palette/sp_night.json Um esquema de cores escuro inspirado em São Paulo: o poste de sódio, o concreto aparente, o vão livre do MASP, a garoa antes da chuva. São três variações, todas escuras por decisão: noite, garoa e jaragua, três jeitos de olhar a mesma cidade.\nO projeto é um contrato e uma ferramenta. O contrato é a paleta e uma camada de papéis que diz qual cor significa o quê. A ferramenta, spn, transforma o mapeamento de cada app em arquivos de tema prontos e se recusa a gerar quando a paleta não passa nos pisos de contraste.\nNenhum hex escolhido à mão: temas, READMEs e previews saem da paleta, então não mostram uma cor que você não vai receber. Contraste como portão: cada par de cores é medido a cada build; comentário ilegível não passa. Acentos separados entre si: pares vizinhos precisam se distinguir pela luminosidade, não só pelo matiz. Ports reproduzíveis: a suíte renderiza os ports publicados e compara byte a byte com o que foi instalado. Para usar um tema, escolha uma variação, copie o arquivo do port para o caminho do app e ative com uma linha. Os guias de cada port estão em sp-night.github.io/ports.\nDocumentação sp-night.github.io github.com/sp-night/sp-night Este site usa a variação Pico do Jaraguá.\n","date":"2 ago. 2026","externalUrl":null,"permalink":"/projects/sp-night/","section":"Projetos","summary":"Um tema escuro com São Paulo como referência: três variações, cores com contraste medido e ports gerados da mesma paleta para terminais, editores e CLIs.","title":"SP Night","type":"projects"},{"content":"","date":"2 ago. 2026","externalUrl":null,"permalink":"/tags/tema/","section":"Tags","summary":"","title":"Tema","type":"tags"},{"content":"","date":"ago. 2, 2026","externalUrl":null,"permalink":"/en/tags/theme/","section":"Tags","summary":"","title":"Theme","type":"tags"},{"content":" rogeriojunior31/Fine-tune-Gemma-models-in-Keras-using-LoRA Jupyter Notebook 0 0 O objetivo # Explorar a adaptação do Gemma 2B a instruções usando Keras e LoRA, sem treinar todos os parâmetros do modelo. O notebook usa o dataset Databricks Dolly 15k e o backend JAX.\nO experimento # Carregamento e preparação dos exemplos de instrução. Geração de respostas antes do ajuste para comparação. LoRA com rank 4, sequências de até 512 tokens e uma época de treinamento. Nova geração com os mesmos prompts após o ajuste. Essa comparação é qualitativa: o projeto não apresenta um benchmark que comprove melhoria geral do modelo.\nComo explorar # Abra o notebook no GitHub para ler o fluxo completo. Para executar, siga as células de instalação e configuração do Kaggle em um ambiente com os recursos necessários para carregar e treinar o modelo, preferencialmente com GPU.\nO acesso ao Gemma exige a configuração de credenciais e os termos do modelo. Não publique seu kaggle.json nem tokens. Como o notebook é um experimento de 2024, confira a compatibilidade das dependências antes de executar em um ambiente atual.\nVer repositório e instruções\n","date":"26 abr. 2024","externalUrl":null,"permalink":"/projects/gemma-lora/","section":"Projetos","summary":"Notebook de fine-tuning de modelos Gemma no Keras usando LoRA.","title":"Fine-tuning do Gemma com LoRA","type":"projects"},{"content":"","date":"26 abr. 2024","externalUrl":null,"permalink":"/tags/keras/","section":"Tags","summary":"","title":"Keras","type":"tags"},{"content":"","date":"26 abr. 2024","externalUrl":null,"permalink":"/tags/llm/","section":"Tags","summary":"","title":"LLM","type":"tags"},{"content":"","date":"26 abr. 2024","externalUrl":null,"permalink":"/tags/lora/","section":"Tags","summary":"","title":"LoRA","type":"tags"},{"content":"","date":"4 fev. 2024","externalUrl":null,"permalink":"/tags/machine-learning/","section":"Tags","summary":"","title":"Machine Learning","type":"tags"},{"content":" rogeriojunior31/house_price_predictor Python 0 0 O problema # Estimar valores de imóveis a partir de características do California Housing Dataset e entender como essas características se relacionam com o preço. É um projeto de estudo de machine learning, não uma ferramenta de avaliação imobiliária para uso comercial.\nComo funciona # Python e scikit-learn para carregar os dados e separar treino e teste. Regressão linear como modelo inicial; Ridge, validação cruzada e GridSearchCV na versão ampliada. RMSE para avaliar as previsões no conjunto de teste. Matplotlib e Seaborn para visualizar características dos dados e comparar valores reais com previstos. Como executar # Com Python 3.9 ou superior (para as dependências fixadas no repositório), em um ambiente virtual:\ngit clone https://github.com/rogeriojunior31/house_price_predictor.git cd house_price_predictor python -m venv .venv # Linux/macOS; no Windows, use .venv\\Scripts\\activate source .venv/bin/activate pip install -r requirements.txt python main.py A execução apresenta o RMSE e gráficos de análise. O carregamento inicial do dataset pode precisar de acesso à internet. Os resultados dependem da execução; não há aqui uma métrica publicada que permita afirmar desempenho em dados de outros mercados.\nVer código e instruções no GitHub\n","date":"4 fev. 2024","externalUrl":null,"permalink":"/projects/house-price-predictor/","section":"Projetos","summary":"Modelo de machine learning em Python para estimar preços de imóveis.","title":"Previsor de preço de imóveis","type":"projects"},{"content":"","date":"4 fev. 2024","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":" Experiência # rogerio@archlinux: ~/cv❯ cat ~/cv/experiencia.tsv | column -t EMPRESACARGOPERÍODO● CSU DigitalSoftware Engineer Specialistago 2026 - atual● KruzerTech Leadjan 2026 - ago 2026● Samsung SDSTech Lead2022 - dez 2025● Linkapi SolutionsEngenheiro Back-End2021 - 2022● FreelanceFreelancer2017 - 2021❯ Stack # rogerio@archlinux: ~❯ eza --tree ~/stack ~/stack├── linguagens│ └── typescript javascript python go bash├── back-end│ └── node.js bun nestjs api-design microservices├── cloud-devops│ └── aws azure docker github-actions elastic-stack├── ia-ml│ └── langchain llamaindex pytorch keras lora-fine-tuning llm-apis└── bancos-de-dados └── postgresql mysql mongodb redis5 directories, 25 files❯ ","externalUrl":null,"permalink":"/resume/","section":"Início","summary":"Experiência profissional e stack.","title":"Currículo","type":"page"},{"content":"","externalUrl":null,"permalink":"/docs/","section":"Documentação","summary":"Documentação dos meus projetos, gerada a partir da pasta docs/ de cada repositório.","title":"Documentação","type":"docs"},{"content":"","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"Artigos e anotações.","title":"Posts","type":"posts"},{"content":"Sou dev de São Paulo. Comecei como freelancer em 2017, passei pelo back-end na Linkapi e fui Tech Lead na Samsung SDS e na Kruzer. Hoje estou na CSU Digital como Software Engineer Specialist, mexendo com ferramentas de IA e aplicações com LLM.\nPasso a maior parte do dia no terminal. Esse é o meu setup:\nrogerio@archlinux: ~❯ fastfetch -` .o+` `ooo/ `+oooo: `+oooooo: -+oooooo+: `/:-:++oooo+: `/++++/+++++++: `/++++++++++++++: `/+++ooooooooooooo/` ./ooosssso++osssssso+` .oossssso-````/ossssss+` -osssssso. :ssssssso. :osssssss/ osssso+++. /ossssssss/ +ssssooo/- `/ossssso+/:- -:/+osssso+- `+sso+:-` `.-/+oso: `++:. `-/+/ .` `/rogerio@archlinux-----------------OS: Arch Linux x86_64Shell: fishTerminal: tmuxTheme: SP NightFont: JetBrains MonoLanguages: TypeScript, JavaScript, Python, Go, BashFocus: IA · LLM · back-end · DevOpsLocation: São Paulo · BRLocale: pt_BR.UTF-8, en_US.UTF-8❯ No que eu ando mexendo # rogerio@archlinux: ~❯ systemctl --user list-units UNITACTIVESUBDESCRIPTION● ai-tooling.serviceactiverunningferramentas de IA para devs● llm-apps.serviceactiverunningRAG, agentes, fine-tuning● backend.serviceactiverunningAPIs e sistemas distribuídos● devops.serviceactiverunningCI/CD, cloud e infra● architecture.serviceactiverunningdesign e code review● self-hosting.serviceactiverunninghomelab e open source● kaggle.timeractivewaitingexperimentos de ML❯ Fora do expediente # SP Night: um tema escuro com São Paulo como referência. Este site usa o flavor Pico do Jaraguá. lazyagents: uma TUI para gerenciar skills, sessões e consumo dos agentes de código com IA, open source desde a v0.3. Homelab: self-hosting e open source. Kaggle: experimentos de ML, como o fine-tuning do Gemma com LoRA. Jogos retrô: caçando conquistas no RetroAchievements. O resto fica na Steam. A trajetória completa está no currículo.\n","externalUrl":null,"permalink":"/sobre/","section":"Início","summary":"Quem eu sou, meu setup e no que ando mexendo.","title":"Sobre","type":"page"}]