Command line

Every feature, scriptable.

Every Wispframe feature is a terminal command. The running app is the engine and the permission holder — the wispframe command is a thin client that hands it work, so your terminal never needs a screen-recording or camera grant.

setup — one click, no dependencies
# 1) Install Wispframe from the Mac App Store and launch it once
#    (grant Screen Recording when macOS asks — the app keeps the permission)
# 2) In the app header, click "⌘ CLI & MCP" — it installs the wispframe command
# 3) Done. The CLI talks to the app (and starts it if it isn't running):
wispframe record --duration 10 --out demo.mp4

Driving Wispframe from an AI agent?

Hand it this one file. It documents every command and MCP tool, the permission model, exit codes and ready-made recipes — enough for a coding agent to work with Wispframe without guessing.

↓ Download wispframe-agent.md

Paths must be absolute

The App Store build is sandboxed. A relative path, or one starting with ~, is refused before any work — and so is any location outside the app container or the folder you pick as the Agent working folder (⌘ CLI & MCP ▸ Choose). The examples on this page use short names to stay readable; write them out in full, under that folder.

wispframe trim --in /Users/you/Movies/clip.mp4 --out /Users/you/Movies/clip.trimmed.mp4 --keep 0-10

Sources & ids

Displays, windows, and apps are addressed by id. Enumerate them as JSON, then target one with --display, --window, or --app.

wispframe list-sources
wispframe record --app com.apple.Safari --out out.mp4

Permissions

Same macOS privacy prompts as any recorder — Screen Recording for capture, Microphone for --mic, Camera for record-pip, Accessibility for keystrokes & scrolling. Granted once in System Settings.

Licensing

Every feature works free with unlimited recording; processed exports carry a small watermark and Pro removes it. The CLI itself is never gated — it reads the same entitlement the app does, so a Pro purchase in the app applies immediately with nothing to activate.

wispframe license                       # status

Codecs & audio

--codec h264 (default) / hevc write .mp4; prores writes .mov. --system-audio and --mic mix into one AAC track, balanced with per-source gains (0.0–2.0).

Sidecars

--record-cursor writes <out>.cursor.json (for Studio auto-zoom); --record-keys writes <out>.keys.json (for keystroke pills), which needs the Accessibility permission and so records nothing in the sandboxed App Store build. Studio reads them back.

Safe by default

Post-processing writes to <out>.part and renames on success, so a failed run never destroys an existing file. Variable-frame-rate recordings are resampled onto a clean clock — outputs never trip the encoder.

Capture

Record displays, windows, apps, webcams, a wired iPhone's screen, and multiple sources at once.

wispframe list-sources

List capturable displays, windows, and applications as JSON. Each display carries both its point size (width/height, what macOS shows in Settings) and its backing pixel size (pixel_width/pixel_height) — every coordinate flag below takes backing pixels, so on a Retina display the two differ by 2×.

Terminal
wispframe list-sources

wispframe detect-text

Report where text is on screen, frame by frame, as JSON — on-device OCR, nothing uploaded. The companion to detect-faces: a face and a visible password are the two things that stop a recording being publishable, and both need a rectangle.

Terminal
wispframe detect-text --in demo.mp4 --out text.json --accurate
--stride <n>
Recognise every Nth frame (default 15); recognition costs roughly 100-200 ms a frame.
--accurate
Vision's slower, more accurate level — measured at 0.97 confidence against 0.40, at about twice the time.
--min-confidence <c>
Drop results below this confidence, 0-1 (default 0.3).

wispframe detect-silence

Report the silent stretches of a video or audio file — and the spans worth keeping, written exactly the way trim --keep wants them, so the two chain without any arithmetic. The app's Trim window does the same thing behind its Cut silence button.

Terminal
wispframe detect-silence --in talk.mp4 --out silence.json
--threshold-db <db>
Silence threshold in dBFS (default -40). -40 is quiet-room quiet, -60 nearly digital silence.
--min-length <s>
Ignore gaps shorter than this (default 0.5). A breath is not a cut.

