en un clic
vhs-demo
// Use when running demo recordings, diagnosing recording failures, or regenerating GIFs from existing MP4s. Covers the Docker + VHS + ffmpeg pipeline.
// Use when running demo recordings, diagnosing recording failures, or regenerating GIFs from existing MP4s. Covers the Docker + VHS + ffmpeg pipeline.
Complete YAML schema reference for File and FileSet resources. Use when writing manifests to manage files (CODEOWNERS, LICENSE, CI workflows, etc.) in one or more repositories, including templating, patches, reconcile modes, delivery method, and import-into behavior.
Complete YAML schema reference for Repository and RepositorySet resources. Use when writing or editing manifests for repo settings, labels, actions, branch protection, rulesets, secrets, variables, or repository defaults.
CI/CD integration patterns for gh-infra: auto-apply on merge, scheduled drift detection, self-managed vs central-management layouts, and authentication setup for GitHub Actions workflows.
Overview of gh-infra and command workflow (import, validate, plan, apply). Use when managing GitHub repository settings, labels, actions settings, rulesets, secrets, variables, or files declaratively via YAML manifests.
Use when pulling live GitHub state back into existing gh-infra manifests with `gh infra import --into`, especially for write/patch/skip decisions, shared file sources, template-backed files, and import safety rules.
Use when creating new VHS demo tapes or editing existing ones. Covers tape syntax, setup scripts, mock-gh data layout, and the checklist for adding a new demo end-to-end.
| name | vhs-demo |
| description | Use when running demo recordings, diagnosing recording failures, or regenerating GIFs from existing MP4s. Covers the Docker + VHS + ffmpeg pipeline. |
Use this skill to run, debug, or regenerate gh-infra demo GIF recordings.
make demo or docs/tapes/vhs.sh directlymake demo
1. go build -o docs/tapes/.gh-infra (GOOS=linux GOARCH=amd64)
2. docs/tapes/vhs.sh
a. docker build → gh-infra-vhs image (VHS + vim)
b. For each *.tape in parallel:
docker run --memory=1g --cpus=2 → produces .mp4
c. For each .mp4 sequentially:
docker run jrottenberg/ffmpeg:7-alpine → produces .gif
3. Copy GIFs to docs/public/
4. Clean up .gh-infra binary
VHS's built-in GIF output is unreliable when multiple containers run in parallel on macOS. The workaround is to output MP4 only from VHS, then convert to GIF via ffmpeg with high-quality settings (lanczos scaling, sierra2_4a dithering, 256 colors).
| File | Role |
|---|---|
docs/tapes/vhs.sh | Orchestrator: parallel recording + sequential GIF conversion |
docs/tapes/Dockerfile | ghcr.io/charmbracelet/vhs + vim |
docs/tapes/*.tape | VHS scenario files |
docs/tapes/setup*.sh | Per-demo setup scripts (mock data, gh wrapper) |
docs/tapes/mock-gh | Generic mock for gh CLI |
docs/tapes/.gh-infra | Cross-compiled Linux binary (ephemeral) |
docs/tapes/*.mp4 and docs/tapes/*.gifdocs/public/demo*.gif (copied by Makefile)make demo forwards DEMO_ENV variables into Docker via -e flags. Use this to pass environment overrides (e.g. GH_INFRA_OUTPUT) into the recording containers.
All tapes run in parallel. Each container requests --memory and --cpus (see vhs.sh). The total resource demand is:
total memory = number_of_tapes × per-container memory
total CPUs = number_of_tapes × per-container CPUs
For example, 6 tapes × --memory=2g --cpus=2 = 12 GB / 12 CPUs.
This is constrained by Docker Desktop's resource allocation, not host RAM. Docker Desktop defaults are often low (e.g. 7.6 GB on a 24 GB machine). If total demand exceeds Docker Desktop's allocation, containers will OOM or produce 0-byte outputs.
Adding a tape increases parallel resource demand. Before adding, check:
ls docs/tapes/*.tape | wc -lcount × per-container memoryIf the total exceeds Docker Desktop's limit, you have two options:
--memory in vhs.sh. This is a last resort since it may cause recording failures for complex tapes.For comfortable parallel recording of 6+ tapes:
| Setting | Recommended |
|---|---|
| Memory | 16 GB (minimum: number_of_tapes × 2 GB) |
| CPUs | 8+ |
| Symptom | Cause | Fix |
|---|---|---|
| 0-byte GIF | MP4 was also 0-byte or missing | Check the tape's setup script and mock data |
| 0-byte MP4 | VHS crashed or setup script failed | Run the single tape manually: docker run --rm -v docs/tapes:/data -w /data gh-infra-vhs <name>.tape |
gh-infra: not found in recording | Binary not copied or wrong arch | Verify GOOS=linux GOARCH=amd64 go build succeeded |
| Docker OOM | Container hit memory limit | Check Docker Desktop memory allocation (see Resource Planning above) |
| Multiple tapes fail simultaneously | Docker Desktop memory too low for parallel count | Increase Docker Desktop memory or reduce tape count |
| "Docker is not running" | Docker daemon not started | Start Docker Desktop or dockerd |
To re-convert existing MP4s without re-recording, run the ffmpeg step manually:
docker run --rm -v docs/tapes:/data -w /data jrottenberg/ffmpeg:7-alpine \
-y -i <name>.mp4 \
-vf "fps=10,scale=1200:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=256[p];[s1][p]paletteuse=dither=sierra2_4a" \
<name>.gif