open-take
CLI

make

Drive the app in real time and deliver the master plus its working directory.

open-take make --plan plan.json --out demos/myapp.mp4

make drives the app (real time) and delivers the polished master at exactly --out, with the working directory beside it: the editable composition.json, plus the kept capture.mp4 and capture.json — the raw footage and the ground-truth event log every later re-render builds on.

The raw capture auto-opens the moment it lands — minutes before the polished render finishes — so the wait is spent watching footage, not a spinner (--no-open to skip).

In practice the plan is authored by your agent from the skill's editorial loop; --plan is the contract between that plan and the camera.

The pre-capture target check

Before a single frame is recorded, every plan target is resolved against the page as loaded, with the capture's own locator semantics — and only the field the capture will actually read (text beats selector for a click; a scroll reads toSelector first).

Two findings refuse the shoot in seconds, before anything is recorded: a target in the plan's cold prefix that doesn't exist, and a selector the page rejects as invalid CSS.

A third is the parse-intent mismatch: a by-text target that resolves — but to a different element than the one inside main carrying that name. Each action searches its own candidate set (a click sees only clickables; a scroll also sees headings and paragraphs) and matches an exact name first, then a substring — so a headline's words can land on whatever element merely contains them, classically a sidebar thumbnail that navigates away. This refuses the shoot only in the shape that is a certainty: a cold-prefix target whose substring match sits outside main, covering only a sliver of the picked element's actual name, while the named element is inside main. Every other mismatch — an exact-name match, an abbreviated label ("Comments" naming a "Comments3" badge button), a landing inside main, anything after the cold prefix — is a warning, and the capture proceeds.

Targets that only exist after earlier steps reveal them aggregate into one advisory; if one never appears, the skipped step fails the run at capture time.

The defects block (exit 2)

Every defective verdict — a structural lint error, a pre-capture refusal, a skipped step, a post-shoot check error — exits 2 and prints a machine-readable report: one JSON object between --- open-take defects v1 --- and --- end open-take defects ---, also written to <name>.take/defects.json when the take dir exists (a refusal never creates the dir, and only writes into one that belongs to this plan's app — the stdout block is always the authority). Each entry names the gate that measured it (plan-lint · precheck · capture · post-shoot · composition), the severity, the field path, the measured values, and — wherever the engine can compute one — the exact fix. Warnings ride along: the late-bound target the gate cannot refuse surfaces only there.

The block is a repair contract, not a log: relay it verbatim to whatever authored the plan, take back the entire corrected plan, and re-run — at most twice, then stop and hand the final block to a human. The skill spells out the loop; the engine never calls a model, it only judges.

Overwrite safety

make refuses to overwrite a take that was shot from a different app — two demos in one folder each get their own name (--out myapp.mp4). The honest case, same app on a new dev-server port, is --force.

Flags

flagdefaultnotes
--out <path>demos/take.mp4non-mp4 extensions are refused; a bare name is completed
--fps <n>60capture and render fps; 30 for fast drafts
--capture-scale <n>2Retina capture — drop to 1 if a heavy page can't hold fps
--draftfast draft render of the delivery
--no-strictexit 0 even when plan steps were skipped or a post-shoot check failed — by default those exit non-zero (the summary lists them either way)
--profile <name>authenticated session from auth
--headedvisible Chrome window; the screencast records the page either way

On this page