Communitygithub.com

mikey-relevanceai/record-demo

Graba un video MP4 a ritmo humano de un cambio en la interfaz de usuario, para adjuntarlo a un PR. Cubre aplicaciones web mediante Playwright sin cabeza y aplicaciones de escritorio Electron mediante captura de pantalla o ventana real.

¿Qué es record-demo?

Esta habilidad permite a un agente de IA grabar un video demostrativo de un cambio en la interfaz de usuario, simulando los movimientos y pausas de una persona real, para adjuntarlo a un Pull Request (PR). Es útil para desarrolladores que necesitan mostrar visualmente cómo funciona un cambio sin requerir que el revisor ejecute el código manualmente. Soporta aplicaciones web mediante Playwright (Chromium sin cabeza con un cursor DOM) y aplicaciones de escritorio Electron (que necesitan captura de pantalla real o por ventana). El flujo de trabajo incluye: elegir la superficie (web o escritorio), recopilar entradas como la URL o variables de entorno, ensayar la grabación antes de la toma final, sondear los nombres reales de los controles (con captura de pantalla) para evitar errores, y verificar el resultado tanto visual como funcionalmente. La habilidad enfatiza la espera en eventos reales en lugar de temporizadores fijos, no modificar la aplicación bajo prueba, y mantener evidencia de fallos. Finalmente, sube el video al PR usando el cliente `gh` (a partir de v2.99.0) con el flag `--attach`.

Compatible con✓Claude Code✓Codex CLI✓Cursor
npx skills add https://github.com/mikey-relevanceai/record-demo/tree/main/skills/record-demo

Preguntar en tu IA favorita

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

Vista previa

Del README del skill

alt

Documentación

Grabar una demo

Graba un recorrido que parece hecho por una persona usando la aplicación: trayectorias curvas del cursor, pulsaciones de teclas por tecla, pausas deliberadas, en lugar de una máquina teletransportándose por la interfaz de usuario.

Las reglas a continuación se aplican a cada grabación, en todas las superficies. Están aquí y no en las referencias de plataforma porque cada una se incumplió una vez y costó una toma, y porque una regla guardada junto a un solo mecanismo es una regla que la siguiente persona no lee.

Elegir la superficie

  • La aplicación web - reference/web.md. Chromium sin cabeza bajo Playwright con un cursor DOM dibujado en la página. Nada llega a la pantalla del operador, así que prefiere esto siempre que el cambio sea visible en un navegador.
  • La aplicación de escritorio - reference/desktop.md. Necesario cuando la demo requiere el shell real de Electron: menús nativos, diálogos de archivo, bandeja, múltiples ventanas o cualquier cosa fuera del renderizador. Linux tiene un ejecutor empaquetado; macOS graba una sola ventana por ID y aún no tiene ejecutor.

Si el cambio es visible en ambas, graba la aplicación web.

Entradas

