Communitygithub.com

thread-of-ariadne/agentshot

Produzieren Sie Produkt-Screenshots und Demovideos unter Windows und macOS – erfassen Sie eine Web-App / Expo Web App / ein Desktop-Fenster / den iOS Simulator / eine iPhone-Datei, gestalten Sie es (Hintergrund, iPhone/Browser/Fensterrahmen, Abheben, Lupe, Pfeile, Schritte, Weichzeichnung, Zoom, Cursor, Schnitte) und rendern Sie PNG oder MP4 in eine versionierte Bibliothek. Nutzen Sie es, wenn der Benutzer nach Screenshots, Mockups, Hilfecenter-Bildern, Changelog-Bildern, Social-Media-Beiträgen (X/Instagram), Demo-/B-Roll-Videos oder Bildschirmaufnahmen seiner App fragt.

Was ist agentshot?

agentshot ist ein vielseitiges CLI-Tool zur Erstellung professioneller Screenshots und Demovideos von Web-Apps, Desktop-Anwendungen, iOS-Simulatoren und vorhandenen Bild- oder Videodateien. Es unterstützt eine breite Palette von Stilisierungsoptionen, einschließlich Hintergrundfarben und -bilder, Geräterahmen (iPhone, Browser, Fenster), Abhebe-Effekte, Lupen, Anmerkungen, Schrittanzeigen, Klickwellen und Cursor-Pfade. Die Ausgabe erfolgt als hochauflösendes PNG oder MP4 und wird in einer versionierten Bibliothek gespeichert, sodass Änderungen nachvollzogen werden können. Der Workflow umfasst das Erfassen von Bildmaterial, das Inspizieren von Szenen (Bildelemente, Klicks, Timeline), das Schreiben eines Rezepts zur Definition von Stil und Schnitten sowie das Rendern des endgültigen Assets. Es läuft unter Windows und macOS (mit nativer Unterstützung für iOS-Simulatoren und Bildschirmaufnahme) und lässt sich nahtlos in Benutzerprojekte integrieren.

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

agentshot: Screenshots und Demovideos

Das Tool befindet sich unter /path/to/agentshot. Führen Sie es aus mit:

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

Im Folgenden steht agentshot für diesen Befehl. Jeder Befehl gibt eine JSON-Zeile aus ("ok": true|false). Lange Render-Vorgänge geben zusätzlich Fortschritt auf stderr aus. Führen Sie agentshot help für die Befehlsliste aus.

