From rn-dev-agent
This skill should be used when the user asks to "capture proof", "record a demo of this feature", "make a video showing it works", "record the flow for the PR", "generate a PR body", "capture screenshots for the PR", "proof-capture", or when a verified feature needs PR-ready proof artifacts (video + numbered screenshots + PROOF.md + PR-BODY.md). Also loaded by /rn-dev-agent:proof-capture and by rn-feature-dev Phase 8.
How this skill is triggered — by the user, by Claude, or both
Slash command
/rn-dev-agent:capturing-proofThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Produce a permanent proof artifact set for a verified feature:
Produce a permanent proof artifact set for a verified feature:
docs/proof/<feature-slug>/ containing a labeled video, numbered screenshots,
PROOF.md, PR-BODY.md, and the rehearsed flow persisted as a replayable
action.
Core principle. Discovery happens before the camera rolls. The video is the replay of a known-good action — never the LLM working out testIDs or navigation paths on screen. If you would not show the rehearsal pass to a reviewer, do not record it.
maestro_run (deterministic, hesitation-free)Establish <feature-slug> (from the command argument, or derive a kebab-case
slug from the feature). If ambiguous, ask the user.
mkdir -p docs/proof/<feature-slug>
Call cdp_status to confirm the app is running and CDP is connected.
Pre-recording readiness check (GH #8, #9):
cdp_status — this auto-detects and auto-dismisses the Dev Client
server picker if a device session is open (GH #9). If cdp_status
returns a warning about the picker, call it again after a few seconds.cdp_navigation_state — verify it returns a valid route name
(not empty, not "DevClientLauncher", not "ServerPicker"). If still stuck,
ask the user to select the Metro server manually.cdp_dev_settings(action="disableDevMenu") — suppress the shake-to-show
dev menu so it doesn't pop up during recording and ruin the video.Do NOT start recording yet. First, walk the described flow once with no video so you can discover testIDs, navigation paths, and state shapes without the camera capturing the search.
Protocol:
device_* / cdp_* calls. If no flow
description was supplied, ask the user to describe the steps before
continuing.<test-app>/.rn-agent/actions/<slug>.yaml (<test-app> = the RN
project's root). Two authoring paths:
maestro_generate(name="<slug>", steps=[...], appId="...") — writes
the YAML from structured steps; does NOT emit the M7 metadata header.cdp_record_test_generate(format="maestro") — converts the recorder
buffer to YAML text; M7 fields are not forwarded by the MCP tool
schema, so the header is not auto-populated.
In both paths, the agent MUST then PREPEND the 5-key M7 metadata header
by hand (id, intent, tags, mutates, status) — see the
creating-actions skill for the full authoring contract (header
validation, replay-to-promote).mutates: true).cdp_run_action({actionId: "<slug>", params: {KEY: "VALUE"}}) — it
records a RunRecord and a clean pass auto-promotes the action
experimental → active. params covers ${VAR} placeholders
(forwarded as -e KEY=VALUE); plain maestro_run(flowPath=..., params={...}) or the maestro-runner CLI are equivalent replays
without the telemetry. The replay must pass end-to-end without a
single failure.cdp_navigation_state /
cdp_store_state — do NOT loop indefinitely.Hard gate. If step 5 fails, fix the flow and repeat (max 3 attempts). Do not move to Step 3 (start recording) until the replay is clean OR the inexpressibility carve-out below has been documented.
Maestro-inexpressibility carve-out. If the flow genuinely cannot be
expressed in Maestro (custom gestures, native-module side-effects,
Reanimated proof captures via cdp_set_shared_value, JS-introspection
mid-flow), document the specific Maestro primitive that is missing in
PROOF.md "Deviations" and proceed to Step 3 — the rehearsal walk via
device_* / cdp_* becomes the artifact. Choosing the fallback without
naming the inexpressibility is a Red Flag — keep trying to express the
flow until you can name what's missing.
After the rehearsal flow has replayed clean, reset the app to the starting screen one more time, then start recording:
# iOS
rn-record-proof start ios docs/proof/<slug>/flow-ios.mp4
# Android
rn-record-proof start android docs/proof/<slug>/flow-android.mp4
If recording fails to start, warn but continue — screenshots are the primary artifact.
Preferred path: with recording running, invoke the Maestro flow generated in Step 2.5.
maestro_run(flowPath="<test-app>/.rn-agent/actions/<slug>.yaml", params={KEY: "VALUE"})
params covers ${VAR} placeholders (forwarded to maestro as -e KEY=VALUE;
keys match [A-Z_][A-Z0-9_]*). Omit it for env-free flows. The
maestro-runner CLI with -e flags is an equivalent Bash path. Use
maestro_run (not cdp_run_action) ON camera — auto-repair mid-recording
would mutate the flow on camera.
While the flow runs, take numbered screenshots at meaningful state changes:
device_screenshot(path="docs/proof/<slug>/<NN-stepname>.jpg")
For each screenshot, verify the expected state via cdp_component_tree,
cdp_store_state, or cdp_navigation_state.
Fallback (only if Maestro cannot express the flow): execute the
rehearsed sequence step-by-step using the same device_* / cdp_* calls
you confirmed in Step 2.5. Every action must be one you already executed
cleanly during rehearsal — do NOT debug, navigate randomly, or "explore"
on camera.
If a step fails on camera: stop recording, rebase the app state, redo Step 2.5. A failure here means the flow drifted between rehearsal and recording — that's a flow bug, not a feature bug. Do not "fix it on camera."
rn-record-proof stop
Attempt GIF conversion:
rn-record-proof convert-gif docs/proof/<slug>/flow-ios.mp4 docs/proof/<slug>/flow-ios.gif
Add timed step labels to the recorded video. Build a JSON array mapping each step to a time range, then call the label subcommand:
rn-record-proof label \
docs/proof/<slug>/flow-ios.mp4 \
docs/proof/<slug>/flow-ios-labeled.mp4 \
'[{"start":0,"end":5,"text":"Step 1: <description>"},{"start":5,"end":12,"text":"Step 2: <description>"}]'
How to estimate time ranges: The recording starts at Step 3 (start recording) and each interaction step takes ~3-8 seconds including the settle wait. Use the step execution order and count ~5s per step as a rough guide. The labels don't need frame-perfect timing — they just need to be close enough that the viewer understands what's happening.
If record_proof.sh label fails (missing ffmpeg or Pillow), warn but continue —
the raw video is still usable, labels are a nice-to-have.
The labeled video replaces the raw video as the primary artifact in PROOF.md.
Before presenting the video to the user, you MUST verify it captured the expected feature. This prevents wasting time on recordings that show the wrong screen, a blank simulator, or an error state.
Validation checklist:
Video file exists and has reasonable size (> 10KB for a real recording):
ls -la docs/proof/<slug>/flow-*.mp4 2>/dev/null
Final screenshot shows the expected end state — take a screenshot
after stopping the recording and verify via cdp_component_tree or
cdp_navigation_state that the app is on the expected screen with the
expected data.
No errors occurred during recording — call cdp_error_log and
verify no new errors appeared during the flow.
Screenshots match the flow description — review each numbered screenshot file exists and has non-zero size.
If validation fails:
Create docs/proof/<slug>/PROOF.md with the standard format:
rn-generate-pr-body docs/proof/<slug>/
Show the user:
cdp_navigation_state
and cdp_store_state snapshots.cdp_error_log clean, every
numbered screenshot non-zero). Report invalid proof — never present it as
complete.device_* on-camera fallback without naming the missing
Maestro primitive in PROOF.md "Deviations"cdp_run_action ON camera (auto-repair may mutate the flow mid-take)brew install ffmpeg)npx claudepluginhub lykhoyda/rn-dev-agent --plugin rn-dev-agentGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.