animate-file-history
Construisez un GIF (ou MP4) montrant l'évolution d'un fichier au cours de la vie du dépôt. La demande est formulée en langage naturel
($ARGUMENTS), donc le travail consiste à : déterminer les fichiers concernés, collecter chaque version provenant de git, les rendre,
supprimer les versions identiques à la précédente, et assembler le tout en une animation.
Le script fourni effectue le parcours git, le rendu, la déduplication visuelle et l'encodage :
scripts/animate-history.sh, relativement au répertoire de base de cette compétence - pas au dépôt de l'utilisateur. Ci-dessous,
$SKILL désigne ce répertoire ; appelez le script via son chemin absolu. --help liste toutes les options. Votre rôle consiste à choisir les fichiers et,
pour les pages, à produire les captures d'écran.
1. Vérifier les outils
command -v git ffmpeg rsvg-convert; ls "/Applications/Google Chrome.app" 2>/dev/null; command -v chromium google-chrome
ffmpeg est requis. Les SVG nécessitent rsvg-convert (brew install librsvg / apt install librsvg2-bin) ou
Chrome/Chromium. Les légendes --label et les pages HTML nécessitent Chrome/Chromium (CHROME=/path remplace
la détection automatique). Si quelque chose manque, indiquez quoi et comment l'installer - ne supprimez pas silencieusement des versions SVG.
2. Interpréter la demande pour trouver les fichiers
Recherchez dans tout l'historique de la branche courante, pas seulement l'arborescence actuelle - les logos sont renommés, déplacés et réexportés, et les fichiers supprimés font toujours partie de l'histoire :
git log --format= --name-only -- ':(glob,icase)**/*logo*' | sort -u
Recherchez ce que la chose est appelée, pas seulement le mot de l'utilisateur. Un logo se trouve aussi dans favicon*,
apple-touch-icon*, *mark*, *lockup*, *wordmark*, *brand* et le nom du produit lui-même - les premières versions
sont souvent uniquement dans le favicon. Élargissez la liste des globs en conséquence et examinez les résultats.
Filtrez pour les types rendables : png jpg jpeg gif webp bmp svg pour les images ; html pour les pages statiques. Ignorez
les fichiers de construction et les copies importées (dist/, build/, node_modules/, .next/).
Regroupez ensuite les correspondances en lignées - une lignée par animation :
- La même œuvre à travers les renommages, déplacements ou changements de format (
logo.png→brand/logo.svg) constitue une lignée. Passez tous ses chemins à une seule exécution ; le script les fusionne en une seule chronologie par date de commit. - Les variantes coexistantes (
logo-dark.svg,logo-mono.svg,favicon.png, les exportations dimensionnées comme[email protected]) sont des lignées séparées. Par défaut, une animation par lignée, et animez uniquement les variantes que la demande signifie plausiblement (généralement le logo principal, pas chaque taille de favicon).
Si le regroupement est véritablement ambigu (plusieurs fichiers "logo" sans lien, ou aucune correspondance), montrez la
liste des candidats avec le nombre de commits (git log --follow --oneline -- <chemin> | wc -l) et demandez avant de rendre.
3a. Images : exécuter le script
"$SKILL/scripts/animate-history.sh" -o logo-history.gif --label <chemin> [<chemin-plus-ancien> ...]
Options utiles : -s 512 ou -s 1200x800 pour le canevas, -t 0.25 secondes par version (valeur par défaut pour les images ; les captures d'écran de pages via --frames sont par défaut à 0.8 ; utilisez la valeur de l'utilisateur s'il
en a donné une, par exemple "0.5s par image" → -t 0.5), --hold 1.5 secondes sur la dernière image, --bg '#0b0b0b' pour les logos conçus pour des fonds sombres, --keep DOSSIER pour conserver les images,
-o x.mp4 pour une vidéo, --skip <sha> (répétable) pour supprimer une version que l'utilisateur ne souhaite pas. Il affiche keep/skip par commit et kept N of M versions sur stderr.
Les chemins sont relatifs au répertoire courant (ou -C DOSSIER), comme tout chemin git ; exécutez depuis la racine du dépôt
et passez-les tels qu'ils apparaissent dans la liste d'historique ci-dessus. Le script suit lui-même les renommages (git log --follow), donc le chemin actuel seul suffit généralement, sauf si le fichier a été recréé sous un nouveau nom.
3b. Pages : capture d'écran de chaque version, puis exécution du script sur le dossier
Une page nécessite un rendu pour chaque commit. Trouvez la source de la page
(index.html, app/page.tsx, src/pages/index.vue, ...) et listez les commits qui l'ont touchée ou ce qu'elle
rend - l'apparence d'une page d'accueil change également via ses composants et son CSS :
git log --format='%H %cs' --reverse -- <fichier page> <ses dossiers composants/styles>
Si cela dépasse environ 40 commits, échantillonnez (un par semaine ou par mois, plus le premier et le dernier) et mentionnez-le.
Les captures d'écran vont dans un dossier nommé <YYYY-MM-DD>_<sha-court>.png, afin que les fichiers soient triés par date et que le nom devienne
la légende.
-
HTML statique : pas de construction. Exportez le commit avec
git archive <sha> | tar -x -C "$snap"et capturez d'écran le fichier avec"$CHROME" --headless=new --hide-scrollbars --window-size=1280,800 --screenshot=... "file://$snap/<page>.html". Supprimez$snapensuite et conservez-le en dehors du dépôt. -
Page avec framework (React, Next, Vue, Astro, ...) : elle doit être exécutée pour s'afficher. Utilisez
snapshot-commit.shpar commit :"$SKILL/scripts/snapshot-commit.sh" -C <depot> -r /<route> -f https://<site production> <sha> "$shots"Il exporte le commit, installe le fichier de verrouillage de ce commit (mis en cache par fichier de verrouillage), démarre le serveur de développement (
-d 'commande avec {port}'si ce n'est pasnpm run dev -- --port {port}), et prend une capture via Playwright (scripts/screenshot-page.mjs, nécessiteplaywright-coreet Chrome - celui du dépôt est trouvé viaPLAYWRIGHT_DIR). Il attend que le réseau soit inactif et chaque<img>, ferme une bannière de cookies, et affiche une ligne :ok,blank,error(une page d'erreur comme "impossible de charger dans ce navigateur") oufail(échec d'installation ou du serveur de développement). Seulokécrit un PNG. Demandez avant d'exécuter cela si cela implique plus de quelques installations.
Vérifiez les résultats avant d'animer, ne faites pas confiance à ok seul :
- N'empruntez jamais le
node_modulesactuel. Les anciens commits importent des paquets que l'arbre actuel a abandonnés (par exemplereact-router-dom), et la page s'affiche vide. C'est pourquoi le script installe par commit. - Commits
blank/error/fail: examinez le journal de développement, essayez une fois de corriger la cause (une variable d'environnement manquante, une commande-dincorrecte,--ignore-scriptssautant une étape de construction nécessaire), sinon ignorez le commit et indiquez combien. - Images cassées (
broken-images=Nsur la ligneok, avec les URL) : ressources que le serveur de développement ne peut pas servir (chemins hébergés sur la plateforme comme/__l5e/..., fichiers gitignorés ou téléchargés).-f <site production>les récupère depuis la production. Si les images sont toujours cassées, mentionnez-le dans le rapport - ne livrez pas un GIF plein de boîtes vides en silence. Corrigez à la volée plutôt que de signaler après. - Examinez une planche contact des images (
ffmpeg -pattern_type glob -i '*.png' -vf scale=320:-1,tile=6x6 -frames:v 1 sheet.png) avant l'exécution finale.
Ensuite :
"$SKILL/scripts/animate-history.sh" --frames "$shots" -s 1280x800 --label -o home-page-history.gif
Les captures d'écran identiques sont supprimées de la même manière que les images identiques, de même que les captures vides (une seule couleur unie)
(--keep-blank pour les conserver). Utilisez une taille de fenêtre fixe pour chaque
capture, et préférez -o x.mp4 pour les pages longues ou détaillées - les GIF de pages entières deviennent volumineux.
3c. Sur plusieurs dépôts
Lorsque le logo vit dans plusieurs dépôts (une application, un tableau de bord, un site web), exécutez le script dans chaque dépôt avec
--keep <dossier> et sans --label, puis copiez chaque image conservée dans un dossier nommé
<YYYY-MM-DD>_<depot>-<sha-court>.png - les lignes keep sur stderr donnent la date et le sha de chaque image conservée dans
l'ordre. Ajoutez -2, -3 aux noms qui entrent en collision (plusieurs fichiers modifiés dans un même commit). Exécutez ensuite
--frames <dossier> --label -t 0.25 sur le dossier fusionné pour une seule chronologie sur tous.
4. Rapport
Donnez le chemin de sortie, combien de versions ont été trouvées et combien ont été incluses dans l'animation, la plage
de dates, et tout ce qui a été ignoré (non rendable, constructions échouées, échantillonnage exclu). Ouvrez-le si demandé (open x.gif).
Écrivez la sortie là où l'utilisateur le souhaite, par défaut dans le répertoire courant - ne la validez jamais sauf
si demandé.
Pièges
- La déduplication se fait sur les pixels rendus, pas sur les octets. Un PNG réexporté ou un SVG reformaté est ignoré s'il s'affiche à l'identique ; un décalage d'un pixel compte comme un changement. C'est le principe - n'ajoutez pas de filtre au niveau des octets par-dessus.
- Les SVG qui référencent des fichiers externes (polices,
<image href>) s'affichent sans eux, puisque seul le SVG lui-même est extrait de l'historique. Le contenu intégré est correct. - Les sources GIF animées ne contribuent que leur première image.
- Les commits de fusion ne sont pas parcourus -
git logmontre les modifications du fichier sur la branche qui les a effectuées, ce qui est ce que vous voulez pour une chronologie. - Les clones superficiels (CI,
--depth 1) n'ont pas d'historique. Vérifiezgit rev-parse --is-shallow-repositoryet suggérezgit fetch --unshallows'il affichetrue. - Les légendes nécessitent Chrome/Chromium car les versions ffmpeg fournies manquent souvent de
drawtext.
Modèle et effort
Le jugement ici est limité (choisir les fichiers, regrouper les lignées, choisir un échantillon) ; le travail lourd est le script et les boucles shell. Par défaut, utilisez Sonnet à faible effort. Opus ou un effort plus élevé n'apporte rien pour cette tâche, et un fork ou un sous-agent est inutile. Augmentez l'effort uniquement lorsque le regroupement des lignées est véritablement ambigu.
La plupart des jetons d'une exécution sont le contexte hérité de la session (CLAUDE.md, listes de compétences et d'outils, ~100k+), relu depuis le cache à chaque tour, pas le travail lui-même. Une exécution dans une session légère coûte bien moins qu'une dans une session chargée.
Repères
Mesurez avec la transcription de la session (somme des usage sur les tours de l'assistant) :
f=$(ls -t ~/.claude/projects/<projet>/*.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"
| Date | Modèle / effort | Tâche | Tours | Jetons sortie | Cache lu | Cache créé | Résultat |
|---|---|---|---|---|---|---|---|
| 23/10/2026 | Sonnet 5.5 / faible | Page d'accueil storra, découverte uniquement (avant rendu) | 9 | 3.6k | 731k | 134k | fichiers + historique de route trouvés en ~7 appels |
Ajoutez une ligne par exécution (exécution complète, pas seulement la découverte) ; comparez Opus / effort plus élevé uniquement si une exécution Sonnet-faible obtient un mauvais regroupement de lignées ou d'échantillonnage.