Was macht show-n-tell?
Sie orchestrieren eine vollständige Pipeline, die jede Website + ein Logo + ein wenig Absicht in ein 5-minütiges, erzähltes, markiertes Demovideo verwandelt. Die Skripte in scripts/ sind dumme Rohre; Sie sind der Dirigent.
Referenzdokumente in diesem Ordner: docs/SCHEMAS.md (YAML + Aktionsgrammatik), docs/GOTCHAS.md (bekannte Probleme + Problemumgehungen), docs/CONTEXT.md („wie gute Ausgabe aussieht“), examples/halyard-spme/ (kanonisches vollständiges Beispiel). Lesen Sie diese bei Bedarf – laden Sie sie nicht vor.
Wann Sie diese Fähigkeit verwenden
- Der Benutzer möchte ein erzähltes Demovideo einer Website (live, lokale Entwicklung oder statisch).
- Der Benutzer hat zumindest eine leichte Absichtslenkung („zeige X, Y, Z“ / „demo den Dashboard-Flow“).
- Der Benutzer hat Zugriff auf ein Logo oder eine Wortmarke.
Lehnen Sie ab, fortzufahren, wenn der Benutzer Ihnen weder Absichtsnotizen noch ein Logo gibt. Generische Demos mit Standard-Branding sind schlechte Demos. Fragen Sie nach Anleitung, anstatt stillschweigend ein schwaches Video zu produzieren.
Umgebungserkennung (vor dem Start lesen)
Bevor Sie irgendetwas tun, bestimmen Sie, in welcher Umgebung Claude läuft:
- Cowork:
mcp__cowork__list_artifactsundmcp__computer-use__screenshotsind in Claudes Werkzeugliste verfügbar. - Claude Code CLI: Diese Werkzeuge fehlen.
Dies ist wichtig, da sich mehrere Phasen zwischen den Umgebungen unterschiedlich verhalten. Kurzreferenz:
| Phase | Claude Code CLI | Cowork |
|---|---|---|
| Arbeitsverzeichnis (Phase 5) | ~/demo-videos/<slug>/ | request_cowork_directory gibt den Pfad aus |
| Site-Exploration öffentlich (Phase 2b) | Playwright MCP-Werkzeuge | Chrome MCP-Werkzeuge oder explore_page.py headless |
| Auth-Erfassung OAuth (Phase 2a) | Ausführen von capture_auth.py über Bash | Benutzer führt capture_auth.py lokal aus |
| Lange Befehle (Phasen 7–9) | Synchron ausführen | nohup + Poll (45s Bash-Timeout) |
| Übergabe (Phase 11) | MP4-Pfad melden | MP4-Pfad + computer://-Link |
Phase 1 — Interview (Eingaben sammeln)
Stellen Sie jeweils ein oder zwei Fragen, nicht alle auf einmal. Erforderlich:
- Ziel-URL — bestätigen, dass sie erreichbar ist.
- Demo-Absichtsnotizen — welche Geschichte wird erzählt? Welche Funktionen sind wichtig?
- Zielgruppe + Ton — intern/extern/Investoren; erklärend/verkaufend/technisch/locker.
- Ziellänge — Standard 5 Min.
- Logo — URL oder Pfad. Wenn nur Text verfügbar ist, weisen Sie auf die Einschränkung hin, akzeptieren Sie es aber.
- Markenfarben — Primär (Tinte) + Akzent. Wenn nicht angegeben, leiten Sie sie mit PIL aus dem Logo ab.
- Auth? — erfordert die Site eine Anmeldung?
- Nein → fortfahren.
- Ja, formularbasiert (Site hat eigene E-Mail/Passwort-Felder, die Sie steuern) →
session.pre_sessionindemo_config.yamlverwenden. Sammeln Sie die Namen der Anmelde-Umgebungsvariablen (NICHT die tatsächlichen Werte) und die Anmelde-URL/Selektoren. Sagen Sie dem Benutzer, dass er die tatsächlichen Anmeldedaten selbst in<working_dir>/.envsetzen soll, niemals im Chat. Sieheexamples/login-flow/. - Ja, OAuth / SSO / Magic-Link / Passkey (Google, Microsoft, Okta, etc.) →
session.storage_stateverwenden. Der Benutzer führt KEINE Befehle aus. SIE startenhelpers/capture_auth.pyfür sie in Phase 2a, und sie melden sich nur interaktiv im geöffneten Browserfenster an. Das erfassteauth.jsonwird dann sowohl für die Phase 2b-Exploration als auch für die Phase 8-Aufnahme verwendet. Sieheexamples/oauth-storage-state/.
Phase 2a — Auth-Erfassung (nur OAuth)
Überspringen Sie diese Phase vollständig, wenn Phase 1 Frage 7 auf „kein Auth“ oder „formularbasiert“ festgelegt wurde. Für OAuth / SSO / Magic-Link / Passkey erfassen Sie JETZT eine authentifizierte Sitzung, vor der Site-Exploration — Phase 2b benötigt sie, um authentifizierte Seiten anzuzeigen.
mkdir -p ~/demo-videos/<demo-slug>/
uv run helpers/capture_auth.py <login_or_start_url> \
--out ~/demo-videos/<demo-slug>/auth.json \
--viewport <recording.viewport from demo_config.yaml; default 1440x900>
Führen Sie dies über das Bash-Werkzeug mit timeout: 600000 (10 Minuten — das Maximum) aus. Das Skript öffnet ein headed Chromium-Fenster. Sagen Sie dem Benutzer in einfachen Worten:
„Ich öffne ein Browserfenster, damit Sie sich anmelden können. Schließen Sie die Anmeldung ab (Google, Microsoft, etc., behandeln Sie 2FA), navigieren Sie zu der Seite, von der die Aufnahme starten soll, und schließen Sie dann das Browserfenster. Ich speichere die Sitzung und fahre automatisch fort.“
Das Skript schreibt auth.json atomar mit Modus 0600. Wenn der Benutzer länger als 10 Minuten braucht (selten, aber möglich bei telefonbasierter 2FA in einem anderen Raum), feuert das Bash-Timeout — führen Sie einfach denselben Befehl erneut aus.
--viewport MUSS mit recording.viewport in demo_config.yaml übereinstimmen. Einige Sites fingerabdrucken die Viewport-Größe; eine Nichtübereinstimmung kann die erfasste Sitzung zum Zeitpunkt der Aufnahme oder Erkundung ungültig machen.
Wenn Playwrights Chromium noch nicht installiert ist (frischer Skill-Klon), zeigt das Skript einen umsetzbaren Fehler an. Führen Sie einmal uv run --with playwright playwright install chromium aus.
Wenn Sie in Claude Code CLI laufen: führen Sie capture_auth.py wie oben beschrieben über Bash aus.
Wenn Sie in Cowork laufen: Claude behandelt dies direkt mit Computer-Use- und Chrome-Werkzeugen — der Benutzer muss sich nur anmelden, wenn der Browser geöffnet wird. Schritte:
-
Stellen Sie sicher, dass ein Arbeitsverzeichnispfad bekannt ist. Wenn Phase 5 noch nicht ausgeführt wurde, rufen Sie jetzt
mcp__cowork__request_cowork_directoryauf, um den Ausgabepfad zu erhalten, und setzen Sie<working_dir>auf<outputs_path>/<demo-slug>/. -
Öffnen Sie Chrome auf dem Desktop des Benutzers:
mcp__computer-use__open_application → "Google Chrome" (oder "Chrome") -
Navigieren Sie zur Anmelde-URL. Bevorzugen Sie das Chrome MCP, wenn verbunden:
- Chrome-Erweiterung verfügbar:
mcp__Claude_in_Chrome__navigatezu<login_or_start_url> - Chrome-Erweiterung nicht verbunden: Verwenden Sie
mcp__computer-use__*-Werkzeuge, um auf die Adressleiste zu klicken und die URL einzugeben
- Chrome-Erweiterung verfügbar:
-
Sagen Sie dem Benutzer, er solle sich anmelden — sagen Sie in einfachen Worten:
„Chrome ist auf der Anmeldeseite geöffnet. Bitte melden Sie sich an (behandeln Sie jegliche 2FA, SSO, etc.), navigieren Sie dann zu der Seite, wo die Aufnahme beginnen soll. Lassen Sie mich wissen, wenn Sie fertig sind.“
-
Warten und beobachten. Pollen Sie alle ~15 Sekunden mit
mcp__computer-use__screenshot. Fahren Sie fort, sobald die URL keine Anmelde-Auth-Seite mehr ist und ein Dashboard oder eine App-Seite sichtbar ist. -
Extrahieren Sie den Sitzungszustand über JavaScript. Führen Sie dieses Snippet mit
mcp__Claude_in_Chrome__javascript_toolaus:(() => { const cookies = document.cookie.split(';').map(c => { const [name, ...rest] = c.trim().split('='); return { name: name.trim(), value: rest.join('='), domain: location.hostname, path: '/', expires: -1, httpOnly: false, secure: location.protocol === 'https:', sameSite: 'Lax' }; }).filter(c => c.name); const ls = {}; for (let i = 0; i < localStorage.length; i++) { const k = localStorage.key(i); ls[k] = localStorage.getItem(k); } const ss = {}; for (let i = 0; i < sessionStorage.length; i++) { const k = sessionStorage.key(i); ss[k] = sessionStorage.getItem(k); } return JSON.stringify({ cookies, origins: [{ origin: location.origin, localStorage: Object.entries(ls).map(([n,v]) => ({name:n,value:v})), sessionStorage: Object.entries(ss).map(([n,v]) => ({name:n,value:v})) }] }, null, 2); })() -
Schreiben Sie das Ergebnis in
<working_dir>/auth.jsonmit dem Write-Werkzeug. Dies ist ein gültiges Playwrightstorage_state-Format —helpers/explore_page.pyundrecord_demo.pykonsumieren es beide überbrowser.new_context(storage_state=...). -
HttpOnly-Cookie-Hinweis. JavaScript kann HttpOnly-Cookies nicht lesen — sie sind absichtlich für
document.cookieunsichtbar. Wenn das Sitzungstoken der Site nur HttpOnly ist (häufig bei älteren Rails/Django-Sitzungs-Cookies), fehlt im extrahierten Zustand. Sagen Sie dem Benutzer:„Hinweis: Als HttpOnly markierte Sitzungs-Cookies sind von JavaScript aus nicht zugänglich, daher habe ich möglicherweise nicht alle Auth-Tokens erfasst. Die Aufnahme wird versuchen, das Erfasste zu verwenden — wenn sie während Phase 8 auf eine Anmeldewand stößt, können wir auf die lokale Verwendung von
capture_auth.pyzurückgreifen.“ Fahren Sie dann fort — viele moderne Sites (Google, Microsoft, Okta) halten genug Zustand in nicht-HttpOnly-Cookies oder localStorage, damit Playwright funktioniert.
Phase 2b — Site-Exploration
Wenn Phase 2a ausgeführt wurde (auth.json existiert), verwenden Sie helpers/explore_page.py, um authentifizierte Seiten anzuzeigen — das Playwright MCP kann storage_state nicht laden und würde nur Anmeldewände sehen. Für Demos ohne Authentifizierung ist das Playwright MCP in Ordnung und interaktiver; verwenden Sie es wie zuvor.
Für authentifizierte Seiten:
mkdir -p ~/demo-videos/<demo-slug>/_explore/
uv run helpers/explore_page.py https://target.example.com/dashboard \
--storage-state ~/demo-videos/<demo-slug>/auth.json \
--out-dir ~/demo-videos/<demo-slug>/_explore/
Dies schreibt drei Dateien pro Seite in _explore/: <slug>.png (Screenshot), <slug>.dom.html (DOM für Selektorauswahl), <slug>.meta.json ({url_requested, final_url, title, status}). Lesen Sie das PNG mit dem Read-Werkzeug, um die Seite zu sehen; grep-en Sie das DOM für Selektoren. Wenn final_url in meta.json auf eine Anmeldeseite zeigt, ist die Sitzung abgelaufen — führen Sie Phase 2a erneut aus.
Für öffentliche Seiten (Landing Page, Marketing-Seiten bei jeder Demo; alles bei einer Demo ohne Authentifizierung) — verwenden Sie die Playwright MCP-Werkzeuge (mcp__plugin_playwright_playwright__*) wie zuvor:
browser_navigatezur Ziel-URL, dann zu 2–5 Seiten, die die Absicht des Benutzers erwähnt.browser_snapshotoderbrowser_take_screenshot, um das Layout jeder Seite zu sehen.- Verwenden Sie
browser_evaluate, um DOM für stabile Selektoren zu lesen (bevorzugen Sie semantische vornth-of-type, wo möglich).
Wenn Sie in Claude Code CLI laufen: verwenden Sie die mcp__plugin_playwright_playwright__*-Werkzeuge wie oben beschrieben.
Wenn Sie in Cowork laufen: Stellen Sie zunächst sicher, dass Chromium verfügbar ist:
uv run --with playwright playwright install chromium
Wählen Sie dann die beste verfügbare Methode:
- Wenn
mcp__Claude_in_Chrome__navigateverfügbar ist (Chrome-Erweiterung verbunden), verwenden Siemcp__Claude_in_Chrome__navigate+mcp__Claude_in_Chrome__read_page, um die Site interaktiv zu erkunden. - Andernfalls fallen Sie auf headless-Exploration zurück:
(Keinmkdir -p <working_dir>/_explore/ uv run helpers/explore_page.py <url> --out-dir <working_dir>/_explore/--storage-statefür öffentliche Seiten erforderlich — das Argument ist jetzt optional.)
Notieren Sie für jede bedeutende Seite:
- Demo-würdige Momente (Scroll-zu-Feature, Klick-zu-Detail, Hover-Tooltip).
- Erforderliche Site-Anpassungen: Sticky-Header-Trick? PDF-Deep-Link? Modal-Blocker? Auth-Wand?
- Selektoren, die fragil aussehen und
wait_for_selector-Verteidigungen benötigen könnten.
Crawlen Sie nicht erschöpfend. 2–5 Aktionen pro Seite sind genug.
Phase 3 — Entwurf storyboard.yaml
Generieren Sie 15–30 Beats. Jeder Beat = eine Kamerabewegung + 1–3 Sätze Erzählung. Siehe docs/SCHEMAS.md für die Aktionsgrammatik (Phase-A-Teilmenge: goto, goto_and_scroll, scroll_into_view, scroll_y, hover, click).
Ziel für ein 5-minütiges Video bei 1,2-facher Beschleunigung:
- Gesamt nach Beschleunigung: ~5:00
- Gesamt-Rohlaufzeit: ~6:00
- Pro-Beat-Durchschnitt: ~12s, davon ~9–10s Erzählung
Harte Regeln beim Verfassen der Erzählung:
- Jede faktische Behauptung muss auf dem Bildschirm zu diesem Beat-Frame sichtbar sein. Keine erfundenen Zahlen („der Agent hat 199 Änderungen markiert“). Wenn Sie es nicht auf dem Screenshot sehen, sagen Sie es nicht.
- Initialismen, die Buchstabe für Buchstabe gelesen werden, müssen mit Bindestrich geschrieben werden:
S-P-M-E,K-Y-B,A-P-I. Der TTS-Prompt erzwingt diese Konvention. - Länge entspricht visuellem Inhalt: 8–18s für Scroll-Beats, 6–12s für Klick-Beats.
- Ton entspricht dem Feld
voice.toneinbranding.yaml.
Gruppieren Sie Beats mental in Segmente (Überblick / Feature A / Feature B / Abschluss), schreiben Sie aber eine flache Liste in YAML — keine Abschnittsmarkierungen.
Phase 4 — Überprüfung in einfacher Sprache
Der Benutzer bearbeitet YAML nicht direkt. Sie präsentieren den Entwurf als nummerierte Liste und akzeptieren Feedback in natürlicher Sprache. Verwenden Sie genau dieses Format:
Hier ist der von mir entworfene Demo-Ablauf. Geschätzte Laufzeit: 5:08 (nach 1,2-facher Beschleunigung).
Sagen Sie mir, was Sie ändern möchten.
ÜBERBLICK (60s)
1. Auf Landingpage landen (10s) — „Willkommen bei Acme Cloud, einer serverlosen Plattform für kleine Teams...“
2. Zu Funktionen scrollen (15s) — „Drei Kernfunktionen treiben die Plattform an...“
3. Zu Ausgaben scrollen (8s) — „Diese zehn Politikbereiche...“
FEATURE 1 — Dashboard (45s)
4. Zum Dashboard navigieren (8s) — „Klicken in das Dashboard...“
5. Live-Aktivitätsfeed hoveren (12s) — „Jedes Projekt zeigt einen Live-Aktivitätsfeed...“
...
ABSCHLUSS (20s)
27. Zurück zur Homepage-Statistik (12s) — „Drei Gründe, warum Teams Acme wählen...“
28. Outro (8s)
Dann: „Soll ich etwas hinzufügen, entfernen oder umordnen? Möchten Sie Anpassungen am Erzählungston? Soll etwas übersprungen werden?“
Übersetzen Sie Feedback in natürlicher Sprache in YAML-Bearbeitungen:
- „Beat 7 überspringen“ → aus YAML entfernen
- „Beat 3 länger machen“ → Erzählung mit mehr Details auf dem Bildschirm erweitern (in zwei Beats aufteilen, wenn viel länger)
- „Pricing irgendwo erwähnen“ → den richtigen Beat identifizieren und einen Satz hinzufügen (überprüfen, ob Pricing auf diesem Beat-Frame tatsächlich sichtbar ist)
- „Ton zu formell“ → Erzählung mit lockerer Formulierung umschreiben
- „Teamseite anstelle von Über uns zeigen“ → URL austauschen + Erzählung anpassen
Präsentieren Sie den aktualisierten Ablauf erneut. Iterieren Sie, bis der Benutzer explizit zustimmt.
Laufzeitabweichungsprüfung vor TTS: Summieren Sie len(beat.narration) / 16 (Zeichen/s bei 140 Wörtern/min) über alle Beats. Wenn estimated * (1 / speed_multiplier) mehr als 30s vom Ziel abweicht, weisen Sie darauf hin: „Das liegt derzeit bei ~6:20 nach Beschleunigung gegenüber Ihrem 5-Minuten-Ziel. Soll ich kürzen?“
Phase 5 — Arbeitsverzeichnis einrichten
mkdir -p ~/demo-videos/<demo-slug>/_assets
cp <logo_path> ~/demo-videos/<demo-slug>/_assets/<logo>.png
# storyboard.yaml, branding.yaml, demo_config.yaml aus Ihren Entwürfen schreiben
Wenn Sie in Claude Code CLI laufen: verwenden Sie ~/demo-videos/<demo-slug>/ wie oben gezeigt.
Wenn Sie in Cowork laufen: rufen Sie mcp__cowork__request_cowork_directory auf, um den Ausgabepfad des Benutzers zu erhalten. Setzen Sie das Arbeitsverzeichnis auf <outputs_path>/<demo-slug>/. Verwenden Sie diesen Pfad für ALLE nachfolgenden Dateischreibvorgänge in den Phasen 6–11 — speichern Sie ihn jetzt und behalten Sie ihn während der gesamten Sitzung konsistent. Erstellen Sie das Unterverzeichnis _assets/ unter diesem Pfad, nicht unter ~/demo-videos/.
Wenn der Benutzer keine Logodatei auf der Festplatte hat und nur eine URL hat, laden Sie es mit curl herunter und legen Sie es in _assets/ ab.