Arbeitsablauf

  1. Lesen Sie zuerst die Regeln des Produkts: agentshot style <Produkt> gibt style.json (Standard-Look) und guidelines.md (was der Benutzer mag) aus. Folgen Sie ihnen. Wenn das Produkt neu ist, führen Sie agentshot style <Produkt> --init aus.
  2. Erfassen (eines auswählen):
    • Web-App oder Expo-App → schreiben Sie eine Szenario-JSON mit "url", führen Sie agentshot capture scenario.json aus.
    • iOS-App auf einem Mac → ein Szenario mit "simulator" (die echte native App im iOS Simulator, siehe "iOS Simulator"); ein schnelles Standbild → agentshot sim snap --name <Aufnahme> --clean-status-bar.
    • Desktop-Programm → ein Szenario mit "window": Sie steuern die echte Maus/Tastatur, während es aufzeichnet (siehe "Desktop-App"). Nur ein Standbild → agentshot snap --window "<Titel>" --name <Aufnahme>. Der Benutzer führt die Aktionen aus → agentshot record start/stop.
    • Der Benutzer hat bereits eine Datei (iPhone-Screenshot / Bildschirmaufnahme) → agentshot import <Datei> --name <Aufnahme>.
  3. Inspizieren: agentshot inspect <Aufnahme> listet Aufnahmen, Element-Boxen (Bildschirmpunkte), Klicks, Dauer und, bei Videos, moves (Zeigerbewegung), changes (Seitenwechsel: große visuelle Sprünge), quiet (nichts bewegt sich: Schnitt oder Beschleunigung) und die Szenario-timeline auf. Planen Sie Schnitte und Zooms anhand dieser Zahlen und bestätigen Sie mit agentshot frames <Aufnahme> --from a --to b (ein Kontaktbogen mit Zeitstempeln; lesen Sie das ausgegebene PNG). Betrachten Sie das Aufnahme-PNG mit dem Lese-Tool, bevor Sie es gestalten.
  4. Schreiben Sie ein Rezept JSON und führen Sie agentshot render recipe.json --note "<was geändert wurde>" aus.
  5. Überprüfen Sie das Ergebnis selbst: Lesen Sie das PNG; bei MP4: agentshot frames <Produkt>/<Asset> (gesamtes Video) und agentshot frames <Produkt>/<Asset> --from 3 --to 4 --every 0.033 --crop x,y,w,h (Bild für Bild um einen Schnitt oder Klick herum). Korrigieren und erneut rendern (eine neue Version wird hinzugefügt). Wenn der Benutzer ein Rezept selbst durchgehen oder anpassen möchte, führen Sie agentshot preview recipe.json im Hintergrund aus: Es öffnet eine lokale Seite mit der Szene und einem Scrubber und aktualisiert live, wenn das Rezept (oder die style.json des Produkts) bearbeitet wird. Es gibt eine JSON-Zeile mit der url aus und bleibt aktiv.
  6. Melden Sie den Ausgabepfad (results[].output). --copy-to <Verz> kopiert es auch in das Projekt des Benutzers.
  7. Lernen: Wenn der Benutzer etwas korrigiert oder lobt, fügen Sie eine datierte Zeile an die guidelines.md des Produkts an (und aktualisieren Sie die Standardwerte in style.json, wenn es sich um einen Standard-Look handelt). Lesen Sie es beim nächsten Mal.

Halten Sie Szenarien und Rezepte im Projekt des Benutzers (z. B. docs/shots/), damit sie nach UI-Änderungen erneut ausgeführt werden können.

Szenario (Web-App erfassen)

Kommentare in den JSON-Beispielen unten sind nur Erklärungen; echte Dateien müssen reines JSON sein.

{
  "name": "ellie-today-drag",          // Aufnahme-Name, eindeutig; mit dem Produktnamen präfixieren
  "url": "http://localhost:8081",       // oder ein Dateipfad
  "device": "iphone",                   // iphone | iphone-max | ipad | desktop | laptop
  "safeArea": true,                     // Expo/RN Web: Chrome meldet iPhone Safe-Area-Insets, die App layoutet
                                        // wie auf einem Gerät ("pad" = Padding erzwingen für Apps, die Insets ignorieren)
  "css": "[class*='navigationMenuRoot'] { display: none }",  // Web-only Chrome ausblenden (Expo Router Tabs erscheinen im Web als Top-Menü)
  "waitFor": "today-list",              // auf dieses Element warten, bevor begonnen wird
  "track": { "row": "text=Plan a birthday" },  // zusätzliche benannte Element-Boxen aufzeichnen
  "steps": [
    { "shot": "main" },                                  // Standbild in voller Auflösung (für Screenshots)
    { "wait": 0.6 },
    { "tap": "add-button" },                             // auf ein Ziel klicken/tippen (bewegt sich zuerst dorthin)
    { "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" }
  ]
}