wispframe detect-cuts

Report where the picture changes abruptly — the shot boundaries — as JSON. Always reports the largest difference it saw, so "no cuts" can be told apart from "your threshold was too high".

Terminal
wispframe detect-cuts --in reel.mp4 --out cuts.json
--threshold <t>
How different two frames must be to count as a cut, 0-1 (default 0.12).
--min-gap <s>
Ignore cuts closer together than this (default 0.4).

wispframe detect-faces

Report where faces are in a video, frame by frame, as JSON — Apple Vision on device, nothing uploaded and no model downloaded. Boxes come back in source pixels, the same space the redact flags take, so one can be piped straight into the other.

Terminal
wispframe detect-faces --in talk.mp4 --out faces.json --stride 3
--stride <n>
Detect every Nth frame and hold the boxes in between (default 1); detection costs roughly 13-27 ms a frame.
--max-seconds <s>
Stop after this many seconds (0 = the whole file).

wispframe list-cameras

List camera devices — built-in, USB, iPhone Continuity, and a wired iPhone's screen (kind IosScreen) — as JSON.

Terminal
wispframe list-cameras

wispframe probe

Capture a display for N seconds and print each frame's PTS — an end-to-end pipeline check, optionally with a CPU/RAM benchmark report.

Terminal
wispframe probe --duration 10 --fps 60 --bench baseline
--display <id>
Display to probe. Defaults to your primary display — id 1 is not “the first screen”, it is an opaque WindowServer id that may not exist at all.
--duration <s>
Seconds to capture (default 10).
--fps <n>
Target frame rate (default 60).
--bench <label>
Also write memory/benchmarks/<label>-*.{md,csv}.

wispframe record

Record a display, window, or app to a file — the full capture → hardware-encode → mux pipeline.

Terminal
wispframe record --out demo.mp4
wispframe record --app com.apple.Safari --system-audio --mic --out tutorial.mp4
wispframe record --record-cursor --out zoomable.mp4
--out <path>
Output file — required. .mp4 (h264/hevc) or .mov (prores).
--display / --window / --app
What to capture (id / window id / bundle id). A window or an app records that window at its native resolution, cropped to it, following it as it moves or is resized.
--duration <s>
Length in seconds (default 10). Recording is unlimited on Free — processed exports carry a small watermark.
--fps / --width / --height
Frame rate (60) and output size. Size defaults to the display's own native resolution — a 4K screen records as 4K. Give one of --width/--height and the other follows the source's aspect ratio.
--codec <c>
h264 (default) · hevc · prores.
--crop "x,y,w,h"
Capture only a sub-rect of the source.
--mask-bg <backend>
Remove the background after recording (vision / onnx).
--system-audio / --mic
Add audio (mixed into one track).
--system-audio-gain / --mic-gain
Balance the mix, 0.0–2.0.
--record-cursor / --record-keys
Write sidecars for Studio zoom / keystrokes. --record-keys needs Accessibility, so it stays empty in the App Store build.
--hide-cursor / --delay <s>
Cursor-free recording · self-timer countdown before start.

wispframe record-pip

Record the screen with a live webcam picture-in-picture — screen and camera captured in parallel, composited live.

Terminal
wispframe list-cameras
wispframe record-pip --camera <uniqueID> --corner br --out pip.mp4
--camera <uniqueID>
From list-cameras. Defaults to the system camera.
--scale / --corner / --margin
Webcam size & placement (0.3 / br / 24).
--shape <kind>
Webcam bubble shape: rect · rounded · circle · triangle · hexagon — circle = classic bubble.
--system-audio / --mic
Audio into the recording.

wispframe record-camera

Record a camera on its own — webcam, USB capture card, an iPhone over Continuity Camera, or a wired iPhone's screen at its native portrait resolution — straight to MP4, no screen involved.

