Community编程与开发github.com

carveragents/show-n-tell

Agent skill from carveragents/show-n-tell

show-n-tell 是什么?

show-n-tell is a Claude Code agent skill that agent skill from carveragents/show-n-tell.

兼容平台✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/carveragents/show-n-tell/tree/main

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

show-n-tell 是做什么的?

You orchestrate a full pipeline that turns any website + a logo + a bit of intent into a 5-minute narrated, branded demo video. The scripts in scripts/ are dumb pipes; you are the conductor.

Reference docs in this folder: docs/SCHEMAS.md (YAML + action grammar), docs/GOTCHAS.md (known issues + workarounds), docs/CONTEXT.md ("what good output looks like"), examples/halyard-spme/ (canonical complete example). Read these as needed — don't pre-load them.

When to use this skill

  • User wants a narrated demo video of a website (live, local dev, or static).
  • User has at least light intent guidance ("show X, Y, Z" / "demo the dashboard flow").
  • User has access to a logo or wordmark.

Refuse to proceed if the user gives you neither intent notes nor a logo. Generic demos with default branding are bad demos. Ask for guidance instead of silently producing a weak video.

Environment Detection (read before starting)

Before doing anything, determine which environment Claude is running in:

  • Cowork: mcp__cowork__list_artifacts and mcp__computer-use__screenshot are available in Claude's tool list.
  • Claude Code CLI: those tools are absent.

This matters because several phases behave differently between environments. Quick-reference:

PhaseClaude Code CLICowork
Working dir (Phase 5)~/demo-videos/<slug>/request_cowork_directory outputs path
Site exploration public (Phase 2b)Playwright MCP toolsChrome MCP tools or explore_page.py headless
Auth capture OAuth (Phase 2a)Run capture_auth.py via BashUser runs capture_auth.py locally
Long commands (Phases 7–9)Run synchronouslynohup + poll (45s bash timeout)
Handoff (Phase 11)Report mp4 pathmp4 path + computer:// link

Phase 1 — Interview (collect inputs)

Ask one or two questions at a time, not all at once. Required:

  1. Target URL — confirm it's reachable.
  2. Demo intent notes — what story does this tell? What features matter?
  3. Audience + tone — internal/external/investors; explanatory/sales/technical/casual.
  4. Length target — default 5 min.
  5. Logo — URL or path. If only text-only is available, flag the limitation but accept.
  6. Brand colors — primary (ink) + accent. If unspecified, infer from the logo with PIL.
  7. Auth? — does the site require login?
    • No → proceed.
    • Yes, form-based (site has its own email/password fields you control) → use session.pre_session in demo_config.yaml. Collect credential env-var names (NOT actual values) and the login URL/selectors. Tell the user to put the actual credentials in <working_dir>/.env themselves before running, never in chat. See examples/login-flow/.
    • Yes, OAuth / SSO / magic-link / passkey (Google, Microsoft, Okta, etc.) → use session.storage_state. The user does NOT run any commands. YOU launch helpers/capture_auth.py for them in Phase 2a, and they only log in interactively in the browser window that opens. The captured auth.json is then used for both Phase 2b exploration AND Phase 8 recording. See examples/oauth-storage-state/.

Phase 2a — Auth capture (OAuth only)

Skip this phase entirely if Phase 1 question 7 settled on "no auth" or "form-based". For OAuth / SSO / magic-link / passkey, capture an authenticated session NOW, before site exploration — Phase 2b needs it to view authenticated pages.

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>

Run this via the Bash tool with timeout: 600000 (10 minutes — the max). The script opens a headed Chromium window. Tell the user in plain words:

"I'm opening a browser window for you to log in. Complete the login (Google, Microsoft, etc., handle 2FA), navigate to the page you want recording to start from, then close the browser window. I'll save the session and continue automatically."

The script writes auth.json with mode 0600 atomically. If the user takes longer than 10 minutes (rare, but possible with phone-based 2FA in another room), the Bash timeout fires — just re-run the same command.

--viewport MUST match recording.viewport in demo_config.yaml. Some sites fingerprint viewport size; mismatch can invalidate the captured session at record time or explore time.

If Playwright's Chromium isn't installed yet (fresh skill clone), the script surfaces an actionable error. Run uv run --with playwright playwright install chromium once.

If running in Claude Code CLI: run capture_auth.py via Bash as described above.

If running in Cowork: Claude handles this directly using computer-use and Chrome tools — the user only needs to log in when the browser opens. Steps:

  1. Ensure a working directory path is known. If Phase 5 hasn't run yet, call mcp__cowork__request_cowork_directory now to get the outputs path and set <working_dir> to <outputs_path>/<demo-slug>/.

  2. Open Chrome on the user's desktop:

    mcp__computer-use__open_application  →  "Google Chrome"  (or "Chrome")
    
  3. Navigate to the login URL. Prefer the Chrome MCP if connected:

    • Chrome extension available: mcp__Claude_in_Chrome__navigate to <login_or_start_url>
    • Chrome extension not connected: use mcp__computer-use__* tools to click the address bar and type the URL
  4. Tell the user to log in — say in plain words:

    "Chrome is open at the login page. Please log in (handle any 2FA, SSO, etc.), then navigate to the page where recording should begin. Let me know when you're done."

  5. Wait and watch. Poll with mcp__computer-use__screenshot every ~15 seconds. Continue once the URL is no longer a login/auth page and a dashboard or app page is visible.

  6. Extract the session state via JavaScript. Run this snippet with mcp__Claude_in_Chrome__javascript_tool:

    (() => {
      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);
    })()
    
  7. Write the result to <working_dir>/auth.json using the Write tool. This is valid Playwright storage_state format — helpers/explore_page.py and record_demo.py both consume it via browser.new_context(storage_state=...).

  8. HttpOnly cookie caveat. JavaScript cannot read HttpOnly cookies — they are intentionally invisible to document.cookie. If the site's session token is HttpOnly-only (common with older Rails/Django session cookies), the extracted state will be missing it. Tell the user:

    "Note: session cookies marked HttpOnly aren't accessible from JavaScript, so I may not have captured all auth tokens. The recording will try to use what was captured — if it hits a login wall during Phase 8, we can fall back to using capture_auth.py locally." Then continue — many modern sites (Google, Microsoft, Okta) keep enough state in non-HttpOnly cookies or localStorage for Playwright to work.

Phase 2b — Site exploration

If Phase 2a ran (auth.json exists), use helpers/explore_page.py to view authenticated pages — the Playwright MCP can't load storage_state and would just see login walls. For non-auth demos, the Playwright MCP is fine and more interactive; use it as before.

For authenticated pages:

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/

This writes three files per page into _explore/: <slug>.png (screenshot), <slug>.dom.html (DOM for selector picking), <slug>.meta.json ({url_requested, final_url, title, status}). Read the PNG with the Read tool to see the page; grep the DOM for selectors. If final_url in meta.json points at a login page, the session expired — re-run Phase 2a.

For public pages (landing page, marketing pages on any demo; everything on a no-auth demo) — use the Playwright MCP tools (mcp__plugin_playwright_playwright__*) as before:

  • browser_navigate to the target URL, then to 2–5 pages the user's intent mentions.
  • browser_snapshot or browser_take_screenshot to see each page's layout.
  • Use browser_evaluate to read DOM for stable selectors (prefer semantic over nth-of-type where possible).

If running in Claude Code CLI: use mcp__plugin_playwright_playwright__* tools as described above.

If running in Cowork: First ensure Chromium is

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能