Communitygithub.com

echarrod/skillsed - Animación del historial de archivos

Convierte el historial de git de un archivo en una animación, un fotograma por cada versión visualmente diferente: la evolución de un logotipo, los rediseños de una página web. Úsalo cuando te pidan animar, reproducir o mostrar la evolución de un logotipo, imagen, icono o página web a lo largo del tiempo.

¿Qué es skillsed - Animación del historial de archivos?

Este skill permite crear animaciones (GIF o MP4) que muestran cómo ha evolucionado visualmente un archivo a lo largo de la historia de un repositorio git. Es especialmente útil para visualizar la evolución de logotipos, iconos, imágenes o páginas web, mostrando cada versión que sea visualmente diferente de la anterior. El skill automatiza todo el proceso: localiza los archivos relevantes en todo el historial (incluyendo archivos renombrados o eliminados), extrae cada versión desde git, renderiza cada una (soportando tanto imágenes como páginas HTML estáticas o basadas en frameworks como React/Vue/Next.js), elimina versiones duplicadas visualmente y genera la animación final. Soporta múltiples plataformas (CLI, cualquier agente que pueda ejecutar scripts bash) y funciona con imágenes (PNG, SVG, JPG, etc.) y páginas web. La inteligencia principal del skill está en la selección de archivos relevantes mediante búsquedas en el historial de git, la agrupación de variantes en linajes separados (por ejemplo, `logo-dark.svg` y `logo-mono.svg` son linajes distintos), y el manejo de casos complejos como logotipos distribuidos en varios repositorios. El trabajo pesado de renderizado y encoding recae en scripts bash incluidos, que utilizan herramientas como ffmpeg, rsvg-convert y Chrome/Chromium para capturas de pantalla.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/echarrod/skillsed/tree/HEAD/skills/animate-file-history

Preguntar en tu IA favorita

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

Documentación

animate-file-history - Animación del historial de archivos

Construye un GIF (o MP4) de cómo se veía algo a lo largo de la vida del repositorio. La solicitud está en lenguaje natural ($ARGUMENTS), así que el trabajo consiste en: determinar a qué archivos se refiere, recopilar cada versión de ellos desde git, renderizar cada una, descartar las versiones que se ven igual que la anterior y unir el resto en una animación.

El script incluido se encarga de recorrer git, renderizar, deduplicar visualmente y codificar: scripts/animate-history.sh, relativo al directorio base de este skill - no al repositorio del usuario. A continuación, $SKILL representa ese directorio; llama al script por su ruta absoluta. --help lista todas las opciones. Tu parte es elegir los archivos y, para páginas, producir las capturas de pantalla.

1. Verificar las herramientas

command -v git ffmpeg rsvg-convert; ls "/Applications/Google Chrome.app" 2>/dev/null; command -v chromium google-chrome

ffmpeg es obligatorio. SVG necesita rsvg-convert (brew install librsvg / apt install librsvg2-bin) o Chrome/Chromium. --label (etiquetas) y páginas HTML necesitan Chrome/Chromium (CHROME=/ruta anula la detección). Si falta algo, indica qué y cómo instalarlo; no omitas versiones SVG en silencio.

2. Resolver la solicitud a archivos

Busca en el historial completo de la rama actual, no solo en el árbol de hoy; los logotipos se renombran, mueven y reexportan, y los archivos eliminados aún pertenecen a la historia:

git log --format= --name-only -- ':(glob,icase)**/*logo*' | sort -u

Busca por lo que la cosa se llama, no solo por la palabra del usuario. Un logotipo también vive en favicon*, apple-touch-icon*, *mark*, *lockup*, *wordmark*, *brand* y el propio nombre del producto; las versiones tempranas suelen estar solo en el favicon. Amplía la lista de globs en consecuencia y observa lo que devuelve.

Filtra a tipos renderizables: png jpg jpeg gif webp bmp svg para imágenes; html para páginas estáticas. Ignora la salida de compilación y copias empaquetadas (dist/, build/, node_modules/, .next/).

Luego agrupa las coincidencias en linajes - un linaje por animación:

  • La misma obra de arte a través de renombres, movimientos o un cambio de formato (logo.png → brand/logo.svg) es un linaje. Pasa todas sus rutas a una sola ejecución; el script las fusiona en una sola línea de tiempo por fecha de commit.
  • Las variantes que coexisten (logo-dark.svg, logo-mono.svg, favicon.png, exportaciones con tamaño como [email protected]) son linajes separados. Por defecto, una animación por linaje, y solo anima las variantes que la solicitud plausiblemente significa (normalmente el logotipo principal, no todos los tamaños de favicon).