Terminal
wispframe list-cameras
wispframe record-camera --camera <uniqueID> --duration 20 --fps 30 --out cam.mp4
--camera <uniqueID>
From list-cameras. Defaults to the system camera.
--duration <s> / --fps <n>
Capture length and frame rate (10 / 30).
--delay <s>
Self-timer countdown before recording starts.

wispframe record-all

Record every connected display simultaneously, each to its own file.

Terminal
wispframe record-all --out-template '/tmp/multi-{n}.mp4' --duration 15
--out-template <tpl>
{n} is replaced with each display id.

wispframe record-live-grid

Record 2–9 live sources composited into ONE file during capture — finished the instant you stop, no post-merge wait.

Terminal
wispframe record-live-grid --sources display:<id>,window:<id> --layout sbs --canvas 4k --seconds 30 --out live.mp4
--sources <list>
display:<id> / window:<id>, comma-separated.
--layout <l>
sbs · grid · rows · pip-* · speaker.
--canvas <c>
1080p · 1440p · 4k · 8k or WxH.
--shape <IDX:KIND>
LIVE cell shapes: rect · rounded · circle · triangle · hexagon — masked during capture.

Post-processing

Composite, redact, frame, trim, retime, and export existing recordings.

wispframe compose

Overlay a video (picture-in-picture), blur/black out regions or faces, and burn in text labels.

Terminal
wispframe compose --base screen.mp4 --overlay cam.mp4 --corner br --scale 0.28 --out pip.mp4
wispframe compose --base interview.mp4 --redact-faces all:blur --out safe.mp4
--base / --out
Base video and output — required.
--overlay <path>
The PiP source (optional if only redacting).
--rect / --corner / --scale / --margin
Overlay placement.
--redact "x,y,w,h:blur|solid[:S-E]"
Redact a region, baked on top — ':2.5-8' limits it to that time window (seconds).
--shape <kind>
Overlay shape: rect | rounded | circle | triangle | hexagon — circle = webcam bubble.
--redact-faces "all|x,y;…[:blur|solid]"
Auto-blur faces, tracked per face.
--text "TEXT:x,y[:size[:#rgb]]"
Burn in a label (CoreText, emoji ok).

wispframe compose-grid

Combine 2–9 videos into one scene — side-by-side, grid, rows, picture-in-picture, or speaker — with per-source audio, offsets, free placement, opacity, cell shapes (circle webcam bubbles) and timed layout keyframes that switch the arrangement mid-video.

Terminal
wispframe compose-grid --sources a.mp4,b.mp4,c.mp4 --layout grid --out grid.mp4
wispframe compose-grid --sources main.mp4,cam.mp4 --layout sbs --shape 1:circle --out talk.mp4 \
  --layout-key 0:sbs --layout-key 12:grid:ease:0.6 --layout-key 40:rows:fade:0.8
--sources <a,b,…>
2–9 files — required.
--layout <l>
sbs · grid · rows · pip-* · speaker.
--audio <IDX:GAIN>
Mix a source's audio (repeatable).
--offset / --place / --opacity
Timing, free placement, alpha.
--shape <IDX:KIND>
Cell shape: rect · rounded · circle · triangle · hexagon — circle = webcam bubble. Repeatable.
--layout-key <T:LAYOUT[:TRANS[:DUR]]>
Switch the arrangement at T seconds; TRANS: cut · slide · ease · fade (cross-dissolve). Repeatable.

wispframe run

Execute a saved Wispframe settings file headless: the JSON the app's 💾 Save settings writes. Compose, trim, redact, studio, subtitler and annotate sessions all replay headless — compose renders the full composition (sources, offsets, keyframes, shapes), subtitler even re-transcribes when the saved session has no transcript — one command, scriptable and MCP-drivable. The file's tool tag is validated with a clear error on mismatch.

