Skip to content
Jump to
CLI

The demotake CLI

A thin command-line client for the DemoTake app on the same Mac. Validate demotake.json specs, run them as tests without video, re-record only the scenes that changed, diff takes and export packages, from a terminal or CI.

Install

The CLI ships inside DemoTake. Put it on your PATH once:

Terminal
mkdir -p ~/.local/bin
ln -sf /Applications/DemoTake.app/Contents/MacOS/demotake-cli ~/.local/bin/demotake
demotake status

This adds a link in your home folder only; no administrator password needed. If demotake isn't found afterwards, add export PATH="$HOME/.local/bin:$PATH" to ~/.zshrc and open a new terminal window. You can also run the CLI by its full path, /Applications/DemoTake.app/Contents/MacOS/demotake-cli.

The file is called demotake-cli inside the app bundle because macOS volumes are usually case-insensitive, and demotake would clash with the app's own DemoTake executable.

demotake talks to the running DemoTake app over its local MCP endpoint, so DemoTake must be installed and running (except for validate and schema, which need no app). Running specs operates real apps, so it needs DemoTake Agent with Screen Recording and Accessibility granted. demotake status shows what's missing.

  1. demotakeyour terminal or CI
  2. 127.0.0.1:47823/mcpbearer token
  3. DemoTake Agentoperates the app, records
The CLI finds the endpoint and token on its own.

Commands

Command What it does
demotake validate <spec> Schema and semantic checks of a demotake.json. No app needed.
demotake test <spec> DemoTest: runs every scene and assertion without recording video. Exits 1 on failures.
demotake run <spec> Runs the spec and records it (Rehearse → Take, per-scene retry), then renders the outputs.
demotake diff <take_id> Which scenes changed compared with the previous run.
demotake export <take_id> Renders videos (optionally under a file size), guides and interactive demos, or writes a portable .take.zip package.
demotake share <take_id> --interactive Shares the take's interactive demo as a DemoTake Cloud link and prints its embed code.
demotake presenter <take_id> Shows the presenter camera as a bubble, side by side or full frame, or imports a presenter video.
demotake screenshots run <spec> Regenerates the spec's store screenshots (App Store, Google Play, web) into --out.
demotake runner Serves scheduled re-recording: claims queued runs from DemoTake Cloud and records, exports and uploads them on this Mac (Team plan).
demotake schema Prints the JSON Schema for demotake.json (for editor completion).
demotake status Whether DemoTake is reachable, which permissions are missing, and whether the licence allows recording and exporting.

validate

Terminal
demotake validate demotake.json

Checks the spec's structure and meaning (unknown fields, missing scenes, bad element queries) and prints errors and warnings with their JSON paths. Nothing runs.

test

Terminal
demotake test demotake.json --junit reports/demotake.xml --commit "$GITHUB_SHA"

Runs the steps and assertions scene by scene with no video. It reuses one "(DemoTest)" take per spec take, so repeated runs don't flood your library. Failure evidence (a blurred snapshot and a UI excerpt) goes into the JUnit report and the take's runs/ folder.

run

Terminal
demotake run demotake.json --only-changed --outputs 16:9,9:16,guide --json > reports/demotake-run.json

Records the spec and renders its outputs. With --only-changed, DemoTake compares each scene's checkpoint (accessibility state plus a perceptual diff of the checkpoint snapshot, ignoring redacted regions) with the last recording of the same spec take, re-records only the scenes that changed and keeps the rest, footage and edits included. If nothing changed, existing exports stay current and no render runs.

Terminal
$ demotake run demotake.json --only-changed --outputs 16:9,guide
Checkout Take: PASS · 8 scene(s) · 3 of 8 scene(s) changed · 3 regenerated, 5 kept

diff

Terminal
demotake diff take_01j…

Lists the scenes whose UI changed between a take and its baseline.

export

Terminal
demotake export take_01j… --format package

Writes a portable .take.zip (take, media, pointer tracks, snapshots) you can import on another Mac or share.

Terminal
demotake export take_01j… --format 16:9,9:16 --quality upload --max-mb 45

Renders videos. --quality upload makes small H.264 files at 30 fps for upload forms and review portals (the default is high). --max-mb keeps each MP4 under that size, in MB of 1,000,000 bytes, encoding again at a lower bitrate if needed. --resolution 2160p (or 4k) renders 3840×2160 for 16:9, native the recording's own pixels (1080p up to 4K, never upscaled); --codec h264|hevc overrides the automatic choice (HEVC for high-quality 4K, H.264 otherwise). --format app_preview --device iphone_6_9 renders an App Store app preview (--orientation portrait|landscape, --poster 5, --fit speed|trim to land within 15–30 s); the line says whether it meets Apple's specification and the command exits 1 when it doesn't. Each line shows the file size; a file still over --max-mb makes the command exit 1. --no-wait returns once the renders are queued.

Terminal
demotake export take_01j… --format 16:9 --subtitles srt,vtt --embed-subtitles
demotake export take_01j… --format srt,vtt,transcript

Subtitles and transcripts, timed to the edited video. --subtitles srt,vtt,md writes them next to each video (md is a Markdown transcript); --embed-subtitles also adds a subtitle track viewers can switch on in their player. With --format srt,vtt,transcript only the files are written, no video. They say what the voiceover says, or the captions when there's no voiceover; --subtitle-source captions uses the captions either way.

Terminal
demotake export take_01j… --format 16:9,guide --languages source,de,sv --subtitles srt,vtt
demotake export take_01j… --format 16:9 --embed-subtitles --subtitle-languages all
demotake export take_01j… --format srt,vtt --languages de