Si la agrupación es genuinamente ambigua (varios archivos "logo" no relacionados, o nada coincide), muestra la lista de candidatos con el recuento de commits (git log --follow --oneline -- <ruta> | wc -l) y pregunta antes de renderizar.

3a. Imágenes: ejecutar el script

"$SKILL/scripts/animate-history.sh" -o logo-history.gif --label <ruta> [<ruta-antigua> ...]

Opciones útiles: -s 512 o -s 1200x800 lienzo, -t 0.25 segundos por versión (predeterminado para imágenes; las capturas de pantalla de páginas vía --frames usan 0.8 por defecto; usa el valor del usuario si lo dio, ej. "0.5s por fotograma" → -t 0.5), --hold 1.5 segundos en el fotograma final, --bg '#0b0b0b' para logotipos diseñados para fondos oscuros, --keep DIR para conservar los fotogramas, -o x.mp4 para video, --skip <sha> (repetible) para omitir una versión que el usuario no quiere. Imprime keep/skip por commit y kept N of M versions (se mantuvieron N de M versiones) en stderr.

Las rutas son relativas al directorio actual (o -C DIR), como cualquier pathspec de git; ejecuta desde la raíz del repositorio y pásalas como las muestra la lista de historial anterior. El script sigue los renombres por sí mismo (git log --follow), por lo que la ruta actual suele ser suficiente a menos que el archivo se haya recreado con un nuevo nombre.

3b. Páginas: capturar cada versión, luego ejecutar el script en la carpeta

Una página necesita renderizarse en cada commit. Encuentra el origen de la página (index.html, app/page.tsx, src/pages/index.vue, ...) y lista los commits que la modificaron o lo que renderiza; el aspecto de una página de inicio también cambia a través de sus componentes y CSS:

git log --format='%H %cs' --reverse -- <archivo-página> <directorios de componentes/estilos>

Si son más de ~40 commits, muestrea (uno por semana o mes, más el primero y el último) y dílo. Las capturas van en una carpeta nombrada <AAAA-MM-DD>_<sha-corto>.png, para que los archivos se ordenen por fecha y el nombre sea el título.

  • HTML estático: sin compilación. Exporta el commit con git archive <sha> | tar -x -C "$snap" y captura la pantalla del archivo con "$CHROME" --headless=new --hide-scrollbars --window-size=1280,800 --screenshot=... "file://$snap/<página>.html". Elimina $snap después y mantenlo fuera del repositorio.

  • Página con framework (React, Next, Vue, Astro, ...): debe ejecutarse para renderizar. Usa snapshot-commit.sh por commit:

    "$SKILL/scripts/snapshot-commit.sh" -C <repo> -r /<ruta> -f https://<sitio-producción> <sha> "$shots"
    

    Exporta el commit, instala el lockfile de ese commit (cacheado por lockfile), inicia el servidor de desarrollo (-d 'comando con {port}' si no es npm run dev -- --port {port}), y captura la pantalla a través de Playwright (scripts/screenshot-page.mjs, necesita playwright-core y Chrome - el propio del repositorio se encuentra via PLAYWRIGHT_DIR). Espera a que la red esté inactiva y cada <img>, descarta el banner de cookies, e imprime una línea: ok, blank (en blanco), error (página de error como "no se pudo cargar en este navegador") o fail (fallo de instalación o servidor). Solo ok escribe un PNG. Pregunta antes de ejecutar esto si implica más de un puñado de instalaciones.

Verifica los resultados antes de animar, no confíes solo en ok:

  • Nunca tomes prestado el node_modules actual. Los commits antiguos importan paquetes que el árbol actual eliminó (ej. react-router-dom), y la página se renderiza en blanco. Por eso el script instala por commit.
  • Commits blank / error / fail: mira el registro de desarrollo, intenta una vez arreglar la causa (una variable de entorno faltante, un comando -d incorrecto, --ignore-scripts saltando un paso de compilación necesario), de lo contrario omite el commit y di cuántos.
  • Imágenes rotas (broken-images=N en la línea ok, con las URLs): assets que el servidor de desarrollo no puede servir (rutas alojadas en plataforma como /__l5e/..., archivos gitignorados o subidos). -f <sitio-producción> los obtiene desde producción. Si las imágenes siguen rotas, dílo en el informe; no envíes un GIF lleno de cuadros vacíos en silencio. Arregla sobre la marcha en lugar de informar después.
  • Mira una hoja de contactos de los fotogramas (ffmpeg -pattern_type glob -i '*.png' -vf scale=320:-1,tile=6x6 -frames:v 1 sheet.png) antes de la ejecución final.

