Communitygithub.com

agentshot: capturas de tela e vídeos de demonstração

Crie capturas de tela de produtos e vídeos de demonstração no Windows e macOS — capture um web app / Expo web app / janela de desktop / iOS Simulator / arquivo do iPhone, estilize (fundo, moldura do iPhone/navegador/janela, elevação, lupa, setas, etapas, desfoque, zoom, cursor, cortes) e renderize PNG ou MP4 em uma biblioteca versionada. Use quando o usuário solicitar capturas de tela, maquetes, imagens para central de ajuda, imagens de changelog, posts sociais (X/Instagram), vídeos de demonstração/B-roll ou gravações de tela de seu aplicativo.

O que é agentshot: capturas de tela e vídeos de demonstração?

O **agentshot** é uma ferramenta profissional de captura e renderização para desenvolvedores que precisam gerar imagens de alta qualidade e vídeos de demonstração de seus aplicativos sem esforço manual. Ele suporta captura de aplicativos web (via Playwright), aplicativos iOS Simulator (nativos), programas de desktop (Windows/macOS) e arquivos importados (capturas de tela do iPhone). A ferramenta orquestra todo o fluxo de trabalho: captura a tela, inspeciona os elementos e o timeline, aplica estilos (como moldura de dispositivo, fundo, desfoque, setas, lupas, cortes e zooms) e renderiza o resultado em PNG ou MP4, armazenando cada versão em uma biblioteca com versionamento automático. É ideal para criar capturas de tela para changelogs, posts em redes sociais, imagens de central de ajuda e vídeos B-roll, pois oferece recursos como cursor animado, anotações, cortes de cena e ajustes finos de timing. O agentshot integra-se perfeitamente a fluxos de desenvolvimento, permitindo que cenários e receitas sejam armazenados no repositório do projeto (por exemplo, em `docs/shots/`) e reexecutados após mudanças na interface do usuário. Sua arquitetura orientada a JSON permite controle preciso sobre cada etapa da captura e renderização, enquanto comandos como `agentshot inspect`, `agentshot frames` e `agentshot preview` fornecem ferramentas de depuração e iteração rápidas.

Funciona com✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/thread-of-ariadne/agentshot/tree/main/skill/agentshot

Perguntar na sua IA favorita

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

Documentação

O que agentshot: capturas de tela e vídeos de demonstração faz?

A ferramenta está em /path/to/agentshot. Execute-a como:

node /path/to/agentshot/bin/agentshot.mjs <comando> ...

Abaixo, agentshot significa esse comando. Cada comando imprime uma linha JSON ("ok": true|false). Renderizações longas também imprimem progresso no stderr. Execute agentshot help para a lista de comandos.

Fluxo de trabalho

  1. Leia as regras do produto primeiro: agentshot style <produto> imprime style.json (aparência padrão) e guidelines.md (o que o usuário gosta). Siga-as. Se o produto for novo, execute agentshot style <produto> --init.
  2. Capture (escolha um):
    • Aplicativo web ou Expo app → escreva um JSON de cenário com "url", execute agentshot capture scenario.json.
    • Aplicativo iOS em um Mac → um cenário com "simulator" (o aplicativo nativo real no iOS Simulator, veja "iOS Simulator"); uma imagem estática rápida → agentshot sim snap --name <capture> --clean-status-bar.
    • Programa de desktop → um cenário com "window": você controla o mouse/teclado real enquanto ele grava (veja "Desktop app"). Apenas uma imagem estática → agentshot snap --window "<titulo>" --name <capture>. O usuário realiza as ações → agentshot record start/stop.
    • O usuário já tem um arquivo (captura de tela do iPhone / gravação de tela) → agentshot import <arquivo> --name <capture>.
  3. Inspecione: agentshot inspect <capture> lista disparos, caixas de elementos (pontos da tela), cliques, duração e, para vídeos, moves (movimento do cursor), changes (mudanças de página: grandes saltos visuais), quiet (nada se move: corte ou acelere) e o timeline do cenário. Planeje cortes e zooms a partir desses números, depois confirme com agentshot frames <capture> --from a --to b (uma folha de contato com timestamps; Leia o PNG que imprime). Olhe para o PNG do disparo com a ferramenta Leitura antes de estilizar.
  4. Escreva uma receita JSON e agentshot render recipe.json --note "<o que mudou>".
  5. Verifique o resultado você mesmo: Leia o PNG; para MP4, agentshot frames <produto>/<ativo> (vídeo inteiro) e agentshot frames <produto>/<ativo> --from 3 --to 4 --every 0.033 --crop x,y,w,h (quadro a quadro em torno de um corte ou clique). Corrija e renderize novamente (uma nova versão é adicionada). Quando o usuário quiser explorar ou ajustar uma receita por conta própria, execute agentshot preview recipe.json em segundo plano: ele abre uma página local com a cena e um controle deslizante e atualiza ao vivo quando a receita (ou o style.json do produto) é editada. Ele imprime uma linha JSON com a url e continua servindo.
  6. Relate o caminho de saída (results[].output). --copy-to <dir> também o copia para o projeto do usuário.
  7. Aprenda: quando o usuário corrige ou elogia algo, anexe uma linha datada ao guidelines.md do produto (e atualize os padrões de style.json se for uma aparência padrão). Leia-o na próxima vez.