Localized takes (languages added and translated in the app or by an agent): --languages renders each format once per language, with the language at the end of the file name (-de.mp4, -sv.mp4) and that language's subtitles, transcript, guide and Reviewer Pack; source is the take's own language and all is every language. --subtitle-languages all with --embed-subtitles puts one subtitle track per language into each MP4.

Terminal
demotake export take_01j… --format interactive --languages source,de

An interactive (click-through) demo: a folder whose index.html opens in any browser without a server (step pictures, a hotspot where each click happened, tooltips, the voiceover when there is one) and a ZIP of it. With --languages every language is in the same demo, with a language switch. The steps are the ones edited in the app (or by an agent with interactive_update); without edits they come straight from the recording.

share

Terminal
demotake share take_01j… --interactive --visibility code --expires 14

Uploads the latest interactive demo export (or makes one) to DemoTake Cloud and prints the link and an <iframe> embed code for websites and docs. --visibility public|code|invite, --code for your own access code, --expires DAYS or never (subscriptions), --no-download to hide the offline ZIP. The app must be signed in.

presenter

Terminal
demotake presenter take_01j… --layout bubble --corner bottom_left --background blur
demotake presenter take_01j… --scene Intro --layout full
demotake presenter take_01j… --import founder.mov --offset 1.5

Styles the presenter camera: --layout bubble|split|full, --corner, --size small|medium|large, --shape circle|rounded, --border none|white|accent, --side left|right (split), --mirror on|off, --background none|blur|remove with --quality fast|balanced|accurate (drawn when the Mac renders), --off to hide it. --scene S --layout hidden|bubble|split|full|inherit sets one scene. --import FILE copies a video of the presenter into the take and plays it from --offset seconds of the cut (--no-audio without its sound, --volume 0…1).

screenshots

Terminal
demotake screenshots run demotake.json --out store-screenshots --only-changed --junit reports/screenshots.xml
demotake screenshots validate demotake.json
demotake screenshots formats

Runs the spec's screenshots section: reaches each screen with its steps, captures it, and renders every format at its exact size into --out (default screenshots), in folders per store and device with a manifest.json. With --only-changed, shots whose screen didn't change keep their files byte for byte. --shot, --formats and --file-type png|jpeg run part of the spec. See Screenshots from agents and CI.

runner

Terminal
export DEMOTAKE_RUNNER_TOKEN=dtr_…        # from DemoTake Web › Re-record on a Schedule › Runners › Add Runner
demotake runner                          # keep serving runs (Ctrl-C to stop)
demotake runner --once --wait 600        # in CI: wait up to 10 minutes for one run, run it, exit

Makes this Mac a runner for scheduled re-recording (Team plan). Each run re-records the take's scenes whose UI changed, keeps your edits, exports, compares the scenes with the last run and uploads the exports, posters and scene pictures (all rendered from the edited take, so redactions apply). DemoTake Agent does the work, so it must be running and allowed to record and operate the app. --runner-token or DEMOTAKE_RUNNER_TOKEN is the runner token (shown once when you add the runner); --once stops after one run (or none), --wait SECONDS keeps polling until a run arrives, --max-runs N, --poll SECONDS (default 30), --json. secret_env steps read their values from this process's environment. Exits 1 when a run failed.

schema

Terminal
demotake schema > demotake.schema.json

Common options

Option Meaning
--junit <file> Write a JUnit XML report (test, run).
--json Print the machine-readable result instead of the summary.
--commit <sha> The source commit being demoed or tested; it's recorded in the proof manifest.
--outputs <list> Comma-separated output formats for run: 16:9, 9:16, 4:3, 1:1, gif, screenshots, reviewer_pack, guide, interactive.
--only-changed run: re-record only the scenes whose UI changed.
--url, --token Connect to a specific endpoint instead of the discovered one.

Connection and environment

The endpoint and token are read from ~/Library/Application Support/DemoTake/ (mcp-endpoint.json and mcp-token). Override them with --url / --token or these environment variables:

Variable Meaning
DEMOTAKE_MCP_URL Full endpoint URL, e.g. http://127.0.0.1:47823/mcp
DEMOTAKE_MCP_PORT Port on 127.0.0.1
DEMOTAKE_MCP_TOKEN Bearer token

Secrets

Specs never contain secrets. A step like this reads DEMO_PASSWORD from the environment of the demotake process, which forwards it to the app for that run only. It is never logged, stored in the take or shown in videos, and secure fields are masked.

JSON
{ "action": "type", "secret_env": "DEMO_PASSWORD", "element": { "role": "securetextfield" } }

Or use {"keychain": {"service": "com.example.demo", "account": "ci"}} for a generic password in the runner's login Keychain.

Exit codes

Code Meaning
0 OK
1 Failed scenes or assertions, an invalid spec, or an export over --max-mb
2 Usage error
3 DemoTake unreachable
4 DemoTake reported an error

In CI

A demotake.json in your repo is a demo and an end-to-end test. Run demotake test on pull requests and demotake run --only-changed on release tags, on a self-hosted macOS runner with a logged-in GUI session and DemoTake Agent installed. The full GitHub Actions setup is in Demo specs and CI.

On the Team plan you can also let DemoTake Cloud schedule the runs: a schedule re-records on a timetable or after each deploy (a webhook from GitHub, Vercel or Netlify), updates the take's share links in place, and notifies Slack. The recording still happens on a Mac: the one that runs demotake runner, or a Mac with DemoTake open and Use this Mac as a runner turned on.