Communitygithub.com

thread-of-ariadne/agentshot

Captura capturas de pantalla y videos de demostración en Windows y macOS: captura una aplicación web / Expo web / ventana de escritorio / Simulador de iOS / archivo de iPhone, luego estilízalo (fondo, marco de iPhone/navegador/ventana, elevación, lupa, flechas, pasos, desenfoque, zoom, cursor, cortes) y renderiza PNG o MP4 en una librería versionada.

¿Qué es agentshot?

**agentshot** es una herramienta especializada para desarrolladores y creadores de contenido que necesitan generar capturas de pantalla y videos demo de alta calidad de sus aplicaciones. Compatible con Windows y macOS, permite capturar desde aplicaciones web (incluyendo Expo), ventanas de escritorio, el Simulador de iOS e incluso archivos existentes como capturas de pantalla de iPhone. Su flujo de trabajo se divide en fases claras: primero, se leen las reglas de estilo del producto; luego se captura la interfaz mediante escenarios JSON que definen pasos como clics, desplazamientos o escritura; a continuación, se inspeccionan los resultados para planificar recortes y zooms; después se escribe una receta JSON para aplicar estilos (fondos, marcos de dispositivo, elevaciones, lupas, anotaciones) y renderizar el PNG o MP4 final; y finalmente se verifica el resultado y se notifica al usuario. La herramienta soporta animaciones precisas (60 fps) con reloj controlado por fotogramas, permite grabar en tiempo real mediante comandos de terminal, y ofrece una vista previa interactiva para ajustar recetas en vivo. Está diseñada para integrarse en proyectos existentes, guardando escenarios y recetas versionados que pueden reutilizarse tras cambios en la UI.

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

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

agentshot: capturas de pantalla y videos demo

La herramienta está en /path/to/agentshot. Ejecútala como:

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

A continuación, agentshot significa ese comando. Cada comando imprime una línea JSON ("ok": true|false). Los renders largos también imprimen progreso en stderr. Ejecuta agentshot help para ver la lista de comandos.

Flujo de trabajo

  1. Primero lee las reglas del producto: agentshot style <producto> imprime style.json (aspecto predeterminado) y guidelines.md (lo que le gusta al usuario). Síguelas. Si el producto es nuevo, ejecuta agentshot style <producto> --init.
  2. Captura (elige una):
    • Aplicación web o Expo → escribe un escenario JSON con "url", ejecuta agentshot capture scenario.json.
    • Aplicación iOS en Mac → un escenario con "simulator" (la aplicación nativa real en el Simulador de iOS, consulta "iOS Simulator"); una imagen fija rápida → agentshot sim snap --name <captura> --clean-status-bar.
    • Programa de escritorio → un escenario con "window": conduces el ratón/teclado real mientras graba (consulta "Desktop app"). Solo una imagen fija → agentshot snap --window "<título>" --name <captura>. El usuario realiza las acciones → agentshot record start/stop.
    • El usuario ya tiene un archivo (captura de pantalla de iPhone / grabación de pantalla) → agentshot import <archivo> --name <captura>.
  3. Inspecciona: agentshot inspect <captura> enumera tomas, cuadros de elementos (puntos en pantalla), clics, duración y, para videos, moves (trayectoria del puntero), changes (cambios de página: grandes saltos visuales), quiet (nada se mueve: cortar o acelerar) y el timeline del escenario. Planifica cortes y zooms a partir de estos números, luego confirma con agentshot frames <captura> --from a --to b (una hoja de contactos con marcas de tiempo; lee el PNG que imprime). Mira el PNG de la toma con la herramienta Read antes de estilizar.
  4. Escribe una receta JSON y agentshot render recipe.json --note "<lo que cambió>".
  5. Verifica el resultado tú mismo: Lee el PNG; para MP4, agentshot frames <producto>/<activo> (video completo) y agentshot frames <producto>/<activo> --from 3 --to 4 --every 0.033 --crop x,y,w,h (fotograma a fotograma alrededor de un corte o clic). Corrige y vuelve a renderizar (se añade una nueva versión). Cuando el usuario quiera revisar o ajustar una receta por sí mismo, ejecuta agentshot preview recipe.json en segundo plano: abre una página local con la escena y un control deslizante, y se actualiza en vivo cuando se edita la receta (o el style.json del producto). Imprime una línea JSON con la url y sigue sirviendo.
  6. Informa la ruta de salida (results[].output). --copy-to <dir> también la copia al proyecto del usuario.
  7. Aprende: cuando el usuario corrige o elogia algo, añade una línea con fecha al guidelines.md del producto (y actualiza los valores predeterminados de style.json si es un aspecto predeterminado). Léelo la próxima vez.

