> ## Documentation Index
> Fetch the complete documentation index at: https://docs.littledemo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo videos in pull requests

Automatically record your app in CI and attach a demo video to every PR.

Every opted-in PR gets a sticky comment with an inline GIF of the feature,
linking to a full video on a shareable page. Reviewers see the change without
checking out the branch.

## Recommended setup

Run this once in the repo:

```bash
littledemo setup --pr-demos --yes
```

The command always tells you what it will create. PR demo automation is opt-in:
plain `littledemo setup --yes` installs the public LittleDemo agent skill and
`AGENTS.md` guidance, but does not create a GitHub workflow.

Add `LITTLEDEMO_API_KEY` as a repo secret. If setup did not write a concrete
project id into the workflow, also add `LITTLEDEMO_PROJECT_ID`.

Commit the generated `.github/workflows/littledemo-pr-demo.yml`. By default it:

- runs on opened, synchronized, reopened, and ready-for-review PRs;
- records same-repo, non-draft PRs only;
- skips fork PRs because they cannot read repo secrets;
- updates one sticky PR comment instead of creating a new comment per push.

## Manual workflow

The core of the generated workflow is:

```yaml
name: LittleDemo PR demo
on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
  workflow_dispatch:

permissions:
  contents: read
  pull-requests: write

jobs:
  demo:
    if: github.event_name == 'workflow_dispatch' || (github.event.pull_request.draft == false && github.event.pull_request.head.repo.full_name == github.repository)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - uses: seangeng/littledemo/action@v1
        with:
          api-key: ${{ secrets.LITTLEDEMO_API_KEY }}
          project-id: ${{ secrets.LITTLEDEMO_PROJECT_ID }}
          start: npm run dev
          wait-on: http://localhost:3000
          url: http://localhost:3000
          prompt: "PR #${{ github.event.number }}: ${{ github.event.pull_request.title }}"
          duration: "10"
```

The action starts your dev server, waits for it, records a scroll tour with the
LittleDemo engine, uploads the result with a thumbnail and GIF attached, uploads the MP4 as a
workflow artifact, and posts one sticky comment that updates in place on every
push — never a comment pile.

## Scripted flows

Point the recording at the thing the PR actually changed with a checked-in
steps file:

```yaml
        with:
          steps-file: .github/demo-steps.json
```

```json
{
  "steps": [
    { "action": "click", "text": "Settings" },
    { "action": "click", "text": "Billing" },
    { "action": "pause", "ms": 1500 }
  ]
}
```

See [Local recording](/cli/record) for the full step schema.

## Recording preview deployments

If your repo already deploys previews (Vercel, Netlify, or similar), skip booting
the app in CI and record the preview URL when the deployment goes live:

```yaml
on:
  deployment_status:

jobs:
  demo:
    if: github.event.deployment_status.state == 'success'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: seangeng/littledemo/action@v1
        with:
          api-key: ${{ secrets.LITTLEDEMO_API_KEY }}
          project-id: ${{ secrets.LITTLEDEMO_PROJECT_ID }}
          url: ${{ github.event.deployment_status.environment_url }}
          prompt: "Preview: ${{ github.event.deployment.ref }}"
```

`deployment_status` events carry no PR context, so the action finds the PR from
the commit automatically (or takes an explicit `pr-number` input).

## Fork PRs

Forks can't read repo secrets. The setup-generated workflow skips fork PRs
before checkout so untrusted PR code cannot run with secrets. If you call the
Action directly and `api-key` or `project-id` is empty, the Action emits a notice
and exits green with the `skipped` output set to `true`, so required checks don't
block community PRs.

## Without the action

The same flow is two CLI commands, usable in any CI system:

```bash
npx --yes @littledemo/cli record http://localhost:3000 \
  --upload --project "$LITTLEDEMO_PROJECT_ID" \
  --prompt "PR demo" --yes --json > result.json

gh pr comment "$PR_NUMBER" --body "[![Demo]($(jq -r .gifUrl result.json))]($(jq -r .shareUrl result.json))"
```

GitHub strips iframes and has no video-embed API for comments, so an inline GIF
linking to the share page is the ceiling — the GIF renders inline as long as it
stays under GitHub's ~10 MB budget (the engine encodes at 640px/12fps to fit).