Terminal
wispframe run compose-settings.json
wispframe run redact-settings.json --out safe.mp4
<settings.json>
The saved session file (tool tag: compose · trim · redact).
--out <path>
Output file; defaults to the session's own output name.

wispframe remove-bg

Remove the background from a clip — Apple's Neural Engine for people, or a general U²-Net model.

Terminal
wispframe remove-bg --in cam.mp4 --out nobg.mp4 --backend vision --bg green
--backend <b>
vision (person, fast) · onnx (general).
--model <m>
u2net (best) · u2netp (lite) — onnx only.
--bg <c>
green · black · white · #rrggbb · image:PATH (15 built-ins pickable in-app, or any file via image:PATH).

wispframe studio

Give a recording that framed, studio-polished look — a backdrop, rounded corners, and a soft shadow — plus optional cursor auto-zoom and keystroke pills.

Terminal
wispframe studio --in raw.mp4 --out framed.mp4 --bg gradient:Dusk --shadow 70
wispframe studio --in raw.mp4 --out framed.mp4 --zoom --zoom-max 2.0
--bg <b>
blur · gradient:NAME · color:#rgb · image:PATH.
--padding / --radius / --shadow
Framing (8% / 16px / 60).
--crop <x,y,w,h>
Keep only a sub-rectangle (source pixels) before framing.
--zoom / --zoom-max / --zoom-follow
Cursor auto-zoom (needs .cursor.json).
--keys
Keystroke pills (needs .keys.json).

wispframe transcribe

Transcribe a video's speech to captions with an on-device Whisper model (Metal). Writes .srt or .vtt; the model downloads and caches on first use.

Terminal
wispframe transcribe --in talk.mp4 --out talk.srt --lang en --words
wispframe transcribe --in eloadas.mp4 --out eloadas.vtt --model large-v3-turbo
--model <m>
Whisper, on-device: large-v3-turbo (default) · large-v3 · medium · small · base. Downloaded and cached on first use.
--lang <l>
Language hint (e.g. hu, en). Omit to auto-detect.
--words
Per-word timestamps (for karaoke/word-highlight).
--out *.json
Write a JSON transcript that keeps word timing (vs cue-level .srt/.vtt).

wispframe subtitle

Burn styled captions from an .srt/.vtt/.json into a video, or convert a caption file between SRT and VTT. 22 one-click style presets.

Terminal
wispframe subtitle --in talk.mp4 --captions talk.srt --out talk-sub.mp4 --preset Karaoke
wispframe subtitle --captions talk.srt --out talk.vtt --export
--preset <p>
22 looks incl. Karaoke, "Word Pop", "Pop Word" (word-by-word popup), "Glow Pop", "Boxed Pop", Aurora / Sunset / Ocean (soft gradient pills), Neon, Serif, Script, Impact, Creator — and more.
--font-size <pct>
Font size as a percent of frame height.
--position <p>
top · middle · bottom.
--font <name>
Font family (Inter, Montserrat, Poppins…).
--style <file.json>
Full per-field style (overrides preset).
--dump-style <file>
Write the resolved style JSON to edit + reuse with --style.
--export
Only convert the caption file (SRT / VTT / JSON).

wispframe enhance

Upscale and sharpen a video with Real-ESRGAN (on-device, ONNX + CoreML). Audio passes through. A heavy pass; the model caches on first use.

Terminal
wispframe enhance --in small.mp4 --out big.mp4 --scale 2
wispframe enhance --in old.mp4 --out 4k.mp4 --scale 4 --max 3840x2160
--model <m>
general (default, fast) · sharp (full RRDBNet x4plus, fp16/ANE) · apple (built-in VTSuperResolutionScaler, macOS 15.4+). Aliases: photo/hq → sharp, native/vt → apple.
--scale <n>
Upscale factor 2–4 (default 2). 3 works and gives a real 3×.
--max <WxH>
Cap output to fit, preserving aspect.
--denoise <0–1>
Denoise strength (0 = sharpest, higher = cleaner).