Mantén los escenarios y recetas en el proyecto del usuario (por ejemplo, docs/shots/) para que puedan reejecutarse después de cambios en la UI.

Escenario (capturar una aplicación web)

Los comentarios en los ejemplos JSON a continuación son solo explicaciones; los archivos reales deben ser JSON simple.

{
  "name": "ellie-today-drag",          // nombre de captura, único; prefija con el producto
  "url": "http://localhost:8081",       // o una ruta de archivo
  "device": "iphone",                   // iphone | iphone-max | ipad | desktop | laptop
  "safeArea": true,                     // Expo/RN web: Chrome informa los insets del área segura de iPhone, la aplicación se distribuye
                                        // como en un dispositivo ("pad" = forzar relleno para aplicaciones que ignoran los insets)
  "css": "[class*='navigationMenuRoot'] { display: none }",  // ocultar chrome solo web (las pestañas de Expo Router se renderizan como un menú superior en web)
  "waitFor": "today-list",              // esperar este elemento antes de empezar
  "track": { "fila": "text=Planear un cumpleaños" },  // cuadros de elementos con nombre adicionales para registrar
  "steps": [
    { "shot": "main" },                                  // imagen fija a resolución completa (para capturas de pantalla)
    { "wait": 0.6 },
    { "tap": "add-button" },                             // hacer clic/tocar un objetivo (se mueve allí primero)
    { "type": "Comprar leche", "into": "title-input" },
    { "press": "Enter" },
    { "drag": "task-cumpleaños", "to": "slot-11am", "duration": 1.4 },
    { "scroll": 400, "duration": 0.8 },
    { "move": [200, 300], "duration": 0.6 },
    { "goto": "/settings" },
    { "waitFor": "settings-title" },
    { "shot": "after" }
  ]
}