Luego:

"$SKILL/scripts/animate-history.sh" --frames "$shots" -s 1280x800 --label -o home-page-history.gif

Las capturas idénticas se descartan igual que las imágenes idénticas, y también las que son completamente de un color plano (usa --keep-blank para conservarlas). Usa un tamaño de ventana fijo para cada captura, y prefiere -o x.mp4 para páginas largas o detalladas; los GIF de páginas completas se vuelven grandes.

3c. En varios repositorios

Cuando el logotipo vive en más de un repositorio (una app, un panel, un sitio web), ejecuta el script en cada repositorio con --keep <dir> y sin --label, luego copia cada fotograma conservado en una carpeta nombrada <AAAA-MM-DD>_<repo>-<sha-corto>.png; las líneas keep en stderr dan la fecha y sha de cada fotograma conservado en orden. Agrega -2, -3 a nombres que colisionan (varios archivos cambiaron en un commit). Luego ejecuta --frames <carpeta> --label -t 0.25 en la carpeta fusionada para una sola línea de tiempo a través de todos ellos.

4. Informe

Proporciona la ruta de salida, cuántas versiones se encontraron y cuántas llegaron a la animación, el rango de fechas y cualquier cosa omitida (no renderizable, compilaciones fallidas, muestreadas). Ábrelo si se pide (open x.gif). Escribe la salida donde el usuario quiera, por defecto en el directorio actual; nunca lo confirms a menos que se solicite.

Advertencias

  • La deduplicación es sobre píxeles renderizados, no bytes. Un PNG reexportado o SVG reformateado se omite si se renderiza idénticamente; un desplazamiento de un píxel cuenta como cambio. Ese es el punto; no añadas un filtro a nivel de bytes encima.
  • Los SVG que referencian archivos externos (fuentes, <image href>) se renderizan sin ellos, ya que solo el SVG en sí se extrae del historial. El contenido incrustado está bien.
  • Las fuentes GIF animadas contribuyen solo con su primer fotograma.
  • Los commits de fusión no se recorren - git log muestra los cambios del archivo en la rama que los hizo, que es lo que se desea para una línea de tiempo.
  • Los clones superficiales (CI, --depth 1) no tienen historial. Verifica git rev-parse --is-shallow-repository y sugiere git fetch --unshallow si imprime true.
  • Las etiquetas necesitan Chrome/Chromium porque las compilaciones de ffmpeg incluidas a menudo carecen de drawtext.

Modelo y esfuerzo

El criterio aquí es pequeño (elegir archivos, agrupar linajes, elegir una muestra); el trabajo pesado recae en el script y los bucles de shell. Por defecto, usa Sonnet con esfuerzo bajo. Opus o mayor esfuerzo no aporta nada para esta tarea, y un fork o subagente es innecesario. Aumenta el esfuerzo solo cuando la agrupación de linajes sea genuinamente ambigua.

La mayoría de los tokens de una ejecución son el contexto heredado de la sesión (CLAUDE.md, listas de skills y herramientas, ~100k+), releído desde caché en cada turno, no el trabajo en sí. Una ejecución en una sesión sin carga cuesta mucho menos que una en una cargada.

Benchmarks

Mide con la transcripción de la sesión (suma usage en los turnos del asistente):

f=$(ls -t ~/.claude/projects/<directorio-proyecto>/*.jsonl | head -1)
jq -s '[.[]|select(.message.usage)|.message.usage]|{turns:length,out:(map(.output_tokens)|add),cache_read:(map(.cache_read_input_tokens)|add),cache_create:(map(.cache_creation_input_tokens)|add)}' "$f"
FechaModelo / esfuerzoTareaTurnosTokens salidaTokens lectura cachéTokens creación cachéResultado
2026-10-23Sonnet 5.5 / bajoPágina de inicio de storra, solo descubrimiento (antes de renderizar)93.6k731k134kArchivos + historial de ruta encontrados en ~7 llamadas

Añade una fila por ejecución (ejecución completa, no solo descubrimiento); compara Opus / mayor esfuerzo solo si una ejecución Sonnet-bajo se equivoca en el linaje o el muestreo.

Skills relacionados