Best for
- "Record a video of " / "take a screen recording" / "make a demo"
- "Show off and send it to me on Slack"
- Any time the deliverable is a video walkthrough of a live web UI.
kirodotdev/KiroCrew/src/kiro_crew/apps/builtins/dev_fleet/skills/feature-demo-recording/SKILL.md
Record a polished headless-browser demo video of a web feature (mouse-follow cursor, caption cards, scene script) and deliver it to Slack. Use when the user asks to "record a video / demo / screen recording" of a feature, dashboard, or web UI flow.
Decision brief
Produce a polished, narrated, Screen-Studio-style recording of a web feature using headless Playwright — an injected cursor that follows the real mouse, click ripples, premium caption cards, and an automatic spring-eased zoom (punch-in) on every click plus dead-air trimming — th…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Declared | Source record | Install path and trigger |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/kirodotdev/KiroCrew --skill "src/kiro_crew/apps/builtins/dev_fleet/skills/feature-demo-recording"Inspect the Agent Skill "feature-demo-recording" from https://github.com/kirodotdev/KiroCrew/blob/5bcf51037a10a420d51a290b505245a3e6f0b1ee/src/kiro_crew/apps/builtins/dev_fleet/skills/feature-demo-recording/SKILL.md at commit 5bcf51037a10a420d51a290b505245a3e6f0b1ee. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Run the setup helper. It creates /.kiro/crew/workspace/.demo-recording-venv with Playwright, and reuses the already-installed browsers in /.cache/ms-playwright/ (they are typically already present from prior Playwright usage, so this is usually instant).
Copy references/recordtemplate.py to your working dir (e.g. /.kiro/crew/workspace/uploads/-video/record.py) and fill in the SCENES.
The recording navigates to the real dashboard, so it needs a valid token.
KCDEMOREFS points back at the skill's references/ directory so the copied record.py can import demoharness (the support modules stay in the skill bundle).
One command turns the raw webm + events.json into the cinematic cut:
Permission review
The documentation asks the agent to run terminal commands or scripts.
RECORD — run the script headless → webm + events.json (cursor/captions/video + event log)The documentation asks the agent to run terminal commands or scripts.
bash <app-skills-dir>/feature-demo-recording/references/setup.shThe documentation asks the agent to create, modify, or delete local files.
Write the URL to a sidecar file the recorder reads, so the JWT never appears inline in aEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 88/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 1,286 | Source | Repository attention, not individual Skill quality |
| Compatibility | 1 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Produce a polished, narrated, Screen-Studio-style recording of a web feature using headless Playwright — an injected cursor that follows the real mouse, click ripples, premium caption cards, and an automatic spring-eased zoom (punch-in) on every click plus dead-air trimming — then transcode to mp4 and (optionally) send it to Slack.
This skill is the distilled, reusable version of the Session Grid demo. The hard parts
(cursor overlay that survives navigation, caption styling, picking the right webm, auth, the
"don't shoot Chinese/PII into the frame" rule, auto-zoom camera + spring easing + dead-air
trim) are already solved in references/. You write a thin scene script; the harness records
an event log, and a pure-Python post-processor turns it into the cinematic cut.
The auto-zoom/easing/trim technique is ported from the open-source
preston176/screen-demo-skill (Playwright +
Remotion), but re-implemented fully local in Python (Pillow + imageio-ffmpeg) — no Node,
no Remotion, no Steel cloud browser, so internal dashboards never leave the machine.
Not for: static screenshots (just use browser_take_screenshot), or recording a native
desktop/terminal app (this is browser-only).
1. SETUP — one-time: venv with Playwright + Chromium + Pillow + h264 ffmpeg (references/setup.sh)
2. SCRIPT — write scenes: a list of (caption, action) using the harness API
3. AUTH — get a fresh tokenized dashboard URL (kirocrew token, or ask the user)
4. RECORD — run the script headless → webm + events.json (cursor/captions/video + event log)
5. POLISH — render.sh: auto-zoom (spring punch-in on clicks) + dead-air trim → demo.mp4
6. SHIP — file_send the mp4 to Slack (or hand back the path)
Track these as todos if the request is non-trivial — RECORD often needs 2-3 iterations to get selectors right, and you don't want to lose the POLISH/SHIP steps.
Two-layer design: RECORD produces the raw webm and an events.json (every click's
timestamp + on-screen focal point + element size; every caption's span). POLISH replays that log
to drive the camera — so the cinematic part is deterministic, re-runnable, and tunable without
re-recording.
Demo work decomposes cleanly into independent pieces. Default to spawning subagents for
anything that can run on its own; reserve the main thread for orchestration, the live
token-bearing recording, and final judgment. Spawn with spawn_sub_agents
(blocks, returns results — best when you need the output to continue) or
spawn_run with a tasks array (fire-and-wait for completion events).
Where subagents help most (run these in parallel):
aria-label/title/text for each control you
need to target. Selector misses are the #1 cause of re-records — scout them first.record.py against this SKILL's scene-design rules and flag:
English-only captions? PII/real-data risk in any scene? preconditions seeded before dependent
actions? selectors as ordered lists? captions short enough? It returns a checklist; you fix
before recording. Cheaper than discovering issues in the webm.preston176/screen-demo-skill) in parallel with implementation.Division of labor, concretely:
| Stage | Main thread | Subagents (parallel) |
|---|---|---|
| SCRIPT | merge + own the final record.py | draft scenes; scout selectors |
| REVIEW | apply fixes | adversarial scene-script review |
| RECORD | run it (holds the live token) | — (single, stateful, token-bearing) |
| POLISH | run render.sh, pick params | — (fast, local) |
| VERIFY | decide pass/fail | sample frames, check zoom/occlusion/PII |
| SHIP | file_send | draft the Slack message text |
Keep on the main thread: the actual RECORD run (it holds the short-lived token and is a single stateful browser session — don't fan that out), and any step that uses the credential. Hand subagents read-only or compute-only work; never pass a live token into a subagent prompt.
Run the setup helper. It creates ~/.kiro/crew/workspace/.demo-recording-venv with Playwright,
and reuses the already-installed browsers in ~/.cache/ms-playwright/ (they are typically
already present from prior Playwright usage, so this is usually instant).
bash <app-skills-dir>/feature-demo-recording/references/setup.sh
It prints the venv's python path and the bundled ffmpeg path. If the venv already exists it's a
no-op. See references/setup.sh for what it checks.
ffmpeg: Playwright bundles one at ~/.cache/ms-playwright/ffmpeg-*/ffmpeg-linux. The setup
script finds it and writes the path to .demo-recording-venv/FFMPEG_PATH. No separate install.
Copy references/record_template.py to your working dir (e.g.
~/.kiro/crew/workspace/uploads/<feature>-video/record.py) and fill in the SCENES.
The harness gives you a Demo object with these methods (full reference:
references/demo_harness.py docstrings):
| Method | What it does |
|---|---|
d.caption(eyebrow, title, sub="", secs=3) | Show a caption card, hold secs. Captions are the narration. |
d.cap_hide() | Hide the current caption (before an action you want unobstructed) |
d.click(selectors, label="") | Glide the cursor to the first visible match and click. selectors = list, tried in order |
d.click_side(selectors, side, label) | Click the left-most / right-most match (for distinct panes/columns) |
d.type(text, delay=35) | Type into the focused element (with the cursor parked there) |
d.press(key) | Keyboard press, e.g. "Enter", "Meta+d" |
d.focus_composer() | Click the first visible textarea / contenteditable |
d.wait(ms) | Plain wait |
d.shot(name) | Debug screenshot -> debug-<name>.png (use liberally while iterating) |
d.goto_nav(text) | Click a top-nav item by exact text (e.g. "Schedule", then "Chat") |
A scene is just calls in sequence. Example (one scene):
d.caption("01 - Split", "Split a chat",
"Press Cmd+D, then pick another session to view them side-by-side.", secs=3)
d.click(['[aria-label="Enter split view"]', '[title*="Split view" i]'], label="enter split")
d.wait(1500)
d.shot("split-opened")
The harness automatically:
localStorage (kc-onboarded=1) so the theme modal never appears,events.json,MAIN_WEBM: <path>, and writes events.json.You don't call any zoom API in your scenes — just d.click(...) and d.caption(...) as usual.
The POLISH step reads events.json and adds the punch-in zooms automatically.
extra_init_css for (c) — see template. Prefer creating fresh demo state over hiding.aria-label, then title, then
visible text (button:has-text("...")). Always d.shot() after a click while iterating so you
can see what actually happened.secs (pass keep=True to hold it) so the
following click/zoom plays unobstructed. Keep captions short — long sub text spans more of
the frame.The recording navigates to the real dashboard, so it needs a valid token.
Preferred: kirocrew token (TTL 20h) -> gives http://localhost:5476?token=....
If kirocrew token is permission-blocked for you (it has been, in agent contexts),
ask the user to paste a fresh tokenized URL. Do not block on it silently.
Write the URL to a sidecar file the recorder reads, so the JWT never appears inline in a command (inline JWTs can trip secret filters):
printf '%s' "<TOKENIZED_URL>" > <workdir>/.tokenurl
The template reads KC_URL env or argv[1]; pass it via the file + a tiny wrapper, or export
KC_URL="$(cat <workdir>/.tokenurl)" just before running.
Tokens expire. If a run dies with "no composer / 403", the token is stale — get a fresh one.
cd <workdir>
KC_DEMO_REFS="<app-skills-dir>/feature-demo-recording/references" \
KC_URL="$(cat .tokenurl)" "$(cat ~/.kiro/crew/workspace/.demo-recording-venv/PY_PATH)" record.py
KC_DEMO_REFS points back at the skill's references/ directory so the copied
record.py can import demo_harness (the support modules stay in the skill bundle).
Watch run.log / stdout. The harness prints each click with coordinates and a final
MAIN_WEBM: <path> + EVENTS: <n>. If selectors miss (!! none visible for ...), fix the
selector list and re-run — recording is cheap and idempotent (each run writes a new webm and
overwrites events.json).
Iterate against screenshots. The debug PNGs are your eyes; open the ones around a failing scene before changing selectors.
One command turns the raw webm + events.json into the cinematic cut:
bash <app-skills-dir>/feature-demo-recording/references/render.sh \
<workdir> <workdir>/<feature>-demo.mp4 --out-fps 30 --dead-air-speed 6
render.sh chains two pure-Python stages (no Node/Remotion/cloud):
camera.py — reads events.json, emits zoom keyframes. Each click -> a punch-in target:
focal = the click point; zoom = min(max_zoom, max(1.0, 0.30 / target_frac)) so smaller
targets zoom in more (capped at --max-zoom, default 1.6). Caption spans become full-speed,
no-zoom windows.postprocess.py — replays frames, applies a spring-eased (Remotion config:
damping=200, stiffness=100, mass=1, overshootClamping -> smooth, no overshoot; 18-frame
transition) zoom/pan around each focal point (wide -> punch-in -> hold -> punch-out), and
time-compresses dead air between click/caption windows by --dead-air-speedx (real cut —
screen-demo-skill's trim only reported dead air; ours actually removes it). Re-encodes h264.Tunables: --max-zoom (1.6), --lead-ms (280, how early the zoom starts before a click),
--hold-ms (1400, how long it stays zoomed after), --transition-frames (18, easing length),
--dead-air-speed (6), --speed (overall playback speedup), --out-fps (30).
The camera is driven entirely by the event log, so you can re-tune the look without
re-recording — just re-run render.sh with different flags against the same webm.
Captions are composited during recording (burned in), but the post-processor keeps caption spans at full speed and zoom=1.0, so they're never sped-up-unreadable or cropped by a zoom.
render.sh already produced an h264 mp4 (yuv420p + faststart — plays everywhere). If you want a
plain transcode without the auto-zoom (rarely), use the h264 ffmpeg directly:
FF="$(cat ~/.kiro/crew/workspace/.demo-recording-venv/FFMPEG_PATH)"
WEBM="$(cat <workdir>/MAIN_WEBM)"
"$FF" -y -i "$WEBM" -vf "scale=1280:-2" -c:v libx264 -pix_fmt yuv420p -crf 23 \
-movflags +faststart <workdir>/<feature>-plain.mp4
Warning: ffmpeg must have libx264. The ffmpeg Playwright bundles is a stripped webm/vp8-only build with no libx264 and no mp4 muxer — it errors with
Unrecognized option 'movflags'.setup.shinstallsimageio-ffmpeg(a full static build) and writes its path toFFMPEG_PATH, so use that.postprocess.pyuses it automatically via imageio.
Warning: Pick the webm by the
MAIN_WEBM:the recorder just printed — NOT "the largest .webm in the dir." A past delivery shipped a stale video because an older, larger webm from a previous run was still sitting in the folder. The harness selects by mtime >= run-start and writes the path to<workdir>/MAIN_WEBM;render.shreads that. Verify the mp4's duration/size changed from the last run before sending.
Then deliver. To DM the user on Slack, use the file_send MCP tool with the mp4 path and a one-line caption.
If Slack delivery isn't requested, just report the local mp4 path.
references/session_grid_scenes.py is the complete, working 6-scene Session Grid script
(split -> fork -> 2x2 grid -> persist -> close -> live-sync). Read it to see real selectors, the
fork precondition fix, and caption phrasing. Adapt it scene-by-scene for a new feature.
references/setup.sh — make/verify the venv (Playwright + Pillow + numpy + imageio + h264 ffmpeg)references/demo_harness.py — the Demo class (cursor/caption/video/webm-picker + event log). Don't edit per-demo.references/record_template.py — copy this, fill in SCENES, run it (RECORD)references/session_grid_scenes.py — the full Session Grid demo as a reference implementationreferences/camera.py — event log -> auto-zoom keyframes (POLISH stage 1)references/spring.py — overdamped spring easing (ported from Remotion's spring())references/postprocess.py — spring zoom/pan + dead-air trim -> h264 mp4 (POLISH stage 2)references/render.sh — one-shot driver: camera.py -> postprocess.pyrecord.py --> page@*.webm + events.json (RECORD: harness)
|
render.sh --> camera.py (events.json -> camera.json: zoom keyframes)
|
postprocess.py (webm + camera.json -> demo.mp4: spring zoom/pan + dead-air trim)
|
file_send --> Slack (SHIP)
Alternatives
PramodDutta/qaskills
Generate optimized test combinations using pairwise (all-pairs) testing algorithms to achieve maximum coverage with minimum test cases across multiple input parameters
PramodDutta/qaskills
Automatically generate comprehensive test cases from user stories and acceptance criteria using BDD patterns, equivalence partitioning, and risk-based prioritization
majiayu000/spellbook
Diagnose slow or freezing VS Code-compatible editors with evidence-first, zero-hardcoded-assumption workflow. Use when the user reports editor lag, typing delay, UI freezes, extension host stalls, file watcher noise, high editor CPU/RSS, uses VS Code/Cursor as a file browser over a large folder, or wants a safe editor performance audit.
aAAaqwq/AGI-Super-Team
REST API design patterns including resource naming, status codes, pagination, filtering, error responses, versioning, and rate limiting for production APIs.