Mantenha cenários e receitas no projeto do usuário (por exemplo, docs/shots/) para que possam ser reexecutados após mudanças na interface do usuário.

Cenário (capturar um aplicativo web)

Os comentários nos exemplos JSON abaixo são apenas explicações; arquivos reais devem ser JSON simples.

{
  "name": "ellie-hoje-arrastar",          // nome da captura, único; prefixo com o produto
  "url": "http://localhost:8081",       // ou um caminho de arquivo
  "device": "iphone",                   // iphone | iphone-max | ipad | desktop | laptop
  "safeArea": true,                     // Expo/RN web: Chrome relata insets de área segura do iPhone, o aplicativo se organiza
                                        // como em um dispositivo ("pad" = forçar padding para aplicativos que ignoram insets)
  "css": "[class*='navigationMenuRoot'] { display: none }",  // ocultar chrome somente web (as abas do Expo Router são renderizadas como um menu superior na web)
  "waitFor": "lista-hoje",              // esperar por este elemento antes de começar
  "track": { "linha": "text=Planejar um aniversário" },  // caixas de elementos nomeados extras para gravar
  "steps": [
    { "shot": "principal" },                                  // imagem estática em resolução total (para capturas de tela)
    { "wait": 0.6 },
    { "tap": "botao-adicionar" },                             // clicar/tocar em um alvo (move-se até lá primeiro)
    { "type": "Comprar leite", "into": "input-titulo" },
    { "press": "Enter" },
    { "drag": "tarefa-aniversario", "to": "slot-11h", "duration": 1.4 },
    { "scroll": 400, "duration": 0.8 },
    { "move": [200, 300], "duration": 0.6 },
    { "goto": "/configuracoes" },
    { "waitFor": "titulo-configuracoes" },
    { "shot": "depois" }
  ]
}

