Skip to content
cccskills
FreePublished on GitHubEnglish overview

mobile-demo-record

Run a mobile app in an iOS simulator with the local services, automate a user journey with Maestro, and capture screen recordings or screenshots. Useful for demonstrating real app behavior and checking mobile changes through the visible interface.

OriginalShow the original description

Run apps/mobile on the iOS simulator against the local stack, drive it with Maestro, and capture clean screen recordings. Use when asked to record, film, screenshot, or demo the mobile app, or to verify a mobile change in the real app.

ParadevAI/Paradev15,720 stars(GitHub 15,720 + cccskills 0)
Works withAWS

Run score Not tested

See how to install

Good for

  • Recording a mobile app demo
  • Capturing screenshots of app screens
  • Replaying a user journey in the simulator
  • Checking a mobile change in the running app

Overview

What it does

This skill runs apps/mobile in an iOS simulator connected to local APIs and other services. It uses Maestro flows to operate the app and capture screen recordings or screenshots. The workflow uses real app state and prepares the data needed for a demo story before recording. Before a take, it can adjust the simulator display and status bar; afterward, it can convert video to a consistent frame rate for easier editing. It also includes steps for cleaning up the data, services, and simulator settings used for the recording.

When it helps

Use it to share real app interactions as a short video or image, or to operate the app in a simulator and check a change. It can also help repeat the same demo steps across recordings.

Example requests

  • “Record a demo of using this app.”
  • “Take a screenshot of this screen.”
  • “Use Maestro to check the changed screen.”

Notes

The workflow uses an iOS simulator, Xcode’s simctl, Maestro, Java, and FFmpeg. Depending on what the recording shows, local services such as an API or database may also need to be prepared. Check that recordings do not show real data. Data and settings created for recording are removed or restored afterward.

This overview was written by AI (OpenAI Codex) from the public SKILL.md. Check the original below for the exact behavior.

Document check

AI checked the SKILL.md for operations that need care and for setup requirements. The score comes only from actually running the skill (hands-on test).

SafetyAre sending data, deleting files, and running commands disclosed?
AGoodIt requires checking for real data in frames and cleaning up recording data and settings.
Easy setupDoes it need few tools or API keys, and are they documented?
BPartly lackingIt requires several tools and local services, with setup details only partly provided.

Not counted in the score. Rated by AI (OpenAI Codex) as of Oct 29, 2026. Treat it as a guide and read the original before installing.

Disagree? Request a re-evaluation

Tell us which point is wrong and why. No login needed. We will check it against the SKILL.md, redo the evaluation, and show the result here.

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

Files included (1)

  • SKILL.md8.7 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Recording the mobile app

There is no CDP for mobile. The equivalent is the iOS simulator, booted headless, driven by Maestro, recorded with simctl. Nothing here opens a window on the user's display.

Rules

  1. Real app state only. Record real sessions, real pull requests, real pages. No mockups, no DOM-style fakery. Seed the data the story needs, then delete it.
  2. No real data in frame. Use the dev account (admin@local.test) and a demo org with demo projects. Read every frame of the contact sheet for names, emails, repo names, and tokens before sharing anything.
  3. One take per story. A host that has connected once is no longer "never connected", a read page is no longer unread. Reset or reseed state before each take.
  4. Report what you recorded against: worktree, API port, simulator UDID, app build date.

Stack

Start each in its own Paradev terminal (superset terminals create --local --workspace $SUPERSET_WORKSPACE_ID --command "..."; without --local the call silently returns nothing). Ports come from .superset/ports.json and the root .env.

ServiceCommandTrap
APIcd apps/api && bun run devA 500 "password authentication failed" means the worktree's Neon branch was cleaned up. Recreate it and rewrite the "# Workspace Database" lines in .env.
Relaycd apps/relay && while true; do CI=1 WRANGLER_SEND_METRICS=false node_modules/.bin/wrangler dev --port $RELAY_PORT --var NEXT_PUBLIC_API_URL:http://localhost:$API_PORT --local; donewrangler dev dies with an empty error whenever a client aborts mid-request, which every app relaunch does. Hence the loop.
Metrocd apps/mobile && CI=1 bunx expo start --dev-client --port 8081CI=1 disables file watching: restart Metro after code edits. Pre-warm the first bundle by curling the launchAsset.url from curl -H 'expo-platform: ios' localhost:8081, or the dev client times out.

apps/mobile/app.config.ts loads the repo-root .env with override: true, so every local bundle points at this workspace's API no matter what apps/mobile/.env says.

