Was macht show-n-tell?
Du orchestrierst eine vollständige Pipeline, die jede Website + ein Logo + eine Absicht in ein 5-minütiges, kommentiertes und gebrandetes Demovideo verwandelt. Die Skripte in scripts/ sind bloße Rohre; du bist der Dirigent.
Referenzdokumente in diesem Ordner: docs/SCHEMAS.md (YAML + Aktionsgrammatik), docs/GOTCHAS.md (bekannte Probleme + Workarounds), docs/CONTEXT.md („Wie gute Ausgabe aussieht“), examples/halyard-spme/ (kanonisches vollständiges Beispiel). Lies diese nach Bedarf – lade sie nicht vorab.
Wann diese Fähigkeit verwenden
- Nutzer möchte ein kommentiertes Demovideo einer Website (live, lokale Entwicklung oder statisch).
- Nutzer hat zumindest eine leichte Absichtsangabe („zeige X, Y, Z“ / „demo den Dashboard-Flow“).
- Nutzer hat Zugriff auf ein Logo oder eine Wortmarke.
Lehne die Fortsetzung ab, wenn der Nutzer dir weder Absichtsnotizen noch ein Logo gibt. Generische Demos mit Standard-Branding sind schlechte Demos. Frage nach Anleitung, anstatt still ein schwaches Video zu produzieren.
Umgebungserkennung (vor dem Start lesen)
Bevor du etwas tust, ermittle, in welcher Umgebung Claude läuft:
- Cowork:
mcp__cowork__list_artifactsundmcp__computer-use__screenshotsind in Claudes Werkzeugliste verfügbar. - Claude Code CLI: Diese Werkzeuge sind nicht vorhanden.
Dies ist wichtig, da sich mehrere Phasen zwischen Umgebungen unterschiedlich verhalten. Kurzübersicht:
| Phase | Claude Code CLI | Cowork |
|---|---|---|
| Arbeitsverzeichnis (Phase 5) | ~/demo-videos/<slug>/ | request_cowork_directory gibt Pfad aus |
| Site-Erkundung öffentlich (Phase 2b) | Playwright MCP-Werkzeuge | Chrome MCP-Werkzeuge oder explore_page.py headless |
| Auth-Capture OAuth (Phase 2a) | Führe capture_auth.py über Bash aus | Nutzer 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)
Stelle ein oder zwei Fragen auf einmal, nicht alle auf einmal. Erforderlich:
- Ziel-URL – bestätige, 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, weise auf die Einschränkung hin, aber akzeptiere es.
- Markenfarben – primär (Tinte) + Akzent. Wenn nicht angegeben, aus dem Logo mit PIL ableiten.
- Auth? – Erfordert die Website eine Anmeldung?
- Nein → fortfahren.
- Ja, formularbasiert (Website hat eigene E-Mail/Passwort-Felder, die du kontrollierst) → verwende
session.pre_sessionindemo_config.yaml. Sammle die Umgebungsvariablen-Namen für Anmeldedaten (NICHT die tatsächlichen Werte) und die Login-URL/Selektoren. Sage dem Nutzer, er solle die tatsächlichen Anmeldedaten selbst in<working_dir>/.envablegen, niemals im Chat. Sieheexamples/login-flow/. - Ja, OAuth / SSO / Magic-Link / Passkey (Google, Microsoft, Okta, usw.) → verwende
session.storage_state. Der Nutzer führt KEINE Befehle aus. DU startesthelpers/capture_auth.pyfür sie in Phase 2a, und sie loggen sich nur interaktiv im geöffneten Browserfenster ein. Das erfassteauth.jsonwird dann sowohl für Phase 2b-Erkundung als auch Phase 8-Aufnahme verwendet. Sieheexamples/oauth-storage-state/.
Phase 2a — Auth-Capture (nur OAuth)
Überspringe diese Phase vollständig, wenn Phase 1 Frage 7 auf „kein Auth“ oder „formularbasiert“ entschieden wurde. Für OAuth / SSO / Magic-Link / Passkey erfasse JETZT eine authentifizierte Sitzung, vor der Site-Erkundung – Phase 2b benötigt sie, um authentifizierte Seiten anzuzeigen.
mkdir -p ~/demo-videos/<demo-slug>/
uv run helpers/capture_auth.py <login_oder_start_url> \
--out ~/demo-videos/<demo-slug>/auth.json \
--viewport <recording.viewport aus demo_config.yaml; Standard 1440x900>
Führe dies über das Bash-Werkzeug mit timeout: 600000 (10 Minuten – das Maximum) aus. Das Skript öffnet ein Chromium-Fenster mit Kopf. Sage dem Nutzer in klaren Worten:
„Ich öffne ein Browserfenster, in dem Sie sich anmelden können. Schließen Sie die Anmeldung ab (Google, Microsoft, usw., inkl. 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 Nutzer länger als 10 Minuten braucht (selten, aber möglich bei telefonbasierter 2FA in einem anderen Raum), feuert der Bash-Timeout – führe einfach denselben Befehl erneut aus.
--viewport MUSS mit recording.viewport in demo_config.yaml übereinstimmen. Manche Websites prüfen die Viewport-Größe; ein Missmatch kann die erfasste Sitzung zur Aufnahme- oder Erkundungszeit ungültig machen.
Wenn Playwrights Chromium noch nicht installiert ist (frischer Skill-Clone), zeigt das Skript einen umsetzbaren Fehler an. Führe einmal uv run --with playwright playwright install chromium aus.
Wenn in Claude Code CLI ausgeführt: führe capture_auth.py wie oben beschrieben über Bash aus.
Wenn in Cowork ausgeführt: Claude handhabt dies direkt mit Computer-Use- und Chrome-Werkzeugen – der Nutzer muss sich nur anmelden, wenn der Browser geöffnet wird. Schritte:
-
Stelle sicher, dass ein Arbeitsverzeichnis-Pfad bekannt ist. Wenn Phase 5 noch nicht ausgeführt wurde, rufe jetzt
mcp__cowork__request_cowork_directoryauf, um den Ausgabepfad zu erhalten, und setze<working_dir>auf<outputs_path>/<demo-slug>/. -
Öffne Chrome auf dem Desktop des Nutzers:
mcp__computer-use__open_application → „Google Chrome“ (oder „Chrome“) -
Navigiere zur Login-URL. Bevorzuge das Chrome MCP, wenn verbunden:
- Chrome-Erweiterung verfügbar:
mcp__Claude_in_Chrome__navigatezu<login_oder_start_url> - Chrome-Erweiterung nicht verbunden: verwende
mcp__computer-use__*-Werkzeuge, um die Adressleiste anzuklicken und die URL einzugeben
- Chrome-Erweiterung verfügbar:
-
Sage dem Nutzer, sich anzumelden – sage in klaren Worten:
„Chrome ist auf der Anmeldeseite geöffnet. Bitte melden Sie sich an (erledigen Sie 2FA, SSO usw.) und navigieren Sie dann zu der Seite, an der die Aufnahme beginnen soll. Lassen Sie mich wissen, wenn Sie fertig sind.“
-
Warte und beobachte. Frage mit
mcp__computer-use__screenshotalle ~15 Sekunden ab. Fahre fort, sobald die URL keine Login-/Auth-Seite mehr ist und ein Dashboard oder eine App-Seite sichtbar ist. -
Extrahiere den Sitzungszustand über JavaScript. Führe 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); })() -
Schreibe das Ergebnis mit dem Write-Werkzeug in
<working_dir>/auth.json. Dies ist gültiges Playwright-storage_state-Format –helpers/explore_page.pyundrecord_demo.pykonsumieren es beide überbrowser.new_context(storage_state=...). -
HttpOnly-Cookie-Vorbehalt. JavaScript kann HttpOnly-Cookies nicht lesen – sie sind absichtlich für
document.cookieunsichtbar. Wenn das Sitzungstoken der Website nur HttpOnly ist (häufig bei älteren Rails/Django-Sitzungscookies), fehlt der extrahierten Zustand. Sage dem Nutzer:„Hinweis: Sitzungscookies, die als HttpOnly markiert sind, sind für JavaScript nicht zugänglich, daher habe ich möglicherweise nicht alle Authentifizierungstoken erfasst. Die Aufnahme wird versuchen, das Erfasste zu verwenden – wenn in Phase 8 eine Anmeldewand auftritt, können wir auf die lokale Verwendung von
capture_auth.pyzurückgreifen.“ Fahre dann fort – viele moderne Websites (Google, Microsoft, Okta) behalten genügend Zustand in nicht-HttpOnly-Cookies oder localStorage, damit Playwright funktioniert.
Phase 2b — Site-Erkundung
Wenn Phase 2a ausgeführt wurde (auth.json existiert), verwende 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; verwende 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 zur Auswahl von Selektoren), <slug>.meta.json ({url_requested, final_url, title, status}). Lese das PNG mit dem Read-Werkzeug, um die Seite zu sehen; durchsuche das DOM mit grep nach Selektoren. Wenn final_url in meta.json auf eine Login-Seite zeigt, ist die Sitzung abgelaufen – führe Phase 2a erneut aus.
Für öffentliche Seiten (Landing-Page, Marketing-Seiten bei jeder Demo; alles bei einer Demo ohne Auth) – verwende die Playwright MCP-Werkzeuge (mcp__plugin_playwright_playwright__*) wie zuvor:
browser_navigatezur Ziel-URL, dann zu 2–5 Seiten, die die Absicht des Nutzers erwähnt.browser_snapshotoderbrowser_take_screenshot, um das Layout jeder Seite zu sehen.- Verwende
browser_evaluate, um das DOM für stabile Selektoren zu lesen (bevorzuge semantische Selektoren gegenübernth-of-type, wo möglich).
Wenn in Claude Code CLI ausgeführt: verwende mcp__plugin_playwright_playwright__* wie oben beschrieben.
Wenn in Cowork ausgeführt: Stelle zuerst sicher, dass Chromium installiert ist. Verwende dann...