Alvos: um nome simples corresponde a data-shot="..." ou data-testid="..." (testID do React Native torna-se data-testid na web, então adicione testIDs aos elementos que deseja apontar), ou qualquer seletor do Playwright (text=Salvar, role=button[name="Salvar"], #id, .class), ou [x, y] em px CSS. Todos os elementos com data-shot/data-testid são gravados com suas caixas, além das entradas track.

Timing: por padrão ("timing": "frame"), o relógio da página é pausado e avançado exatamente um quadro por vez (60 qps) com uma captura de tela em resolução total por quadro, para que as animações do aplicativo sejam suaves em qualquer resolução; a captura leva algumas vezes mais tempo que o cenário. Use "timing": "real" apenas se o aplicativo quebrar sob um relógio controlado (um passo então expira). agentshot capture relata os tempos de clique (clicks) para planejar cuts/zoom e erros/avisos do console (console). Sobreposições de desenvolvimento (toast do Expo LogBox, indicador do Next.js) são ocultadas; "devOverlays": true as mantém. Prefira um segmento contínuo cuts em vez de vários cortes duros: saltos entre segmentos parecem entrecortados.

Encontrando alvos em um aplicativo sem testIDs: abra a página com Playwright e liste botões/inputs (role, aria-label, texto), depois use text=..., role=button[name=/^Minha filha/] ou [aria-label='Sua oração'] e nomeie caixas que deseja elevar/lupa por meio de track. Digitar em um campo coberto por um rodapé fixo ainda funciona (o campo recebe foco).

Expo: inicie a compilação web primeiro (npx expo start --web, geralmente http://localhost:8081). Módulos somente nativos podem não funcionar na web; se uma tela quebrar, peça ao usuário uma captura de tela/gravação do iPhone e faça import.

Desktop app (cenário com "window")

agentshot windows lista janelas (título, processo, tamanho). A janela é correspondida pelo título, depois pelo nome do processo, restaurada se minimizada e trazida para frente. As coordenadas são pixels da janela: veja uma imagem estática primeiro (agentshot snap --window "X" --name x-probe, Leia o PNG) e nomeie as caixas que você usa em track.

{
  "name": "tour-notas",
  "window": "Notes",                              // parte do título ou nome do processo
  "track": { "nav-recente": [20, 200, 190, 40], "nav-pesquisa": [20, 96, 190, 40], "conteudo": [232, 40, 1030, 650], "perfil": [16, 718, 150, 62] },
  "cursor": [1000, 330],                          // onde o ponteiro começa
  "steps": [
    { "shot": "inicio" },                           // estático = o quadro gravado neste momento
    { "wait": 1 },
    { "click": "nav-recente", "duration": 0.9 },   // deslizar até lá (com easing, leve arco), clicar imediatamente
    { "waitStill": 0.6, "region": "conteudo" },    // aguardar a tela mudar, depois estabilizar
    { "shot": "recente" },
    { "wheel": 4, "at": [760, 460] },             // rolar 4 notches para baixo (negativo = para cima)
    { "click": "nav-pesquisa" }, { "press": "ctrl+a" },
    { "type": "Plano semanal", "cps": 12 },         // qualquer texto, incluindo scripts não latinos
    { "press": "Enter" },                         // teclas: enter esc tab space backspace delete arrows home end f1..f12, ctrl/alt/shift/win+x
    { "drag": [100, 300], "to": [400, 300], "duration": 1.2 },
    { "click": [640, 400], "button": "right" }, { "click": [640, 400], "double": true },
    { "note": "batida 2" }                          // marcador no timeline
  ]
}
  • O resultado tem timeline (início/fim de cada passo em segundos de vídeo, at = momento do clique) e shots (imagens estáticas cortadas do vídeo). As receitas usam nomes de track como alvos ("blur" em "perfil" etc.).

  • waitStill primeiro espera (até changeTimeout, 3 s) até que a região difira de como estava (change, diferença média de pixel, padrão 6; "change": false para apenas deixar estabilizar), depois até que nada tenha mudado pelos segundos fornecidos (threshold 0.6). Use uma region sem partes animadas (players, fundos vivos).

  • Clique logo após chegar: um cursor descansando em um controle ~0,5 s faz com que dicas de ferramentas do Windows apareçam no vídeo.

  • Campos que mantêm texto antigo: press ctrl+a antes de type.

  • O driver inicia antes da gravação (precisa de alguns segundos) e move o cursor real: não use o computador durante esse período. As capturas de desktop são 1x, portanto uma lupa parece suave; prefira lift.

  • Imagens estáticas a qualquer momento de uma gravação: agentshot snap <capture> --at 12.4 --shot name.

  • Pequenas alterações (um popup fechando) podem não atingir change em toda a janela: forneça region em torno delas.

  • Atalhos: mod é Ctrl no Windows e Cmd no macOS ("press": "mod+a"), portanto um cenário é executado em ambos.

Gravação manual (o usuário faz as ações; o cursor é registrado e desenhado pelo renderizador):

agentshot record --name app-filtro --window "Figma" --duration 12   # grava 12 s, depois para
agentshot record start --name app-filtro --window "Figma"           # ou inicia ...
agentshot record stop                                               # ... e para depois

macOS

Mesmos comandos e cenários que no Windows; o gravador/mac.swift é compilado no primeiro uso (requer as Ferramentas de Linha de Comando do Xcode macOS 14+). Execute agentshot doctor primeiro: o aplicativo que executa o agente (Terminal, iTerm, Claude, VS Code) precisa de Gravação de Tela e Acessibilidade em Ajustes do Sistema > Privacidade e Segurança (agentshot doctor --request abre os prompts; reinicie esse aplicativo após conceder). Sem Gravação de Tela, os títulos das janelas são apenas nomes de aplicativos e a gravação falha; sem Acessibilidade, o driver não pode clicar ou digitar.

  • Coordenadas (track, passos, alvos da receita) são pontos; imagens estáticas e vídeo estão na escala de pixels da tela (2 no Retina, inspect mostra scale), portanto elevações e zooms permanecem nítidos.
  • ScreenCaptureKit grava a própria janela: ela pode estar parcialmente coberta, mas não deve estar minimizada.
  • node scripts/selftest-mac.mjs verifica tudo no TextEdit (e no simulador se um estiver inicializado) e imprime o que falhou. Verificação de sincronia: agentshot record ... --show-cursor queima o cursor real em; compare-o com o ponteiro registrado (agentshot frames vs inspect) como qualquer gravação.

iOS Simulator (macOS)

O aplicativo nativo em vez de sua compilação web: fontes reais, módulos nativos, animações iOS. Inicialize um simulador (open -a Simulator), execute o aplicativo nele (npx expo run:ios ou uma compilação de desenvolvimento), então:

agentshot sim devices                                       # simuladores inicializados
agentshot sim snap --name app-inicio --clean-status-bar       # imagem estática sem perdas, 9:41 / bateria cheia
agentshot sim record start --name app-fluxo                  # outra pessoa dirige ...
agentshot sim record stop

Um cenário o dirige com idb (brew install facebook/fb/idb-companion, pipx install fb-idb); as coordenadas são pontos do dispositivo (Leia um sim snap e divida seus pixels por scale):

{
  "name": "app-onboarding",
  "simulator": "booted",                        // ou um UDID ou parte do nome do dispositivo
  "statusBar": "clean",                         // 9:41 durante a captura, limpo depois
  "appearance": "light",                        // ou "dark"
  "openUrl": "exp://127.0.0.1:8081/--/hoje",   // deep link antes da gravação (ou "launch": "<bundle id>")
  "track": { "add": [330, 760, 48, 48], "title": [24, 120, 340, 44] },
  "steps": [
    { "shot": "hoje" },
    { "tap": "add" },
    { "waitStill": 0.5 },
    { "type": "Comprar leite" },                      // no campo focado
    { "press": "enter" },                        // enter esc backspace tab space arrows home lock
    { "swipe": [200, 600], "to": [200, 250], "duration": 0.4 },
    { "openUrl": "exp://127.0.0.1:8081/--/configuracoes" },
    { "waitStill": 0.6 },
    { "shot": "configuracoes" }
  ]
}

As imagens estáticas são capturas de tela do simulador sem perdas; toques e deslizes tornam-se o ponteiro de toque e cliques, portanto as receitas usam "pointer": "touch" e "device": "iphone-black" como nas capturas do navegador. Sem idb, apenas os passos wait/waitStill/agentshot/openUrl/launch funcionam.

Receita (estilo e renderização)

{
  "name": "arrastar-hoje",                 // nome do ativo na biblioteca
  "product": "ellie",                   // pasta da biblioteca; os padrões de style.json se aplicam
  "capture": "ellie-hoje-arrastar",
  "shot": "principal",                       // definido para um PNG estático; omita para um vídeo MP4
  "size": "16:9",                       // 16:9 16:10 4:3 3:2 1:1 4:5 9:16, ou largura/altura
  "background": "lavender",             // lavender peach sage sky rose mint neutral midnight ink white,
                                        // qualquer cor/gradiente CSS, ou uma imagem em public/ (backgrounds/x.jpg)
  "backgroundBlur": 0.02,               // para fundos de foto, fração do lado curto
  "device": "iphone-black",             // iphone-black iphone-natural iphone-white browser window none
  "url": "app.ellie.so/hoje",          // texto da barra do navegador; "title": título da janela para "window"
  "padding": 0.08, "tilt": 12,          // margem do dispositivo; inclinação 3D em graus
  "position": [0.69, 0.5],              // centro do dispositivo na tela, deixa espaço para um título ao lado
  "accent": "#6d5ce8",                  // cor dos passos, contornos, rótulos, ondulações de clique
  "font": "Gilda Display", "labelFont": "Inter",  // títulos / rótulos de elevação: Inter Manrope Poppins Nunito Fraunces Lora
                                        // "Playfair Display" "DM Serif Display" "Gilda Display" "Cormorant Garamond" Caveat
  "lift":  { "target": "linha-tarefa", "label": "Arrraste para o seu dia", "start": 3.9, "pad": 10, "dim": 0.1 },
  "loupe": { "target": "chip-etiqueta", "anchor": [0.2, 0.5], "zoom": 2.3, "size": 0.12, "offset": [-0.15, 0.12] },
  "annotations": [
    { "type": "step", "text": "1", "at": { "target": "botao-adicionar", "direction": "top", "offset": [-30, -10] }, "accent": "#ff6b6b" },
    { "type": "text", "text": "Toque em + para começar", "at": [400, 150], "fontSize": 18, "accent": "#333" },
    { "type": "arrow", "from": [400, 165], "to": [360, 210], "color": "#ff6b6b", "stroke": 2 }
  ],
  "hideCursor": false,                   // ocultar o cursor nos quadros (padrão: seguir o cenário)
  "cuts": [                              // para MP4: quais partes do vídeo bruto incluir
    { "from": 0, "to": 10.6, "speed": 1 },       // em segundos (do timeline de inspeção); speed > 1 = acelerado
    { "from": 15.2, "to": 23.0, "speed": 0.7 },
    { "from": 120.5, "to": 127.3, "speed": 1 }
  ],
  "zoom": [                              // zooms de vídeo (opcional — corta a área ampliada para
    { "from": 0, "to": 10.6, "region": [20, 40, 190, 340] },  // coordenadas de pixel x,y,w,h)
    { "from": 15.2, "to": 23.0, "target": "botao-adicionar" }
  ],
  "transition": "crossfade 0.3"          // entre cortes (crossfade | cut | fade 0.5 | wipe 0.4)
}

Dicas

  • Produto novo: execute agentshot style <produto> --init para criar os arquivos de diretrizes e estilo.
  • Pós-processamento: você pode ajustar cores, adicionar legendas e cortar a saída com ferramentas externas como ImageMagick ou ffmpeg.
  • Depuração: use agentshot inspect para entender o timeline e os elementos; use agentshot frames para visualizar quadros-chave.
  • Versionamento: a biblioteca mantém várias versões do mesmo ativo. Sempre especifique --note ao renderizar para rastrear as mudanças.
# Exemplo de fluxo de trabalho completo
# 1. Inicializar o estilo do produto
agentshot style meu-app --init

# 2. Capturar um cenário
cat > captura.json << 'EOF'
{
  "name": "captura-tutorial",
  "url": "http://localhost:3000",
  "device": "iphone",
  "waitFor": "conteudo-principal",
  "steps": [
    { "shot": "tela-inicial" },
    { "wait": 0.5 },
    { "tap": "botao-proximo" },
    { "waitFor": "tela-seguinte" },
    { "shot": "passo-dois" }
  ]
}
EOF
agentshot capture captura.json

# 3. Inspecionar e planejar
agentshot inspect captura-tutorial

# 4. Renderizar como imagem estática
cat > receita.json << 'EOF'
{
  "name": "tutorial-passo1",
  "product": "meu-app",
  "capture": "captura-tutorial",
  "shot": "tela-inicial",
  "size": "1:1",
  "background": "sage",
  "device": "iphone-black",
  "padding": 0.05,
  "lift": { "target": "botao-proximo", "label": "Próximo passo", "start": 0, "pad": 5, "dim": 0.15 }
}
EOF
agentshot render receita.json --note "Primeira foto do tutorial"

# 5. Verificar o resultado
agentshot frames meu-app/tutorial-passo1

Solução de problemas

  • Erro de permissão no macOS: execute agentshot doctor e conceda Gravação de Tela e Acessibilidade ao seu terminal/IDE.
  • Falha na captura do iOS Simulator: certifique-se de que o simulador esteja inicializado e que o aplicativo esteja em execução. Use agentshot sim devices para listar simuladores disponíveis.
  • Falha na captura do aplicativo web: verifique se o servidor de desenvolvimento está em execução e acessível no URL especificado.
  • Erros de renderização: verifique os logs do console para obter detalhes. Use agentshot inspect para garantir que o cenário de captura e os nomes dos ativos estejam corretos.
  • Cortes/zooms incorretos: ajuste os valores from/to com base no timeline de agentshot inspect.

Habilidades Relacionadas