Simulator

U=$(xcrun simctl list devices available | grep -m1 "iPhone 17 Pro (" | grep -oE '[0-9A-F-]{36}')
xcrun simctl boot $U && xcrun simctl bootstatus $U -b
xcrun simctl ui $U appearance light
xcrun simctl status_bar $U override --time "9:41" --batteryState discharging \
  --batteryLevel 100 --cellularBars 4 --wifiBars 3 --dataNetwork wifi
xcrun simctl spawn $U defaults write sh.superset.mobile EXDevMenuIsOnboardingFinished -bool YES
xcrun simctl openurl $U "superset://expo-development-client/?url=http%3A%2F%2Flocalhost%3A8081&disableAutoLaunch=1&disableFab=1"
  • simctl boot does not launch Simulator.app. Keep it that way.
  • The status bar override resets on shutdown. Reapply it after every boot.
  • No dev client installed, or it crashes on launch after a native dependency change? Rebuild: From apps/mobile (cd apps/mobile from the repo root), run bunx expo prebuild -p ios, then xcodebuild -workspace ios/Superset.xcworkspace -scheme Superset -configuration Debug -sdk iphonesimulator -derivedDataPath <scratch>/dd (about 10 minutes), then xcrun simctl install $U <path to Superset.app>. Set SENTRY_DISABLE_AUTO_UPLOAD=true. Never set CODE_SIGNING_ALLOWED=NO: it drops the keychain entitlement and the app crashes on first SecureStore read. Pure JS changes need no rebuild.

Driving

Maestro needs JAVA_HOME=/opt/homebrew/opt/openjdk/libexec/openjdk.jdk/Contents/Home. Flows live in apps/mobile/.maestro/flows/. Sign in with tapOn: { id: dev-sign-in-button }.

  • Write one flow per story. Prefer tapOn by visible text, add a testID when text is ambiguous. inputText types character by character, which reads as a person typing on film.

  • Maestro takes 7 to 25 seconds to start. Launch it before you start recording, and begin the flow with a waitForAnimationToEnd or a short extendedWaitUntil so the take opens on a settled screen.

  • The dev session has plan: null, so Home shows the paywall. Seed a subscriptions row on the worktree's Neon branch (plan pro, reference_id = the org id, stripe_subscription_id sub_temp_...) and delete it after.

  • Need a host without a second machine? POST /api/trpc/host.ensure with the session JWT registers one, and holding ws://localhost:$RELAY_PORT/v2/control?hostId=<org>:<machineId> open with Authorization: Bearer <jwt> marks it online. Delete the v2_users_hosts and v2_hosts rows after. For a story with a real agent working, point the app at a real local host-service instead.

  • Maestro matches the whole accessibility label, and rows carry extra text (the Settings row is , Pages, ). Match with a regex: tapOn: ".*Pages.*". Dump what it sees with maestro --udid $U hierarchy.

  • Metro fails with ENOENT ... react-native-worklets/.worklets/<n>.js? Its cache outlived the generated files. Restart it with --clear.

Pages in the app

Pages need three more things locally, none of which setup provides:

  • Object storage. The API writes page files to R2_ENDPOINT (localhost:9000, nothing listens there) while the usercontent Worker reads its own local R2. Run a minimal S3 stand-in on :9000 (PUT with x-amz-copy-source, GET, HEAD, POST ?delete), publish through page.assets.upload then page.publish, then copy every stored object across with bunx wrangler r2 object put superset-private-dev/<key> --local --env dev --file <f> --content-type <type> from apps/usercontent.
  • The Worker's secret. apps/usercontent/.dev.vars needs USERCONTENT_TOKEN_SECRET set to the value in the root .env, or every page answers 500. Start it with cd apps/usercontent && bun run dev.
  • Transport security. The dev build allows local networking only, and <id>.frame.usercontent.localhost does not count, so the page fails with error -1022. On the simulator's installed copy only: PlistBuddy -c "Set :NSAppTransportSecurity:NSAllowsArbitraryLoads true" -c "Add :NSAppTransportSecurity:NSAllowsArbitraryLoadsInWebContent bool true" "$(xcrun simctl get_app_container $U sh.superset.mobile app)/Info.plist", then relaunch. Revert it after.

tRPC calls from a script need authorization: Bearer <jwt> plus x-superset-organization-id, because the JWT carries no active organization. Tap to comment did not open the comment popover under Maestro on the simulator (2026-09-19, cause unknown); film comments through "Show all comments" and Reply instead.

