Communitygithub.com

agentshot : captures d'écran et vidéos de démonstration

Générez des captures d'écran produit et des vidéos de démonstration sur Windows et macOS – capturez une application web / Expo web / fenêtre de bureau / simulateur iOS / fichier iPhone, puis stylisez-la (arrière-plan, cadre iPhone/navigateur/fenêtre, surélévation, loupe, flèches, étapes, flou, zoom, curseur, coupes) et rendez-la en PNG ou MP4 dans une bibliothèque versionnée.

Qu'est-ce que agentshot : captures d'écran et vidéos de démonstration ?

Le skill `agentshot` automatise la création de captures d'écran et de vidéos de démonstration pour les produits web, mobiles et desktop sur Windows et macOS. Il est idéal pour les développeurs qui ont besoin de captures d'écran, de maquettes, d'images pour centre d'aide, d'images de changelog, de publications sur les réseaux sociaux (X/Instagram), de vidéos de démonstration ou d'enregistrements d'écran de leur application. Il fonctionne en trois étapes : capture (d'une application web, d'un simulateur iOS, d'une fenêtre de bureau ou d'un fichier importé), inspection (analyse des scènes, des boîtes d'éléments, des clics et de la durée pour planifier les coupes et les zooms), puis rendu (stylisation de la sortie avec des cadres, des arrière-plans, des annotations, des effets de loupe et de surélévation). Le skill crée une bibliothèque versionnée des ressources et prend en charge des recettes JSON réutilisables pour une génération cohérente sur l'ensemble d'un projet. Il utilise Playwright pour l'automatisation web, ScreenCaptureKit pour les captures desktop sous macOS, et idb pour le contrôle du simulateur iOS.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait agentshot : captures d'écran et vidéos de démonstration ?

L'outil se trouve dans /path/to/agentshot. Exécutez-le comme suit :

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

Ci-dessous, agentshot désigne cette commande. Chaque commande imprime une ligne JSON ("ok": true|false). Les longs rendus impriment également la progression sur stderr. Exécutez agentshot help pour la liste des commandes.

Flux de travail

  1. Lisez d'abord les règles du produit : agentshot style <produit> imprime style.json (aspect par défaut) et guidelines.md (ce que l'utilisateur aime). Suivez-les. Si le produit est nouveau, exécutez agentshot style <produit> --init.
  2. Capturez (choisissez une option) :
    • Application Web ou Expo → écrivez un JSON de scénario avec "url", exécutez agentshot capture scenario.json.
    • Application iOS sur Mac → un scénario avec "simulator" (l'application native réelle dans le simulateur iOS, voir "Simulateur iOS") ; une image fixe rapide → agentshot sim snap --name <capture> --clean-status-bar.
    • Programme de bureau → un scénario avec "window" : vous contrôlez la souris/le clavier pendant qu'il enregistre (voir "Application de bureau"). Juste une image fixe → agentshot snap --window "<titre>" --name <capture>. L'utilisateur effectue les actions → agentshot record start/stop.
    • L'utilisateur a déjà un fichier (capture d'écran iPhone / enregistrement d'écran) → agentshot import <fichier> --name <capture>.
  3. Inspectez : agentshot inspect <capture> liste les scènes, les boîtes d'éléments (points écran), les clics, la durée et, pour les vidéos, les moves (déplacements du pointeur), changes (changements de page : grands sauts visuels), quiet (rien ne bouge : coupe ou accélère) et la timeline du scénario. Planifiez les coupes et les zooms à partir de ces nombres, puis confirmez avec agentshot frames <capture> --from a --to b (une planche contact avec horodatages ; Lisez le PNG qu'il imprime). Regardez le PNG de la scène avec l'outil Read avant de styliser.
  4. Écrivez une recette JSON et agentshot render recipe.json --note "<ce qui a changé>".
  5. Vérifiez vous-même le résultat : Lisez le PNG ; pour MP4, agentshot frames <produit>/<ressource> (vidéo entière) et agentshot frames <produit>/<ressource> --from 3 --to 4 --every 0.033 --crop x,y,w,h (image par image autour d'une coupe ou d'un clic). Corrigez et rendez à nouveau (une nouvelle version est ajoutée). Lorsque l'utilisateur souhaite parcourir ou modifier lui-même une recette, exécutez agentshot preview recipe.json en arrière-plan : cela ouvre une page locale avec la scène et un curseur de défilement et se met à jour en direct lorsque la recette (ou le style.json du produit) est modifiée. Cela imprime une ligne JSON avec l'url et continue de servir.
  6. Signalez le chemin de sortie (results[].output). --copy-to <dir> le copie également dans le projet de l'utilisateur.
  7. Apprenez : lorsque l'utilisateur corrige ou félicite quelque chose, ajoutez une ligne datée au guidelines.md du produit (et mettez à jour les paramètres par défaut de style.json s'il s'agit d'un aspect par défaut). Relisez-le la prochaine fois.