Ziele: Ein bloßer Name passt auf data-shot="..." oder data-testid="..." (React Native testID wird data-testid im Web, fügen Sie also testIDs zu den Elementen hinzu, auf die Sie zeigen möchten), oder auf einen beliebigen Playwright-Selektor (text=Save, role=button[name="Save"], #id, .class), oder [x, y] in CSS-Px. Alle Elemente mit data-shot/data-testid werden mit ihren Boxen aufgezeichnet, zusammen mit track-Einträgen.

Timing: Standardmäßig ("timing": "frame") wird die Seitenuhr angehalten und genau ein Frame nach dem anderen vorgerückt (60 fps) mit einem Screenshot in voller Auflösung pro Frame, sodass App-Animationen in jeder Auflösung flüssig sind; die Aufnahme dauert einige Male länger als das Szenario. Verwenden Sie "timing": "real" nur, wenn die App unter einer kontrollierten Uhr kaputt geht (ein Schritt wird dann mit Timeout abgebrochen). agentshot capture meldet Klickzeiten (clicks) zur Planung von cuts/zoom und Konsolenfehler/-warnungen (console). Entwickler-Overlays (Expo LogBox Toast, Next.js-Indikator) werden ausgeblendet; "devOverlays": true behält sie. Bevorzugen Sie ein durchgehendes cuts-Segment gegenüber mehreren harten Schnitten: Sprünge zwischen Segmenten wirken ruckelig.

Ziele in einer App ohne testIDs finden: Öffnen Sie die Seite mit Playwright und listen Sie Schaltflächen/Eingaben (role, aria-label, Text) auf, verwenden Sie dann text=..., role=button[name=/^My daughter/] oder [aria-label='Your prayer'], und benennen Sie Boxen, die Sie durch track hervorheben/lupe möchten. Das Tippen in ein Feld, das von einer klebrigen Fußzeile bedeckt ist, funktioniert trotzdem (das Feld erhält Fokus).

Expo: Starten Sie zuerst den Web-Build (npx expo start --web, normalerweise http://localhost:8081). Nur-native Module funktionieren möglicherweise nicht im Web; wenn ein Bildschirm kaputt geht, bitten Sie den Benutzer um einen iPhone-Screenshot/eine Aufnahme und importieren Sie sie (import).

Desktop-App (Szenario mit "window")

agentshot windows listet Fenster auf (Titel, Prozess, Größe). Das Fenster wird nach Titel, dann nach Prozessnamen zugeordnet, wiederhergestellt, wenn es minimiert ist, und in den Vordergrund gebracht. Koordinaten sind Fenster-Pixel: Betrachten Sie zuerst ein Standbild (agentshot snap --window "X" --name x-probe, lesen Sie das PNG) und benennen Sie die Boxen, die Sie in track verwenden.

{
  "name": "notes-tour",
  "window": "Notes",                              // Titelteil oder Prozessname
  "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],                          // wo der Zeiger beginnt
  "steps": [
    { "shot": "home" },                           // Standbild = der aufgezeichnete Frame zu diesem Zeitpunkt
    { "wait": 1 },
    { "click": "nav-recent", "duration": 0.9 },   // dorthin gleiten (abgerundet, leichter Bogen), sofort klicken
    { "waitStill": 0.6, "region": "content" },    // warten, bis sich der Bildschirm ändert, dann bis zur Beruhigung
    { "shot": "recent" },
    { "wheel": 4, "at": [760, 460] },             // 4 Stufen nach unten scrollen (negativ = nach oben)
    { "click": "nav-search" }, { "press": "ctrl+a" },
    { "type": "Weekly plan", "cps": 12 },         // beliebiger Text, einschließlich Nicht-lateinischer Schriften
    { "press": "Enter" },                         // Tasten: 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" }                          // Markierung in der Timeline
  ]
}
  • Das Ergebnis hat timeline (Start/Ende jedes Schritts in Videosekunden, at = Klickmoment) und shots (Standbilder aus dem Video geschnitten). Rezepte verwenden track-Namen als Ziele ("blur" auf "profile" usw.).

  • waitStill wartet zuerst (bis zu changeTimeout, 3 s), bis sich die Region von ihrem vorherigen Zustand unterscheidet (change, mittlere Pixeldifferenz, Standard 6; "change": false um nur zu warten, bis sie sich beruhigt), dann bis sich für die angegebene Zeit nichts geändert hat (threshold 0.6). Verwenden Sie eine region ohne animierte Teile (Player, Live-Hintergründe).

  • Klicken Sie direkt nach der Ankunft: Ein Cursor, der ~0,5 s über einem Bedienelement ruht, lässt Windows-Tooltips ins Video einblenden.

  • Felder, die alten Text behalten: press ctrl+a vor type.

  • Der Treiber startet vor der Aufnahme (er benötigt einige Sekunden) und bewegt den echten Cursor: Verwenden Sie die Maschine in der Zwischenzeit nicht. Desktop-Aufnahmen sind 1x, daher sieht eine Lupe weich aus; bevorzugen Sie lift.

  • Standbilder zu jedem Zeitpunkt einer Aufnahme: agentshot snap <Aufnahme> --at 12.4 --shot name.

  • Kleine Änderungen (ein Popup schließt sich) erreichen möglicherweise nicht den change-Wert über das gesamte Fenster: Geben Sie region um sie herum an.

  • Tastenkürzel: mod ist Strg unter Windows und Cmd unter macOS ("press": "mod+a"), sodass ein Szenario auf beiden läuft.

Manuelle Aufnahme (der Benutzer führt die Aktionen aus; der Cursor wird protokolliert und vom Renderer gezeichnet):

agentshot record --name app-filter --window "Figma" --duration 12   # zeichnet 12 s auf, dann Stopp
agentshot record start --name app-filter --window "Figma"           # oder start ...
agentshot record stop                                               # ... und später stoppen

macOS

Gleiche Befehle und Szenarien wie unter Windows; recorder/mac.swift wird bei der ersten Verwendung kompiliert (benötigt die Xcode Command Line Tools und macOS 14+). Führen Sie zuerst agentshot doctor aus: Die App, die den Agenten ausführt (Terminal, iTerm, Claude, VS Code) benötigt Bildschirmaufnahme und Bedienungshilfen in den Systemeinstellungen > Datenschutz & Sicherheit (agentshot doctor --request öffnet die Aufforderungen; starten Sie die App nach der Gewährung neu). Ohne Bildschirmaufnahme sind Fenstertitel nur App-Namen und die Aufnahme schlägt fehl; ohne Bedienungshilfen kann der Treiber nicht klicken oder tippen.

  • Koordinaten (track, Schritte, Rezeptziele) sind Punkte; Standbilder und Videos haben die Pixel- Skalierung des Displays (2 auf Retina, inspect zeigt scale), sodass Abhebungen und Zooms scharf bleiben.
  • ScreenCaptureKit zeichnet das Fenster selbst auf: Es kann teilweise verdeckt sein, darf aber nicht minimiert sein.
  • node scripts/selftest-mac.mjs überprüft alles auf TextEdit (und dem Simulator, falls einer gestartet ist) und gibt aus, was fehlgeschlagen ist. Sync-Prüfung: agentshot record ... --show-cursor brennt den echten Cursor ein; vergleichen Sie ihn mit dem protokollierten Zeiger (agentshot frames vs inspect) wie bei jeder Aufnahme.

iOS Simulator (macOS)

Die native App anstelle ihres Web-Builds: echte Schriftarten, native Module, iOS-Animationen. Starten Sie einen Simulator (open -a Simulator), führen Sie die App darin aus (npx expo run:ios oder ein Dev-Build), dann:

agentshot sim devices                                       // gestartete Simulatoren
agentshot sim snap --name app-home --clean-status-bar       // verlustfreies Standbild, 9:41 / voller Akku
agentshot sim record start --name app-flow                  // jemand anderes steuert ...
agentshot sim record stop

Ein Szenario steuert es mit idb (brew install facebook/fb/idb-companion, pipx install fb-idb); Koordinaten sind Gerätepunkte (Lesen Sie ein sim snap und teilen Sie seine Pixel durch scale):

{
  "name": "app-onboarding",
  "simulator": "booted",                        // oder eine UDID oder ein Teil des Gerätenamens
  "statusBar": "clean",                         // 9:41 während der Aufnahme, danach gelöscht
  "appearance": "light",                        // oder "dark"
  "openUrl": "exp://127.0.0.1:8081/--/today",   // Deep Link vor der Aufzeichnung (oder "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" },                      // in das fokussierte Feld
    { "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" }
  ]
}

Standbilder sind verlustfreie Simulator-Screenshots; Tippen und Wischen werden zum Touch-Zeiger und zu Klicks, daher verwenden Rezepte "pointer": "touch" und "device": "iphone-black" wie bei Browser-Aufnahmen. Ohne idb funktionieren nur wait/waitStill/agentshot/openUrl/launch-Schritte.

Rezept (Stil und Rendern)

{
  "name": "today-drag",                 // Asset-Name in der Bibliothek
  "product": "ellie",                   // Bibliotheksordner; style.json-Standardwerte werden angewendet
  "capture": "ellie-today-drag",
  "shot": "main",                       // für ein PNG-Standbild setzen; für ein MP4-Video weglassen
  "size": "16:9",                       // 16:9 16:10 4:3 3:2 1:1 4:5 9:16, oder Breite/Höhe
  "background": "lavender",             // lavender peach sage sky rose mint neutral midnight ink white,
                                        // jede CSS-Farbe / jeder Verlauf oder ein Bild unter public/ (backgrounds/x.jpg)
  "backgroundBlur": 0.02,               // für Fotohintergründe, Anteil der kurzen Seite
  "device": "iphone-black",             // iphone-black iphone-natural iphone-white browser window none
  "url": "app.ellie.so/today",          // Browserleistentext; "title": Fenstertitel für "window"
  "padding": 0.08, "tilt": 12,          // Geräterand; 3D-Neigung in Grad
  "position": [0.69, 0.5],              // Gerätemittelpunkt auf der Leinwand, lässt Platz für einen Titel daneben
  "accent": "#6d5ce8",                  // Farbe von Schritten, Konturen, Beschriftungen, Klickwellen
  "font": "Gilda Display", "labelFont": "Inter",  // Titel / Lift-Beschriftungen: Inter Manrope Poppins Nunito Fraunces Lora
                                        // "Playfair Display" "DM Serif Display" "Gilda Display" "Cormorant Garamond" Caveat
  "lift":  { "target": "task-row", "label": "Ziehen Sie es auf Ihren Tag", "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": { "anchor": [0.5, 0.5] }, "to": { "target": "add-button" }, "tail": 12, "head": 18 },
    { "type": "step", "target": "a-b", "label": "Stufe 3", "at": 2.0 },
    { "type": "blur", "target": "task-birthday", "radius": 8, "exclude": [16, 20, 220, 32] },
    { "type": "cut", "at": 1.2 },
    { "type": "cursor", "shape": "hand" },
    { "type": "caption", "text": "Los geht's", "align": "right" },
    { "type": "zoom", "target": "row-0", "start": 3.6, "end": 5.1, "scale": 2.5 },
    { "type": "highlight", "target": "title-input", "style": "glow", "glowColor": "#ffffff" }
  ],
  "title": [
    { "width": 0.28, "height": 0.16, "text": "Heute", "fontSize": 42, "align": "right", "vAlign": "bottom", "x": 0.45, "y": 0.28 },
    { "lines": "Ziehen, um zu planen", "x": 0.45, "y": 0.53 }
  ],
  "cuts": [
    { "segment": [0, 1.2], "speed": 1.2 },
    { "segment": [1.4, 3.8], "speed": 2.0, "blend": "fade", "blendDuration": 0.3 },
    { "segment": [4.0, 8.0], "clip": [4.4, 7.6] }
  ],
  "loop": 8.2,                          // Endpunkt der Schleife (in Sekunden), wenn das Video am Ende die Szene wiederholt
  "titleHold": 2.0,                     // Titel nach dem letzten Frame halten
  "progress": false                     // Fortschrittsbalken deaktivieren (für Vorschaubilder)
}

Verwandte Skills