{
  "markdown": "# aidemo — your coding agent makes the demo video\n\n**[aidemo.top](https://aidemo.top)** · [watch a real 51s output ▶](https://github.com/tandryukha/aidemo/releases/download/v0.3.0/wikipedia-showcase-demo.mp4) · [authoring guide](docs/AUTHORING.md) · [render in CI](docs/CI.md)\n\nTell your coding agent *\"record a 45s demo of the checkout flow\"* — get back a\npolished **MP4 with voiceover, synced captions, and auto-zoom**. Any MCP-capable\nagent (Claude Code, Codex CLI, Gemini CLI) writes one `storyboard.json`; the\nheadless engine drives a real Chrome, records a **deterministic replay**, voices\nit, captions it, and trims the dead time. Because the replay is deterministic,\n**the demo re-renders itself in CI** when the product changes — no re-recording,\nno API key, about **$0 a render**. An **open-source (MIT) alternative to Screen\nStudio, Clueso, or Demosmith** for when you'd rather your coding agent make the\ndemo.\n\n[![Website](https://img.shields.io/badge/website-aidemo.top-1a7f37)](https://aidemo.top)\n[![ci](https://github.com/tandryukha/aidemo/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/tandryukha/aidemo/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![npm](https://img.shields.io/npm/v/%40tandryukha%2Faidemo?logo=npm&label=npm&color=cb3837)](https://www.npmjs.com/package/@tandryukha/aidemo)\n[![Homebrew](https://img.shields.io/badge/Homebrew-tandryukha%2Faidemo-fbb040?logo=homebrew&logoColor=white)](https://github.com/tandryukha/homebrew-aidemo)\n[![GitHub Marketplace](https://img.shields.io/badge/Marketplace-aidemo%20Demo%20Video-2ea44f?logo=githubactions&logoColor=white)](https://github.com/marketplace/actions/aidemo-demo-video)\n[![MCP Registry](https://img.shields.io/badge/MCP%20Registry-aidemo-1f6feb)](https://registry.modelcontextprotocol.io)\n[![Works with Claude Code](https://img.shields.io/badge/works%20with-Claude%20Code-d97757)](#three-ways-to-use-it)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/tandryukha/aidemo/badge)](https://scorecard.dev/viewer/?uri=github.com/tandryukha/aidemo)\n[![Glama](https://glama.ai/mcp/servers/tandryukha/aidemo/badges/score.svg)](https://glama.ai/mcp/servers/tandryukha/aidemo)\n\n**Install:** Claude Code `/plugin marketplace add tandryukha/aidemo` · CI `uses: tandryukha/aidemo@stable` · CLI `npx -y @tandryukha/aidemo` · Homebrew `brew install tandryukha/aidemo/aidemo`\n<br>Published on the [GitHub Marketplace](https://github.com/marketplace/actions/aidemo-demo-video), [npm](https://www.npmjs.com/package/@tandryukha/aidemo), a [Homebrew tap](https://github.com/tandryukha/homebrew-aidemo), and the [MCP Registry](https://registry.modelcontextprotocol.io).\n\n[![aidemo demoing itself on Wikipedia — recorded with aidemo](docs/demo.gif)](https://github.com/tandryukha/aidemo/releases/download/v0.3.0/wikipedia-showcase-demo.mp4)\n\n<sub>Real output — a ~51 s self-narrated tour of Wikipedia (portal search →\nAda Lovelace → focus-zoom → click through to the Analytical Engine → glide\nscroll), authored by Claude from one `storyboard.json` and recorded as a\ndeterministic replay. The preview GIF is silent;\n**[watch the full version with narration ▶](https://github.com/tandryukha/aidemo/releases/download/v0.3.0/wikipedia-showcase-demo.mp4)**.</sub>\n\n## Three ways to use it\n\n1. **From your coding agent** — the fastest path. In **Claude Code**:\n   `/plugin marketplace add tandryukha/aidemo` then\n   `/plugin install record-demo@aidemo` (bundles the skill **and** the MCP\n   server). In **Codex / Gemini / any MCP agent**:\n   `npx -y github:tandryukha/aidemo#stable repo-init`. Then just say\n   *\"record a 45s demo of &lt;flow&gt;\"* and the agent authors + renders it.\n2. **Locally, free & offline** —\n   `AIDEMO_TTS_PROVIDER=local aidemo render <dir> --headless`. An in-process\n   voice model + script-timed captions mean **no API key, ~$0, fully offline**.\n   See [docs/LOCAL_MODELS.md](docs/LOCAL_MODELS.md).\n3. **In CI, self-maintaining** — drop `uses: tandryukha/aidemo@stable` into a\n   workflow. When the product changes, it replays the committed storyboard and\n   commits fresh media — **no key, no LLM tokens, ~$0** on free runner minutes.\n   See [docs/CI.md](docs/CI.md).\n\n**Free & open source.** MIT-licensed. Runs on GitHub's free Actions tier, or\nfully local at $0 with the in-process voice — no API key, no cloud upload, no\ntelemetry. Works against **localhost and auth-walled apps** (your own Chrome).\n\n## From one sentence to a narrated MP4\n\nYou type a sentence, the agent writes an artifact you can read and edit, the\nengine records and cuts it:\n\n**1 · What you type** — one line to any MCP-capable agent (Claude Code here):\n\n```\nclaude \"record a 45s demo touring Wikipedia: search for Ada Lovelace,\nopen the Analytical Engine, then glide down the article\"\n```\n\n**2 · What the agent authors** — a plain, editable `storyboard.json` (excerpt:\nnarration + a fixed browser action-spec, side by side — no generated code):\n\n```jsonc\n{\n  \"title\": \"A quick tour of Wikipedia\",\n  \"zoom\": {},                                  // Screen-Studio-style auto-zoom\n  \"scenes\": [\n    { \"id\": \"search\",\n      \"narration\": \"Start at the Wikipedia portal and search for Ada Lovelace.\",\n      \"actions\": [\n        { \"op\": \"goto\", \"url\": \"https://www.wikipedia.org/\" },\n        { \"op\": \"type\", \"target\": { \"selector\": \"#searchInput\" }, \"text\": \"Ada Lovelace\" },\n        { \"op\": \"click\", \"target\": { \"selector\": \"button[type=submit]\" } } ] },\n    { \"id\": \"engine\",\n      \"narration\": \"Her notes on Babbage's Analytical Engine hold the first computer program.\",\n      \"actions\": [\n        { \"op\": \"focus\", \"target\": { \"selector\": \"#firstHeading\" } },\n        { \"op\": \"click\", \"target\": { \"selector\": \"a[href*='Analytical_Engine']\" } },\n        { \"op\": \"scrollBy\", \"dy\": 900, \"easing\": \"glide\" } ] }\n  ]\n}\n```\n\n**3 · How it's recorded + cut** — `aidemo render` drives a real Chrome (smooth\nanimated cursor, human-cadence typing, auto-zoom), then trims the dead time and\nsyncs to the narration:\n\n```\nstoryboard.json\n   → voice     OpenAI / ElevenLabs / local TTS → audio/narration.mp3 + voice.json\n   → record    drives Chrome, animated cursor  → recordings/raw.{webm,mp4} + timeline.json\n   → captions  Whisper word timestamps         → generated/captions.{srt,vtt,cues.json}\n   → compose   trim idle · sync · auto-zoom · cards · caption · mux → output/final-demo.mp4\n```\n\n**4 · What you get** — `output/final-demo.mp4`, plus a README-ready GIF\n(`aidemo gif`) and named stills (`aidemo stills`) from the same take. UI changed?\nRe-run against the same storyboard — no re-recording by hand.\n\nThe design goal: demos that look **human-made and snappy**, not like an AI\nclicking around and waiting between screenshots — by separating **authoring**\n(slow, one-time — figure out the flow) from **recording** (a fast deterministic\nreplay with a smooth animated cursor).\n\n## What teams render with it\n\n- **GitHub README demos** — `aidemo gif demos/onboarding`, drop the autoplaying\n  GIF into the readme (the GIFs on this page are exactly that).\n- **Landing-page hero videos** — the muted-autoplay MP4 on\n  [aidemo.top](https://aidemo.top) is a rendered demo, poster frame and all.\n- **Release / what-shipped demos** — narrate the new feature, then\n  `gh release upload v1.4.0 demos/whats-new/output/final-demo.mp4`.\n- **Customer & prospect demos** — personalized flows against your real app:\n  localhost, auth walls, your own logged-in Chrome; nothing leaves the machine.\n\n## Render in CI (self-maintaining demos)\n\nCommit a storyboard and the **[aidemo GitHub Action](docs/CI.md)** keeps its\ndemo media in sync — a fresh narrated, captioned MP4 (and GIF) on every relevant\nchange. Deterministic replay + a local voice mean **no API key, no LLM tokens,\nabout $0** (just free runner minutes). It's the loop a screen recorder can't\nrun: your demo maintains itself.\n\n```yaml\n# .github/workflows/demo.yml\n- uses: actions/checkout@v4\n- run: sudo apt-get update && sudo apt-get install -y ffmpeg   # ubuntu ships Chrome, not ffmpeg\n- uses: tandryukha/aidemo@stable\n  with:\n    demos: demos/*\n    tts: local        # in-process voice → no keys, no tokens\n    gif: \"true\"\n```\n\nFull recipe, templates (auto-commit / PR-comment / cron-refresh), and the\nalways-fresh-embeds trick: **[docs/CI.md](docs/CI.md)**,\n**[docs/EMBEDS.md](docs/EMBEDS.md)**, **[docs/recipes/](docs/recipes/)**.\n\n## Quick start (self-contained smoke test)\n\nA bundled fixture store (search → results → cart → checkout) that renders a\nfinished demo with zero external dependencies:\n\n```bash\nnpm install                                # Node 20+, system Chrome, ffmpeg on PATH\nnode examples/local-demo/serve.mjs         # terminal 1: fixture on :8787\nnode bin/aidemo.mjs render examples/local-demo --headless   # terminal 2\nopen examples/local-demo/output/final-demo.mp4   # xdg-open on Linux, start on Windows\n```\n\nVoice/captions need `OPENAI_API_KEY` in `.env` — **or** `AIDEMO_TTS_PROVIDER=local`\n(no key, offline), **or** `OPENAI_BASE_URL` at a local server. See\n[docs/LOCAL_MODELS.md](docs/LOCAL_MODELS.md). No Playwright browser download is\nneeded — the engine uses your system Chrome (`channel: \"chrome\"`).\n\n[![Quickstart output — the bundled fixture rendered end-to-end](docs/quickstart.gif)](https://github.com/tandryukha/aidemo/releases/download/v0.3.0/quickstart-demo.mp4)\n\n<sub>The bundled fixture rendered end-to-end — narrated, captioned, auto-trimmed.\nSilent preview; **[full version ▶](https://github.com/tandryukha/aidemo/releases/download/v0.3.0/quickstart-demo.mp4)**.</sub>\n\n## CLI\n\nEach step is independently runnable and re-runnable — regenerate voice without\nre-recording, recompose without re-transcribing, etc.\n\n```bash\naidemo init <name>            # scaffold demos/<name>/ with a starter storyboard\naidemo voice   <dir>          # per-scene TTS → narration.mp3 + voice.json\naidemo record  <dir>          # drive Chrome → raw video + timeline.json\naidemo probe   <dir>          # record-only dry run (verify selectors), no key needed\naidemo captions <dir>         # Whisper → captions.{srt,vtt,cues.json} (--offline for no network)\naidemo compose <dir>          # trim + sync + zoom + cards + caption + mux → final-demo.mp4\naidemo gif     <dir>          # final-demo.mp4 → README-ready GIF (autoplays on GitHub)\naidemo render  <dir>          # voice → record → captions → compose\naidemo guide                  # print the canonical authoring guide\naidemo doctor                 # check Node, ffmpeg, Chrome, voice endpoint\n```\n\nAdd `--headless` for CI/fixtures; omit it for real sites that need your\nlogged-in session. `--profile <dir>` picks the Chrome user-data dir;\n`--capture native|obs` switches to high-fidelity screen capture. `voice`/`render`\n**skip TTS for unchanged scenes**, and `record` **salvages a failed take** (keeps\nthe footage + drops a screenshot/frame-dump in `logs/`).\n\n## Agent interface (MCP)\n\n`aidemo mcp` runs a **stdio** MCP server (no network listener) exposing the engine\nto any MCP client. The Claude Code plugin bundles it; `aidemo repo-init` registers\nit agent-neutrally (`.mcp.json` for Claude Code, `.gemini/settings.json` for\nGemini; `codex mcp add aidemo -- npx -y github:tandryukha/aidemo#stable mcp` for\nCodex).\n\n- **Authoring tools** — `get_authoring_guide` serves\n  [docs/AUTHORING.md](docs/AUTHORING.md) version-matched from the engine (can't go\n  stale); `get_storyboard_schema`, `validate_storyboard`, `init_demo`, `doctor`.\n- **Pipeline tools run as jobs** — `probe`/`record`/`render`/`voice`/`captions`/\n  `compose`/`gif` return a `jobId` immediately; `job_status` reports stage,\n  per-scene progress, and (on failure) the screenshot/frame-dump paths.\n\n## Why it's built this way\n\n- **Deterministic replay, not an LLM in the loop.** The recording runs a fixed\n  action-spec at full speed, so the video is smooth. The agent only *authors* the\n  storyboard (and confirms selectors once), never during capture.\n- **Declarative action-spec + fixed player** (not generated `spec.ts`). Safer,\n  editable, and it emits a **timeline** for free — compose fits each scene's video\n  to its narration by trimming/speeding only the idle parts, freeze-holding a\n  static page for any remainder instead of ugly slow-motion.\n- **Captions via overlaid PNGs, not libass.** Many ffmpeg builds lack\n  `subtitles`/`drawtext`; aidemo rasterizes each caption with headless Chrome and\n  overlays it with time-gated `enable` — works on any ffmpeg with `overlay`.\n- **Cinematic polish is compose-time, not record-time** — a bad zoom is a\n  recompose, never a re-record. See [docs/POLISH.md](docs/POLISH.md).\n\n## Deeper docs\n\n- **[docs/AUTHORING.md](docs/AUTHORING.md)** — the canonical storyboard schema,\n  action vocabulary, and demo-director principles (served by the engine).\n- **[docs/LOCAL_MODELS.md](docs/LOCAL_MODELS.md)** — no-key rendering: in-process\n  Kokoro voice, local speech servers (speaches), ElevenLabs, offline captions.\n- **[docs/POLISH.md](docs/POLISH.md)** — auto-zoom, scroll easing, music ducking,\n  intro/outro cards, motion blur, cursor control, native/OBS high-fidelity capture.\n- **[docs/CHATGPT_APPS.md](docs/CHATGPT_APPS.md)** — recording ChatGPT Apps SDK\n  widgets (dedicated profile, nested iframes, `waitForWidget`).\n- **[docs/CI.md](docs/CI.md)** · **[docs/EMBEDS.md](docs/EMBEDS.md)** · **[docs/recipes/](docs/recipes/)** — CI rendering, always-fresh embeds, agent-in-CI recipes.\n\n## Setup\n\nPrereqs: **Node 20+**, **Google Chrome**, **ffmpeg + ffprobe** on `PATH`.\nDeveloped and tested on macOS; Linux works for the default (Playwright) capture\nand `--capture obs`. Run `aidemo doctor` to check your setup.\n\n```bash\nnpm install\ncp .env.example .env      # add OPENAI_API_KEY, or use AIDEMO_TTS_PROVIDER=local (no key)\n```\n\n## Project layout (per demo)\n\n```\ndemos/<name>/          ← your working area (untracked; scaffold with `aidemo init`)\n  input/      brief.md\n  generated/  storyboard.json  timeline.json  captions.{srt,vtt,cues.json}\n  recordings/ raw.webm (or raw.mp4 for native/OBS capture)\n  audio/      scene-*.mp3  narration.mp3  voice.json\n  output/     final-demo.mp4\n  logs/       <command>.log  fail-<scene>-<n>.{png,json} (on a failed action)\n```\n\n## Security & trust\n\n- **No telemetry, no analytics, no install-time scripts** (`package.json` has no\n  `postinstall`/`preinstall`).\n- **Network is user-initiated only:** `api.openai.com` (only `voice`/`captions`,\n  your key — or a local server via `OPENAI_BASE_URL`), `api.elevenlabs.io` (opt-in),\n  `huggingface.co` (download-only, once, for `AIDEMO_TTS_PROVIDER=local`), and\n  `github.com` (your own `gh`, for `aidemo feedback`). Recording/composing are\n  fully local. The MCP server is **stdio-only** — no listener.\n- **Small, auditable surface:** ~20 source files, 7 runtime deps, MIT. Pin an\n  immutable ref if you're wary of the moving `#stable` tag:\n  `npx -y github:tandryukha/aidemo#v0.8.0`.\n- Full detail: [docs/LOCAL_MODELS.md](docs/LOCAL_MODELS.md#what-leaves-the-machine)\n  · report vulnerabilities privately per [SECURITY.md](SECURITY.md).\n\n## Roadmap\n\n- **Comments on the video** (pause & comment) and **in-place transcript editing**:\n  captions map to scenes, so editing a line marks that scene dirty and\n  `aidemo voice --scene <id>` + `compose` regenerates only the delta.\n- **Web UI**, project history, brand kits, changelog integrations.\n- **Hosted public MCP** (see [docs/plans/public-mcp.md](docs/plans/public-mcp.md)).\n\nShipped: the **GitHub Action** (CI re-render), cinematic polish (auto-zoom,\nscroll easing, music ducking, intro/outro cards, motion blur, post-hoc cursor\ncontrol), native/OBS capture, the agent-neutral **MCP server** + authoring guide,\nElevenLabs and **in-process local voice** providers, and the **Claude Code plugin**.\n\n## Contributing\n\nIssues and PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup, the\nsmoke test, and the DCO sign-off requirement. Recording-session feedback has a fast\npath: `aidemo feedback demos/<name>` pre-fills a structured issue.\n\n## License\n\n[MIT](LICENSE) © Andrii Taran\n",
  "bytes": 16116,
  "sha": "96e9e55be3774ea1563269e98a332e25f7bda00a08a969190b7e7d8b1bc41dca",
  "repo_slug": "tandryukha/aidemo",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_tandryukha_aidemo_2b12b3fb/readme"
}