Use when creating demo GIFs for Swift package READMEs, recording iOS simulator videos, or setting up demo apps for SwiftUI libraries
83
—
Does it follow best practices?
Impact
65%
1.44xAverage score across 3 eval scenarios
Passed
No known issues
Record and optimize demo GIFs for Swift package READMEs. Swift packages need a separate demo app since SwiftUI previews only run in Xcode Canvas, not the iOS Simulator.
digraph demo_flow {
"SwiftUI Preview" [shape=box];
"iOS Simulator" [shape=box];
"Xcode Canvas only" [shape=box, style=filled, fillcolor=lightyellow];
"Recordable with xcrun" [shape=box, style=filled, fillcolor=lightgreen];
"SwiftUI Preview" -> "Xcode Canvas only" [label="runs in"];
"Demo App" -> "iOS Simulator" [label="runs in"];
"iOS Simulator" -> "Recordable with xcrun";
}SwiftUI #Preview macros CANNOT be recorded. You must create a demo app.
| Step | Command/Action |
|---|---|
| Create demo dir | mkdir -p demo |
| Boot simulator | xcrun simctl boot "iPhone SE (3rd generation)" |
| Open simulator | open -a Simulator |
| Record video | xcrun simctl io booted recordVideo --codec=h264 demo/raw.mov |
| Stop recording | Ctrl+C |
| Convert to GIF | See FFmpeg command below |
| Optimize GIF | gifsicle -O3 --lossy=80 demo/out.gif -o demo/out.gif |
Create demo/DemoApp/ with Xcode project that imports your package locally:
demo/DemoApp/Critical: Use local package reference, not remote URL, to test current development code.
# Boot simulator (smaller = smaller GIF)
xcrun simctl boot "iPhone SE (3rd generation)"
open -a Simulator
# Run demo app in Xcode (Cmd+R), then record
xcrun simctl io booted recordVideo --codec=h264 demo/raw.mov
# Ctrl+C to stopREQUIRED: Before converting .mov files to GIF, you MUST ask the user using AskUserQuestion:
Question: "How should the GIF be sized?"
Options:
- Full size (keep entire screen including status bar)
- Cropped (remove status bar and bottom navigation)Do NOT assume cropping. Do NOT convert without asking first.
ffmpeg -i demo/raw.mov -filter_complex \
"[0:v] fps=12,scale=300:-1:flags=lanczos,split [a][b]; \
[a] palettegen=max_colors=128:stats_mode=diff [p]; \
[b][p] paletteuse=dither=floyd_steinberg:diff_mode=rectangle" \
-y demo/output.gif
gifsicle -O3 --lossy=80 demo/output.gif -o demo/output.gifffmpeg -i demo/raw.mov -filter_complex \
"[0:v] crop=in_w:in_h*0.55:0:in_h*0.12,fps=12,scale=300:-1:flags=lanczos,split [a][b]; \
[a] palettegen=max_colors=128:stats_mode=diff [p]; \
[b][p] paletteuse=dither=floyd_steinberg:diff_mode=rectangle" \
-y demo/output.gif
gifsicle -O3 --lossy=80 demo/output.gif -o demo/output.gifCrop parameters: crop=in_w:in_h*0.55:0:in_h*0.12 keeps 55% height starting at 12% from top.
<p align="center">
<img src="demo/demo1.gif" width="280" alt="Demo 1"> <img src="demo/demo2.gif" width="280" alt="Demo 2">
</p>Side-by-side: Use between images, width 240-280px each.
# Demo - ignore everything except GIFs
demo/*
!demo/*.gif| Mistake | Fix |
|---|---|
| Converting without asking about sizing | Always ask user: full size or cropped? |
| Trying to record SwiftUI previews | Create demo app, run in simulator |
| "No devices booted" error | Run xcrun simctl boot "iPhone SE (3rd generation)" first |
| Demo app uses remote package | Use Add Local package reference |
| API mismatch after package changes | Xcode → File → Packages → Reset Package Caches |
| GIFs too large (>1MB) | Reduce fps (12), scale (300px), use gifsicle |
| Recording before app runs | Run app in Xcode (Cmd+R) first, THEN start recording |
| Type | Width | FPS | Target Size |
|---|---|---|---|
| Hero demo | 280-300px | 12 | < 200KB |
| Feature demo | 240px | 10-12 | < 150KB |
af7cba7
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.