Conservez les scénarios et les recettes dans le projet de l'utilisateur (par exemple docs/shots/) afin qu'ils puissent être réexécutés après des modifications de l'interface utilisateur.

Scénario (capturer une application web)

Les commentaires dans les exemples JSON ci-dessous sont des explications uniquement ; les fichiers réels doivent être du JSON simple.

{
  "name": "ellie-today-drag",          // nom de la capture, unique ; préfixez avec le produit
  "url": "http://localhost:8081",       // ou un chemin de fichier
  "device": "iphone",                   // iphone | iphone-max | ipad | desktop | laptop
  "safeArea": true,                     // Expo/RN web : Chrome signale les marges de sécurité iPhone, l'application se dispose
                                        // comme sur un appareil ("pad" = force le remplissage pour les applications qui ignorent les marges)
  "css": "[class*='navigationMenuRoot'] { display: none }",  // masque le chrome web uniquement (les onglets Expo Router s'affichent comme un menu en haut sur le web)
  "waitFor": "today-list",              // attend cet élément avant de commencer
  "track": { "row": "text=Plan a birthday" },  // boîtes d'éléments nommées supplémentaires à enregistrer
  "steps": [
    { "shot": "main" },                                  // image fixe en pleine résolution (pour les captures d'écran)
    { "wait": 0.6 },
    { "tap": "add-button" },                             // cliquer/appuyer sur une cible (s'y déplace d'abord)
    { "type": "Buy milk", "into": "title-input" },
    { "press": "Enter" },
    { "drag": "task-birthday", "to": "slot-11am", "duration": 1.4 },
    { "scroll": 400, "duration": 0.8 },
    { "move": [200, 300], "duration": 0.6 },
    { "goto": "/settings" },
    { "waitFor": "settings-title" },
    { "shot": "after" }
  ]
}