Establécelas antes de la primera toma. Léelas del proyecto donde puedas (su README, scripts en package.json, el proceso principal de Electron); pregunta al usuario lo que no puedas encontrar en lugar de adivinar.

  • Web: la URL de la aplicación en ejecución, pasada al grabador como PR_RECORDER_BASE_URL (p. ej. http://localhost:3000). La aplicación ya debe estar ejecutándose desde el checkout que tiene el cambio, incluyendo ediciones no confirmadas - un checkout fresco de la misma rama no las tendrá, y Git se niega a hacer checkout de una rama dos veces. También debe estar en el estado que la demo necesite. Si el flujo requiere un usuario autenticado o datos sembrados, es responsabilidad de la configuración del proyecto, no del grabador - pero confírmalo antes de que comience la captura, o la toma que obtengas será de una pantalla de inicio de sesión.
  • Escritorio:
    • DEMO_APP_DIR - el directorio en el que se ejecuta el comando de lanzamiento de la aplicación.
    • DEMO_WINDOW_TITLE - el título exacto de la ventana principal, utilizado para encontrar tanto la ventana X11 como la página del renderizador.
    • DEMO_LAUNCH_CMD - opcional. Un comando de shell que inicia la aplicación con depuración remota en {port}. El valor predeterminado, pnpm dev --remoteDebuggingPort {port} --noSandbox, funciona con electron-vite.

Dónde vive la habilidad

<dir-habilidad> en estos documentos significa el directorio desde el que se cargó este SKILL.md. En Claude Code es ${CLAUDE_SKILL_DIR}, que funciona tanto para instalaciones de proyecto, personales como de complementos. En otros lugares, usa la ruta desde la que se cargó la habilidad - para Codex, una carpeta .agents/skills/record-demo en el repositorio o ~/.agents/skills/record-demo. Resuélvela una vez y usa la ruta absoluta; los scripts nunca asumen dónde está instalada la habilidad.

Ensayar antes de la toma que cuenta

Ejecuta todo el flujo de principio a fin antes de grabar la que enviarás. Una demo se descubre, no se escribe: los nombres de los controles no son los que esperas, un botón hace algo diferente a lo que dice, y una superficie tarda más en estabilizarse de lo que suponías. Descubrirlo en cámara significa que el espectador te ve descubrirlo.

El ensayo es barato y la regrabación es barata. Enviar una toma con un giro equivocado, o pedir al revisor que ignore los ocho segundos centrales, no lo es.

Sondear los nombres reales de los controles primero

Nunca escribas un script contra un control sin haber confirmado que existe y que hace lo que su nombre sugiere. Carga la aplicación una vez, vuelca los nombres accesibles y toma una captura de pantalla:

const nombres = await page
  .getByRole("button")
  .evaluateAll((els) =>
    els.map((e) => (e.getAttribute("aria-label") || e.textContent || "").trim()).filter(Boolean),
  );
console.log(JSON.stringify(nombres));
await page.screenshot({ path: "/tmp/sonda.png" });

Luego lee la captura de pantalla. El volcado te dice que existe un nombre; solo la imagen te dice qué es el control. Cuatro formas en que esto muerde:

  • Un nombre que no es el que adivinarías. El nombre accesible de un conmutador era el nombre del elemento seleccionado actualmente, no "Seleccionar proyecto".
  • Un nombre que no es lo que parece. Un botón Archivos en una barra lateral era un alternador de sección, por lo que al hacer clic se colapsaba la sección en lugar de navegar a ningún lado. Eso se envió en una toma.
  • Un nombre que es parte de otro nombre. getByLabel("Primer mensaje") también coincidió con una opción cercana cuya etiqueta contenía "primer mensaje", por lo que la escritura nunca llegó al campo y nada falló. Pasa exact: true o coincide también por rol además del nombre.
  • Algo que parece texto pero no lo es. El encabezado de un selector leído de una captura de pantalla era el marcador de posición de un campo de entrada, por lo que getByText nunca pudo coincidir con él. Confirma que un localizador se resuelve antes de escribir un script contra él.

Cuando varios elementos comparten un nombre - un elemento aparece en la barra lateral, el encabezado de la página y la ruta de navegación - delimita con .first().

Conducirlo como lo haría una persona

Encuentra los controles por rol visible o texto (getByRole, getByText, getByLabel, getByPlaceholder). Nunca selectores CSS, nunca atributos solo para pruebas, y nunca agregues un gancho a la aplicación para que una grabación pueda encontrar algo. Los scripts de demostración son desechables y por PR; mantenlos fuera del repositorio.

Nunca modifiques la aplicación, la habilidad o el código de producción para una demo. Si la demo necesita que la aplicación sea diferente, la demo está mal.

Nunca esperar en el reloj

waitForTimeout(9000) para "dejar que el editor cargue" es la causa principal de demos que se pueden ver pero son aburridas. Siempre paga el peor caso, y cada uno de esos segundos está en el archivo. Espera en lo que realmente estás esperando - el primer control con el que interactuarás - para que la demo continúe en el momento en que la aplicación esté lista y falle ruidosamente, nombrando el localizador, en lugar de conducir una página medio construida.

Las pausas fijas son solo para el ritmo: una pausa después de una acción para que el espectador pueda asimilar lo que cambió. Segundos, no decenas de segundos, y nunca como sustituto de una espera.

Un archivo escrito no es una prueba

Los grabadores vacían un archivo parcial cuando el script lanza una excepción, y algunas herramientas de captura escriben al salir lo que haya sucedido. Por lo tanto, que el archivo exista no significa nada por sí solo. Antes de creer en una toma:

  • Comprueba el estado de salida y stderr, y lee el error si lo hay - generalmente nombra el localizador que no coincidió con nada.
  • Comprueba si hay una captura obsoleta que ya tenga la ruta de salida. Una captura que quedó ejecutándose de un intento anterior aún posee el nombre de archivo y producirá silenciosamente una grabación de lo incorrecto.
  • Comprueba los fotogramas. Extrae una hoja de contactos, el fotograma final y cualquier transición de la que no estés seguro, y míralos.

Verificar la demo, no el script

Una salida limpia dice que el script se ejecutó, no que la función funcionó. Confirma ambas:

  • Visual - el cambio está en pantalla en los fotogramas, en el estado que la solicitud pidió.
  • Funcional - el estado persistido realmente cambió, leído de la base de datos o de la API en lugar de inferido de la interfaz de usuario.

Cuando la afirmación es sobre el diseño - dos paneles lado a lado, un panel acoplado a un borde - afírmalo a partir de los cuadros delimitadores. Que los elementos existan no dice nada sobre dónde están.

Mantén el estado final durante unos tres segundos para que el espectador llegue a él, luego verifica el códec, las dimensiones y la duración del archivo de salida con ffprobe antes de entregarlo.

Conservar la evidencia

Conserva los registros de fallos, las tomas parciales y las capturas de pantalla hasta que una toma haya tenido éxito. Elimina el estado desechable solo después de tener algo que enviarías. Un intermedio descartado a menudo es el único registro de por qué la toma salió mal.

No molestar la máquina en la que estás grabando

Una grabación local se ejecuta en la computadora real de una persona mientras la usa.

  • Dale a la aplicación su propio perfil desechable y nunca toques el perfil real del operador.
  • Siembra lo que la demo necesite antes del primer lanzamiento, o las pantallas de primera ejecución aparecerán delante de ellos.
  • Controla cada proceso que inicies, y detenlo cuando hayas terminado - especialmente las capturas, que siguen ejecutándose después de que el script regrese.
  • Inicia procesos de larga duración como tareas en segundo plano de las que tengas un control, no con un & al final dentro de un envoltorio en primer plano: cuando el envoltorio sale, se lleva el servidor con él.
  • Detén un proceso de la manera que espera ser detenido. Un servidor de desarrollo eliminado con SIGKILL omitió su trampa de limpieza y dejó un archivo de entorno reescrito y un archivo de puerto obsoleto detrás. Envía señal al proceso que iniciaste y déjalo limpiar. Nunca mates por patrón (pkill -f next): en una máquina compartida, eso elimina también los servidores de otras personas.
  • Comprueba con qué backend habla la aplicación bajo demo. Un lanzador de desarrollo por defecto apuntaba a una API de producción a menos que se le indicara lo contrario, por lo que los clics de una demo habrían escrito datos reales. Apúntalo a un backend local o de desarrollo antes de la primera toma.
  • Verifica cualquier recurso externo del que dependa la demo - una CLI que debe haber iniciado sesión, un servicio que debe estar activo - antes de tomar la pantalla o iniciar la captura, para que una dependencia faltante falle en un segundo en lugar de a mitad de la toma. Nunca realices una acción con efectos secundarios, como enviar un mensaje, solo para demostrar que una herramienta se lanzó.
  • Si una toma necesita su pantalla, su gestor de ventanas o su entrada, dilo y pregunta, en lugar de tomarlo.

Obtener el archivo en un PR

gh sube el video por sí mismo, desde v2.99.0:

gh pr comment <numero> --body-file ./nota.md --attach ./demo.mp4

--attach también funciona en gh pr create, gh pr edit y los equivalentes de gh issue. Es repetible, hasta 50 archivos por comando, y sube al CDN de user-attachments para que GitHub renderice el video en línea.

Cuatro cosas que vale la pena saber:

  • El texto alternativo es solo para imágenes. './captura.png#El estado de error' establece texto alternativo en una imagen; la misma sintaxis en un video es rechazada con cannot set alt text on video. Adjunta videos con una ruta simple.
  • Un cuerpo que ya referencia la ruta local se reescribe. Escribe ![alt](./demo.mp4) donde lo quieras y gh intercambia la URL subida; de lo contrario, el adjunto se agrega al final.
  • gh pr edit --attach sin la bandera de body mantiene el body existente y le agrega contenido, por lo que se puede agregar una demo a la descripción de un PR después del hecho.
  • Comprueba la versión antes de confiar en ella. En gh anterior a 2.99.0 no hay --attach, y el CDN no es accesible de ninguna otra forma a través de la API - así que recurre a darle a la persona la ruta del archivo para que lo arrastre al PR por sí misma.

Skills relacionados