peekaboo capture
capture replaces watch as the unified long-running capture tool. It has three subcommands:
capture live— adaptive PNG burst capture of screens/windows/regions with idle/active FPS, diff-based frame keeping, contact sheet, and metadata.capture action— start adaptive live capture, run a child command, keep post-roll, stop early, and validate output artifacts.capture video— ingest an existing video, sample frames (by FPS or interval), optionally skip diff filtering, and emit the same outputs.
The MCP server exposes the same primitive as the capture tool. MCP arguments use snake_case names such as duration_seconds, active_fps, threshold_percent, output_dir, and video_out.
A hidden alias capture watch maps to capture live for backwards compatibility. The old standalone watch command/tool is removed.
#Common Outputs
- PNG frames (kept frames only)
contact.pngcontact sheetmetadata.json(CaptureResult) with stats, warnings, grid info, and source (live|video)- Optional MP4 (
--video-out) built from kept frames
For capture video, metadata.json and JSON stdout include options.video with the requested sampling/trim options plus the effective FPS used by the frame reader.
#capture live flags
- Targeting:
--mode screen|window|frontmost|area,--screen-index,--app,--pid,--window-title,--window-index,--region x,y,width,height(global coords) - Focus:
--capture-focus auto|background|foreground - Cadence:
--duration(<=180),--idle-fps,--active-fps,--threshold,--heartbeat-sec,--quiet-ms - Caps:
--max-frames(default 800),--max-mb - Diff/output:
--highlight-changes,--resolution-cap(default 1440),--diff-strategy fast|quality,--diff-budget-ms,--video-out <path> - Paths:
--path <dir>(default tempcapture-sessions/capture-<uuid>),--autoclean-minutes(default 120)
#capture action flags
- Targeting/focus/cadence/caps/output: same as
capture live, except--durationis replaced by--duration-limit(default 60, max 180). - Action timing:
--pre-roll-ms(default 250),--post-roll-ms(default 500),--action-timeout(defaults to the remaining duration after roll time). - Command: pass the child command after
--, e.g.peekaboo capture action -- echo smoke. Commander also accepts--command -- echo smoke, but the--form is clearer for commands with their own flags.
The command exits non-zero if the child command exits non-zero, times out, or required capture artifacts are missing/empty. JSON output includes the child command exit code/stdout/stderr, the normal CaptureResult, and artifact validation details.
#capture video flags
- Required:
--input <video>(positionalinputargument) - Sampling:
--sample-fps <fps>(default 2) XOR--every-ms <ms> - Trim:
--start-ms,--end-ms - Diff:
--no-diff(keep all sampled frames); otherwise uses diff/keep logic - Caps/output:
--max-frames,--max-mb,--resolution-cap(default 1440),--diff-strategy,--diff-budget-ms,--video-out - Paths:
--path,--autoclean-minutes
Validation: video source rejects targeting/focus/cadence flags; live rejects sampling/trim/no-diff. Video runs may keep a single frame when no motion is detected (emits a noMotion warning) instead of failing.
#Examples
# Live, change-aware capture of frontmost window for 45s
peekaboo capture live --duration 45 --idle-fps 1 --active-fps 8 --threshold 2.0
# Live, target specific screen, MP4 output
peekaboo capture live --mode screen --screen-index 1 --video-out /tmp/capture.mp4
# Live, record an explicit desktop region; --region also infers area mode
peekaboo capture live --region 100,120,640,360 --duration 10
# Capture a command-driven flow with pre/post-roll and JSON proof
peekaboo capture action --duration-limit 10 --json -- ./test-flow.sh --smoke
# Video ingest, sample 2 fps, trim first 5s
peekaboo capture video /path/to/demo.mov --sample-fps 2 --start-ms 5000 --video-out /tmp/demo.mp4
# Video ingest, keep all sampled frames at 500ms interval (no diff filtering)
peekaboo capture video /path/to/demo.mov --every-ms 500 --no-diff
#Design notes
- Hidden alias:
capture watchmaps tocapture live; the old standalonewatchtool was removed. - Live defaults: max duration 180s,
--max-frames800, resolution cap 1440, diff strategyfastunless--diff-strategy qualityis set. - Action capture uses the same live sampler and can stop it early once the child command and post-roll complete.
- Video ingest uses the same diff/keep logic as live;
--no-diffkeeps every sampled frame. When no motion is detected, you may end up with a single kept frame plus anoMotionwarning. - Core types:
CaptureScope/Options/Resultwith a pluggableCaptureFrameSource(ScreenCapture for live, AVAssetReader for video). Optional MP4 is written byVideoWriterwhen--video-outis set. - Quick smokes:
peekaboo capture live --mode screen --duration 5 --active-fps 8 --threshold 0→ frames > 0, contact sheet exists.peekaboo capture video /path/demo.mov --sample-fps 2 --start-ms 5000 --video-out /tmp/demo.mp4→ ≥2 kept frames and MP4 written.
#Troubleshooting
- Verify Screen Recording + Accessibility permissions (
peekaboo permissions status). - In SSH, LaunchAgent, Codex, and other background launchd sessions, prefer a Bridge host with Screen Recording.
- Confirm your target (app/window/selector) with
peekaboo list/peekaboo seebefore rerunning. - Re-run with
--jsonor--verboseto surface detailed errors.
Legacy screen/area capture now rejects wallpaper-only or redacted false-success frames instead of writing them as valid output. Use --no-remote --capture-engine cg only when the caller is in the active Aqua session and has TCC.