Capturing

Run capture commands from a scratch directory. Use an absolute path to the Maestro flow when recording outside the repo.

mkdir -p raw shots cfr
xcrun simctl io $U recordVideo --codec h264 --force raw/01-story.mov & REC=$!
maestro test <repo>/apps/mobile/.maestro/flows/<story>.yml
kill -INT $REC; wait $REC
xcrun simctl io $U screenshot shots/01.png
  • Stop with SIGINT only. Any other signal leaves an unplayable file.
  • recordVideo writes a frame only when the screen changes, so the file is variable frame rate and wall-clock marks do not map to video time. Normalize before choosing cut points: ffmpeg -i raw/01-story.mov -vf fps=30 -an -c:v libx264 -crf 14 -pix_fmt yuv420p cfr/01.mp4.
  • A screenshot after a sleep never catches a sub-second flash. Record, then extract frames with ffmpeg -vf fps=10.
  • Before changing simulator variants, record the existing appearance, content size, and AppleLanguages value (including whether it was unset) so cleanup can restore them.
  • Variants: simctl ui $U appearance dark, simctl ui $U content_size extra-extra-extra-large, and simctl spawn $U defaults write "Apple Global Domain" AppleLanguages -array de-DE followed by a relaunch.

For a framed demo video, use the shared mobile-demo-film skill after recording.

Cleanup

Delete only the rows and objects created for this recording: subscriptions, hosts, demo sessions, and, for Pages, published pages, comments, and their objects in the S3 stand-in and local R2. Restore any organization or user names changed for the demo.

Stop every service started for the recording, including the usercontent Worker and storage stand-in when used. Restore the simulator's prior appearance, content size, and AppleLanguages value (remove the override if it was originally unset), revert any installed app transport-security changes, clear status-bar overrides, then xcrun simctl shutdown $U. Recordings and screenshots stay in the scratch directory unless the user asks for them in the repo.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

10x

FreeSummary

Review how you use Superset and identify unused features that fit your workflow. Get a short list of suggestions, learn about each option, and set up selected features such as scheduled agents, parallel workspaces, or shared tasks.

  • Find unused Superset features worth exploring
  • Set up scheduled agent tasks
  • Start parallel work in separate workspaces
ParadevAI/Paradev15.7KUpdated Oct 29, 2026

automate

FreeSummary

Set up recurring tasks in Superset with an agent prompt, a schedule or event trigger, and a chosen execution workspace. After explicit confirmation, create the automation, check its saved settings, and review a real first run.

  • Scheduling a daily or weekly agent task
  • Starting agent work when a GitHub pull request opens
  • Triggering tasks from selected Slack reactions
ParadevAI/Paradev15.7KUpdated Oct 29, 2026

browser

FreeSummary

Browse pages, click controls, fill fields, and inspect screenshots or console messages through Superset's browser pane. Use it to preview a running web app, check interface behavior, and work through browser tasks in a visible session.

  • Preview a locally running web app
  • Capture screenshots of a page
  • Inspect console errors
ParadevAI/Paradev15.7KUpdated Oct 29, 2026

Build Stripe payments, subscriptions, and invoicing using verified documentation and API parameter definitions. The skill guides product selection, sandbox testing, and webhook handling, where server notifications determine payment and subscription state.

  • Choose Stripe products for payments or recurring billing
  • Implement Checkout or invoice flows
  • Investigate Stripe code that compiles but behaves incorrectly
ParadevAI/Paradev15.7KUpdated Oct 29, 2026

cdp-verification

FreeSummary

Verify a UI change or reproduce a bug in the running desktop app using the Chrome DevTools Protocol (CDP), a browser debugging interface. Follow the real user journey and compare screenshots with measurements such as route, scroll position, and persisted state.

  • Reproducing a UI bug in the running app
  • Verifying a UI change end to end
  • Checking behavior after a route or workspace switch
ParadevAI/Paradev15.7KUpdated Oct 29, 2026

ci-triage

FreeSummary

Diagnose failed GitHub Actions runs by finding the first meaningful error, separating code problems from infrastructure issues and intermittent failures, and comparing the base branch. Get a focused report explaining the PR’s involvement and recommended next steps.

  • Investigating failed PR checks
  • Separating intermittent test failures from code defects
  • Checking whether the base branch already fails
ParadevAI/Paradev15.7KUpdated Oct 29, 2026

See all skills by ParadevAI

Report a problem with this skill