Objetivos: un nombre simple coincide con data-shot="..." o data-testid="..." (el testID de React Native se convierte en data-testid en web, por lo tanto añade testIDs a los elementos que quieras señalar), o cualquier selector de Playwright (text=Guardar, role=button[name="Guardar"], #id, .class), o [x, y] en px CSS. Todos los elementos con data-shot/data-testid se registran con sus cuadros, más las entradas de track.

Temporización: por defecto ("timing": "frame") el reloj de la página se pausa y avanza exactamente un fotograma a la vez (60 fps) con una captura de pantalla a resolución completa por fotograma, por lo que las animaciones de la aplicación son suaves a cualquier resolución; la captura toma algunas veces más que el escenario. Usa "timing": "real" solo si la aplicación se rompe con un reloj controlado (un paso entonces expira). agentshot capture informa los tiempos de clic (clicks) para planificar cuts/zoom, y errores/advertencias de consola (console). Las superposiciones de desarrollo (toast de Expo LogBox, indicador de Next.js) están ocultas; "devOverlays": true las mantiene. Prefiere un segmento continuo de cuts en lugar de varios cortes duros: los saltos entre segmentos se ven bruscos.

Encontrar objetivos en una aplicación sin testIDs: abre la página con Playwright y lista botones/entradas (role, aria-label, texto), luego usa text=..., role=button[name=/^Mi hija/] o [aria-label='Tu oración'], y nombra los cuadros que quieras elevar/lupa mediante track. Escribir en un campo cubierto por un pie de página adhesivo aún funciona (el campo recibe el foco).

Expo: primero inicia la compilación web (npx expo start --web, generalmente http://localhost:8081). Los módulos solo nativos pueden no funcionar en web; si una pantalla se rompe, pide al usuario una captura de pantalla/grabación de iPhone e importala.

Aplicación de escritorio (escenario con "window")

agentshot windows lista ventanas (título, proceso, tamaño). La ventana se empareja por título, luego por nombre de proceso, se restaura si está minimizada y se trae al frente. Las coordenadas son píxeles de la ventana: mira primero una imagen fija (agentshot snap --window "X" --name x-probe, lee el PNG) y nombra los cuadros que uses en track.

{
  "name": "notes-tour",
  "window": "Notas",                              // parte del título o nombre del proceso
  "track": { "nav-recent": [20, 200, 190, 40], "nav-search": [20, 96, 190, 40], "contenido": [232, 40, 1030, 650], "perfil": [16, 718, 150, 62] },
  "cursor": [1000, 330],                          // donde comienza el puntero
  "steps": [
    { "shot": "home" },                           // fija = el fotograma grabado en este momento
    { "wait": 1 },
    { "click": "nav-recent", "duration": 0.9 },   // deslizarse allí (suavizado, ligero arco), hacer clic de inmediato
    { "waitStill": 0.6, "region": "contenido" },    // esperar a que la pantalla cambie, luego que se estabilice
    { "shot": "recent" },
    { "wheel": 4, "at": [760, 460] },             // desplazar 4 muescas hacia abajo (negativo = arriba)
    { "click": "nav-search" }, { "press": "ctrl+a" },
    { "type": "Plan semanal", "cps": 12 },         // cualquier texto, incluidos scripts no 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": "compás 2" }                          // marcador en la línea de tiempo
  ]
}
  • El resultado tiene timeline (inicio/fin de cada paso en segundos de video, at = momento del clic) y shots (fijas extraídas del video). Las recetas usan nombres de track como objetivos ("blur" en "perfil" etc.).

  • waitStill primero espera (hasta changeTimeout, 3 s) hasta que la región difiera de cómo estaba (change, diferencia media de píxeles, predeterminado 6; "change": false para solo dejar que se estabilice), luego hasta que nada cambió durante los segundos dados (threshold 0.6). Usa una region sin partes animadas (reproductores, fondos vivos).

  • Haz clic justo después de llegar: un cursor reposando en un control ~0.5 s hace que los tooltips de Windows aparezcan en el video.

  • Campos que retienen texto antiguo: press ctrl+a antes de type.

  • El controlador se inicia antes de la grabación (necesita unos segundos) y mueve el cursor real: no uses la máquina mientras tanto. Las capturas de escritorio son 1x, por lo que una lupa se ve suave; prefiere lift.

  • Imágenes fijas en cualquier momento de una grabación: agentshot snap <captura> --at 12.4 --shot nombre.

  • Los cambios pequeños (que se cierra un popup) pueden no alcanzar change en toda la ventana: da region alrededor de ellos.

  • Atajos: mod es Ctrl en Windows y Cmd en macOS ("press": "mod+a"), por lo que un escenario funciona en ambos.

Grabación manual (el usuario hace las acciones; el cursor se registra y lo dibuja el renderizador):

agentshot record --name app-filter --window "Figma" --duration 12   # graba 12 s, luego se detiene
agentshot record start --name app-filter --window "Figma"           # o iniciar ...
agentshot record stop                                               # ... y detener después

macOS

Mismos comandos y escenarios que en Windows; recorder/mac.swift se compila en el primer uso (necesita las herramientas de línea de comandos de Xcode y macOS 14+). Ejecuta agentshot doctor primero: la aplicación que ejecuta el agente (Terminal, iTerm, Claude, VS Code) necesita Grabación de pantalla y Accesibilidad en Preferencias del Sistema > Privacidad y Seguridad (agentshot doctor --request abre los avisos; reinicia esa aplicación después de concederlos). Sin Grabación de pantalla los títulos de las ventanas son solo nombres de aplicación y la grabación falla; sin Accesibilidad el controlador no puede hacer clic ni escribir.

  • Las coordenadas (track, pasos, objetivos de receta) son puntos; las imágenes fijas y el video están a la escala de píxeles de la pantalla (2 en Retina, inspect muestra scale), por lo que las elevaciones y zooms permanecen nítidos.
  • ScreenCaptureKit graba la ventana en sí: puede estar parcialmente cubierta, pero no debe estar minimizada.
  • node scripts/selftest-mac.mjs verifica todo en TextEdit (y el simulador si uno está iniciado) e imprime lo que falló. Comprobación de sincronización: agentshot record ... --show-cursor quema el cursor real en el video; compáralo con el puntero registrado (agentshot frames vs inspect) como cualquier grabación.

iOS Simulator (macOS)

La aplicación nativa en lugar de su compilación web: fuentes reales, módulos nativos, animaciones de iOS. Inicia un simulador (open -a Simulator), ejecuta la aplicación en él (npx expo run:ios o una compilación de desarrollo), luego:

agentshot sim devices                                       # simuladores iniciados
agentshot sim snap --name app-home --clean-status-bar       # imagen fija sin pérdida, 9:41 / batería completa
agentshot sim record start --name app-flow                  # alguien más conduce ...
agentshot sim record stop

Un escenario lo conduce con idb (brew install facebook/fb/idb-companion, pipx install fb-idb); las coordenadas son puntos del dispositivo (lee un sim snap y divide sus píxeles por scale):

{
  "name": "app-onboarding",
  "simulator": "booted",                        // o un UDID o parte del nombre del dispositivo
  "statusBar": "clean",                         // 9:41 durante la captura, borrado después
  "appearance": "light",                        // o "dark"
  "openUrl": "exp://127.0.0.1:8081/--/today",   // enlace profundo antes de grabar (o "launch": "<bundle id>")
  "track": { "add": [330, 760, 48, 48], "title": [24, 120, 340, 44] },
  "steps": [
    { "shot": "today" },
    { "tap": "add" },
    { "waitStill": 0.5 },
    { "type": "Comprar leche" },                      // en el campo enfocado
    { "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/--/settings" },
    { "waitStill": 0.6 },
    { "shot": "settings" }
  ]
}

Las imágenes fijas son capturas de pantalla del simulador sin pérdida; los toques y deslizamientos se convierten en el puntero táctil y clics, por lo que las recetas usan "pointer": "touch" y "device": "iphone-black" como en las capturas del navegador. Sin idb solo funcionan los pasos wait/waitStill/agentshot/openUrl/launch.

Receta (estilo y renderizado)

{
  "name": "today-drag",                 // nombre del activo en la biblioteca
  "product": "ellie",                   // carpeta de la biblioteca; se aplican los valores predeterminados de style.json
  "capture": "ellie-today-drag",
  "shot": "main",                       // establece para un PNG fijo; omítelo para un video MP4
  "size": "16:9",                       // 16:9 16:10 4:3 3:2 1:1 4:5 9:16, o ancho/alto
  "background": "lavender",             // lavender peach sage sky rose mint neutral midnight ink white,
                                        // cualquier color/gradiente CSS, o una imagen en public/ (backgrounds/x.jpg)
  "backgroundBlur": 0.02,               // para fondos de foto, proporción del lado corto
  "device": "iphone-black",             // iphone-black iphone-natural iphone-white browser window none
  "url": "app.ellie.so/today",          // texto de la barra del navegador; "title": título de la ventana para "window"
  "padding": 0.08, "tilt": 12,          // margen del dispositivo; inclinación 3D en grados
  "position": [0.69, 0.5],              // centro del dispositivo en el lienzo, deja espacio para un título a su lado
  "accent": "#6d5ce8",                  // color de pasos, contornos, etiquetas, ondas de clic
  "font": "Gilda Display", "labelFont": "Inter",  // títulos / etiquetas de elevación: Inter Manrope Poppins Nunito Fraunces Lora
                                        // "Playfair Display" "DM Serif Display" "Gilda Display" "Cormorant Garamond" Caveat
  "lift":  { "target": "task-row", "label": "Arrástralo a tu día", "start": 3.9, "pad": 10, "dim": 0.1 },
  "loupe": { "target": "label-chip", "anchor": [0.2, 0.5], "zoom": 2.3, "size": 0.12, "offset": [-0.15, 0.12] },
  "annotations": [
    { "type": "step", "target": "row-principal", "label": "Paso 1", "color": "#ffffff", "background": true, "radius": true },
    { "type": "arrow", "from": [0.32, 0.29], "to": [0.38, 0.48], "color": "#ffffff", "width": 6, "style": "solid" },
    { "type": "note", "x": 0.55, "y": 0.7, "label": "¿Nuevo en Ellie?", "width": 150, "align": "left", "color": "#ffffff", "background": true },
    { "type": "cursor", "x": 0.34, "y": 0.33, "shape": "dot", "color": "#ffffff" }
  ],
  "blur": { "target": "perfil", "radius": 6, "exclude": "avatar" },
  "cuts": [
    { "from": 0, "to": 1.2, "speed": 1 },
    { "from": 4.5, "to": 5.8, "speed": 3 },
    { "from": 7, "to": 9, "zoom": 1.4, "anchor": [0.3, 0.5] },
    { "from": 9, "to": 11, "crop": [130, 230, 330, 550] }
  ],
  "info": [
    { "title": "Ellie – Asistente de citas", "subtitle": "Arrastra tareas a tu horario", "icon": "public/logos/ellie.jpg" },
    { "title": "Lleva un registro de tus planes", "subtitle": "Solo se necesita un clic" }
  ],
  "timeline": { "show": true, "height": 22, "color": "#6d5ce8", "labels": false, "markers": ["compás 2"], "trim": [0, 10] },
  "pointer": "click",                   // "click" (círculo pequeño) "touch" (círculo semitransparente) "none"
  "resolution": 144,                    // 72 144 288 300 ppi
  "credits": "© 2025 Ellie Inc."
}

Grupos de recetas: en lugar de un único objeto {}, un array separa las escenas, cada una con su propio capture/shot/cuts, renderizadas en secuencia en un MP4. intro/outro añade una tarjeta de título/final. Ejemplo:

[
  { "intro": { "title": "Ellie", "subtitle": "Agenda inteligente", "duration": 2 } },
  { "name": "crear-tarea", ... },
  { "name": "arrastrar", "capture": "ellie-today-drag", ... },
  { "outro": { "title": "Prueba Ellie", "subtitle": "grellie.com", "duration": 3, "action": "cta" } }
]

Cada grupo debe tener un name único (establecido o por defecto) y una salida results[].output. La música de fondo: "audio": "public/audio/chill.mp3" (o "none"). intro/outro también puede ser un video corto ("video": "public/intros/globe.mp4").

Línea de tiempo: las escenas que no sean intro/outro deben tener una propiedad timeline si quieres la barra de progreso; pueden compartir estilo.

Cortes automáticos: si se omite cuts, toda la escena se renderiza completa (speed: 1). "trim": [0, 10] recorta el video a los primeros 10 segundos.

Superposiciones de video: "overlay": { "file": "file.mp4", "position": "bottom-left", "scale": 0.12, "opacity": 0.6, "radius": true, "shadow": true } añade un video PiP (el usuario grabando, una reacción). El archivo se reproduce en bucle o hasta que dure la escena.

Renderizado

agentshot render recipe.json --note "nuevo flujo de arrastre" compila el video/PNG en la biblioteca del producto:

products/
  ellie/
    today-drag/
      1.png                                # primera versión
      render-1.json                        # la receta usada
      note-1.txt                           # "nuevo flujo de arrastre"
      2.png
      render-2.json
      note-2.txt

products/ellie/style.json contiene los valores predeterminados de los productos (fondo, dispositivo, inclinación, relleno, posición, acento, familia de fuentes, resolución) y guidelines.md para notas narrativas. Los activos versionados permiten comparar versiones: siempre renderiza en una nueva versión pero informa la última. El usuario puede cambiar style.json (o proporcionar uno específico en la receta con "style": "...").

Para renderizar directamente a la ubicación de la UI de producción: --copy-to ../assets/shots/.

applyStyle (cambiar el aspecto de una imagen existente)

Toma un PNG, aplica el fondo, el marco del dispositivo y los créditos, imprime el PNG renderizado en stdout (única línea JSON). Los parámetros se pasan como banderas: agentshot applyStyle <archivo> --background "lavender" --device "iphone-black" --url "ellie.so". No se necesita ningún escenario.

Integración con Claude

Cuando se te pida que tomes una captura de pantalla:

  1. Identifica qué capturar (página web, aplicación Expo, ventana de escritorio, Simulador de iOS). Si es una aplicación web, ¿está en ejecución el servidor web? (Pregunta al usuario; si no, pídeles que comiencen npx expo start o npm run dev).
  2. Escribe un escenario JSON. Asegúrate de que la URL coincida con el servidor en ejecución. Usa shots/ dentro del proyecto del usuario. Solicita la URL si no está clara y las dimensiones aproximadas del dispositivo (o smartphone/tableta/escritorio).
  3. Ejecuta agentshot capture scenario.json. Comprueba la salida.
  4. Ejecuta agentshot inspect <captura> para ver tomas/bloques de escenario, duración y, para videos, moves, changes, quiet y timeline.
  5. Escribe una receta JSON y agentshot render recipe.json. Comprueba la salida.
  6. Lee el PNG renderizado (o fotogramas de una sección del MP4) para verificar que se vea bien. Pregunta al usuario cómo se ve, luego ajusta y vuelve a renderizar si es necesario.
  7. Reporta la biblioteca actualizada al usuario (products/<producto>/<activo>/<n-último>.(png|mp4)), manteniendo los activos versionados.

Nota: Desktop app y Simulador deben ejecutarse en un monitor que el agente pueda leer (macOS / Windows con herramientas de accesibilidad). En Simulador de iOS, el agente puede no ver el contenido de la aplicación sin idb; usa sim snap para imágenes fijas.`

Skills relacionados