wispframe trim

Keep or cut time ranges, concatenated seamlessly into one shorter clip.

Terminal
wispframe trim --in demo.mp4 --keep 2-5 --keep 30-45 --out short.mp4
wispframe trim --in demo.mp4 --cut 12-18 --out cleaned.mp4
--keep <A-B>
Range to keep (repeatable).
--cut <A-B>
Range to remove — output is the complement.

wispframe speed

Change playback speed globally, or ramp individual segments up and down.

Terminal
wispframe speed --in demo.mp4 --factor 2 --out fast.mp4
wispframe speed --in demo.mp4 --segment 10-20:4 --segment 40-42:0.5 --out ramped.mp4
--factor <0.25–4.0>
Global speed.
--segment <A-B:F>
Per-segment ramp (repeatable).
--audio <pitch|mute>
Audio handling in non-1× regions.

wispframe to-gif

Convert a clip to an animated GIF — pure-Rust encoder, no ffmpeg.

Terminal
wispframe to-gif --in clip.mp4 --out clip.gif --width 480 --fps 15
--width <px>
Output width, height auto (default 640).
--fps <n>
Frame rate (default 15).

wispframe burn-timer

Burn a running MM:SS elapsed-time clock into a video — the GUI's 'Burn elapsed time', headless.

Terminal
wispframe burn-timer --in take.mp4 --out timed.mp4 --position bottom-right
--position <p>
top · bottom · bottom-left · bottom-right (default bottom-right).

wispframe annotate-image

Render arrows, boxes, text, steps and blur onto a still image — the screenshot Annotate editor, headless. Same JSON spec as annotate-video.

Terminal
wispframe annotate-image --in shot.png --out shot-annotated.png --spec anns.json
--spec <json>
Annotation list; timing fields are ignored for stills.

wispframe annotate-video

Bake timed annotations — arrows, boxes, ellipses, pen, highlighter, text, numbered steps, blur — onto a video. Each carries a [start, end) band so it shows only when relevant.

Terminal
wispframe annotate-video --in demo.mp4 --spec annotations.json --out annotated.mp4
--spec <path>
JSON file: an array of { kind, …geometry, start, end }.
kinds
arrow · rect · ellipse · line · pen · highlight · text · step · blur.
coords
Frame pixels; a/b two-point, points[] for pen, pos+text for text.

Stills

Screenshots, a scrolling capture, and a screen colour picker.

wispframe screenshot

Capture a still PNG — a full display, a single window, or a dragged region.

Terminal
wispframe screenshot --full --out shot.png
wispframe screenshot --region 100,100,800,600 --out crop.png --clipboard
--full / --region / --window
What to capture.
--clipboard
Also copy the image.

wispframe pick-color

Sample one pixel's colour on a display and print its HEX + RGB.

Terminal
wispframe pick-color --at 640,360 --clipboard
# → #FAC800  rgb(250, 200, 0)

wispframe scroll-capture

Auto-scroll a region and stitch the frames into one tall PNG — a long page, chat, or document. Not available in the App Store build: it needs the Accessibility permission, which the sandbox forbids. Use screenshot --region.

Terminal
wispframe scroll-capture --region 400,120,900,700 --out tall.png
--region "x,y,w,h" / --out
Scrollable rect and output — required.
--max-frames / --step-frac
Safety cap (60) and scroll step (0.66).

Account

Inspect and manage the license.

wispframe license

Show the entitlement. Pro is purchased in the app through the App Store; the CLI reads the same entitlement, so there is nothing to activate here.

Terminal
wispframe license
--action <a>
status. Pro is bought in the app through the App Store, so there is nothing to activate here.

Every command supports -h/--help for the authoritative, always-current option list. Free processed exports carry a small watermark; Pro removes it. The CLI is free on both tiers.