Cibles : un nom nu correspond à data-shot="..." ou data-testid="..." (le testID React Native devient data-testid sur le web, donc ajoutez des testID aux éléments que vous souhaitez cibler), ou tout sélecteur Playwright (text=Save, role=button[name="Save"], #id, .class), ou [x, y] en px CSS. Tous les éléments avec data-shot/data-testid sont enregistrés avec leurs boîtes, ainsi que les entrées track.

Timing : par défaut ("timing": "frame"), l'horloge de la page est mise en pause et avancée exactement d'une image à la fois (60 ips) avec une capture d'écran en pleine résolution par image, de sorte que les animations de l'application sont fluides à n'importe quelle résolution ; la capture prend quelques fois plus de temps que le scénario. Utilisez "timing": "real" uniquement si l'application se brise avec une horloge contrôlée (une étape expire alors). agentshot capture signale les temps de clic (clicks) pour planifier les cuts/zoom, et les erreurs/avertissements de la console (console). Les superpositions de développement (toast Expo LogBox, indicateur Next.js) sont masquées ; "devOverlays": true les conserve. Préférez un segment cuts continu plutôt que plusieurs coupes dures : les sauts entre les segments donnent un aspect saccadé.

Trouver des cibles dans une application sans testIDs : ouvrez la page avec Playwright et listez les boutons/entrées (role, aria-label, texte), puis utilisez text=..., role=button[name=/^My daughter/] ou [aria-label='Your prayer'], et nommez les boîtes que vous souhaitez surélever/louper via track. La saisie dans un champ recouvert par un pied de page collant fonctionne toujours (le champ obtient le focus).

Expo : démarrez d'abord la version web (npx expo start --web, généralement http://localhost:8081). Les modules natifs uniquement peuvent ne pas fonctionner sur le web ; si un écran se brise, demandez à l'utilisateur une capture d'écran/enregistrement iPhone et importez-le.

Application de bureau (scénario avec "window")

agentshot windows liste les fenêtres (titre, processus, taille). La fenêtre est identifiée par son titre, puis par son nom de processus, restaurée si elle est minimisée et amenée au premier plan. Les coordonnées sont en pixels de la fenêtre : regardez d'abord une image fixe (agentshot snap --window "X" --name x-probe, Lisez le PNG) et nommez les boîtes que vous utilisez dans track.

{
  "name": "notes-tour",
  "window": "Notes",                              // partie du titre ou nom du processus
  "track": { "nav-recent": [20, 200, 190, 40], "nav-search": [20, 96, 190, 40], "content": [232, 40, 1030, 650], "profile": [16, 718, 150, 62] },
  "cursor": [1000, 330],                          // où le pointeur commence
  "steps": [
    { "shot": "home" },                           // image fixe = l'image enregistrée à ce moment
    { "wait": 1 },
    { "click": "nav-recent", "duration": 0.9 },   // glisser là (assoupli, léger arc), cliquer immédiatement
    { "waitStill": 0.6, "region": "content" },    // attendre que l'écran change, puis se stabilise
    { "shot": "recent" },
    { "wheel": 4, "at": [760, 460] },             // faire défiler 4 crans vers le bas (négatif = vers le haut)
    { "click": "nav-search" }, { "press": "ctrl+a" },
    { "type": "Weekly plan", "cps": 12 },         // n'importe quel texte, scripts non latins inclus
    { "press": "Enter" },                         // touches : 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": "beat 2" }                          // marqueur dans la timeline
  ]
}
  • Le résultat a une timeline (début/fin de chaque étape en secondes vidéo, at = moment du clic) et des shots (images fixes extraites de la vidéo). Les recettes utilisent les noms track comme cibles ("blur" sur "profile" etc.).

  • waitStill attend d'abord (jusqu'à changeTimeout, 3 s) que la région diffère de ce qu'elle était (change, différence de pixel moyenne, par défaut 6 ; "change": false pour seulement la laisser se stabiliser), puis jusqu'à ce que rien n'ait changé pendant les secondes données (threshold 0.6). Utilisez une region sans parties animées (lecteurs, arrière-plans en direct).

  • Cliquez immédiatement après l'arrivée : un curseur reposant sur un contrôle ~0,5 s fait apparaître des info-bulles Windows dans la vidéo.

  • Champs qui conservent l'ancien texte : press ctrl+a avant type.

  • Le pilote démarre avant l'enregistrement (il a besoin de quelques secondes) et déplace le curseur réel : n'utilisez pas la machine pendant ce temps. Les captures de bureau sont en 1x, donc une loupe semble molle ; préférez lift.

  • Images fixes à tout moment d'un enregistrement : agentshot snap <capture> --at 12.4 --shot name.

  • Les petits changements (fermeture d'une popup) peuvent ne pas atteindre change sur toute la fenêtre : donnez region autour d'eux.

  • Raccourcis : mod est Ctrl sur Windows et Cmd sur macOS ("press": "mod+a"), donc un scénario fonctionne sur les deux.

Enregistrement manuel (l'utilisateur effectue les actions ; le curseur est enregistré et dessiné par le moteur de rendu) :

agentshot record --name app-filter --window "Figma" --duration 12   # enregistre 12 s, puis s'arrête
agentshot record start --name app-filter --window "Figma"           # ou démarrer ...
agentshot record stop                                               # ... et arrêter plus tard

macOS

Mêmes commandes et scénarios que sous Windows ; recorder/mac.swift est compilé lors de la première utilisation (nécessite les outils de ligne de commande Xcode et macOS 14+). Exécutez d'abord agentshot doctor : l'application qui exécute l'agent (Terminal, iTerm, Claude, VS Code) a besoin des autorisations Screen Recording et Accessibility dans Réglages Système > Confidentialité et sécurité (agentshot doctor --request ouvre les invites ; redémarrez cette application après avoir accordé). Sans Screen Recording, les titres de fenêtre sont juste des noms d'application et l'enregistrement échoue ; sans Accessibility, le pilote ne peut pas cliquer ni taper.

  • Les coordonnées (track, étapes, cibles de recette) sont des points ; les images fixes et les vidéos sont à l'échelle de pixels de l'écran (2 sur Retina, inspect montre scale), donc les surélévations et les zooms restent nets.
  • ScreenCaptureKit enregistre la fenêtre elle-même : elle peut être partiellement couverte, mais ne doit pas être minimisée.
  • node scripts/selftest-mac.mjs vérifie tout sur TextEdit (et le simulateur s'il est démarré) et imprime ce qui a échoué. Vérification de synchronisation : agentshot record ... --show-cursor grave le curseur réel ; comparez-le avec le pointeur enregistré (agentshot frames vs inspect) comme tout enregistrement.

Simulateur iOS (macOS)

L'application native au lieu de sa version web : polices réelles, modules natifs, animations iOS. Démarrez un simulateur (open -a Simulator), exécutez l'application dedans (npx expo run:ios ou une build de développement), puis :

agentshot sim devices                                       # simulateurs démarrés
agentshot sim snap --name app-home --clean-status-bar       # image fixe sans perte, 9:41 / batterie pleine
agentshot sim record start --name app-flow                  # quelqu'un d'autre pilote ...
agentshot sim record stop

Un scénario le pilote avec idb (brew install facebook/fb/idb-companion, pipx install fb-idb) ; les coordonnées sont en points de l'appareil (Lisez un sim snap et divisez ses pixels par scale) :

{
  "name": "app-onboarding",
  "simulator": "booted",                        // ou un UDID ou une partie du nom de l'appareil
  "statusBar": "clean",                         // 9:41 pendant la capture, effacé après
  "appearance": "light",                        // ou "dark"
  "openUrl": "exp://127.0.0.1:8081/--/today",   // lien profond avant l'enregistrement (ou "launch": "<bundle id>")
  "track": { "add": [330, 760, 48, 48], "title": [24, 120, 340, 44] },
  "steps": [
    { "shot": "today" },
    { "tap": "add" },
    { "waitStill": 0.5 },
    { "type": "Buy milk" },                      // dans le champ focalisé
    { "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" }
  ]
}

Les images fixes sont des captures d'écran du simulateur sans perte ; les tapotements et les balayages deviennent le pointeur tactile et les clics, donc les recettes utilisent "pointer": "touch" et "device": "iphone-black" comme pour les captures de navigateur. Sans idb, seules les étapes wait/waitStill/agentshot/openUrl/launch fonctionnent.

Recette (style et rendu)

{
  "name": "today-drag",                 // nom de la ressource dans la bibliothèque
  "product": "ellie",                   // dossier de la bibliothèque ; les valeurs par défaut de style.json s'appliquent
  "capture": "ellie-today-drag",
  "shot": "main",                       // défini pour une image PNG ; omettez pour une vidéo MP4
  "size": "16:9",                       // 16:9 16:10 4:3 3:2 1:1 4:5 9:16, ou largeur/hauteur
  "background": "lavender",             // lavender peach sage sky rose mint neutral midnight ink white,
                                        // toute couleur CSS/dégradé, ou une image sous public/ (backgrounds/x.jpg)
  "backgroundBlur": 0.02,               // pour les arrière-plans photo, part du petit côté
  "device": "iphone-black",             // iphone-black iphone-natural iphone-white browser window none
  "url": "app.ellie.so/today",          // texte de la barre de navigateur ; "title": titre de fenêtre pour "window"
  "padding": 0.08, "tilt": 12,          // marge de l'appareil ; inclinaison 3D en degrés
  "position": [0.69, 0.5],              // centre de l'appareil sur le canevas, laisse de la place pour un titre à côté
  "accent": "#6d5ce8",                  // couleur des étapes, contours, étiquettes, ondulations de clic
  "font": "Gilda Display", "labelFont": "Inter",  // titres / étiquettes de surélévation : Inter Manrope Poppins Nunito Fraunces Lora
                                        // "Playfair Display" "DM Serif Display" "Gilda Display" "Cormorant Garamond" Caveat
  "lift":  { "target": "task-row", "label": "Glissez-le sur votre journée", "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": "arrow", "from": [0.7, 0.15], "to": [0.35, 0.42], "note": "Ajoutez une tâche", "start": 2.3, "duration": 1.5, "outline": 0.01 },
    { "type": "step", "at": [0.12, 0.05], "number": 1, "label": "Ouvrir aujourd'hui", "start": 0.6, "duration": 2.5 },
    { "type": "highlight", "target": "slot-11am", "start": 7.8, "duration": 1.2 },
    { "type": "label", "at": [0.7, 0.92], "label": "Déplacement d'une tâche", "start": 7, "duration": 2.5, "outline": 0.006 },
    { "type": "blur", "target": "profile", "start": 8, "duration": 5 },
    { "type": "cut", "start": 5, "duration": 1 },
    { "type": "delay", "start": 5, "duration": 1 },
    { "type": "speed", "start": 1.5, "duration": 6.7, "rate": 2 }
  ]
}
  • Sauf cut, les annotations commencent lorsque le compteur vidéo atteint leur start (et durent duration secondes, ou "fade": 0 pour disparaître immédiatement). Les annotations omettent start / duration si elles sont affichées tout le temps (utilisez maxStart / minDuration dans l'annotation d'image PNG).
  • cut et delay : voir ci-dessous.
  • speed : rate 2 = 2× plus rapide, 0,5 = 2× plus lent ; "rate": 0 coupe (jette) ce segment.
  • blur et highlight ciblent des éléments track nommés ; highlight encadre la cible, blur rend tout flou sauf la cible. "blur": 0.08 utilise des rectangles de flou au lieu d'un masque de gradient (pas de rupture de l'effet de profondeur de champ).
  • step connaît le compte : step 2 continue là où step 1 s'est arrêté (connaît les trous de timing). "step": { "target": "task-row", "number": 3, "label": "of 4", "anchor": "below" }. step peut être placé hors de la vidéo, en ayant un start avant/après le métrage, en utilisant un nombre négatif pour l'ordre des étapes.
  • arrow en points utilisateur (de l'image ; 0…1 x, puis y = centre) ou "target": "add-button" pour pointer sur l'écran capturé.
  • label : idem.
  • Tout outline (contour en fraction de la largeur, 0,01 ≈ 12 px sur un écran Retina) ajoute une bordure lumineuse. Omettre = pas de bordure. Les annotations qui omettent outline n'en ont pas ; définir "outline": 0.006 dessine un trait de 7 px.

Coupes et délais

Les annotations cut / delay sont différentes : elles n'ont pas d'effet visuel mais contrôlent le métrage.

{ "type": "cut", "start": 3, "duration": 1.2, "fade": 0.15 }
{ "type": "delay", "start": 6.8, "duration": 0.35 }
  • cut : flou de transition entre start et start + duration ; la vidéo coupe les images à la fin (les images 5 x, fade 0,15 s). Pour une coupe dure avec le curseur au même endroit, utilisez duration: 0.16. fade par défaut = duration * 0.3 (la première bosse ralentit donc les choses). À l'intérieur des cuts la vidéo est mise en pause (les steps sont ignorées) ; après la coupe, les steps continuent normalement.
  • delay : la vidéo se fige (la dernière image avant le délai) pendant duration. Pour permettre à une animation de se terminer, utilisez delay avant cut.

Utilisez les informations des inspect et frames : les changes (sauts visuels) et quiet (pauses) indiquent où couper, et les moves indiquent le déplacement du curseur que vous pouvez ignorer.

Aperçu

Lors du débogage, exécutez agentshot preview recipe.json en arrière-plan pendant que l'utilisateur modifie la recette avec un éditeur. Ouvrez l'URL imprimée : la page affiche la scène avec un curseur de défilement. Chaque fois que la recette ou le style.json du produit est enregistré, la page se recharge. L'aperçu imprime une ligne JSON avec l'url et continue de servir.

Guide de style (style.json)

Exécutez agentshot style <produit> pour voir le style actuel. Les recettes omettent les champs et les valeurs par défaut viennent d'ici. Les valeurs par défaut initiales de agentshot style --init : agentshot style <produit> --init > style.json.

{
  "accent": "#6d5ce8",
  "font": "Inter",
  "labelFont": "Inter",
  "background": "mint",
  "device": "iphone-black",
  "size": "16:9",
  "padding": 0.08,
  "tilt": 0,
  "position": [0.5, 0.5],
  "backgroundBlur": 0.02,
  "pointer": "hand",
  "cornerRadius": 16,
  "shadow": 0.08,
  "brandPosition": "bottom left",
  "brandLogo": null
}

Tous les champs des recettes et ici sont facultatifs ; les valeurs par défaut codées en dur complètent le reste.

  • pointer : hand, touch, none (pointeur de souris / cercle tactile).
  • shadow : ombre de l'appareil (partage de la largeur).
  • brandPosition : top left, top right, bottom right, bottom left ou none. brandLogo est un chemin d'accès à un fichier image sous public/ ; par défaut brand.svg dans le dossier du produit, ou un visuel générique. "brandLogo": null masque la marque, brandPosition: "none" aussi.
  • backgroundBlur est ignoré pour les couleurs unies (lavender, mint, …).

Photos comme arrière-plan

Placez les images d'arrière-plan sous public/backgrounds/ (ou dans le dossier du produit).

{
  "background": "pexels-kampus.jpg",
  "backgroundBlur": 0.08
}

Référencez-les par leur nom de fichier (pexels-kampus.jpg) ou leur chemin relatif (../shared/prints.jpg).

Commandes CLI

Ces commandes aident à trouver des cibles, tester des recettes et résoudre des problèmes.

agentshot doctor

Vérifie l'environnement : versions de Node.js, Playwright, macOS Screen Recording / Accessibility. Recommande des correctifs.

agentshot doctor
agentshot doctor --request           # Demande les autorisations macOS (redémarrez l'application après)

agentshot style <produit> [--init]

Imprime style.json et guidelines.md pour le produit. --init les initialise avec les valeurs par défaut.

agentshot capture <scenario.json>

Exécute le scénario de capture et enregistre la capture dans la bibliothèque.

agentshot inspect <capture>

Liste les scènes, les boîtes d'éléments, les clics, la timeline et les métadonnées.

agentshot frames <capture> [--from s] [--to e] [--every s] [--crop x,y,w,h] [--shots]

Génère une planche contact PNG (par défaut une image par seconde du métrage principal). --shots affiche uniquement les images fixes nommées. --crop x,y,w,h recadre – utile pour inspecter la région quiet / change autour des coupes.

agentshot list [<produit>] [--all-users]

Liste les captures et les ressources rendues.

agentshot render <recipe.json> [--note <msg>] [--version l] [--no-version] [--copy-to <dossier>]

Rend la ressource. --note est stocké dans le journal des versions. --version 0 écrase une version existante.

agentshot preview <recipe.json>

Lance un serveur local avec une page de prévisualisation interactive.

agentshot snap <capture> [--at s] [--shot name]

Image PNG fixe à partir d'une capture existante.

agentshot windows

Liste les fenêtres de bureau (titre, processus, taille).

agentshot snap --window "<titre>" --name <capture>

Capture d'écran fixe d'une fenêtre de bureau.

agentshot import <fichier> --name <capture>

Importe une image/vidéo existante.

agentshot record start/stop

Enregistrement manuel d'une fenêtre de bureau.

agentshot sim devices

Liste les simulateurs iOS démarrés.

agentshot sim snap/record

Capture d'écran/enregistrement du simulateur iOS.

agentshot help [<commande>]

Aide détaillée.

Bibliothèque et versionnement

Les captures et les ressources sont stockées sous ~/.agentshot/<produit>/. Tous les fichiers sont versionnés :

~/.agentshot/ellie/
├── captures/
│   └── ellie-today-drag/v1/
│       ├── snap.mp4               # vidéo brute
│       ├── scenario.json
│       └── meta.json
├── today-drag/v1/
│   ├── recipe.json
│   ├── snap.png                   # ressource rendue
│   └── meta.json
├── today-drag/v2/
│   └── …
├── style.json
└── guidelines.md

agentshot render crée automatiquement la prochaine version v{n+1}, sauf si --version est spécifié. --no-version l'écrit directement sans numéro de version (pour les exports uniques). --copy-to <dossier> copie le(s) fichier(s) de sortie (snap.png, snap.mp4) vers le projet de l'utilisateur.

agentshot list n'affiche que les ressources (pas captures).

Notes techniques

  • Pilote de bureau : utilise node-ffi (Windows) ou un binaire Swift compilé (macOS) pour déplacer la souris et taper. Un délai de 3 s au démarrage pour laisser l'utilisateur dégager la main.
  • Web : Playwright avec une horloge contrôlée (ou en temps réel). Les captures sont en pleine résolution (pas de facteur d'échelle).
  • Simulateur iOS : idb via son interface REST. L'agent doit démarrer un simulateur (ou l'utilisateur l'a déjà fait).
  • Rendu : Sharp (images) et FFmpeg (vidéos) avec un calque de composition SVG pour les annotations, les cadres, les ombres et les arrière-plans.
  • Presse-papiers : Pour type sur desktop, agentshot copie le texte dans le presse-papiers et colle (Ctrl+V / Cmd+V).

Dépannage

  • Desktop : aucune fenêtre listée → l'agent n'a pas la permission Screen Recording (macOS) ou l'application est en mode admin (Windows).
  • Desktop : les clics ne fonctionnent pas → absence d'autorisation Accessibility (macOS).
  • Web : la page ne se charge pas → le serveur de développement n'est pas en cours d'exécution ou l'URL est incorrecte.
  • Simulateur : idb non trouvé → brew install facebook/fb/idb-companion && pipx install fb-idb.
  • Erreur de rendu : font introuvable → installez la police localement (Google Fonts, etc.). Les polices sont référencées par leur nom de famille.
  • La vidéo rendue est saccadée → utilisez "timing": "frame" dans le scénario (par défaut) et évitez les cuts qui dépassent les segments de capture.

Meilleures pratiques

  1. Lisez toujours d'abord guidelines.md – il contient les préférences de style du produit et des commentaires antérieurs.
  2. Prévisualisez avant de rendre – utilisez agentshot preview pour itérer rapidement.
  3. Gardez les fichiers de capture/recette dans le projet – ils peuvent être réexécutés après des modifications de l'interface utilisateur.
  4. Utilisez track pour les cibles clés – cela évite de coder en dur les coordonnées qui changent avec la mise en page.
  5. Pour les applications Expo – testez d'abord sur le web (npx expo start --web) ; utilisez le simulateur pour les modules natifs.
  6. Apprenez des retours – ajoutez des lignes à guidelines.md lorsque l'utilisateur corrige ou félicite un résultat.
  7. Versionnez tout – agentshot render crée automatiquement des versions, ce qui permet de comparer et de revenir en arrière.

Skills associés