Skip to main content
Glama

Screencast MCP

An MCP server that lets an agent record the screen, watch the footage, and make minimal ffmpeg edits — over stdio, on Windows.

Capture the desktop, a monitor, a window, or a region; sample a recording into frames the agent can actually look at; trim, crop, redact, annotate, zoom toward clicks, and export for GitHub or social. No cloud service, no telemetry: ffmpeg and ffprobe behind 58 typed tools.

For developers who want their coding agent to see and prove UI changes on Windows: bug repros, UI verification, and demo clips the agent records, checks, and edits itself. Capture is Windows-only; the watch and edit tools work on any OS with ffmpeg. Free for non-commercial use (CC BY-NC-ND 4.0); why not OBS, Playwright, or a screenshot MCP?

Documentation

npm MCP Registry CI License: CC BY-NC-ND 4.0 Last commit

TypeScript Node.js Model Context Protocol ffmpeg Capture

Made with the tool: start_recording with events: true, one click, then zoom { highlightClicks: true } and export_gif. How it was made · more workflows

Quick start · Tools · Configuration · Usage · Privacy · Threat model

Quick start

You need Windows 10 or 11, Node.js 22+, and FFmpeg 8 or newer on PATH (winget install Gyan.FFmpeg, the full build). Older builds run most tools, but transcribe (the whisper filter) and backend: "wgc" (gfxcapture) need FFmpeg 8, and essentials or distro builds can lack them (Ubuntu LTS apt install ffmpeg gives 6.x). Capture is Windows-only; the watch, edit, and produce tools work anywhere ffmpeg runs. After connecting, ask the agent to run doctor: it reports the ffmpeg version, the filters and devices it has, OCR, and anything missing.

Add it to your client:

Client

How

Claude Code

claude mcp add screencast -- cmd /c npx -y @tmhs/screencast-mcp, or the plugin (the server plus bug-repro, README-demo, and UI-verify skills): /plugin install screencast --marketplace TMHSDigital/screencast-mcp (older Claude Code: /plugin marketplace add TMHSDigital/screencast-mcp, then /plugin install screencast@screencast-mcp)

Claude Desktop

Download screencast-mcp.mcpb from the latest release and open it (one click)

Cursor, VS Code, others

The JSON config below, or step-by-step on Connect your client

{
  "mcpServers": {
    "screencast": { "command": "npx", "args": ["-y", "@tmhs/screencast-mcp"] }
  }
}

Then ask your agent:

Record my VS Code window for five seconds while I reproduce the bug, then show me the frames where something changed.

More in the workflows: a bug-repro GIF for a PR, a README demo, a UI verification loop, a social clip, a cheap review of a long recording, zoom toward clicks, and the whole edit in one call.

Related MCP server: screencast

Overview

Screencast MCP gives an agent a screen recorder it can drive and reason about. It speaks Model Context Protocol over stdio and exposes ffmpeg as a small, typed tool surface rather than a flag soup. The defining capability is the watch loop: an agent records footage, samples it into PNG frames, and views those frames to confirm what actually happened on screen.

The design choices are deliberate rather than incidental:

  • Capture is always explicit. A recording or screenshot happens only on a tool call — nothing auto-fires and there is no background or scheduled capture.

  • Footage is made viewable. sample_frames turns a video into images returned straight to the model, so "watch what happened" is a first-class operation, not an afterthought.

  • Presets over raw flags. Quality is draft / standard / high; the agent never reasons about codecs, CRF, or pixel formats.

  • Safe by default. Output lands under SCREENCAST_HOME, never inside a project checkout, and the public repo's .gitignore blocks captured media from being committed.

  • Recordings end. When the client disconnects (or the server gets SIGINT/SIGTERM), every active recording is finalized and the server exits. Every recording also has a maxDurationSec cap (default one hour). A recording interrupted by a hard crash is reconciled on the next start (orphan reaping).

What it can do beyond record-and-look:

  • Zoom toward clicks. Record with events: true and zoom glides in on each click and rings it, Screen Studio style.

  • Review before sharing. In clients with MCP Apps, review_recording opens an inline player where a person trims and draws redaction boxes.

  • Find and cover secrets. find_text reads the screen with Windows OCR and returns rectangles for redact_region.

  • One call, one encode. pipeline runs trim, crop, redact, callouts, and an export as a single ffmpeg pass; recipe: "tutorial" turns a raw recording into a cut, zoomed, normalized, captioned mp4.

  • Record a covered window. backend: "wgc" records a window's own surface through Windows Graphics Capture.

Why not just...

Instead of

The difference

OBS, ShareX, Game Bar

Built for a person at the controls. Here the agent starts and stops the recording, looks at the frames, and makes the edits through typed tools, with no GUI step.

Playwright or Puppeteer video

Browser pages only, and the video is a file the model never sees. Here: any window or monitor, frames returned to the model, plus wait_for_change, find_text, and screen_diff for checking what happened.

A screenshot-only MCP server

Single stills. Here: video over time, an input event log, scene-change sampling, redaction, and export, so the agent can show a sequence, not one moment.

Tools

58 tools in 6 toolsets, generated from the server's own schemas by npm run docs (do not edit between the markers). Each name links to its reference page with every parameter, an example call, and what it returns; mcp-tools.json is the same list as JSON, and llms-full.txt all of it in one file.

Core

Always loaded, whatever SCREENCAST_TOOLSETS selects.

Tool

What it does

get_media_info

Probe a media file with ffprobe and return duration, resolution, frame rate, codecs, container format, and size.

doctor

Check the setup: ffmpeg/ffprobe (FFmpeg 8+?), optional filters, capture devices, Windows OCR, settings, and enabled toolsets; problems says what is missing and how to fix it. Call on first use or when a tool reports a missing feature.

Capture

Record or screenshot the desktop, a monitor, a window, or a region. Every capture is an explicit tool call: nothing records on its own.

Tool

What it does

start_recording

Start a background screen recording. Returns a session id; finalize it with stop_recording. Never auto-starts.

stop_recording

Stop a recording gracefully so the file is finalized; returns the path and duration.

pause_recording

Pause a recording; until resume_recording nothing is captured, and the gap is left out of the file, events, and markers.

resume_recording

Resume a paused recording (same target and settings).

save_replay

Save the last N seconds of a replay buffer (start_recording replayBufferSec) to an mp4; the buffer keeps running.

list_sessions

List all recording sessions (active and finished) with their status, target, output path, and whether the process is still alive.

get_session

Inspect a single recording session by id, including live status and whether its output file exists on disk.

read_events

Read the input events (clicks, scroll, cursor, shortcuts, typing bursts) of a recording made with events: true, in video seconds and pixels; e.g. types: ['down'], then sample_frames there.

add_marker

Mark a labelled moment on a recording, live or at a second. Kept in the session and a sidecar; chapters and pipeline turn markers into chapters.

screenshot

Capture one PNG of the screen, a monitor, a window, or a region, returned inline and by path.

list_audio_devices

List DirectShow audio devices and flag a likely loopback (Stereo Mix or a virtual-audio driver), for start_recording's audio.device.

list_video_devices

List DirectShow cameras for start_recording's webcam.device.

list_targets

List the desktop, monitors, and visible windows (topmost first, with capturability per backend). Each entry has a target string to pass as-is to capture tools; use it instead of guessing a title.

Watch

Turn footage into something a model can read: frames, contact sheets, diffs, OCR, and a searchable text timeline.

Tool

What it does

review_recording

Open a recording for a person to review: in MCP Apps clients an inline player to scrub, trim, and redact, then export; elsewhere just the video's details.

player_frames

Preview frames for the review player: JPEGs on an even grid over the video plus frames at scene changes, with their real times. Used by the inline player; agents should use sample_frames or contact_sheet instead. (app-only: called by the review player, not the agent)

sample_frames

Sample PNG frames from a video (by fps, timestamps, or scene changes) and return the first few inline so the model can see what happened.

contact_sheet

Tile timestamped frames of a video into one image to see a whole recording at a glance (the cheapest first look).

screen_diff

Compare two screenshots or frames: SSIM score, changed share, and changed boxes in b's pixels, to check a UI change happened only where expected.

wait_for_change

Wait until part of the screen changes or settles, instead of guessing a sleep. Returns the elapsed time, changed regions (screenshot pixels; add origin for desktop), and the final state.

find_text

OCR (built into Windows) on the screen, an image, or video frames, with line and match boxes in image pixels (add origin for desktop coordinates). Locate UI text or secrets (e.g. regex 'sk-|ghp_|api.?key') to redact. Best-effort: review results.

index_recording

Build a recording's text timeline (.index.json: OCR per scene, events, markers, transcript) for search_recording.

search_recording

Search an index_recording timeline (screen text, events, markers, transcript): timecoded hits, best first, secrets masked. No frames unless asked.

Edit

Cut, convert, compress, and redact. A tool that writes a file refuses to replace an existing output unless overwrite: true; default output paths are always unique.

Tool

What it does

trim

Cut a video down to one sub-clip by start + (end or duration). For several segments use clip; to combine with other edits use pipeline.

concat

Join videos end to end with hard cuts: stream copy when they match, else a re-encode (mode says which). For transitions use xfade_transition or assemble_highlights.

convert

Convert media to mp4, webm, or gif. For a size-bounded GIF/WebP prefer export_gif; for a smaller mp4, compress or export_preset.

export_gif

Export an animated GIF or WebP that fits a size budget (for PRs, issues, READMEs), stepping fps, width, and quality down until it fits.

crop

Crop a video to a pixel rectangle; one running off the frame is rejected.

scale

Resize a video to a target width and/or height and re-encode. Provide one side to keep the aspect ratio, or both to set an exact size.

speed

Change playback speed by a factor (>1 faster, <1 slower) and re-encode. Audio is retempo'd to match when the source has an audio track.

compress

Re-encode a video smaller (H.264 CRF ladder, optional width cap). For a platform target use export_preset.

clip

Extract several frame-exact segments, each to its own file. For one segment, trim does the same.

cut_idle

Remove dead air: cut stretches where the screen is frozen (and silent), keeping a short pad. Returns the time saved.

cut_by_transcript

Edit a video by its transcript: cut quoted text, cue numbers, or fillers. Also writes the re-timed .srt.

redact_region

Cover given rectangles in a video (e.g. secrets on screen). Not automatic detection: find them with find_text redact: true. Off-frame regions are rejected.

pipeline

Run several edits (trim, crop, scale, speed, cut_idle, redact, callout, keystroke_overlay, cursor, reframe, zoom, backdrop, audio, burn_subtitles, then optionally export_preset or export_gif) in one ffmpeg pass: one re-encode, no intermediate files. Prefer it over chaining edit tools; a recipe does the usual polish in one call.

Produce

Annotate, frame, and assemble a finished piece. Tools that combine clips normalize each input to a common resolution, fps, and audio rate first.

Tool

What it does

overlay

Composite an image or video (logo, watermark, picture-in-picture) onto a video at a pixel position, optionally scaled and time-limited; keeps the base's audio and length.

callout

Annotate a video with timed boxes, text labels, and arrows. Fallback fonts used are listed in fallbackFonts; characters no font covers are reported in warnings.

keystroke_overlay

Burn keycast-style badges for shortcuts, clicks, and typing from the recording's input event log (start_recording events: true). Never shows typed text: the log has none.

cursor

Draw a smoothed, scaled cursor that hides when idle from the event log of a start_recording cursor: "events" recording (no OS cursor in the video), with click ripples and an optional spotlight.

backdrop

Frame a video or screenshot on a gradient, color, or wallpaper with padding, rounded corners, and a drop shadow, optionally on a 16:9/1:1/9:16/4:5 canvas.

burn_subtitles

Burn SRT/ASS subtitles (e.g. from transcribe) into a video in the bundled font.

chapters

Write chapters (markers, scene changes, transcript, or a list) into an mp4/mkv/mov copy without re-encoding; returns YouTube chapter text. Can mux an SRT as soft subtitles.

xfade_transition

Join two videos with an xfade transition (audio crossfaded); they need not match in size, fps, or audio. For more clips use assemble_highlights.

assemble_highlights

Stitch clips (including title cards) into one video with cuts or xfade transitions; they need not match in size, fps, or audio.

title_card

Generate a title card clip (centered text on a solid background, silent audio track) to stitch in with assemble_highlights. Uncoverable characters are reported in warnings.

reframe

Re-aspect a video to 16:9, 9:16, 1:1, or 4:5 by padding or cropping.

zoom

Smooth animated zoom-and-pan into the action and back out, from keyframes or planned from logged clicks or screen changes.

export_preset

Encode a platform-ready H.264 file (aspect, fps, bitrate, faststart) for a named platform.

bug_report

Package a recording as a paste-ready repro folder: secret-scanned, redacted clip and GIF, contact sheet, steps from the event log, OCR'd errors, environment, report.md for gh issue create --body-file.

step_guide

Turn a recording's event log into a numbered how-to: a ringed screenshot and caption per step, marker headings; Markdown and/or one HTML file. Never includes typed text.

Audio

Extract, clean up, level, transcribe, and score the soundtrack.

Tool

What it does

extract_audio

Extract the audio track of a media file to its own file (mp3, aac, wav, or copy). Returns the output path.

normalize_audio

Normalize loudness to a delivery target (two-pass EBU R128 loudnorm); video is copied. Reports loudness before and after.

denoise

Reduce steady background noise (fan, hum, hiss) in a recording's audio with an adaptive FFT denoiser. Video is copied untouched. Returns the output path.

transcribe

Transcribe a recording's speech to an SRT subtitle file, locally, with FFmpeg 8's whisper filter (needs a whisper.cpp model file). Returns the SRT path and the text. Pair with burn_subtitles to caption the video.

music_bed

Lay music under a video: looped or trimmed to length, faded, leveled, and mixed with any existing audio. Video is stream-copied.

narrate

Offline voiceover with the built-in Windows voices: speaks each line at its time or marker over the audio, plus an SRT.

IMPORTANT

redact_region covers the regions you declare. It is not automatic secret detection, so it cannot find a secret you did not point it at. The default box style is a solid fill, which is irreversible; blur and pixelate are softer but can be partially recovered, so prefer box for real secrets. They have minimum strengths: blur uses a radius of at least 8 px (or half the region's smaller side) applied three times, and pixelate uses blocks of at least 16 px. Coordinates are in the displayed frame, after any rotation the file carries, and pipeline refuses a redact placed after zoom. A region that falls outside the frame is rejected rather than silently doing nothing.

Targets

Every capture tool takes a single target string, so an agent never has to juggle quoting:

Target

Captures

full

The whole virtual desktop

monitor:<index>

One display; 0 is always primary

window:<title>

The on-screen rectangle a window occupies (case-insensitive exact title, else substring; topmost wins)

window:exe=<app.exe>

That app's topmost window, without relying on its title

window:hwnd=<handle>

One exact window by handle (hex 0x1A2B or decimal)

region:<x>,<y>,<w>,<h>

An absolute pixel rectangle

For window: targets, screenshot and start_recording both report matchedWindow, matchCount, matchKind (exact, substring, exe, or hwnd), and the captured region. When the title matched only as a substring, or several windows matched, the result carries a windowWarning listing the candidate titles, so a generic title like window:Code cannot quietly record a different window. Pass exactTitle: true to refuse the substring fallback entirely.

Output is written under SCREENCAST_HOME (default <homedir>/.screencast-mcp) into recordings/, frames/, screenshots/, and edits/. Any tool also accepts an explicit output path; a relative one resolves under that tool's SCREENCAST_HOME subfolder, never the server's working directory.

Output confinement. When the client sends workspace roots (the MCP roots capability), or SCREENCAST_ALLOWED_DIRS is set, an explicit output path (or sample_frames outputDir) must sit inside SCREENCAST_HOME, one of those roots, or one of those folders; anything else is refused with an error naming the allowed folders. The roots are re-read when the client reports they changed. With neither, any path you can write to is accepted, as before. doctor reports the folders in effect as storage.allowedOutputDirs.

Edit and produce tools write to a <name>.partial.<ext> file next to the output and rename it into place only when ffmpeg succeeds, so a failed, timed-out, or cancelled job never leaves a truncated file at output. The job timeout scales with the media's length (at least 10 minutes, or 4x the duration); set SCREENCAST_JOB_TIMEOUT_MS to override it. Clients that send a progress token get notifications/progress updates while a job runs, and cancelling the request stops ffmpeg.

Configuration

ffmpeg and ffprobe must be on PATH, or pointed at with FFMPEG_PATH / FFPROBE_PATH; the server checks per call and returns an install hint if either is missing (macOS: brew install ffmpeg; Linux: apt install ffmpeg, for the non-capture tools; distro packages may predate FFmpeg 8, so transcribe needs a newer static build). doctor shows what the ffmpeg in use supports.

Variable

Default

Purpose

SCREENCAST_HOME

<homedir>/.screencast-mcp

Where recordings, frames, screenshots, and edits are written

SCREENCAST_ALLOWED_DIRS

none

;-separated folders explicit outputs may also go to; when set, or when the client sends roots, outputs outside SCREENCAST_HOME, the roots, and these folders are refused

SCREENCAST_MAX_RECORDING_SEC

3600

Default recording cap (0 disables it)

SCREENCAST_JOB_TIMEOUT_MS

scales with length

Override the edit job timeout

SCREENCAST_WHISPER_MODEL

none

whisper.cpp model for transcribe

SCREENCAST_RETENTION_DAYS

off

Delete screenshots, frames, and leftover raw event logs older than this many days at startup (never recordings or edits)

SCREENCAST_PS_TIMEOUT_MS

20000 (OCR 60000)

Limit for the PowerShell helpers that list monitors and windows and run OCR

SCREENCAST_CONFIRM_CAPTURE

off

Set to 1 to ask the user to confirm every live capture (start_recording, screenshot, find_text on a target, wait_for_change) through MCP elicitation; clients without elicitation are refused

SCREENCAST_TOOLSETS

all

Comma-separated toolsets to expose (capture, watch, edit, produce, audio); the rest are not loaded, which shrinks the tool list the agent pays for on every turn

FFMPEG_PATH / FFPROBE_PATH

PATH lookup

Explicit ffmpeg / ffprobe binaries

Toolsets. The full tool list (tools/list) is about 70 KB, roughly 17k tokens of context; capture alone is about 16 KB. Set SCREENCAST_TOOLSETS to load only the groups an agent needs, for example capture,watch for a QA agent that records and looks but never edits. core (doctor, get_media_info) is always on; unset, empty, all, or a value naming no known toolset loads everything, and unknown names are ignored with a warning (and listed by doctor).

Toolset

Tools

capture

start_recording, stop_recording, pause_recording, resume_recording, save_replay, list_sessions, get_session, read_events, add_marker, screenshot, list_audio_devices, list_video_devices, list_targets

watch

review_recording, player_frames, sample_frames, contact_sheet, screen_diff, wait_for_change, find_text, index_recording, search_recording

edit

trim, concat, convert, export_gif, crop, scale, speed, compress, clip, cut_idle, cut_by_transcript, redact_region, pipeline

produce

overlay, callout, keystroke_overlay, cursor, backdrop, burn_subtitles, chapters, xfade_transition, assemble_highlights, title_card, reframe, zoom, export_preset, bug_report, step_guide

audio

extract_audio, normalize_audio, denoise, transcribe, music_bed, narrate

core (always)

get_media_info, doctor

The server also sends MCP instructions at initialize: the record, look, edit workflow, which tool to reach for when, and the toolsets in effect, so each tool's own description stays short.

Capture consent. With SCREENCAST_CONFIRM_CAPTURE=1, each live capture first asks the user through the client (MCP elicitation), showing what will be captured: the matched window, the duration, the audio source, and the output path. Only the user can answer, not the model, so a prompt injection cannot approve its own capture. Declining, cancelling, or not answering within 5 minutes captures nothing. A client that does not support elicitation fails closed: the tool returns an error and nothing is captured.

Log messages. The server declares the MCP logging capability: ffmpeg warnings (dropped frames, a full audio buffer, a warning from an edit job that still succeeded) and a recording that ends on its own (cap reached, window closed, recorder crash) are sent as notifications/message, filtered by the level the client sets with logging/setLevel.

Usage

Workflows: copy-paste recipes with the tool calls and real outputs are on the docs site: bug-repro clip for a PR, README demo GIF, agent UI verification loop, social clip, reviewing a long recording, zoom toward every click, and the whole edit in one call.

A typical watch loop — record, sample, look:

// 1. record a region for a few seconds
start_recording { "target": "region:0,0,1280,720", "quality": "draft" }
//    -> { "sessionId": "rec-…", "outputPath": "…/recordings/rec-….mp4" }

// 2. finalize the file
stop_recording { "sessionId": "rec-…" }
//    -> { "durationSec": 4.2, "finalizedGracefully": true }

// 3. look at it: the frames come back inline, so the model sees them directly
sample_frames { "input": "…/recordings/rec-….mp4", "timestamps": [0.5, 2, 3.5] }
//    -> { "frames": ["…/frames/…/frame_000_0.5s.png", …], "inlineImages": 3 }
//       + 3 image blocks the client shows to the model

Don't know where to look? sample_frames { "input": "…", "mode": "scenes" } returns only the frames where the screen actually changed (plus the opening frame), with their frameTimes. Screen recordings are mostly static, so this is usually far cheaper than a fixed rate. sceneThreshold (default 0.1) sets how big a change counts, and in fps mode dedupe: true drops near-identical frames.

screenshot { "target": "window:My App" } is the one-shot equivalent for a still, and also returns the image inline.

Catching a flaky failure: the useful footage is the half minute before the test failed, and by then it is too late to start recording. Run an instant-replay buffer instead and save it when something goes wrong:

// 1. keep a rolling 60 s buffer for the whole test loop (maxDurationSec 0 = no cap)
start_recording { "target": "window:My App", "replayBufferSec": 60, "maxDurationSec": 0, "events": true }
//    -> { "sessionId": "rec-…", "replay": { "bufferSec": 60, "segmentSec": 2 } }

// 2. a run fails: keep the last 30 s; the buffer keeps running for the next failure
save_replay { "sessionId": "rec-…", "lastSec": 30 }
//    -> { "outputPath": "…/recordings/replay-….mp4", "durationSec": 30, "eventsPath": "…/replay-….events.jsonl" }

// 3. done: stop and discard the buffer (save: true would write the whole buffer)
stop_recording { "sessionId": "rec-…" }

The buffer is a ring of 2 s MPEG-TS segments under SCREENCAST_HOME/replay, so disk use stays at about the buffer length plus 6 s however long it runs (the same bitrate as an ordinary recording of that target). Encoding costs the same CPU as an ordinary recording. A save snapshots the segments it needs, joins them and cuts with a stream copy, so it returns in about a second; the clip can hold up to 2 s of earlier frames behind an edit list (pass reencode: true for a frame-exact file). Buffers no live recording owns are deleted when the server starts.

Filing the bug an agent just reproduced (record with events: true so the clicks become steps):

bug_report { "sessionId": "rec-…", "title": "Save fails on a read-only folder", "expected": "The file saves or a clear error" }
//    -> { "outputDir": "…/edits/bug-report-…", "reportPath": "…/report.md", "steps": 6,
//         "errors": ["Error: Access to the path is denied."], "redaction": { "found": 1, … } }
// review report.md and the returned contact sheet, then:
gh issue create --title "Save fails on a read-only folder" --body-file …/report.md

Documenting a task as a how-to (record with events: true; add_marker between phases gives section headings):

step_guide { "sessionId": "rec-…", "title": "Export a report as PDF" }
//    -> { "outputDir": "…/edits/step-guide-…", "markdownPath": "…/guide.md", "htmlPath": "…/guide.html",
//         "steps": [{ "n": 1, "caption": "Click File", "section": "Open the report", "image": "step-01.png" }, …] }

Inline images are downscaled JPEGs (maxImageWidth, default 1280) and capped per call (maxInlineImages, default 8, max 20); the full-resolution PNGs stay on disk. Pass returnImage: false / returnImages: false to get paths only.

sample_frames writes at most maxFrames frames per call (default 100, max 1000). In fps mode it probes the video first; if the rate would exceed the cap, it samples at a lower rate so the frames still span the whole video, and the result's capNote says what it did.

Command line and CI

The same binary is a headless CLI when the first argument is a subcommand (no arguments still starts the MCP server). record records the screen while a command runs, exits with that command's code, and on failure writes a GIF of the last 30 s and a contact sheet:

npx -y @tmhs/screencast-mcp record --target full -- npm run test:e2e
npx -y @tmhs/screencast-mcp call doctor                # any tool, JSON args inline or @file.json

record options: --target, --fps, --out (default screencast-evidence), --artifacts failure|always|never, --last <sec>, --no-gif, --no-contact-sheet, --discard-on-success, --max-duration; it writes evidence.json alongside. For GitHub Actions on windows-latest, the composite action in action.yml wraps it and uploads the evidence as an artifact:

- uses: TMHSDigital/screencast-mcp@main # pin a release tag or SHA
  with:
    command: npm run test:e2e
    target: window:exe=MyApp.exe

More on the CI page.

Prompts and resources

Beyond tools, the server offers prompts: ready-made workflows that clients such as Claude Code and VS Code show as slash commands.

Prompt

What it does

bug-repro-clip

Record, find the bug moment, check for secrets, trim, annotate, and export a GIF for an issue.

file-bug-report

Record a repro with input events, package it with bug_report (redacted clip, GIF, steps, error text, report.md), review it, and file it with gh issue create once you confirm.

document-steps

Record a task with input events and markers, turn it into a step-by-step guide with step_guide, and tidy the captions.

demo-gif

Record a feature walkthrough and export a GIF small enough for a README or PR.

verify-ui-change

Screenshot before, make the change, wait for the screen to settle, diff, and confirm the text.

review-recording

Summarize what happens in a recording, with timestamps.

It also offers resources, so a client can list and attach recordings without a filesystem tool: screencast://sessions (every session), screencast://sessions/{id} (one session), and screencast://sessions/{id}/poster (a JPEG preview frame). Clients are notified when a recording starts or stops.

Windows notes

  • Multi-monitor offsets. gdigrab has no "capture monitor N" selector, so a monitor target captures the whole virtual desktop and crops to that display's pixel bounds (from System.Windows.Forms.Screen.AllScreens). monitor:1 grabs the second display at its real offset; monitor:0 is always primary.

  • Window capture resolves the window to the on-screen rectangle it occupies and captures that, rather than the window's own surface — gdigrab's native title= grab returns a blank frame for GPU- or DirectComposition-composited windows (Chrome, Electron, UWP). Target it by title, or without relying on the title by window:exe=Code.exe (that app's topmost window) or window:hwnd=0x1A2B (one exact window); results report the matched title. The window must be visible, on top, and not minimized (a minimized window is rejected with a clear error), the capture includes anything drawn over that rectangle, and for start_recording the rectangle is fixed once at start. Use backend: "wgc" (below) to capture the window itself instead.

  • Windows Graphics Capture (backend: "wgc", FFmpeg 8+). Captures a window's own surface by handle, even when other windows cover it. On screenshot and find_text it takes 1-2 s instead of ~0.2 s, so it is opt-in. On start_recording it records the window's client area while it is covered, moved, or in the background. gfxcapture only emits a frame when the window presents, so a small recorder process repaints one pixel of the window every 200 ms and repeats the latest frame at the requested fps; it stops on q like ffmpeg, so stop_recording and maxDurationSec work the same. The first frame takes a second or two, and start_recording returns once it is captured. No audio with wgc yet.

  • Fullscreen-exclusive apps often produce black frames under gdigrab; run the source in borderless-windowed mode for reliable capture.

  • System audio needs a loopback device. gdigrab is video-only, so start_recording with audio.source = system captures from a separate dshow input. Windows has no native loopback, so this needs a virtual-audio device (enable Stereo Mix, or install a driver such as screen-capture-recorder's virtual-audio-capturer or VB-CABLE). Run list_audio_devices to find it. Microphone capture is intentionally not supported.

  • Windows on ARM64. CI runs the unit, ffmpeg-integration and gdigrab capture-smoke suites on a native windows-11-arm runner with arm64 Node. gyan.dev has no arm64 build; CI uses BtbN's FFmpeg 8.1 winarm64-gpl-shared build (from a month-end autobuild-* release, which are kept), which has gdigrab, gfxcapture (WGC) and drawtext but is built without whisper and libvpx: transcribe and .webm output need another build. Run node scripts/platform-probe.mjs after npm run build to see what your machine supports (doctor now reports arch).

Privacy

  • The server makes no network requests and has no telemetry. It runs ffmpeg, ffprobe, and PowerShell on your machine and talks to your MCP client over stdio. OCR (find_text) and speech (narrate) use the engines built into Windows, so screen text and narration scripts are processed locally and never sent anywhere.

  • What a tool returns goes to your model provider. Inline screenshots and frames, OCR text, event summaries, and every other tool result reach your agent, and your client sends them to the model like any other tool result. Files on disk stay on disk unless a tool returns them or you share them.

  • What is stored, and where. Everything goes under SCREENCAST_HOME (default <homedir>/.screencast-mcp) unless a call names another path:

    • recordings/: recordings, plus each one's .events.jsonl when the event log is on

    • screenshots/: screenshot output, and find_text / wait_for_change captures only with keep: true

    • frames/: sample_frames and contact_sheet output

    • edits/: edit and produce output

    • sessions.json: the session registry (ids, targets, paths, times)

    find_text, wait_for_change, and screen_diff delete their captures after the call by default, since a secret scan's screenshot shows the secret.

  • What the event log records. Only with start_recording events: true (or cursor: "events", which also leaves the OS cursor out of the video for the cursor tool to redraw), and only while that recording runs. Mouse input is recorded system-wide, not only over the recorded window: clicks, scrolls, and the cursor position (sampled about 30 times a second), each with its time. Typing is recorded only as bursts, a start time and a length on a 0.5 s grid, with no key names and no per-key times: masked (default) records nothing more. shortcuts also records chords made with Ctrl, Alt, or Win by name (Ctrl+S), with their times; Ctrl+Alt+key that types a character on AltGr layouts stays typing. No mode records typed text. If the log has gaps (Windows removed the hook, input went to an elevated window or the lock screen, or the helper stopped), read_events reports truncated: true and lists them.

  • Microphone capture is not supported. System audio is recorded only with audio.source = system.

  • Deleting stored data. Delete files under SCREENCAST_HOME, or the whole folder while nothing is recording. Set SCREENCAST_RETENTION_DAYS to delete screenshots, frames, and leftover raw event logs older than that each time the server starts. Recordings and edits are never deleted automatically.

Threat model

WARNING

Screen capture can recordanything on screen at the moment of capture — passwords, tokens, private messages, and other secrets. window: captures the screen rectangle a window occupies, so overlays, notifications, or another window drawn over it are captured too. Treat recordings, screenshots, and sampled frames as sensitive by default.

  • Capture is always explicit. Nothing auto-fires; capture is gated behind an explicit tool call. Set SCREENCAST_CONFIRM_CAPTURE=1 to also require the user's confirmation, through the client, before each live capture (see Configuration).

  • The server makes no network requests. Files are written to the local filesystem only. What a tool returns to your agent (frames, OCR text, event summaries) is sent to your model provider like any other tool result; see Privacy.

  • Public repo, private captures. The .gitignore blocks recordings, frames, screenshots, and common video/image output so test media cannot be committed by accident.

  • Review before sharing. Sample frames or inspect a recording before handing a file to another tool or person, so you know what it contains. In clients that support MCP Apps, review_recording opens an inline player where a person can scrub the whole recording and draw redaction boxes before anything leaves the machine. The player gets frames through the MCP connection; no local web server is started.

  • Redaction covers what you declare. redact_region covers only the rectangles you specify. find_text can help find them: OCR with a query such as regex: "sk-|ghp_|api.?key" and redact: true returns ready-made rectangles, and scanEverySec checks a whole video rather than one frame. But OCR is best-effort; it can miss small or stylised text, so treat it as an aid, not a guarantee. Use the default box style for a solid irreversible fill, and still review the output before sharing.

  • The input event log never records what you type. start_recording events: true hooks mouse and keyboard input system-wide for that recording only, in a helper that exits with it (or with the server). Typing is logged only as bursts on a 0.5 s grid, never key by key, so the log does not reveal which keys were pressed, how many, or their timing. keys: "shortcuts" also names chords held with Ctrl, Alt, or Win (Ctrl+S). Cursor positions and clicks still reveal what you pointed at, so treat .events.jsonl like the recording beside it. See Privacy for exactly what each mode records.

  • System audio is sensitive too. When audio.source = system, the recording captures everything playing on the machine (call audio, notifications, media). Treat audio-bearing recordings with the same care as the video.

Project structure

.
├── src/
│   ├── index.ts          # MCP server entry (stdio); registers every tool, reaps orphans
│   ├── cli.ts            # headless CLI: record -- <command>, call <tool>
│   ├── prompts.ts        # MCP prompts (workflows as slash commands)
│   ├── resources.ts      # MCP resources (sessions, posters)
│   ├── wgcRecorder.ts    # recorder process for backend: "wgc"
│   ├── tools/            # one file per tool
│   ├── utils/            # pure builders and helpers (ffmpeg args, targets, sessions, ...)
│   └── __tests__/        # vitest: unit, ffmpeg integration, guarded local-capture harness
├── assets/               # bundled fonts and the review player (assets/ui)
├── docs/                 # GitHub Pages site; tools/, llms.txt, and the recipe pages are generated
├── scripts/              # Claude Desktop bundle (.mcpb) and the docs generators (npm run docs)
├── plugin/               # Claude Code plugin: the server plus workflow skills
├── action.yml            # GitHub Action: record a test run on windows-latest
├── mcp-tools.json        # tool manifest, generated from the registry by npm run docs
├── server.json           # MCP Registry listing (name matches package.json mcpName)
├── .github/workflows/    # CI, release, npm publish, Pages, ecosystem drift check
├── ROADMAP.md · CONTRIBUTING.md · SECURITY.md · LICENSE
└── package.json

Development

git clone https://github.com/TMHSDigital/screencast-mcp.git
cd screencast-mcp
npm install
npm run build      # tsc -> dist/
npm test           # vitest: unit tests, plus the ffmpeg integration suite when ffmpeg is on PATH
npm run dev        # tsx watch
npm run docs       # regenerate mcp-tools.json, the tool tables, docs/tools/, llms.txt

The tool tables in this README and on the site, mcp-tools.json, and the per-tool pages are generated from the registered tools' schemas; after adding or changing a tool, run npm run docs (the docs test fails on a stale copy; npm run docs:check checks without writing).

To run your build from a client, point it at dist/index.js: "command": "node", "args": ["C:/path/to/screencast-mcp/dist/index.js"].

The integration suite (src/__tests__/integration) runs the real edit and produce builders through ffmpeg against lavfi-generated fixtures and checks the probed result (durations, dimensions, streams, loudness). It skips when ffmpeg is missing; set REQUIRE_FFMPEG=1 to make a missing ffmpeg fail instead, as CI's Linux job does.

The capture path can't be exercised on CI's headless Linux runners, so an end-to-end harness lives behind a flag and is skipped by default:

RUN_LOCAL_CAPTURE_TESTS=1 npm test   # Windows + ffmpeg + a real display

Agent evals (evals/) score tool selection, argument validity and outcomes on scripted tasks against lavfi-generated fixtures, through the built server over MCP. The default oracle mode replays known-good calls and needs no model or network; --agent anthropic runs a real model (install the SDK ad hoc with npm install --no-save @anthropic-ai/sdk; EVAL_MODEL defaults to claude-sonnet-5-5). Live-capture tools are always blocked.

npm run build && npm run eval                  # oracle mode
npm run eval -- --agent anthropic --json evals/results/baseline.json

Contributing

Issues and pull requests are welcome — see CONTRIBUTING.md and the Code of Conduct. Security reports go through SECURITY.md.

License

Released under the CC-BY-NC-ND-4.0 license: free to use and share for non-commercial purposes, with attribution and without modification. For other uses, open an issue.

Can I use it at work? Only for non-commercial purposes under this license. If your use is commercial (inside a paid product or service, or work done mainly for commercial advantage), or you are not sure, open an issue to ask about a commercial license. The licensing model is described in the TMHSDigital licensing standard.

Documentation · Roadmap · Report an issue · License

Built by TMHSDigital · Back to top ↑

Available Tools

57 tools
add_markerAdd MarkerA

Mark a labelled moment on a recording, live or at a second. Kept in the session and a sidecar; chapters and pipeline turn markers into chapters.

NameRequiredDescriptionDefault
atNoVideo second (default: now, while recording).
inputNoOr a video path (needs at).
labelYese.g. "bug appears".
sessionIdNoRecording to mark (a stopped one needs at).

Output Schema

NameRequiredDescription
countYes
markersPathYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a non-destructive write operation. The description adds useful behavior beyond the annotations by disclosing persistence ('Kept in the session and a sidecar') and downstream consumption by chapters and pipeline.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no wasted words. The core action is front-loaded, followed immediately by persistence and downstream behavior.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that annotations, a fully documented schema, and an output schema are present, the description supplies the key missing context: markers persist in session and sidecar and feed chapters/pipeline. It does not elaborate on permissions or error behavior, but little is missing for a simple marking tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the detailed parameter meanings are already documented in the schema. The description adds only the high-level distinction between live marking and marking at a second, which is useful but not more specific than the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Mark a labelled moment on a recording') plus the two modes ('live or at a second'). It also differentiates markers from the sibling 'chapters' tool by explaining that 'chapters and pipeline turn markers into chapters.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when this is appropriate: while recording live or at a specific second. It does not state explicit exclusions or name a direct alternative, but the consumer relationship with 'chapters' and 'pipeline' makes the intended workflow clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

assemble_highlightsAssemble HighlightsB
Destructive

Stitch clips (including title cards) into one video with cuts or xfade transitions; they need not match in size, fps, or audio.

NameRequiredDescriptionDefault
fpsNoCommon output fps (default 30).
clipsYesClip paths, in order.
widthNoCommon output width (default 1920).
heightNoCommon output height (default 1080).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
durationNoTransition seconds (default 1).
overwriteNoAllow replacing an existing file at the output path (default false).
transitionNocut (default) or an xfade name (fade, wipeleft, slideup, ...).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the agent knows this is a write operation. The description adds useful context that inputs need not match in size, fps, or audio, which is beyond the schema. But it does not mention overwrite behavior or that it creates a new file at the output path, leaving some behavioral gaps for a destructive tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no wasted words. It conveys the core action and a key differentiator efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given rich annotations, a complete input schema, and an output schema, the description covers the main purpose and a key constraint (heterogeneous inputs). Minor gap: it does not mention the overwrite/destructive aspect, but that is partially covered by annotations and the overwrite parameter description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all parameters are documented in the schema. The description adds no additional meaning about parameters beyond what the schema provides; baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('stitch') and resource ('clips into one video'), and notes it handles title cards and heterogeneous inputs. However, it does not explicitly name the sibling tool concat, which likely handles similar stitching with matching properties, so sibling differentiation is only implied.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus concat or xfade_transition, nor any exclusions or prerequisites. The mention of cuts or xfade transitions is about capability, not selection criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

backdropAdd BackdropA
Destructive

Frame a video or screenshot on a gradient, color, or wallpaper with padding, rounded corners, and a drop shadow, optionally on a 16:9/1:1/9:16/4:5 canvas.

NameRequiredDescriptionDefault
imageNoInstead: a wallpaper image, scaled to cover.
inputYesPath to the source video or image (png/jpg).
aspectNoOutput on this aspect's canvas (1920x1080, ...), content scaled to fit.
colorsNoInstead: 1 color = solid, 2-4 = diagonal gradient.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits (screenshots for an image).
presetNoGradient: desktop (default, dark slate), rec (red), amber, light.
radiusNoCorner radius px (default ~1.2% of the longer side; 0 = square).
shadowNoShadow blur px (default ~2.5%; 0 = none).
paddingNopx around the content (default 6% of the longer side).
overwriteNoAllow replacing an existing file at the output path (default false).
shadowOpacityNoDefault 0.5.

Output Schema

NameRequiredDescription
widthYes
heightYes
outputPathYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true with openWorldHint=false, so the agent knows this writes files in a closed local scope. The description adds the canvas/aspect constraint but does not warn about overwriting existing output paths or that the operation is non-idempotent, which is exactly the behavior the destructive flag is pointing at.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One well-formed sentence, front-loaded with the verb and the tool's value proposition, with the optional canvas variants trailing. Every clause maps to a parameter or capability; nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists and all parameters are documented, so the description only needs to convey core behavior, which it does. It falls slightly short on when-to-use guidance and file-writing/overwrite semantics, but for an 11-param tool with a fully documented schema this is close to sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so every parameter is already documented, including enum values and defaults. The description restates the treatments (padding, rounded corners, drop shadow, gradient) but adds no syntax or precedence detail (e.g., how colors vs. image vs. preset interact) beyond the schema, making a baseline 3 correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('Frame') applied to a specific resource (video or screenshot) and enumerates the distinct visual treatments (gradient, color, wallpaper; padding, rounding, shadow, canvas aspect). No sibling tool (overlay, callout, title_card, reframe) offers this composite framing behavior, so an agent can distinguish it at a glance.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It implies usage ('Frame a video or screenshot') and lists the canvas options, but never states when to pick this over reframe, overlay, or title_card, nor any prerequisites or exclusions. The context is inferred rather than spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bug_reportBug Report PackageA
Destructive

Package a recording as a paste-ready repro folder: secret-scanned, redacted clip and GIF, contact sheet, steps from the event log, OCR'd errors, environment, report.md for gh issue create --body-file.

NameRequiredDescriptionDefault
endNoClip end s (default: recording end).
gifNoAlso export a GIF (default true).
inputNoRecording path (uses its .events.jsonl).
startNoClip start s (default: end - clipSec).
titleNoIssue title.
actualNoWhat happened.
redactNoBox out OCR-found secrets in every output (default true; needs Windows OCR).
clipSecNoClip length without start (default 30).
regionsNoExtra boxes (video px; start/end on the clip clock).
expectedNoWhat should happen.
maxBytesNoGIF size budget (default 10000000).
maxFramesNoScan frame cap (default 30).
outputDirNoPackage folder (default: a new one in SCREENCAST_HOME/edits).
overwriteNoReplace a report already in outputDir.
sessionIdNoOr a stopped session's id.
errorPatternNoError-line regex.
scanEverySecNoOCR every N s (default 1).
secretPatternNoSecret regex (default: API keys, tokens, password: values).

Output Schema

NameRequiredDescription
clipPathYes
jsonPathYes
outputDirYes
reportPathYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is partly covered. The description adds useful behavioral context: the package is secret-scanned, outputs are redacted, OCR is used, steps come from the event log, and a report.md is generated for gh issue create. It does not explicitly warn about overwriting an existing report, but the schema's overwrite parameter covers that detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence that names the core action first and then lists the packaged artifacts. Every clause corresponds to a real output or processing step, and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 18 optional parameters, full schema descriptions, annotations, and an output schema, the description is sufficiently complete at the task level. It explains what the package contains and how it is built. The main remaining gap is not naming an input recording or sessionId explicitly in the prose, but the schema covers those parameters fully.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 18 parameters in detail. The description does not add syntax or meaning beyond what the schema provides; it only confirms that redaction, GIF export, OCR, and report generation are supported. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: package a recording as a repro folder. The listed outputs (redacted clip/GIF, contact sheet, steps, OCR'd errors, environment, report.md) make clear this is a bug-report packaging tool, not a generic export, screenshot, or step guide. It is readily distinguishable from sibling tools like export_gif or contact_sheet.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the usage scenario: creating a paste-ready bug repro package for gh issue create. However, it does not explicitly say when to use this versus alternatives such as step_guide, review_recording, or manually combining screenshot/contact_sheet/export_gif. No exclusions or prerequisites are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

burn_subtitlesBurn In SubtitlesA
Destructive

Burn SRT/ASS subtitles (e.g. from transcribe) into a video in the bundled font.

NameRequiredDescriptionDefault
inputYesPath to the source video.
styleNoclean (default for .srt): outlined line. social: big bold text on a dark box. .ass keeps its own styling unless set.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).
subtitlesYesPath to an .srt (e.g. from transcribe) or .ass subtitle file.

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false and openWorldHint=false, so the risk profile is covered. The description adds only the 'bundled font' constraint (styling is fixed, not user-supplied), and says nothing about whether the source video is preserved or how overwrite protection behaves — though the schema covers the latter.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence naming the action, the input formats, and the styling constraint; nothing redundant. The mention of the source tool is a compact, useful workflow cue rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema and full parameter documentation, the essentials are covered. However, for a destructive, non-idempotent media write, the description omits whether the input video is left untouched and what happens when subtitles cannot be parsed or the chosen style conflicts with .ass styling — gaps the structured fields don't close.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including the style enum's meaning and the output/overwrite defaults, so the schema does the heavy lifting. The description adds almost nothing parameter-level beyond reinforcing accepted subtitle formats, which the schema already states — baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: burn subtitles (SRT/ASS) into a video. The parenthetical '(e.g. from transcribe)' ties it to the upstream sibling, so the agent can place it in a workflow, though it does not explicitly contrast with adjacent post-processing tools like overlay or title_card.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The reference to transcribe implies a when-to-use context (caption burn-in after transcription), but there is no explicit statement of when to prefer this over overlay/title_card, nor any prerequisite or exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

calloutAdd CalloutsA
Destructive

Annotate a video with timed boxes, text labels, and arrows. Fallback fonts used are listed in fallbackFonts; characters no font covers are reported in warnings.

NameRequiredDescriptionDefault
inputYesPath to the source video.
itemsYesBoxes, text labels, and arrows, drawn in order (later on top), in video pixels. Each shows from..to seconds (default: whole video); color is a name, #RRGGBB, or name@alpha.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
fontFileNoFont: a .ttf/.otf/.ttc path or a C:\Windows\Fonts file name. Default: bundled Inter, with a covering system font for scripts it lacks (CJK, emoji, Arabic, ...).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false, and readOnlyHint=false, so the safety bar is low. The description adds genuine beyond-annotation context by disclosing that substituted fonts appear in fallbackFonts and uncovered characters surface in warnings, which is real behavioral information. It stops short of explaining what 'destructive' means here (the output path/overwrite interaction).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the core action front-loaded and the fallback-font caveat following. Every sentence carries information and nothing is repeated from the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full parameter coverage, the description need not explain return values, and it correctly flags the fallbackFonts/warnings fields. It leaves the destructive-overwrite relationship to the schema, which is acceptable but a small gap for a tool annotated as destructive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all five parameters are already documented, including from/to timing, color formats, and overwrite semantics. The description adds no parameter-level detail beyond what the schema provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb and resource (annotate a video) plus the three annotation kinds it draws (timed boxes, text labels, arrows). This is enough to distinguish it functionally from generic tools like overlay or title_card, though it never names a sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies annotation but gives no when-to-use condition, no prerequisites, and no guidance on choosing it over annotate-adjacent siblings such as overlay, title_card, or cursor. Nothing tells the agent when this is the wrong tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

chaptersChaptersA
Destructive

Write chapters (markers, scene changes, transcript, or a list) into an mp4/mkv/mov copy without re-encoding; returns YouTube chapter text. Can mux an SRT as soft subtitles.

NameRequiredDescriptionDefault
fromNomarkers (default; add_marker, else the file's chapters), scenes (screen changes), or transcript (SRT sections).
inputNoPath to the video.
outputNoOptional .mp4/.mkv/.mov path. Defaults under SCREENCAST_HOME/edits.
chaptersNoOr explicit { start, title } chapters.
textOnlyNoReturn chapters and YouTube text only; write no file.
overwriteNoAllow replacing an existing output file.
sessionIdNoOr a stopped recording's id.
subtitlesNoAlso mux this .srt/.vtt/.ass as a soft subtitle track.
transcriptNoThe .srt for from: transcript.
minChapterSecNoShortest chapter (default 1; scenes 10, transcript 30).
subtitleLanguageNoISO 639-2, e.g. "eng".

Output Schema

NameRequiredDescription
youtubeYes
chaptersYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, and the description usefully clarifies the operation writes into a *copy* without re-encoding, so the source video is not mutated, and that default output lands under SCREENCAST_HOME/edits. It still does not mention that an existing output requires the overwrite flag or what happens on failure, but the annotations plus the copy semantics cover the main risk.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action, and the parenthetical enumerates sources compactly. The trailing subtitle sentence is slightly bolted-on but each sentence carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present the description needn't explain returns, and the no-re-encoding/copy detail is valuable for a destructive tool. However, with zero required parameters across 11 options there are meaningful input combinations (input vs sessionId, transcript required for from:transcript) that the description does not disambiguate, leaving gaps the schema alone must close.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents every parameter including the `from` enum and default minChapterSec values. The description restates the source options ('markers, scene changes, transcript, or a list') and subtitle muxing, adding confirmation but no format or default detail beyond the schema — the baseline 3 for full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (write) and resource (chapters) plus the accepted sources and the fact it operates on an mp4/mkv/mov copy without re-encoding. It also flags two side capabilities (YouTube text output, soft-subtitle mux) that separate it from plain subtitle tools, though it never names a sibling such as burn_subtitles.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied through the enumerated chapter sources (markers, scenes, transcript, explicit list); there is no explicit 'use this when...' statement and no exclusion of alternatives. The natural alternative, burn_subtitles for hard-burned subs versus this tool's soft mux, is never distinguished, leaving the agent to infer the routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

clipExtract ClipsA
Destructive

Extract several frame-exact segments, each to its own file. For one segment, trim does the same.

NameRequiredDescriptionDefault
inputYesPath to the source video.
outputNoOptional output path. Only honored for a single segment; multi-segment output lands under SCREENCAST_HOME/edits.
segmentsYes{start, end} segments in seconds; each becomes its own file.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
countYes
outputsYes

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare write, destructive, non-idempotent, and closed-world behavior. The description adds useful context about frame-exact extraction and one-file-per-segment output, but it does not elaborate on overwrite behavior or other destructive details beyond what annotations and schema provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action, and the sibling distinction is placed immediately after. No wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a complete input schema and an output schema, the description supplies the essential selection context and the trim alternative. It is nearly complete, though it could briefly reinforce multi-segment output destination behavior, which is currently only in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so parameter meanings are already fully documented. The description adds only the notion that each segment produces its own file; it does not provide additional syntax or constraints beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: extract frame-exact segments, with the output behavior that each segment becomes its own file. It also distinguishes the tool from the single-segment sibling trim.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly routes the agent away from single-segment use by noting trim does the same for one segment. It does not explicitly state prerequisites or all when-not conditions, but the key alternative is named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compressCompress VideoA
Destructive

Re-encode a video smaller (H.264 CRF ladder, optional width cap). For a platform target use export_preset.

NameRequiredDescriptionDefault
inputYesPath to the source video.
levelNoCRF 23 / 28 / 32 (default medium).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
maxWidthNoWidth cap in px (only downscales).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already disclose destructiveHint=true and idempotentHint=false, so the safety profile is covered. The description adds the CRF ladder mechanism, useful context beyond annotations, but doesn't say what gets overwritten, that output defaults under SCREENCAST_HOME/edits, or that overwrite=false by default — all relevant for a destructive, non-idempotent tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero waste, with the mechanism stated first and the routing hint second. Nothing redundant against the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema and full annotations, the description doesn't need to explain return values or safety. It's sufficient to call correctly, though it leaves the overwrite/destructive semantics implied rather than stated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so every parameter is already documented, including CRF values per level and the downscale-only behavior of maxWidth. The description merely echoes 'CRF ladder' and 'width cap' without adding syntax or defaults beyond the schema — baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Re-encode a video smaller') and immediately qualifies the mechanism (H.264 CRF ladder, optional width cap), which distinguishes it from encode-adjacent siblings like convert and export_preset. An agent can tell exactly what this tool produces.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'For a platform target use export_preset' names the alternative and the condition selecting it. It doesn't address other plausible rivals (scale, convert) or note when not to compress, so it's clear but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

concatConcatenate VideosA
Destructive

Join videos end to end with hard cuts: stream copy when they match, else a re-encode (mode says which). For transitions use xfade_transition or assemble_highlights.

NameRequiredDescriptionDefault
inputsYesVideo paths to join, in order.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false and openWorldHint=false, so the safety profile is covered. The description adds genuinely new behavioral context the annotations cannot: it explains the two execution paths (stream copy when inputs match, re-encode otherwise), which tells the agent results may differ in quality/speed depending on input compatibility. It stops short of saying what happens to an existing output file or whether re-encoding loses quality, keeping it out of 5 territory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly packed sentences with zero filler: the core behavior first, the sibling routing second. Every clause carries information an agent needs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and the description covers purpose, execution modes, and alternatives. The remaining gap is the phantom `mode` reference, which leaves the agent guessing whether mode selection is automatic or exposed as a parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so inputs/output/overwrite are already documented and the baseline is 3. The description does add meaning about `inputs` (matching inputs allow stream copy, mismatched ones force a re-encode), but it also references a `mode` parameter that does not exist in the schema — a misleading pointer an agent could act on and get an error.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Join videos end to end with hard cuts') and scopes it to hard cuts only, which immediately separates it from transition-based siblings. It names the exact alternatives (xfade_transition, assemble_highlights) an agent should consider instead, so the tool is distinguishable without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gives the alternative and the condition that selects it: 'For transitions use xfade_transition or assemble_highlights.' That is the classic when-not-use routing an agent needs, and it is stated rather than implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

contact_sheetContact SheetB
Destructive

Tile timestamped frames of a video into one image to see a whole recording at a glance (the cheapest first look).

NameRequiredDescriptionDefault
modeNoeven (default) or scenes (strongest changes; static stretches take no tiles).
countNoFrames to tile (default 12).
inputYesPath to the source video.
outputNoOptional output .png path. Defaults under SCREENCAST_HOME/frames.
posterNoWrite one representative poster frame instead of a sheet.
columnsNoTiles per row (default: roughly square).
overwriteNoAllow replacing an existing file at the output path (default false).
tileWidthNoTile width in px (default 320).
returnImageNoReturn the sheet inline (default true).
maxImageWidthNoMax inline image width (default 1280).
sceneThresholdNoMode scenes: change needed, 0-1 (default 0.1).

Output Schema

NameRequiredDescription
outputPathYes
inlineImagesYes

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and readOnlyHint=false, yet the description never explains why: it writes a PNG to disk, has an overwrite guard defaulting to false, and can emit a poster frame instead of a sheet. Those are precisely the behaviors an agent needs before calling a destructive tool, and the description adds none of them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the action and result, with the parenthetical qualifier earning its place by signaling cost. There is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema and full schema descriptions cover return values and parameters, so the description needn't restate them. But for an 11-parameter tool that writes files destructively, the absence of any note on disk output, the overwrite guard, or the even-vs-scenes tradeoff leaves a meaningful gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter including mode, count, poster, and overwrite is already documented in the schema. The description adds no syntax, defaults, or mode-selection guidance beyond what structured data provides, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('tile timestamped frames of a video into one image') plus the resulting artifact, so an agent knows exactly what is produced. It hints at its place in the workflow ('cheapest first look') but never names the nearest sibling, sample_frames, so differentiation is only implied.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'The cheapest first look' implies a first-pass triage use case, which is useful context. However, there is no explicit when-not guidance and no alternative named (sample_frames, review_recording, get_media_info), so the agent must infer the routing decision.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

convertConvert FormatA
Destructive

Convert media to mp4, webm, or gif. For a size-bounded GIF/WebP prefer export_gif; for a smaller mp4, compress or export_preset.

NameRequiredDescriptionDefault
fpsNogif only: fps (default 12).
inputYesPath to the source media.
widthNogif only: width in px (default 720).
formatYesmp4 (H.264), webm (VP9), or gif (palette).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, non-idempotent, and non-read-only behavior, so the safety profile is covered. The description adds format-specific intent but does not elaborate on overwrite behavior, side effects, or output handling beyond what the schema already states.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with the core action front-loaded and alternatives immediately afterward. There is no wasted prose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema and fully described input schema, the description does not need to explain return values or parameter syntax. It is nearly complete, though it could clarify overwrite/destructive behavior slightly more given that the tool writes files.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all six parameters including fps, width, format, output, and overwrite are documented in the schema. The description adds no parameter-level detail beyond the format list, which is already covered by the schema's format enum.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (convert media) and enumerates the exact output formats, so the agent can distinguish it from generic editing tools. It also names sibling alternatives for specific cases, making the tool's scope clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent away from this tool when a size-bounded GIF/WebP is desired (prefer export_gif) and when a smaller mp4 is desired (compress or export_preset). That is concrete alternative guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cropCrop VideoB
Destructive

Crop a video to a pixel rectangle; one running off the frame is rejected.

NameRequiredDescriptionDefault
xYes
yYes
inputYesPath to the source video.
widthYes
heightYes
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the safety profile is covered structurally. The description adds one genuinely useful behavioral fact: out-of-frame rectangles are rejected rather than clamped. It says nothing about what is destroyed (e.g. overwriting an existing output) or about defaults, so it only partly extends the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the operation first and the constraint second; no filler and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, non-idempotent mutation with 7 parameters, 43% schema coverage, and an output path default under SCREENCAST_HOME/edits, the description omits coordinate-origin semantics and overwrite behavior. An output schema exists, so return values need no explanation, but the input-side gaps are material.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 43%, so the description needs to compensate, yet it says nothing about x/y being the rectangle origin, whether that origin is top-left, or how width/height interact with odd dimensions. The phrase 'pixel rectangle' only weakly signals that the four required integers are pixel units.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb (crop) and resource (video) plus the unit of the operation (a pixel rectangle), which clearly separates it from generic transforms. It does not name or contrast with adjacent siblings such as reframe, scale, or trim, so an agent must still infer the boundary itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to choose crop over reframe, scale, or trim, and no prerequisites or side conditions are mentioned. The only extra clause ('one running off the frame is rejected') is a validation rule, not usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cursorRe-rendered CursorA
Destructive

Draw a smoothed, scaled cursor that hides when idle from the event log of a start_recording cursor: "events" recording (no OS cursor in the video), with click ripples and an optional spotlight.

NameRequiredDescriptionDefault
sizeNoTimes a typical cursor's size (default 1.5).
inputYesPath to the recording.
clicksNoRipple on clicks (default true).
dryRunNoReturn the plan; write nothing.
eventsNoEvent log (default: the input's .events.jsonl).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).
smoothingNo0 = as logged, 1 = floaty (default 0.5).
spotlightNoDim all but the area around the cursor.
hideAfterSecNoHide when the mouse rests this long; 0 = never (default 2).

Output Schema

NameRequiredDescription
segmentsYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the write profile is covered. The description adds real behavioral detail (hides when idle, click ripples, optional spotlight) but largely mirrors schema parameters (clicks, spotlight, hideAfterSec) and says nothing about the output file/dry-run/overwrite semantics, which only the schema carries.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the action, no wasted words. The nested clause "from the event log of a start_recording cursor:\"events\" recording" is syntactically awkward and needs re-reading, costing it the top score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and 100% parameter coverage, the description needn't explain returns or per-param syntax. It supplies the crucial input-dependency context; the only gap is that destructive/write-file behavior is delegated entirely to annotations and the overwrite/dryRun params.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with all 10 parameters documented (size scaling factor, smoothing 0–1, hideAfterSec semantics, dryRun, overwrite). The description adds only a gloss on smoothing/scale/ripples/spotlight that the schema already specifies, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ("Draw a smoothed, scaled cursor") and names the exact input it applies to: the event log of a start_recording cursor:"events" recording. This differentiates it from keystroke_overlay/callout overlays by identifying the required recording mode, though it never names a sibling alternative directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear precondition for use — the recording must have no OS cursor baked in and must be cursor:"events" — so an agent knows which recordings this applies to. It stops short of explicit when-not-to-use rules or naming a fallback tool when those conditions fail.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cut_by_transcriptCut By TranscriptB
Destructive

Edit a video by its transcript: cut quoted text, cue numbers, or fillers. Also writes the re-timed .srt.

NameRequiredDescriptionDefault
srtYesIts .srt (transcribe; words: true for word timing).
inputYesPath to the source video.
dryRunNoOnly report the cuts.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
removeNoCue numbers, or transcript text quoted exactly (must occur once).
fillersNoAlso cut fillers (um, uh...) that have their own cue.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
cutsYes
removedSecYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the mutation profile is covered structurally. The description adds useful behavioral context by saying it cuts transcript elements and also writes a re-timed .srt, but it does not elaborate on overwrite behavior, dry-run reporting, or how the output file relates to the source.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single front-loaded sentence with a clarifying colon and a second clause for the .srt side effect. Every clause is informative and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full schema coverage, the description need not explain return values or every parameter detail. It covers the core action and the important side effect of writing a re-timed .srt, though it leaves usage selection against sibling editing tools implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all parameters in detail, including the remove and fillers parameters. The description echoes the remove/filler concepts but adds no syntax or constraints beyond what the schema provides, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Edit') and resource ('video by its transcript') and enumerates the transcript-based cut modes: quoted text, cue numbers, and fillers. This clearly distinguishes the tool from generic trimming or clipping siblings by mechanism, but it does not explicitly name or compare against those alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit guidance on when to use this tool versus siblings like trim, clip, or cut_idle, nor are prerequisites or exclusions stated. The transcript-based framing implies a use case, but the agent must infer the selection conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cut_idleCut Idle StretchesA
Destructive

Remove dead air: cut stretches where the screen is frozen (and silent), keeping a short pad. Returns the time saved.

NameRequiredDescriptionDefault
inputYesPath to the source video.
dryRunNoOnly report what would be cut.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
keepSecNoSeconds kept at each edge of a cut (default 0.4).
useAudioNoRequire silent audio too (default true when there is audio).
overwriteNoAllow replacing an existing file at the output path (default false).
minIdleSecNoOnly cut still stretches at least this long (default 2).

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructive=true, readOnly=false and non-idempotent, so the safety profile is covered. The description adds genuinely non-structured behavior: the detector requires frozen frames AND silence, a short pad is preserved at each edge, and the call reports time saved — details an agent can't get from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the operation and its detection criteria are front-loaded, and the return value follows. No filler, nothing repeated from the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter destructive tool with no output schema, the description covers what is cut, the safety pad, and the return value (time saved), while the schema carries paths, overwrite, and dryRun. What's missing is whether the source is left untouched (a new file under edits/) — relevant for a destructive-hinted tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all seven parameters are already documented, making 3 the baseline. The description does add a conceptual link ('keeping a short pad' ↔ keepSec, '(and silent)' ↔ useAudio) but no formats, units, or defaults beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource: 'cut stretches where the screen is frozen (and silent)' precisely describes the operation, and 'remove dead air' frames the intent. It differentiates itself implicitly from trim/cut_by_transcript by naming the detection signal (frozen screen + silence), though it doesn't call out a sibling by name.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Remove dead air' implies the use case (a recording with idle/frozen spans), but there is no explicit when-to-use vs. when-not, and no routing to alternatives such as cut_by_transcript (which removes silence/speech-based gaps) or trim. An agent must infer that this is the screen-freeze variant.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

denoiseDenoise AudioA
Destructive

Reduce steady background noise (fan, hum, hiss) in a recording's audio with an adaptive FFT denoiser. Video is copied untouched. Returns the output path.

NameRequiredDescriptionDefault
inputYesPath to the source video or audio file.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
strengthNoHow hard to reduce noise: light (6 dB), medium (12 dB, default), strong (20 dB).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds useful behavior beyond the annotations: the denoiser is adaptive FFT-based, video is copied untouched, and the tool returns the output path. With destructiveHint=true already declared, this context helps clarify the operation, though it could more explicitly state whether the source file is left unchanged.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences are front-loaded with the core purpose, then add two important behavioral facts. There is no redundant or filler text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter media transformation tool with full schema coverage, annotations, and an output schema, the description is complete enough. It covers the operation, the untouched video stream, and the returned output path without needing to restate structured details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameter meanings are already well documented in the input schema. The description does not add parameter-specific semantics beyond what the schema provides, making 3 the appropriate baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: reduce steady background noise in a recording's audio using an adaptive FFT denoiser. The examples of fan, hum, and hiss make the purpose concrete and distinguish it from adjacent audio tools such as normalize_audio or compress.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear condition for use by naming steady background noise such as fan, hum, and hiss. It does not explicitly state when not to use it or point to sibling alternatives, so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doctorCheck SetupA
Read-onlyIdempotent

Check the setup: ffmpeg/ffprobe (FFmpeg 8+?), optional filters, capture devices, Windows OCR, settings, and enabled toolsets; problems says what is missing and how to fix it. Call on first use or when a tool reports a missing feature.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
okYes
envYes
ocrYes
wgcYes
ffmpegYes
serverYes
devicesYes
ffprobeYes
filtersYes
storageYes
problemsYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive/closed-world, so the safety profile is covered. The description adds genuine value beyond that: it explains the `problems` output tells what is missing and how to fix it, framing this as diagnosis rather than repair. It doesn't mention cost or runtime of the checks, but that's minor.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, both load-bearing: the first scopes the checks, the second states the trigger. The trigger guidance is placed last where it's easy to find, and nothing is repeated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't spell out return values, and it still flags the key `problems` field. For a read-only, zero-parameter diagnostic, everything an agent needs to decide to call it is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing to document and the baseline of 4 applies. The description correctly requires no input to invoke it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific action (check the setup) and enumerates exactly what is inspected: ffmpeg/ffprobe versions, optional filters, capture devices, Windows OCR, settings, and enabled toolsets. None of the siblings do diagnostics, so an agent can distinguish this from the recording/editing tools without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives two explicit trigger conditions — 'Call on first use' and 'when a tool reports a missing feature' — which is precisely the when-to-use guidance an agent needs for a diagnostic tool. The alternative (remediation tools) is implicitly excluded because this only reports problems.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_gifExport GIF or WebPA
Destructive

Export an animated GIF or WebP that fits a size budget (for PRs, issues, READMEs), stepping fps, width, and quality down until it fits.

NameRequiredDescriptionDefault
fpsNoStarting frame rate (default 12).
inputYesPath to the source video.
startNoStart second.
widthNoStarting width in px (default 960).
formatNogif (default) or webp (usually much smaller).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
durationNoSeconds to export (default: to the end).
maxBytesNoSize budget in bytes (default 10000000, under GitHub's 10 MB image limit).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and non-idempotent, so the write/safety profile is already covered. The description adds the important behavioral fact that the tool iteratively steps fps, width, and quality down until the budget is met, which is not inferable from annotations or schema. It doesn't mention overwrite semantics, but the schema spells those out.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the action and its purpose, then the adaptive mechanism. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description doesn't need to explain return values, and full schema coverage handles parameters. What it must convey — the self-tightening export behavior — it does, though it could note the default format or the overwrite implication for full completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description's phrasing frames fps/width as starting points that get reduced, which reinforces but does not meaningfully exceed the schema's own 'Starting frame rate'/'Starting width' wording.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (export GIF/WebP) plus the defining mechanism: it degrades fps/width/quality until it fits a size budget. That mechanism is what separates it from siblings like convert, compress, and export_preset. It does not explicitly name those siblings, so it falls just short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage context ('for PRs, issues, READMEs'), which implies when to reach for it. However, it offers no exclusions and doesn't route the agent away from convert, compress, or export_preset when those might be the better fit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_presetExport for PlatformB
Destructive

Encode a platform-ready H.264 file (aspect, fps, bitrate, faststart) for a named platform.

NameRequiredDescriptionDefault
fitNoFit to the platform aspect: pad (default) or crop.
inputYesPath to the source video.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
platformYesSets aspect, size, fps, bitrate. steam_trailer: 1080p 5.5 Mbps CBR, -14 LUFS. vertical_reel: 1080x1920 over a blurred copy of itself, -14 LUFS (ignores fit).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is known. The description adds useful encoding traits (aspect, fps, bitrate, faststart) but says nothing about whether an existing output file gets replaced or where files land, which is the destructive behavior an agent should be warned about.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence that front-loads the verb and the output format. Nothing redundant or padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, and every parameter is documented in the schema. However, for a tool flagged destructive with an overwrite option, the description should mention the overwrite/replacement behavior and output location to be fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the enum semantics for platform, fit, output, and overwrite are fully documented in structured data. The description only reiterates the platform-driven settings (aspect, fps, bitrate) already present in the schema, adding no new meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb (encode) plus resource (platform-ready H.264 file) and scope (a named platform), so the agent knows exactly what the tool produces. It doesn't distinguish itself from nearby siblings like export_gif or compress, which leaves some ambiguity about which export path to take.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers no when-to-use conditions and never mentions alternatives such as compress, convert, or export_gif. The only implied usage is that the platform parameter drives the settings, which the schema already states.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

extract_audioExtract AudioA
Destructive

Extract the audio track of a media file to its own file (mp3, aac, wav, or copy). Returns the output path.

NameRequiredDescriptionDefault
inputYesPath to the source media.
formatYesAudio output codec. copy keeps the source codec without re-encoding.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=false, so the write/overwrite risk is flagged by structured data. The description adds that output goes 'to its own file' and returns that path, but does not restate the overwrite default or warn that an existing file at the target path may be replaced — context that would matter for a destructive tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the operation and formats come first. The trailing 'Returns the output path' is largely redundant given the tool has an output schema, costing it a perfect score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full-coverage schema, annotations covering the safety profile, and an output schema handling return values, the description is sufficient to call the tool correctly. The remaining gap is sibling disambiguation against convert and the audio-processing tools, which the description does not address.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with input, format (including the 'copy' semantics), output, and overwrite default all documented inline, so the baseline is 3. The description only repeats the format enum already listed in the schema and adds no new meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Extract') and resource ('audio track of a media file'), enumerates the supported output formats, and produces a distinct artifact ('its own file'), which separates it from siblings like convert, normalize_audio, and denoise. An agent can identify the operation without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the operation itself (pull the audio track out of a media file), but the description never says when to pick this over convert, which could plausibly also produce an audio file, or over normalize_audio/denoise for audio-only post-processing. No exclusions or prerequisites are named.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_textFind Text (OCR)A
Read-onlyIdempotent

OCR (built into Windows) on the screen, an image, or video frames, with line and match boxes in image pixels (add origin for desktop coordinates). Locate UI text or secrets (e.g. regex 'sk-|ghp_|api.?key') to redact. Best-effort: review results.

NameRequiredDescriptionDefault
keepNoLive target: keep the capture and return its path (default false: deleted after reading).
inputNoImage or video file to read instead of a live target.
queryNoText to find (case-insensitive, tolerates OCR misreads like I/l, O/0, _/-). Omit to return all text.
regexNoTreat query as a regular expression (case-insensitive).
redactNoAlso return padded match rectangles ready for redact_region's regions.
targetNoLive screen target (full | monitor:<i> | window:... | region:...), or pass input.
backendNoLive target: gdigrab (default) = what is visible; wgc (window:, FFmpeg 8+) = the window even if covered.
maxFramesNoscanEverySec frame cap (default 30; ~1 s each).
timestampNoVideo input: second to read (default 0).
exactTitleNowindow: targets match the whole title only (default false).
returnImageNoReturn the image with matches outlined (default: true with a query).
scanEverySecNoVideo input: scan a frame every N s across the clip (e.g. for secrets before sharing); matches and redactRegions get times. Widens to stay within maxFrames.

Output Schema

NameRequiredDescription
imageSizeYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive, closed-world, so safety is covered; the description adds the genuinely useful trait that OCR is best-effort and results should be reviewed. It also discloses the coordinate frame (image pixels vs. desktop coordinates) and the keep/delete capture behavior. It doesn't mention performance cost beyond the ~1 s/frame note carried in the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with what it does and what it returns before the use cases and the best-effort caveat. No filler and no repetition of schema fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 12 optional parameters, an output schema, and full annotation coverage, the description supplies exactly the missing layer: the three input modes (live target, file, video frames), the coordinate semantics of returned boxes, and the accuracy caveat. An agent can pick a mode and interpret results without further reading.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so per-parameter meaning is largely already documented (query fuzziness, regex, redact, backend, scanEverySec, maxFrames). The description's added value is the coordinate-frame distinction, but it references an `origin` option that does not exist anywhere in the input schema, which risks sending the agent after a nonexistent parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (OCR over screen, image, or video frames) and specifies the return artifacts: line and match boxes in image pixels. It also distinguishes itself from capture siblings (screenshot, sample_frames) and from redact_region by positioning its output as input to redaction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete use contexts (locate UI text, hunt secrets via regex like 'sk-|ghp_|api.?key' for redaction) and points at the downstream redact_region tool. It lacks explicit when-not guidance, e.g. when to use transcribe or review_recording instead, or that video scanning should prefer sample_frames if full-clip OCR isn't needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_media_infoGet Media InfoA
Read-onlyIdempotent

Probe a media file with ffprobe and return duration, resolution, frame rate, codecs, container format, and size.

NameRequiredDescriptionDefault
inputYesPath to the media file to probe.

Output Schema

NameRequiredDescription
fpsYes
inputYes
widthYes
heightYes
audioCodecYes
videoCodecYes
durationSecYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is fully covered. The description adds the mechanism (ffprobe) which hints at behavior on unsupported files, but does not say what happens on a missing/corrupt file or whether probing is slow for large media.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the verb and resource, then the return payload. No filler, nothing repeated from structured fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations fully populated, the description only needs to establish what the tool does and on what input, which it does. It stops short of covering failure modes or path requirements for a tool whose whole risk surface is 'file may not exist.'

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a single, well-documented 'input' path parameter, so the schema carries the load. The description adds nothing about accepted path forms (local vs remote, relative vs absolute) or whether the path must already exist.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (probe), a specific resource (a media file), the mechanism used (ffprobe), and enumerates the exact fields returned. An agent can distinguish it from siblings like get_session or read_events purely from the text.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the agent can infer this is a pre-flight inspection step before convert/compress/trim, but the description never says when to call it versus alternatives or whether it is a prerequisite for other tools. No exclusions or prerequisites are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_sessionGet SessionA
Read-onlyIdempotent

Inspect a single recording session by id, including live status and whether its output file exists on disk.

NameRequiredDescriptionDefault
sessionIdYesSession id returned by start_recording.

Output Schema

NameRequiredDescription
idYes
aliveYes
statusYes
fileExistsYes
outputPathYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive behavior, so the safety profile is covered. The description adds useful behavioral context by saying it reports live status and checks whether the output file exists on disk, which is beyond what the annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence with no filler. It conveys purpose and the two most important pieces of returned information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter read-only lookup with annotations and an output schema, the description covers enough to call correctly and understand what it returns. It could be slightly stronger by noting behavior when the session is missing, but that is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is one parameter with 100% schema description coverage, so the schema already explains that sessionId comes from start_recording. The description says 'by id' but adds no extra format, validation, or lookup semantics beyond the schema baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: inspect a single recording session by id, and adds that it reports live status and output-file existence. This clearly distinguishes it from list_sessions or the recording-control siblings, though it does not explicitly name alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: use it when you have a session id from start_recording and need to inspect that one session. There is no explicit when-to-use guidance, exclusions, or named alternative tool for related inspection needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

index_recordingIndex RecordingA
Destructive

Build a recording's text timeline (.index.json: OCR per scene, events, markers, transcript) for search_recording.

NameRequiredDescriptionDefault
forceNoRe-OCR despite a matching cached index.
inputNoRecording path.
maxFramesNoKeyframes to OCR (default 120).
sessionIdNoOr a stopped session id.
transcriptNoAn .srt, or 'whisper' to transcribe. Default: <video>.srt if any.
sceneThresholdNoChange starting a segment (default 0.03).

Output Schema

NameRequiredDescription
segmentsYes
indexPathYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the agent knows this writes/overwrites something. The description usefully identifies the written artifact, but it omits operationally important facts: that OCR is expensive, that results are cached (only visible in the force parameter's schema text), and what gets overwritten when an index already exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the artifact and the downstream purpose both come immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and the six parameters are fully documented in the schema. The remaining gap is behavioral: cost, caching and overwrite semantics are not addressed despite destructiveHint=true.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter including force, maxFrames, transcript and sceneThreshold is already documented. The description adds no parameter-level meaning beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

A specific verb ('Build') and resource ('a recording's text timeline'), including the concrete artifact name (<video>.index.json) and its contents. It also names the downstream consumer, search_recording, which helps separate it from neighbors like transcribe or read_events, though it doesn't explicitly contrast with those siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'for search_recording' implies this is a prerequisite for searching, but the description never says when to use it versus alternatives such as transcribe or chapters, nor when not to run it. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

keystroke_overlayKeystroke OverlayA
Destructive

Burn keycast-style badges for shortcuts, clicks, and typing from the recording's input event log (start_recording events: true). Never shows typed text: the log has none.

NameRequiredDescriptionDefault
keysNoshortcuts (default): the chord (Ctrl + S); masked: modifiers only (Ctrl + …).
sizeNoFont px (default 4.5% of the frame height).
colorNoText color (default white).
inputYesPath to the recording.
clicksNoShow clicks (default true).
dryRunNoReturn the planned badges; write nothing.
eventsNoEvent log (default: the input's .events.jsonl).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
typingNoShow typing as "Typing…" (default true).
fontFileNoFont: a .ttf/.otf/.ttc path or a C:\Windows\Fonts file name. Default: bundled Inter, with a covering system font for scripts it lacks (CJK, emoji, Arabic, ...).
positionNoDefault bottom (centred).
lingerSecNoSeconds a badge stays up (default 1.2).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
badgesYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and non-idempotent writes, so the safety profile is covered. The description adds genuinely non-derivable behavior: it never renders typed text because the log contains none, which prevents an agent from expecting keystroke content and explains a privacy-relevant constraint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero filler, with the core action front-loaded and the prerequisite and privacy constraint trailing efficiently. Nothing could be removed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained, and the description covers purpose, prerequisite, and the no-typed-text guarantee. The main residual gap is routing guidance against the other visual-overlay siblings, which keeps it from a 5 for a 13-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and all 13 parameters are documented inline (keys modes, size, lingerSec, overwrite, etc.), so baseline is 3. The description only adds the events-log prerequisite, which is useful linkage but not parameter-level detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Burn keycast-style badges') and resource (shortcuts, clicks, typing) sourced from the recording's input event log, which cleanly separates it from sibling overlay/callout/cursor tools. The parenthetical about start_recording events: true further pins down what it operates on.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the essential precondition — the recording must have been made with start_recording events: true — which is a real gating condition an agent needs before calling. It stops short of naming alternatives (e.g., overlay or cursor) or when NOT to use it, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_audio_devicesList Audio DevicesA
Read-onlyIdempotent

List DirectShow audio devices and flag a likely loopback (Stereo Mix or a virtual-audio driver), for start_recording's audio.device.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
noteYes
devicesYes
loopbackDeviceYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly, idempotent, non-destructive, and closed-world behavior. The description adds meaningful context beyond that: it enumerates DirectShow audio devices and applies a loopback heuristic (Stereo Mix or virtual-audio driver).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence front-loads the action and resource, then adds the loopback flagging and downstream use case without wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter listing tool with an output schema, the description supplies enough to invoke and interpret it: what is listed, what the likely loopback flag means, and where its results belong. The output schema can carry return-value details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the baseline is 4. No parameter guidance is needed or missing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('List DirectShow audio devices') and adds the key behavioral detail that it flags a likely loopback device. It is clearly distinguishable from sibling list_video_devices and other recording tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly ties the tool to start_recording's audio.device, telling the agent when this list is useful. It does not name exclusions or alternatives, but the intended workflow context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_sessionsList SessionsA
Read-onlyIdempotent

List all recording sessions (active and finished) with their status, target, output path, and whether the process is still alive.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
countYes
sessionsYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured data. The description adds useful behavioral detail beyond that — that both active and finished sessions are returned, and that each carries a live-process flag — but says nothing about ordering, volume, or cost of the call.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the resource first, scope second, and returned fields last. Every clause carries information and nothing is padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description does not need to explain return values, and annotations cover safety; the field enumeration is mildly redundant but harmless. The one real gap is the lack of a routing hint versus get_session for a toolset with 50+ siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes no parameters, so the baseline is 4; the description correctly implies a no-argument, list-everything call rather than hinting at filters that don't exist.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource: "List all recording sessions", with scope narrowed to "(active and finished)" and a preview of the returned fields. It does not explicitly distinguish itself from the sibling get_session, which is the one obvious source of confusion for an agent choosing between them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the word "all" and the parenthetical scope; there is no statement telling the agent to use this instead of get_session when it already knows an ID, nor any prerequisite or ordering guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_targetsList Capture TargetsA
Read-onlyIdempotent

List the desktop, monitors, and visible windows (topmost first, with capturability per backend). Each entry has a target string to pass as-is to capture tools; use it instead of guessing a title.

NameRequiredDescriptionDefault
exeNoOnly list windows of this executable, e.g. 'Code.exe' or 'code'.
titleContainsNoOnly list windows whose title contains this text (case-insensitive).
capturableOnlyNoLeave out windows neither backend can capture (minimized, off screen). Default false.

Output Schema

NameRequiredDescription
fullYes
noteYes
windowsYes
monitorsYes
wgcAvailableYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool is read-only, idempotent, non-destructive, and closed-world. The description adds useful behavioral context beyond annotations: ordering is topmost first, capturability is included per backend, and entries expose a pass-through `target` string.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences, front-loaded with what is listed and followed immediately by how to use the returned `target`. Every sentence contributes directly to selection or invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, so the description need not explain return values. With complete parameter documentation, annotations covering safety, and a clear statement of contents and intended use, the definition is complete enough for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents the three filter parameters. The description does not add parameter-specific meaning, which is acceptable given the schema already carries that information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource set: it lists desktop, monitors, and visible windows. It also clarifies the key output field (`target`) and how it relates to capture tools, which distinguishes it from sibling capture/manipulation tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage guidance: pass the returned `target` as-is to capture tools and use this instead of guessing a title. It does not explicitly describe when not to use the tool or name a sibling alternative, but the intended workflow is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_video_devicesList Video DevicesA
Read-onlyIdempotent

List DirectShow cameras for start_recording's webcam.device.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
devicesYes

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, and openWorldHint=false, so the safety profile is fully covered. The description adds the useful 'DirectShow' qualifier (implying a Windows-only enumeration) but nothing on return shape or failure modes. With annotations carrying the behavioral burden, a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence with zero filler. The resource and the consumer are front-loaded, so an agent can act on it immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, annotations are rich, and there are no parameters, so the description need not explain return values. The only small gap is that it doesn't say whether a DirectShow/platform prerequisite could make the list empty or fail, but for a zero-arg enumeration tool this is nearly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters and schema coverage is 100%, so the baseline is 4. No parameter-level explanation is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) and a specific resource (DirectShow cameras), and ties the output to a concrete consumer: start_recording's webcam.device. This distinguishes it from sibling device-enumeration tools like list_audio_devices and list_targets without needing to open any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'for start_recording's webcam.device' tells the agent exactly when to call it: to obtain a valid device value before starting a recording. It does not explicitly name exclusions or alternatives, but the intended workflow is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

music_bedAdd Music BedA
Destructive

Lay music under a video: looped or trimmed to length, faded, leveled, and mixed with any existing audio. Video is stream-copied.

NameRequiredDescriptionDefault
duckNoDuck the music under the original audio (default false).
musicYesMusic audio file.
videoYesPath to the video.
fadeInNoFade-in seconds (default 1).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
fadeOutNoFade-out seconds (default 2).
overwriteNoAllow replacing an existing file at the output path (default false).
musicVolumeNo0..1 (default 0.25 over existing audio, 0.8 alone).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and non-idempotent, and the description adds genuinely new behavioral context: the video is stream-copied (no re-encode, fast and lossless for video), and music is looped or trimmed to fit. It does not restate overwrite semantics, which the schema covers, but the stream-copy disclosure is a real behavioral detail an agent would otherwise not know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence, front-loaded with the core action and followed by the transforming operations, with zero filler. Every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With full schema coverage, an output schema, and rich annotations, the description supplies the remaining important context — stream copy and music fitting behavior. Only the interaction between duck and musicVolume defaults is left implicit, a minor gap for an audio-mixing tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter is already documented with types, defaults, and ranges. The description gestures at the parameters semantically ('faded, leveled', 'mixed with any existing audio' hinting at duck/musicVolume) but adds no format or syntax detail beyond the schema, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — lay music under a video — and enumerates the operations performed (loop/trim, fade, level, mix). It is clearly distinguishable from siblings like normalize_audio or extract_audio because no sibling performs music-overlay mixing, though it never names a contrasting sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when the tool applies (adding background music to an existing video) but gives no explicit when-to-use/when-not guidance and no reference to alternatives such as normalize_audio or duck-related options. The agent must infer the selection context from the tool name and purpose alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

narrateNarrateA
Destructive

Offline voiceover with the built-in Windows voices: speaks each line at its time or marker over the audio, plus an SRT.

NameRequiredDescriptionDefault
duckNoDuck the original audio (default true).
rateNoDefault 1.
linesYes
videoYesPath to the video.
voiceNoVoice name or part (doctor lists them).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds useful context beyond the annotations by disclosing that narration uses built-in Windows voices, works offline, and also produces an SRT. It does not mention the destructive/overwrite behavior signaled by destructiveHint=true or the overwrite default, leaving those details to the schema and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The single sentence is front-loaded with the core purpose and contains no filler. Every phrase contributes to describing the voiceover mechanism, timing behavior, and SRT output.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich schema coverage, annotations, and presence of an output schema, the description is mostly complete for an agent to understand the tool's role. It does not mention the required video path or overwrite implications, but those are adequately covered by the schema and annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is high at 86%, so the baseline is 3, but the description adds meaningful semantics for the nested lines array by explaining that each line is spoken at its time or marker. It also clarifies the audio-overlay and SRT output behavior, though it does not discuss rate, duck, or overwrite parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource: it produces an offline voiceover using built-in Windows voices and speaks each line at its time or marker. This clearly separates it from sibling audio tools like music_bed, transcribe, or burn_subtitles, though it does not explicitly name alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the phrase 'offline voiceover' and the explanation that lines are spoken at timestamps or markers. However, the description does not state when to use this tool instead of related siblings such as music_bed, transcribe, or burn_subtitles, nor does it give any exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

normalize_audioNormalize LoudnessA
Destructive

Normalize loudness to a delivery target (two-pass EBU R128 loudnorm); video is copied. Reports loudness before and after.

NameRequiredDescriptionDefault
inputYesPath to the source video or audio file.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
targetNoyoutube (-14 LUFS, default), podcast (-16), broadcast (-23), or a LUFS number.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the description is not responsible for the safety profile. It adds useful behavioral context beyond the annotations: two-pass EBU R128 processing, video copy-through, and before/after loudness reporting.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One compact sentence with the core operation front-loaded and no wasted text. The parenthetical implementation detail earns its place by clarifying the loudness standard.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full schema, annotations, and an output schema, the description is nearly complete for correct invocation. It could mention overwrite or output-default behavior, but those are already covered in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all four parameters, including target enum values and LUFS meaning. The description reinforces the delivery-target concept but adds no parameter-level detail beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Normalize loudness'), names the delivery-target concept, and distinguishes itself from sibling audio transformations by describing the exact standard (two-pass EBU R128) and the handling of video ('video is copied').

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The delivery-target framing implies this is for final loudness compliance, but the description gives no explicit when-to-use/when-not guidance and does not name alternatives such as denoise or compress.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

overlayOverlay Image or VideoA
Destructive

Composite an image or video (logo, watermark, picture-in-picture) onto a video at a pixel position, optionally scaled and time-limited; keeps the base's audio and length.

NameRequiredDescriptionDefault
xYesLeft, px.
yYesTop, px.
endNoHide after this second.
inputYesPath to the base video.
shapeNocircle: centre square masked round (webcam).
startNoShow from this second.
widthNoScale to this width (other side keeps aspect).
heightNoScale to this height.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overlayYesOverlay image or video path.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false, and readOnlyHint=false, so the write/irreversibility profile is covered. The description adds genuinely new behavioral facts: the base's audio and length are preserved and the overlay can be scaled and time-limited, which an agent could not infer from annotations or schema. It stops short of stating that a new output file is produced rather than the input being modified in place.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence packs the verb, the two media roles, the placement, and the preservation guarantee with no filler. The semicolon clause is the one piece of information an agent most needs after the action itself, so nothing needs reordering.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and annotations carry the destructive/non-idempotent profile. The description covers the key semantic guarantee (audio and duration preserved). The only gap is not clarifying that results land at a new output path by default versus mutating the input, though the schema's output/overwrite parameters hint at it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% across all 11 parameters, so the schema already documents x/y as pixel offsets, start/end as time bounds, and width/height as scale factors. The description only echoes those concepts at a high level ('pixel position, optionally scaled and time-limited') without adding format or edge-case detail. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb ('Composite') and resources ('image or video ... onto a video') and clarifies intent with concrete parenthetical examples (logo, watermark, picture-in-picture). It implicitly separates itself from overlay-adjacent siblings like keystroke_overlay or callout by restricting input to an arbitrary image/video file, but it never explicitly names or contrasts those siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The examples (logo, watermark, picture-in-picture) imply when to reach for this tool, but there is no explicit when-not guidance, no mention of prerequisites (e.g., need a base video already), and no routing to alternatives such as keystroke_overlay, title_card, or backdrop for other overlay types. Usage is only inferable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pause_recordingPause RecordingA
Idempotent

Pause a recording; until resume_recording nothing is captured, and the gap is left out of the file, events, and markers.

NameRequiredDescriptionDefault
sessionIdYesFrom start_recording.

Output Schema

NameRequiredDescription
statusYes
sessionIdYes
recordedSecYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this is a non-read-only but non-destructive, idempotent mutation. The description adds real value beyond them by disclosing the consequence: capture halts and the gap is excluded from the output file, events, and markers. It stops short of describing edge cases such as pausing an already-paused or stopped session.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the action first and the consequence second; no sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation, and the annotations carry the safety profile. The description covers the essential behavior; only failure/edge-case behavior for invalid session state is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter exists and schema description coverage is 100%, with the schema even noting it comes 'From start_recording.' The description adds nothing about sessionId, so the baseline 3 applies when the schema does all the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Pause a recording') and immediately names the paired sibling resume_recording, so the agent can distinguish it from stop_recording or save_replay without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The clause 'until resume_recording nothing is captured' establishes the usage context and the pairing that selects this tool over stop_recording. There is no explicit exclusion (e.g., what to do if the session is already stopped), but the correct moment to call it is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pipelineEdit PipelineA
Destructive

Run several edits (trim, crop, scale, speed, cut_idle, redact, callout, keystroke_overlay, cursor, reframe, zoom, backdrop, audio, burn_subtitles, then optionally export_preset or export_gif) in one ffmpeg pass: one re-encode, no intermediate files. Prefer it over chaining edit tools; a recipe does the usual polish in one call.

NameRequiredDescriptionDefault
inputYesPath to the source video.
stepsNoEdits in order, each { op, ...its tool's options }; export_preset/export_gif only last. Times and pixels are relative to the video as it is at that step (after earlier trims, speed, crops). zoom follow:"clicks" plans from the event log; burn_subtitles takes subtitles or transcribe:true.
dryRunNoReturn the plan (ffmpeg command, output size) without running it.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
recipeNoPolish preset expanded to steps (see dryRun): pr_demo = cut_idle, click zoom, GIF <=10 MB; tutorial = + audio, captions, 1080p mp4; social_reel = 9:16, big captions. Given steps replace its same-op step.
qualityNoEncoder preset for an mp4 result (default standard).
chaptersNoKeep the input's markers as chapters, re-timed through trims and speed.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
stepsYes
processesYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and non-idempotent, and the description adds genuinely new behavioral context: the whole pipeline runs as a single re-encode with no intermediate files, which affects failure cost and output quality. It doesn't expand on overwrite/output-file clobbering, but the schema's overwrite param covers that, so the gap is minor.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, purpose and mechanism first, preference guidance second. The parenthetical op list is dense but earns its space by signaling breadth. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, annotations covering the safety profile, and fully described parameters, the description needs only to convey purpose and selection guidance, which it does. A brief note that a recipe can substitute for hand-built steps would round it out, but an agent has enough to act correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each step variant is fully documented in the schema itself, including ordering and relative-time semantics, so the description's step list largely restates structured data. It adds the useful constraint that export steps must be last, but nothing about parameters beyond that. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action (run multiple edits in one ffmpeg pass) and enumerates the supported edit ops, so an agent can immediately see it subsumes the individual edit siblings. The 'one re-encode, no intermediate files' line pins down the distinguishing mechanism.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Prefer it over chaining edit tools; a recipe does the usual polish in one call' explicitly names the alternative pattern and prescribes when this tool wins. This is the rare case of a stated when-to-use with a named competitor strategy.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_eventsRead Input EventsA
Read-onlyIdempotent

Read the input events (clicks, scroll, cursor, shortcuts, typing bursts) of a recording made with events: true, in video seconds and pixels; e.g. types: ['down'], then sample_frames there.

NameRequiredDescriptionDefault
toNoLatest video second.
fromNoEarliest video second.
inputNoOr a recording path, or its .events.jsonl.
limitNoMost events to return (default 200).
typesNodown/up (mouse buttons; clicks are down), move (sampled cursor), wheel, key (shortcut), typing (burst), gap (events may be missing).
sessionIdNoSession id of a recording started with events: true.
inFrameOnlyNoDrop events whose cursor was outside the recorded area.

Output Schema

NameRequiredDescription
totalYes
matchedYes
summaryYes
returnedYes
eventsPathYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this a safe, idempotent, non-destructive read, so the description only needs to add what annotations cannot. It does that by disclosing the prerequisite that the recording must have been started with events: true and by fixing the coordinate systems ('video seconds and pixels'), which prevents an agent from guessing at unit conversion. It says nothing about what happens when no events exist or about paging through more than the limit, which keeps it below a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence in which the resource is named before the constraints and the workflow hint comes last, so nothing is buried. It is a semicolon-spliced run-on, though, and the embedded example is slightly harder to parse than a short second sentence would be.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value shape need not be described, and all seven parameters are documented in the schema. The description covers the two things neither annotations nor schema can supply: the events: true prerequisite and the units of the time range, making the definition sufficient to call correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3 and the schema already documents every parameter. The description still earns above baseline by fixing the interpretation of the numeric range as milliseconds-to-video-seconds and pixels, and by showing a concrete filter call shape ('types: [\'down\']').

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (read the input events) and enumerates exactly what those events are: clicks, scroll, cursor, shortcuts, typing bursts. It also scopes the resource to 'a recording made with events: true', which no sibling tool reads, so an agent can distinguish it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the precondition for use ('a recording made with events: true') and a workflow hand-off ('then sample_frames there'), which routes the agent to the correct next tool. It stops short of stating when NOT to use it or what to do when no events were recorded, so it is clear but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

redact_regionRedact RegionsA
Destructive

Cover given rectangles in a video (e.g. secrets on screen). Not automatic detection: find them with find_text redact: true. Off-frame regions are rejected.

NameRequiredDescriptionDefault
padNoGrow each region by this many px (default 0).
colorNoBox fill color (default black).
inputYesPath to the source video.
styleNobox (default): irreversible fill; blur/pixelate are partially recoverable.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
regionsYesPixel rectangles (x, y, width, height), each optionally limited to start..end seconds.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false and non-idempotent, so the safety profile is covered structurally. The description adds the off-frame rejection behavior, which is genuine extra context, but says nothing about the output file being created, overwrite risk, or processing cost despite being a destructive mutation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action, then the exclusion, then the constraint. No filler or restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema, full param coverage and rich annotations, the description covers purpose, the detection alternative, and region validation. It leaves unmentioned that a new output file is written by default, but that is documented in the schema's output param.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including the style enum's irreversibility note and the start/end timing on regions, so the baseline is 3. The description only implies region semantics through 'rectangles' and the off-frame rejection, adding little beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Cover given rectangles in a video') with a concrete use case (secrets on screen). It also differentiates itself from the detection capability by pointing at find_text, so an agent can tell what this tool is and is not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the negative case ('Not automatic detection') and names the alternative tool plus the exact flag needed ('find_text redact: true'). The 'Off-frame regions are rejected' note sets a precondition the agent must respect before calling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

reframeReframe Aspect RatioA
Destructive

Re-aspect a video to 16:9, 9:16, 1:1, or 4:5 by padding or cropping.

NameRequiredDescriptionDefault
fitNopad (default): letterbox, nothing lost. crop: fill and center-crop.
inputYesPath to the source video.
aspectYesTarget aspect ratio.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false, and readOnlyHint=false. The description adds that the operation works by padding or cropping, which hints crop discards picture content, but it does not mention the file-overwrite behavior or default output location that a destructive write tool would benefit from stating.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with the key constraint (supported ratios) front-loaded and zero filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema and fully documented parameters, the description needs only to convey the core effect, which it does. It stops slightly short for a destructive write tool by not noting that output files may be replaced.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all five parameters including the fit and aspect enums are already documented in detail. The description only restates the aspect enum and the pad/crop choice without adding new semantics, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Re-aspect') plus resource ('video'), and enumerates the four supported target ratios, which makes it easy to distinguish from neighboring tools. It does not differentiate itself from crop or scale, which also change framing dimensions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: an agent can infer it should be called when a video needs a different aspect ratio. There is no explicit guidance on when to prefer this over crop, scale, or export_preset, despite those siblings overlapping in function.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resume_recordingResume RecordingA
Destructive

Resume a paused recording (same target and settings).

NameRequiredDescriptionDefault
sessionIdYesFrom start_recording.

Output Schema

NameRequiredDescription
statusYes
sessionIdYes
recordedSecYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=true, idempotentHint=false and openWorldHint=false, so the safety profile is carried by structured data. The description adds useful context that the original target and settings are reused, but it never addresses what is destructive about resuming (e.g., appending/overwriting the existing capture) nor any failure conditions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with the key constraint ('same target and settings') front-loaded. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists and annotations cover the safety profile, so the description needn't explain returns. It is nearly complete for a one-parameter lifecycle tool, with the only real gap being the unaddressed destructiveHint=true behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter, and schema coverage is 100% with the description 'From start_recording.' The description adds nothing parameter-specific beyond implying the session determines target/settings; baseline 3 is appropriate when the schema does the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (resume) and resource (a paused recording), and the parenthetical 'same target and settings' pins down that it continues the existing session rather than starting a new one. It is distinguishable from start_recording/pause_recording/stop_recording, though it never names them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The word 'paused' implies a precondition (the session must currently be paused) and the schema note 'From start_recording' ties the sessionId back to session creation. However, there is no explicit guidance on what to do if the session is not paused, or on why one would resume vs. start a new recording.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

review_recordingReview RecordingA
Read-onlyIdempotent

Open a recording for a person to review: in MCP Apps clients an inline player to scrub, trim, and redact, then export; elsewhere just the video's details.

NameRequiredDescriptionDefault
inputNoPath to the video.
sessionIdNoOr the session id of a stopped recording.

Output Schema

NameRequiredDescription
fpsYes
inputYes
widthYes
heightYes
hasAudioYes
durationSecYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), so the description earns credit for the extra context it adds: behavior is client-dependent, with an inline scrub/trim/redact/export player in MCP Apps clients and a passive details view elsewhere. The tension between 'trim and redact' and readOnlyHint is best read as UI capabilities rather than this call mutating anything, but it is left for the agent to resolve.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single sentence, front-loaded with the action and then the two client modes, with no filler. The parenthetical clause ('in MCP Apps clients an inline player to scrub...') is slightly compressed but still parseable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema and annotations available, the description only needs the mode-dependent behavior delta, which it delivers. The main omission is the mutually exclusive input/sessionId requirement, which an agent must get from the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both properties are documented, including the either/or between a file path and a stopped session id. The description adds nothing about parameters and does not even restate that exactly one of input/sessionId must be supplied, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('open a recording for a person to review') and clarifies the deliverable in each context (interactive player vs. plain video details). It implicitly separates itself from pure-data siblings like get_media_info or get_session, though it never names them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: 'for a person to review' suggests human-in-the-loop work versus programmatic extraction. It never says when to pick this over get_media_info, get_session, or screenshot, and gives no prerequisites, so the agent must infer the routing itself.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sample_framesSample FramesA
Read-onlyIdempotent

Sample PNG frames from a video (by fps, timestamps, or scene changes) and return the first few inline so the model can see what happened.

NameRequiredDescriptionDefault
fpsNoFrames per second (mode fps).
modeNoscenes: only frames where the screen changed (strongest first), usually the cheapest review. Default: fps or timestamps, whichever is given.
inputYesPath to the source video file.
dedupeNoMode fps: drop near-duplicate frames (default false).
maxFramesNoFrame cap (default 100); fps is lowered to fit while still spanning the video.
outputDirNoOptional folder for the frames (a relative path resolves under SCREENCAST_HOME/frames). Defaults to SCREENCAST_HOME/frames/<id>.
timestampsNoSeconds to grab a frame at (mode timestamps).
returnImagesNoReturn the first maxInlineImages frames inline (default true).
maxImageWidthNoMax inline image width (default 1280).
sceneThresholdNoMode scenes: change needed to count, 0-1 (default 0.1).
maxInlineImagesNoFrames to embed inline (default 8); all are listed by path.

Output Schema

NameRequiredDescription
modeYes
framesYes
frameDirYes
frameCountYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive/closed-world, so the safety bar is low. The description still adds real value beyond them by disclosing the inline-image return behavior and its purpose ("so the model can see what happened"), which tells the agent to expect image content in the response. It does not mention that frames are also written to disk, a mild tension with readOnlyHint that stops short of a contradiction because the schema documents outputDir.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence covering what is sampled, the three strategies, and what comes back. No wasted clauses, no restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full parameter coverage, the description needn't explain return values and is complete enough to call correctly. The only gap is that the on-disk side effect and default frame caps are left entirely to the schema, which is acceptable but means the description alone would mislead a reader into thinking this is purely a read.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and every parameter carries a substantive description (defaults, caps, mode scoping), so the schema does the heavy lifting. The description reinforces the three modes but adds no syntax or default detail beyond what the schema already states; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ("Sample PNG frames from a video") and enumerates the three sampling strategies (fps, timestamps, scene changes), which maps directly onto the mode enum. An agent can tell immediately what this does and how the output differs from a plain screenshot or contact_sheet tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical list of modes implies usage, and the schema's mode description adds the crucial guidance ("scenes ... usually the cheapest review"), but the description itself never says when to prefer this over siblings like contact_sheet, screenshot, or screen_diff, nor what preconditions apply. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

save_replaySave ReplayA
Destructive

Save the last N seconds of a replay buffer (start_recording replayBufferSec) to an mp4; the buffer keeps running.

NameRequiredDescriptionDefault
outputNoOutput .mp4 path (default under SCREENCAST_HOME/recordings).
lastSecNoSeconds back from now (default and max: the buffer length).
reencodeNoFrame-exact re-encode. Default: instant stream copy that may hide up to 2 s of earlier frames.
overwriteNoAllow replacing an existing file at the output path (default false).
sessionIdYesSession id of a replay buffer.

Output Schema

NameRequiredDescription
sessionIdYes
outputPathYes
durationSecYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and non-idempotent, and the description adds the crucial behavioral fact that 'the buffer keeps running' after a save — i.e., the source buffer is not consumed even though the output file is written. It stops short of warning about overwriting existing files, which the schema covers but the description does not reinforce.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence plus a semicolon clause carrying the one non-obvious behavior. No filler, no restating of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-parameter tool with full schema coverage, an output schema, and rich annotations, the description covers the essential prerequisite and the post-call buffer state. A brief note on overwrite behavior and failure when no buffer exists would make it complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already explains lastSec, output, reencode, overwrite and sessionId in detail. The description only echoes the 'last N seconds' notion of lastSec and adds no format, default, or interaction detail beyond the structured fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (save) and resource (last N seconds of a replay buffer) and names the exact artifact produced (mp4). It also ties the tool to the enabling call (start_recording replayBufferSec), so an agent can distinguish it from trim/clip/stop_recording siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The parenthetical '(start_recording replayBufferSec)' implies a replay buffer must already exist, which is useful usage context. But it never states when to choose this over the many siblings (clip, trim, concat, stop_recording) or what to do if no buffer is running.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scaleScale VideoA
Destructive

Resize a video to a target width and/or height and re-encode. Provide one side to keep the aspect ratio, or both to set an exact size.

NameRequiredDescriptionDefault
inputYesPath to the source video.
widthNoTarget width in px. Omit to derive from height (keeps aspect).
heightNoTarget height in px. Omit to derive from width (keeps aspect).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the safety profile is covered structurally. The description adds the meaningful behavioral note that the video is re-encoded, hinting at quality/processing cost, but it does not discuss overwrite risk, encoding defaults, or what happens when the output path already exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with zero filler; the core operation is front-loaded and the aspect-ratio rule follows immediately. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations covering the destructive/mutating profile, the description needs only the core behavior plus the aspect-ratio rule, both of which are supplied. Remaining gaps, such as re-encode quality settings or confirmation of the default output location, are minor given the structured fields.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so every parameter already documents its meaning, including the aspect-ratio derivation behavior for width/height. The description largely restates that schema-level logic ('one side... or both') rather than adding new semantic detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Resize a video... and re-encode') with the target dimensions made clear, so the operation is unambiguous. It does not name or distinguish itself from adjacent siblings like crop, reframe, or zoom, which is the only thing keeping it from a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The sentence 'Provide one side to keep the aspect ratio, or both to set an exact size' tells the agent how to use the width/height pair, which is useful implied usage. However, there is no guidance on when to choose scale versus siblings like crop, reframe, or export_preset, and no prerequisites or exclusions are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

screen_diffScreen DiffA
Read-onlyIdempotent

Compare two screenshots or frames: SSIM score, changed share, and changed boxes in b's pixels, to check a UI change happened only where expected.

NameRequiredDescriptionDefault
aYesBefore image (or video: first frame).
bYesAfter image (or video); scaled to a's size.
returnImageNoReturn b inline with changes outlined (default true).
pixelThresholdNoMean 0-255 difference for a ~32x32 cell to count as changed (default 12).

Output Schema

NameRequiredDescription
ssimYes
regionsYes
meanDiffYes
identicalYes
changedFractionYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive), so the bar is lower; the description adds real value by disclosing the output fields and, importantly, the coordinate frame ('changed boxes in b's pixels'), which matters because the schema notes b is scaled to a's size. It does not mention cost, resolution limits, or what happens with mismatched aspect ratios beyond the scaling note.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the action and outputs first and the motivation last; every clause carries information. The phrase 'changed boxes in b's pixels, to check' makes the reader re-parse slightly, but the density is appropriate for a tool with an output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't enumerate return values, yet it summarizes them anyway and covers the core behavior for a read-only diff tool. The remaining gap is guidance on when a change-check should use wait_for_change instead, but nothing an agent needs in order to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents a, b, returnImage, and pixelThreshold thoroughly (including the ~32x32 cell and default 12 semantics). The description adds only the output coordinate-frame hint and nothing about thresholds or the inline-image toggle, which is the expected baseline when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Compare two screenshots or frames') and names the concrete outputs (SSIM score, changed share, changed boxes), so an agent can tell this apart from screenshot, wait_for_change, or sample_frames. It stops short of naming a sibling it is easily confused with, so the differentiation is implied rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The closing clause 'to check a UI change happened only where expected' gives a clear intended use case, which is enough for an agent to pick this over wait_for_change (time-based) or screenshot (single capture). It offers no explicit when-not conditions or named alternatives, so it is strong context without full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

screenshotTake ScreenshotB
Destructive

Capture one PNG of the screen, a monitor, a window, or a region, returned inline and by path.

NameRequiredDescriptionDefault
outputNoOptional output .png path. Defaults to a file under SCREENCAST_HOME/screenshots.
targetYesfull | monitor:<i> (0 = primary) | window:<title> (or window:exe=<app.exe> / window:hwnd=<n>) | region:<x>,<y>,<w>,<h>. Titles match exactly, else as a substring; topmost wins.
backendNogdigrab (default, ~0.2 s): what is visible. wgc (window:, FFmpeg 8+, ~1-2 s): the window even if covered.
overwriteNoAllow replacing an existing file at the output path (default false).
exactTitleNowindow: targets match the whole title only, never a substring (default false).
returnImageNoReturn the image inline (default true; the PNG on disk stays full size).
maxImageWidthNoMax inline image width (default 1280).

Output Schema

NameRequiredDescription
targetYes
backendYes
outputPathYes
inlineImagesYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses the key side effect channel — the capture is written to a path as well as returned inline — which aligns with destructiveHint=true and readOnlyHint=false rather than contradicting them. However, it never mentions that writing fails if the path exists unless overwrite is set, nor the default location, so the destructive/write profile is only partially explained beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler; the verb, artifact, target scopes, and return modes all land immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema and complete parameter documentation, the description only needs to orient the agent, which it does. The remaining gap is that the write-to-disk side effect and its overwrite gating are implied rather than stated, which matters given destructiveHint=true.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all seven parameters are already documented in detail (including backend tradeoffs and default values), which establishes the baseline of 3. The description only adds the framing that output is dual-channel (inline plus file), which lightly motivates returnImage and output but adds no new semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Capture), an explicit format (one PNG), and enumerates the four target scopes (screen, monitor, window, region), plus the two return channels. An agent knows exactly what it gets. It stops short of naming which sibling handles adjacent jobs (sample_frames, contact_sheet, list_targets), so it is clear but not differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no statement of when to reach for this versus siblings like sample_frames, contact_sheet, or list_targets, and no exclusions or prerequisites. Usage is only inferable from the tool name and the enumerated targets.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_recordingSearch RecordingA
Read-onlyIdempotent

Search an index_recording timeline (screen text, events, markers, transcript): timecoded hits, best first, secrets masked. No frames unless asked.

NameRequiredDescriptionDefault
inputNoRecording path.
limitNoMax hits (default 10).
queryYesText; tolerates OCR misreads.
regexNoquery is a regex.
imagesNoThumbnails of the top N hits (default 0).
sessionIdNoOr a stopped session id.

Output Schema

NameRequiredDescription
hitsYes
totalYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, non-destructive. The description adds real behavioral context the agent couldn't infer: hits are timecoded, ranked best-first, secrets are masked in output, and frames are omitted by default.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence with the resource and scope front-loaded and every clause earning its place; zero padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be explained, and the description covers indexing source, ranking, masking and frame behavior. Slightly thin on prerequisites (the recording must already be indexed) but otherwise complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema documents all six parameters including defaults and limits. The description only nudges on the images parameter ('No frames unless asked') and adds nothing for query, regex, input or sessionId.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource: searches an index_recording timeline across screen text, events, markers and transcript, which ties it to the index_recording sibling. It doesn't distinguish itself from find_text, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by 'Search an index_recording timeline' and the caveat 'No frames unless asked' hints at when to request images. No explicit when/when-not, prerequisites, or named alternatives among the many siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

speedChange SpeedA
Destructive

Change playback speed by a factor (>1 faster, <1 slower) and re-encode. Audio is retempo'd to match when the source has an audio track.

NameRequiredDescriptionDefault
inputYesPath to the source video.
factorYesSpeed multiplier: >1 is faster, <1 is slower (e.g. 2 = double speed).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false and readOnlyHint=false, so the safety profile is covered. The description adds non-obvious behavior beyond that: the operation re-encodes and audio is retempo'd when present, which implies quality implications and audio handling that the agent would not otherwise know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with zero waste. The core behavior (speed change + re-encode) is front-loaded, followed by the important audio side effect.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists and annotations cover the safety profile, so the description need not explain return values or overwrite semantics. It covers the key behavioral details an agent needs (re-encode, audio retempo) but does not mention the default output location or overwrite interaction, which are left to the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents input, factor, output and overwrite. The description restates the factor direction (>1 faster, <1 slower), which duplicates the schema rather than adding new parameter-level detail. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource (change playback speed) and adds mechanism (re-encode, audio retempo), so an agent knows exactly what it does. It does not explicitly differentiate itself from related siblings such as compress or trim, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The factor semantics (>1 faster, <1 slower) imply when to use the tool, but there is no explicit 'use this when' guidance, no named alternatives, and no exclusions. Usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

start_recordingStart RecordingB
Destructive

Start a background screen recording. Returns a session id; finalize it with stop_recording. Never auto-starts.

NameRequiredDescriptionDefault
fpsNoFrames per second (default 30).
keysNoWith events: masked (default) logs typing only as 0.5 s-grid bursts, never keys; shortcuts also names Ctrl/Alt/Win chords. Typed text is never logged.
audioNoAudio (default none). No microphone capture.
cursorNoevents: leave the OS cursor out and log it (implies events) for the cursor tool to redraw.
eventsNoAlso log clicks, scroll, cursor, and typing (video-timed, video pixels) for read_events (default false; ~1 s slower start).
outputNoOutput .mp4 path (default under SCREENCAST_HOME/recordings).
targetYesfull | monitor:<i> (0 = primary) | window:<title> (or window:exe=<app.exe> / window:hwnd=<n>) | region:<x>,<y>,<w>,<h>. With gdigrab a window's rectangle is resolved once at start (visible, on top); it does not follow the window.
webcamNoAlso record a camera to <output>.webcam.mp4, aligned for overlay.
backendNogdigrab (default): the screen rectangle. wgc (window: targets, FFmpeg 8+): the window's own surface, even when covered or moved; client area only, no audio. ddagrab: one display on the GPU, low CPU.
encoderNoauto = first working GPU encoder, else x264 (default with ddagrab; else x264).
qualityNoEncoder preset (default standard).
overwriteNoAllow replacing an existing file at the output path (default false).
exactTitleNowindow: targets match the whole title only, never a substring (default false).
maxDurationSecNoAuto-stop after this many seconds (default 3600 or SCREENCAST_MAX_RECORDING_SEC; max 7 days; 0 = no cap).
replayBufferSecNoInstant replay: keep only the last N s (bounded disk) for save_replay. gdigrab only.

Output Schema

NameRequiredDescription
statusYes
backendYes
sessionIdYes
outputPathYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety burden is partly carried. The description adds that the operation is non-blocking ("background") and returns a session id, but it never mentions the destructive surface the annotations flag — overwriting an existing output file, disk consumption, or the ~1s startup cost of event logging.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the action and followed by the required follow-up. No filler; the only weak line is "Never auto-starts," whose phrasing is ambiguous about what exactly would auto-start.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter, nested-schema tool, the description covers the essential contract (start, get a session id, finish with stop_recording) and an output schema exists so return values need not be explained. However, it omits concurrency behavior, permission/device prerequisites, and failure modes that matter for a long-running destructive capture.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with rich per-field docs (target syntax, backend trade-offs, keys/audio privacy semantics), so the schema does the heavy lifting. The description adds nothing about any of the 15 parameters, which is acceptable at full coverage but is the baseline, not a value-add.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Start a background screen recording") and the sibling that closes the loop (stop_recording). It is clearly distinguishable from list_sessions, get_session, and screenshot, though it does not distinguish itself from a replay-buffer style capture (save_replay) which is a nearby concept.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names stop_recording as the required follow-up, which is real workflow guidance, and "Never auto-starts" implies the agent must explicitly invoke it. But it gives no guidance on what to do if a session is already running, whether concurrent recordings are allowed, or how this relates to pause_recording/resume_recording.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

step_guideStep-by-Step GuideA
Destructive

Turn a recording's event log into a numbered how-to: a ringed screenshot and caption per step, marker headings; Markdown and/or one HTML file. Never includes typed text.

NameRequiredDescriptionDefault
ocrNoOCR shots for captions and secret boxes (default true; needs Windows OCR).
inputNoRecording path (uses its .events.jsonl).
titleNoGuide title.
formatNomd + images/, self-contained html, or both (default).
outputDirNoGuide folder (default: new in SCREENCAST_HOME/edits).
overwriteNoReplace a guide already in outputDir.
sessionIdNoOr a stopped session's id.

Output Schema

NameRequiredDescription
outputDirYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and non-read-only, so the bar is lower; the description nonetheless discloses what the artifacts are and, importantly, the exclusion property 'Never includes typed text', a privacy trait an agent cannot infer from the schema. It still doesn't say that an existing guide in outputDir is replaced, though the overwrite parameter partly covers that.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One dense sentence plus a short qualifier, with the core transform front-loaded and no filler. The trailing 'Never includes typed text' is terse to the point of being slightly ambiguous about where the exclusion applies (captions, screenshots, or both).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With seven fully described parameters, an output schema and annotations covering the write/destructive profile, the description supplies the missing conceptual picture of the output bundle. What remains thin is the prerequisite context (a recording must exist and carry markers) and any steering among the many sibling post-processing tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents ocr, input, title, format, outputDir, overwrite and sessionId, which sets the baseline at 3. The description corroborates the format enum ('Markdown and/or one HTML file') and hints at how markers shape the output, but adds no syntax or defaulting detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise transform: an event log becomes a numbered how-to with per-step ringed screenshots, captions and marker headings, emitted as Markdown and/or a single HTML file. That verb+resource+output triple separates it cleanly from siblings like chapters, review_recording, convert and concat.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: you run it on a recording's event log to get a written guide. No sibling is named as an alternative or exclusion, so an agent deciding between step_guide, chapters and review_recording gets no routing help. The 'Never includes typed text' note hints at a privacy-sensitive situation but does not frame when to pick this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stop_recordingStop RecordingA
Idempotent

Stop a recording gracefully so the file is finalized; returns the path and duration.

NameRequiredDescriptionDefault
saveNoReplay buffer: write it all to outputPath first (default: discard).
sessionIdYesSession id returned by start_recording.

Output Schema

NameRequiredDescription
statusYes
sessionIdYes
outputPathYes
durationSecYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description adds that stopping is graceful and finalizes the file. It does not address whether buffered/in-progress data can be lost, which is the main behavioral risk for a stop operation, so it is useful but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with the action and the key consequence front-loaded; nothing wasted, nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With only two well-described parameters, an output schema covering return values, and annotations covering the safety profile, the definition gives an agent enough to invoke it correctly. The only missing element (stop vs pause guidance) is minor given the sibling names.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters (sessionId, save) are documented in the schema, so baseline 3 applies. The description adds no meaning about the save/discard behavior or sessionId expectations beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Stop a recording") plus the outcome ("file is finalized"), which implicitly separates it from pause_recording/resume_recording. It stops short of naming a sibling explicitly, so it is clear but not maximally differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the effect (finalize the file); there is no statement of when to stop versus pause, whether stopping requires an active session, or what happens if the session is already stopped.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

title_cardTitle CardA
Destructive

Generate a title card clip (centered text on a solid background, silent audio track) to stitch in with assemble_highlights. Uncoverable characters are reported in warnings.

NameRequiredDescriptionDefault
bgNoBackground color (default black).
fpsNoCard fps (default 30).
boldNoUse the bold weight (default true).
textYesTitle text. Multiple lines are allowed (use \n).
widthNoCard width (default 1920).
heightNoCard height (default 1080).
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
durationNoCard length in seconds (default 3).
fontFileNoFont: a .ttf/.otf/.ttc path or a C:\Windows\Fonts file name. Default: bundled Inter, with a covering system font for scripts it lacks (CJK, emoji, Arabic, ...).
fontSizeNoText size in px (default 96).
fontColorNoText color (default white).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds behavior beyond the annotations: the output is a real clip with a silent audio track (important for downstream concat/assembly) and unsupported glyphs surface as warnings rather than failing. It does not explain why the tool is flagged destructive (file creation at an output path, overwriting guarded by the overwrite param), which the schema partially covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero waste, with the core artifact description front-loaded and the caveat about warnings placed second. Nothing redundant with the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

All 12 parameters are documented in the schema and an output schema exists, so the description need not cover them. It covers the artifact's nature, audio characteristic, and error surface; a note about where the file lands or failure modes would make it complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds meaning by noting text is centered on the background, that the audio is silent, and that unrenderable characters are reported — context that relates to fontFile fallback behavior and makes the text parameter's rendering model clearer.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (generate) and resource (title card clip) and describes the artifact precisely: centered text on a solid background with a silent audio track. That output specification is what distinguishes it from overlay/callout/xfade siblings, which modify existing media rather than create a standalone clip.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete intended use — stitch the result in with assemble_highlights — which tells the agent where this fits in a workflow. It does not say when to prefer e.g. overlay or burn_subtitles instead of a standalone card, so no explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

transcribeTranscribe SpeechA
Destructive

Transcribe a recording's speech to an SRT subtitle file, locally, with FFmpeg 8's whisper filter (needs a whisper.cpp model file). Returns the SRT path and the text. Pair with burn_subtitles to caption the video.

NameRequiredDescriptionDefault
inputYesPath to the video or audio to transcribe.
modelNoPath to a whisper.cpp model file (ggml-*.bin). Defaults to SCREENCAST_WHISPER_MODEL.
wordsNoOne word per cue, for word timing (cut_by_transcript).
outputNoOptional output .srt path. Defaults under SCREENCAST_HOME/edits.
languageNoSpoken language code, e.g. 'en', or 'auto' (default).
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
cuesYes
textYes
srtPathYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false; the description adds useful context that processing is local, that an external whisper.cpp model file is required, and what is produced (SRT path plus text). The destructiveness is implied by writing an SRT file (mitigated by overwrite=false default documented in schema) but never explicitly discussed, leaving a small gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences: the action and output first, the engine/prerequisite second, and the sibling pairing last. No filler, every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations covering the mutation profile, the description needn't restate return values, and it still gives a one-line summary of them. It doesn't cover failure modes (missing model, unsupported language) or rough runtime expectations, which for a moderately complex local inference tool would be the finishing touch.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all six parameters (input, model, words, output, language, overwrite) are already documented. The description reinforces the model requirement but adds no syntax, format, or trade-off detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (transcribe), resource (a recording's speech), and concrete output artifact (an SRT subtitle file), plus names the engine used. An agent can immediately distinguish this from siblings like burn_subtitles or cut_by_transcript, both of which are explicitly referenced or implied.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context ('Pair with burn_subtitles to caption the video') and a prerequisite ('needs a whisper.cpp model file'), which routes the agent correctly. It stops short of explicit when-not-to-use guidance or naming an alternative transcription path, so it's a strong 4 rather than a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

trimTrim VideoA
Destructive

Cut a video down to one sub-clip by start + (end or duration). For several segments use clip; to combine with other edits use pipeline.

NameRequiredDescriptionDefault
endNoEnd time in seconds. Use end OR duration.
exactNoRe-encode for a frame-exact cut with the removed content really gone (default true). false = fast stream copy that snaps to a keyframe and keeps hidden earlier frames; never use it to remove secrets.
inputYesPath to the source video.
startYesStart time in seconds.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
durationNoClip length in seconds. Use end OR duration.
overwriteNoAllow replacing an existing file at the output path (default false).

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, non-idempotent, non-read-only, so the safety profile is covered. The description adds nothing about overwrite behavior, default output location, or the keyframe/stream-copy caveat — that substance lives in the schema's 'exact' and 'overwrite' descriptions. Useful routing but limited added behavioral context beyond structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with zero filler, and the core operation is front-loaded ahead of the alternatives. Slightly terse for a destructive 7-param tool, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, annotations cover the safety profile, and all 7 params are documented in the schema, so the description needn't explain return values. What remains missing — that it writes a file which can overwrite an existing one by default — is handled by the 'overwrite' param description, so the definition is essentially complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including the end-vs-duration exclusivity and the frame-exact / keyframe tradeoff. The description only restates the 'end or duration' rule already in the schema, adding no syntax, units, or format detail beyond it. Baseline 3 for a fully documented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (cut down to one sub-clip) and the exact mechanism (start + end or duration), which is more precise than the title 'Trim Video'. It also explicitly names the siblings it is not (clip, pipeline), so an agent can separate it from them without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: single segment goes here, multiple segments go to clip, combining with other edits goes to pipeline. That is a named alternative plus the condition that selects it, which is the top of the scale.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

wait_for_changeWait for Screen ChangeA
Read-onlyIdempotent

Wait until part of the screen changes or settles, instead of guessing a sleep. Returns the elapsed time, changed regions (screenshot pixels; add origin for desktop), and the final state.

NameRequiredDescriptionDefault
keepNoKeep the final screenshot on disk and return its path (default false).
modeNochange (default): return once it differs from the start. settle: once it has been still for settleSec.
targetYesWhat to watch: full | monitor:<i> | window:<title> (or exe=/hwnd=) | region:<x>,<y>,<w>,<h>.
settleSecNoMode settle: seconds of stillness (default 1).
exactTitleNowindow: targets match the whole title only (default false).
intervalMsNoPause between checks in ms (default 250).
timeoutSecNoGive up after this many seconds (default 30; a timeout is a result, not an error).
returnImageNoReturn the final state inline (default true).
pixelThresholdNoMean 0-255 difference for a ~32x32 cell to count as changed (default 12).

Output Schema

NameRequiredDescription
modeYes
originYes
outcomeYes
regionsYes
elapsedSecYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this a read-only, idempotent, non-destructive operation, so safety is covered. The description adds the blocking/polling nature of the call and the notion of settle versus change, which goes somewhat beyond the annotations. However, the remaining disclosure (elapsed time, changed regions, final state) duplicates the output schema, so net new behavioral context is modest.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with the action front-loaded and the return information second. Every clause carries weight and nothing is repeated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema, rich parameter descriptions, and complete annotations, the description only needs to convey the wait semantics and the change/settle intent, which it does. Minor gaps remain around environment requirements (desktop session, permissions) that an agent might want before calling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so every parameter including mode, target, timeoutSec, and pixelThreshold is already documented with defaults and bounds. The description adds only one detail that the schema lacks: 'add `origin` for desktop' for changed regions, which is thin and references something not present as an input parameter. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: waits until part of the screen changes or settles. The 'instead of guessing a sleep' clause makes the intent unmistakable. It does not, however, contrast itself with the nearest sibling, screen_diff, so an agent must still infer the boundary between them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Instead of guessing a sleep' implies the usage context (waiting on a UI change rather than a fixed delay), which is useful implied guidance. There is no explicit when-not-to-use, no named alternative such as screenshot or screen_diff, and no mention of prerequisites like needing a desktop session.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

xfade_transitionCrossfade TransitionA
Destructive

Join two videos with an xfade transition (audio crossfaded); they need not match in size, fps, or audio. For more clips use assemble_highlights.

NameRequiredDescriptionDefault
inputAYesOutgoing video.
inputBYesIncoming video.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
durationNoTransition length in seconds (default 1).
overwriteNoAllow replacing an existing file at the output path (default false).
transitionNoxfade name (default fade): fade, wipeleft, slideup, circleopen, dissolve, ...

Output Schema

NameRequiredDescription
outputPathYesPath of the file written.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and readOnly=false, so the write semantics are covered; the description adds genuinely new context that the annotations cannot: audio is crossfaded, and inputs need not match in size, fps, or audio. That tolerance statement is the key operational fact for this tool and is stated plainly. It stops short of noting that the existing output file may be replaced, which is the residual destructive-behavior gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short clauses and one routing sentence, no filler. The core operation and the audio detail are front-loaded, and the sibling routing is held to the end where it belongs.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so return values need no explanation, and annotations cover the destructive profile. The description supplies the tolerance and audio-crossfade behavior an agent needs before invoking. Slight gap: no mention of what happens to an existing output path, which matters for a destructive tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and every parameter is documented in-schema including defaults (duration 1, overwrite false, transition fade). The description adds nothing about parameters beyond the implicit point that no audio-matching parameter is needed. Baseline 3 is correct when the schema carries this load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb plus resource ('Join two videos with an xfade transition') with an explicit scope limit ('two videos') and a named transition mechanism. The parenthetical '(audio crossfaded)' disambiguates it from a plain concatenation, so an agent can tell it apart from concat/assemble_highlights without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes multi-clip work away: 'For more clips use assemble_highlights.' That is a clear alternative with a selecting condition. It does not, however, address the nearest ambiguous sibling, concat, so an agent choosing between a hard cut join and a crossfade join still has to infer the distinction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

zoomZoom and PanA
Destructive

Smooth animated zoom-and-pan into the action and back out, from keyframes or planned from logged clicks or screen changes.

NameRequiredDescriptionDefault
inputYesPath to the source video.
dryRunNoReturn the planned keyframes only (editable, pass back).
eventsNoEvents log (default: the input's .events.jsonl); must match the input's timing and size, so use the original recording.
followNoWithout keyframes: clicks (from the events log of start_recording events: true) or changes (where the screen changed). auto (default): clicks if logged, else changes.
outputNoOptional output path. Defaults under SCREENCAST_HOME/edits.
holdSecNoAuto mode: stay zoomed this long after activity (default 2).
maxZoomNoAuto mode: the furthest it zooms in (default 2.5).
keyframesNoViews reached by time t: a source rectangle (x, y, width, height), or { t, full: true } to zoom out. Omit to plan them (see follow).
overwriteNoAllow replacing an existing file at the output path (default false).
transitionSecNoHow long each zoom/pan eases (default 0.6).
highlightColorNoRing color (default #FF4545).
highlightClicksNoRing each logged click (default false).

Output Schema

NameRequiredDescription
keyframesYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false, and openWorldHint=false, so the agent knows this writes something non-idempotently. The description adds that zoom is directional (in and back out) and keyframe/tracking driven, which is useful context. It does not state that a new file is rendered to `output`, nor that the source video is left untouched, which are the real behavioral questions for a mutating render tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the core behavior and the two sourcing modes are packed in without redundancy. Nothing could be cut without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values needn't be explained, and the 12 parameters are fully documented in-schema. What's mildly under-served is the write/render lifecycle: that the tool always produces an output file (defaulting under SCREENCAST_HOME/edits) and that `dryRun` is the safe preview path. For a destructive render tool, one sentence on that would make the definition complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% across all 12 parameters, including enums, bounds, and the nested keyframe shape, so the schema does the heavy lifting. The description adds only the conceptual pairing of 'keyframes' vs 'planned from logged clicks or screen changes', which the schema already encodes via `follow`. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a concrete verb pair (zoom-and-pan) and its effect (smooth animated, into the action and back out), plus the two input modes (keyframes or planned). It's clear what the tool produces, but it never distinguishes itself from adjacent transform tools like crop, reframe, or scale, which an agent could plausibly reach for instead.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'from keyframes or planned from logged clicks or screen changes' implies the two operating modes, but which mode to pick and when is left to the schema's `follow` and `keyframes` fields. There is no explicit statement of when NOT to use this (e.g. prefer reframe for changing aspect ratio, crop for static framing), so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 58 tool updatesv0.47.0
    • Addedadd_marker
    • Changedassemble_highlights4 fields changed
      • changedInput schema / properties / clips / description
        Previous value: -"Two or more clip paths, in order. Clips are auto-normalized, so they need not match."New value: +"Clip paths, in order."
      • changedInput schema / properties / duration / description
        Previous value: -"Transition length in seconds when not a cut (default 1)."New value: +"Transition seconds (default 1)."
      • changedInput schema / properties / transition / description
        Previous value: -"'cut' (default, hard cuts) or an xfade transition name (fade, wipeleft, slideup, ...)."New value: +"cut (default) or an xfade name (fade, wipeleft, slideup, ...)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addedbackdrop
    • Addedbug_report
    • Changedburn_subtitles2 fields changed
      • changedInput schema / properties / style / description
        Previous value: -"'clean' (default): a modest outlined line. 'social': large bold text on a dark box, for muted autoplay."New value: +"clean (default for .srt): outlined line. social: big bold text on a dark box. .ass keeps its own styling unless set."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedcallout4 fields changed
      • addedInput schema / properties / fontFile
        Added value: +{
        +  "description": "Font: a .ttf/.otf/.ttc path or a C:\\Windows\\Fonts file name. Default: bundled Inter, with a covering system font for scripts it lacks (CJK, emoji, Arabic, ...).",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedInput schema / properties / items / description
        Previous value: -"Annotations, drawn in order (later on top). Each is a box, a text label, or an arrow, shown between from and to (seconds). Coordinates are video pixels."New value: +"Boxes, text labels, and arrows, drawn in order (later on top), in video pixels. Each shows from..to seconds (default: whole video); color is a name, #RRGGBB, or name@alpha."
      • changedInput schema / properties / items / items / oneOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "color": {
        -        "description": "Color name, #RRGGBB, or name@alpha.",
        -        "type": "string"
        -      },
        -      "fill": {
        -        "description": "Fill instead of outline.",
        -        "type": "boolean"
        -      },
        -      "from": {
        -        "description": "Show from this second (default: start).",
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "height": {
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "thickness": {
        -        "description": "Outline px (default 4).",
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "to": {
        -        "description": "Hide after this second (default: end).",
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "box",
        -        "type": "string"
        -      },
        -      "width": {
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "x": {
        -        "type": "number"
        -      },
        -      "y": {
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "width",
        -      "height"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "background": {
        -        "description": "Dark panel behind the text (default true).",
        -        "type": "boolean"
        -      },
        -      "color": {
        -        "description": "Color name, #RRGGBB, or name@alpha.",
        -        "type": "string"
        -      },
        -      "from": {
        -        "description": "Show from this second (default: start).",
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "size": {
        -        "description": "Font size px (default 32).",
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "text": {
        -        "minLength": 1,
        -        "type": "string"
        -      },
        -      "to": {
        -        "description": "Hide after this second (default: end).",
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "text",
        -        "type": "string"
        -      },
        -      "x": {
        -        "type": "number"
        -      },
        -      "y": {
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x",
        -      "y",
        -      "text"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "color": {
        -        "description": "Color name, #RRGGBB, or name@alpha.",
        -        "type": "string"
        -      },
        -      "from": {
        -        "description": "Show from this second (default: start).",
        -        "minimum": 0,
        -        "type": "number"
        -      },
        -      "thickness": {
        -        "description": "Shaft px (default 8).",
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "to": {
        -        "description": "Hide after this second (default: end).",
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "type": {
        -        "const": "arrow",
        -        "type": "string"
        -      },
        -      "x1": {
        -        "description": "Tail x.",
        -        "type": "number"
        -      },
        -      "x2": {
        -        "description": "Head x: the point the arrow points at.",
        -        "type": "number"
        -      },
        -      "y1": {
        -        "description": "Tail y.",
        -        "type": "number"
        -      },
        -      "y2": {
        -        "description": "Head y.",
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "x1",
        -      "y1",
        -      "x2",
        -      "y2"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "color": {
        +        "type": "string"
        +      },
        +      "fill": {
        +        "description": "Fill instead of outline.",
        +        "type": "boolean"
        +      },
        +      "from": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "height": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "thickness": {
        +        "description": "Outline px (default 4).",
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "to": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "box",
        +        "type": "string"
        +      },
        +      "width": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "x": {
        +        "type": "number"
        +      },
        +      "y": {
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "width",
        +      "height"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "background": {
        +        "description": "Dark panel behind the text (default true).",
        +        "type": "boolean"
        +      },
        +      "color": {
        +        "type": "string"
        +      },
        +      "from": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "size": {
        +        "description": "Font size px (default 32).",
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "text": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "to": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "text",
        +        "type": "string"
        +      },
        +      "x": {
        +        "type": "number"
        +      },
        +      "y": {
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x",
        +      "y",
        +      "text"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "color": {
        +        "type": "string"
        +      },
        +      "from": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "thickness": {
        +        "description": "Shaft px (default 8).",
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "to": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "type": {
        +        "const": "arrow",
        +        "type": "string"
        +      },
        +      "x1": {
        +        "type": "number"
        +      },
        +      "x2": {
        +        "description": "Head (x2,y2) is the point the arrow points at.",
        +        "type": "number"
        +      },
        +      "y1": {
        +        "type": "number"
        +      },
        +      "y2": {
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "x1",
        +      "y1",
        +      "x2",
        +      "y2"
        +    ],
        +    "type": "object"
        +  }
        +]
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addedchapters
    • Changedclip4 fields changed
      • changedInput schema / properties / segments / description
        Previous value: -"One or more {start, end} segments. Each becomes its own output file."New value: +"{start, end} segments in seconds; each becomes its own file."
      • removedInput schema / properties / segments / items / properties / end / description
        Removed value: -"Segment end in seconds."
      • removedInput schema / properties / segments / items / properties / start / description
        Removed value: -"Segment start in seconds."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "count": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "outputs": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "outputs",
        +    "count"
        +  ],
        +  "type": "object"
        +}
    • Changedcompress3 fields changed
      • changedInput schema / properties / level / description
        Previous value: -"How hard to compress (CRF 23 / 28 / 32). Default medium."New value: +"CRF 23 / 28 / 32 (default medium)."
      • changedInput schema / properties / maxWidth / description
        Previous value: -"Optional width cap in px; only ever downscales. Height follows aspect."New value: +"Width cap in px (only downscales)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedconcat2 fields changed
      • changedInput schema / properties / inputs / description
        Previous value: -"Two or more video paths to join, in order. Matching inputs are stream-copied; others are re-encoded."New value: +"Video paths to join, in order."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedcontact_sheet8 fields changed
      • changedInput schema / properties / count / description
        Previous value: -"How many frames to tile (default 12, max 48)."New value: +"Frames to tile (default 12)."
      • changedInput schema / properties / maxImageWidth / description
        Previous value: -"Downscale the inline image to at most this width (default 1280)."New value: +"Max inline image width (default 1280)."
      • changedInput schema / properties / mode / description
        Previous value: -"'even' spreads frames evenly across the video (default); 'scenes' uses the opening frame plus the strongest scene changes, so static stretches take no tiles."New value: +"even (default) or scenes (strongest changes; static stretches take no tiles)."
      • changedInput schema / properties / poster / description
        Previous value: -"Instead of a sheet, write one representative poster frame (ffmpeg's thumbnail filter over 30 candidates spread across the video), e.g. for a video thumbnail."New value: +"Write one representative poster frame instead of a sheet."
      • changedInput schema / properties / returnImage / description
        Previous value: -"Also return the sheet inline as an image the model can view directly (default true)."New value: +"Return the sheet inline (default true)."
      • changedInput schema / properties / sceneThreshold / description
        Previous value: -"Mode 'scenes': how much a frame must change to count (default 0.1)."New value: +"Mode scenes: change needed, 0-1 (default 0.1)."
      • changedInput schema / properties / tileWidth / description
        Previous value: -"Width of each tile in px (default 320)."New value: +"Tile width in px (default 320)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "inlineImages": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "outputPath": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath",
        +    "inlineImages"
        +  ],
        +  "type": "object"
        +}
    • Changedconvert4 fields changed
      • changedInput schema / properties / format / description
        Previous value: -"Target format. Converts mp4 <-> gif/webm (H.264 / VP9 / palette gif)."New value: +"mp4 (H.264), webm (VP9), or gif (palette)."
      • changedInput schema / properties / fps / description
        Previous value: -"Output fps (gif only; default 12)."New value: +"gif only: fps (default 12)."
      • changedInput schema / properties / width / description
        Previous value: -"Output width in px, height auto (gif only; default 720)."New value: +"gif only: width in px (default 720)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedcrop5 fields changed
      • removedInput schema / properties / height / description
        Removed value: -"Crop height in pixels."
      • removedInput schema / properties / width / description
        Removed value: -"Crop width in pixels."
      • removedInput schema / properties / x / description
        Removed value: -"Left edge of the crop in pixels."
      • removedInput schema / properties / y / description
        Removed value: -"Top edge of the crop in pixels."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addedcursor
    • Addedcut_by_transcript
    • Changedcut_idle3 fields changed
      • changedInput schema / properties / dryRun / description
        Previous value: -"Only report the stretches that would be cut; write nothing."New value: +"Only report what would be cut."
      • changedInput schema / properties / keepSec / description
        Previous value: -"Keep this much of each stretch at both edges so cuts are not abrupt (default 0.4)."New value: +"Seconds kept at each edge of a cut (default 0.4)."
      • changedInput schema / properties / useAudio / description
        Previous value: -"Count a stretch as idle only if the audio is also silent (default true when the video has audio). Set false to cut frozen video even while sound plays."New value: +"Require silent audio too (default true when there is audio)."
    • Changeddenoise1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addeddoctor
    • Changedexport_gif6 fields changed
      • changedInput schema / properties / duration / description
        Previous value: -"Export only this many seconds (default: to the end)."New value: +"Seconds to export (default: to the end)."
      • changedInput schema / properties / format / description
        Previous value: -"gif (plays everywhere, default) or webp (animated WebP, usually much smaller)."New value: +"gif (default) or webp (usually much smaller)."
      • changedInput schema / properties / maxBytes / description
        Previous value: -"File-size budget in bytes (default 10000000, under GitHub's 10 MB limit for images). Quality steps down until the file fits."New value: +"Size budget in bytes (default 10000000, under GitHub's 10 MB image limit)."
      • changedInput schema / properties / start / description
        Previous value: -"Start at this many seconds into the video."New value: +"Start second."
      • changedInput schema / properties / width / description
        Previous value: -"Starting width in px (default 960); height follows the aspect ratio."New value: +"Starting width in px (default 960)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedexport_preset3 fields changed
      • changedInput schema / properties / fit / description
        Previous value: -"How to fit the source into the platform aspect: pad (default) or crop."New value: +"Fit to the platform aspect: pad (default) or crop."
      • changedInput schema / properties / platform / description
        Previous value: -"Target platform. Sets aspect, resolution, fps, and bitrate. steam_trailer: 1920x1080, H.264 High, padded 5.5 Mbps CBR, AAC 48 kHz at -14 LUFS. vertical_reel: 1080x1920 with the footage centred over a blurred copy of itself, audio at -14 LUFS (fit is ignored)."New value: +"Sets aspect, size, fps, bitrate. steam_trailer: 1080p 5.5 Mbps CBR, -14 LUFS. vertical_reel: 1080x1920 over a blurred copy of itself, -14 LUFS (ignores fit)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedextract_audio1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedfind_text12 fields changed
      • changedInput schema / properties / backend / description
        Previous value: -"For a live target: gdigrab (default) reads what is visible; 'wgc' (window: targets, FFmpeg 8+) reads the window's own surface even when other windows cover it."New value: +"Live target: gdigrab (default) = what is visible; wgc (window:, FFmpeg 8+) = the window even if covered."
      • changedInput schema / properties / exactTitle / description
        Previous value: -"For window: targets, match the title exactly (default false)."New value: +"window: targets match the whole title only (default false)."
      • changedInput schema / properties / input / description
        Previous value: -"Or read text from an image or video file (one of target / input)."New value: +"Image or video file to read instead of a live target."
      • changedInput schema / properties / keep / description
        Previous value: -"For a live target: keep the captured screenshot and return its path (default false: it is deleted after reading, since it may show the secrets being looked for)."New value: +"Live target: keep the capture and return its path (default false: deleted after reading)."
      • changedInput schema / properties / maxFrames / description
        Previous value: -"With scanEverySec: most frames to read (default 30); each takes about a second."New value: +"scanEverySec frame cap (default 30; ~1 s each)."
      • changedInput schema / properties / query / description
        Previous value: -"Text to look for. Case-insensitive, and tolerant of common OCR misreads (_ vs -, I vs l, O vs 0; regexes get the _ vs - tolerance). Without a query, all recognised text is returned."New value: +"Text to find (case-insensitive, tolerates OCR misreads like I/l, O/0, _/-). Omit to return all text."
      • changedInput schema / properties / redact / description
        Previous value: -"Also return padded rectangles around each match, ready to pass to redact_region (regions) to cover them. Detection is best-effort: review the result."New value: +"Also return padded match rectangles ready for redact_region's regions."
      • changedInput schema / properties / returnImage / description
        Previous value: -"Return the image inline with matches outlined in red (default true when there is a query)."New value: +"Return the image with matches outlined (default: true with a query)."
      • changedInput schema / properties / scanEverySec / description
        Previous value: -"For a video input: read a frame every N seconds across the whole clip instead of one frame, so text shown at any moment is found (use it to check a clip for secrets before sharing). Each match gets its time, and redactRegions get start/end. The interval widens to stay within maxFrames."New value: +"Video input: scan a frame every N s across the clip (e.g. for secrets before sharing); matches and redactRegions get times. Widens to stay within maxFrames."
      • changedInput schema / properties / target / description
        Previous value: -"Read text live from the screen: 'full' | 'monitor:<index>' | 'window:<title>' (or window:exe=<app.exe> / window:hwnd=<handle>) | 'region:...'."New value: +"Live screen target (full | monitor:<i> | window:... | region:...), or pass input."
      • changedInput schema / properties / timestamp / description
        Previous value: -"For a video input: the second to read (default 0). Ignored with scanEverySec."New value: +"Video input: second to read (default 0)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "imageSize": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "height": {
        +          "type": "number"
        +        },
        +        "width": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "width",
        +        "height"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "imageSize"
        +  ],
        +  "type": "object"
        +}
    • Changedget_media_info1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "audioCodec": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "durationSec": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "fps": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "height": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "input": {
        +      "type": "string"
        +    },
        +    "videoCodec": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "width": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "input",
        +    "durationSec",
        +    "width",
        +    "height",
        +    "fps",
        +    "videoCodec",
        +    "audioCodec"
        +  ],
        +  "type": "object"
        +}
    • Changedget_session1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "alive": {
        +      "type": "boolean"
        +    },
        +    "fileExists": {
        +      "type": "boolean"
        +    },
        +    "id": {
        +      "type": "string"
        +    },
        +    "outputPath": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "id",
        +    "status",
        +    "outputPath",
        +    "alive",
        +    "fileExists"
        +  ],
        +  "type": "object"
        +}
    • Addedindex_recording
    • Addedkeystroke_overlay
    • Changedlist_audio_devices1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "devices": {
        +      "items": {},
        +      "type": "array"
        +    },
        +    "loopbackDevice": {
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "note": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "devices",
        +    "loopbackDevice",
        +    "note"
        +  ],
        +  "type": "object"
        +}
    • Changedlist_sessions1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "count": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "sessions": {
        +      "items": {
        +        "additionalProperties": {},
        +        "properties": {
        +          "alive": {
        +            "type": "boolean"
        +          },
        +          "id": {
        +            "type": "string"
        +          },
        +          "outputPath": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "status",
        +          "outputPath",
        +          "alive"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "count",
        +    "sessions"
        +  ],
        +  "type": "object"
        +}
    • Addedlist_targets
    • Addedlist_video_devices
    • Changedmusic_bed6 fields changed
      • changedInput schema / properties / duck / description
        Previous value: -"Duck the music under the original audio via a sidechain (default false)."New value: +"Duck the music under the original audio (default false)."
      • changedInput schema / properties / fadeIn / description
        Previous value: -"Music fade-in seconds (default 1)."New value: +"Fade-in seconds (default 1)."
      • changedInput schema / properties / fadeOut / description
        Previous value: -"Music fade-out seconds (default 2)."New value: +"Fade-out seconds (default 2)."
      • changedInput schema / properties / music / description
        Previous value: -"Path to the music audio file (looped/trimmed to the video length)."New value: +"Music audio file."
      • changedInput schema / properties / musicVolume / description
        Previous value: -"Music level 0..1 (default 0.25 over existing audio, 0.8 alone)."New value: +"0..1 (default 0.25 over existing audio, 0.8 alone)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addednarrate
    • Changednormalize_audio2 fields changed
      • changedInput schema / properties / target / description
        Previous value: -"Loudness target: 'youtube' (-14 LUFS, default), 'podcast' (-16 LUFS), 'broadcast' (EBU R128, -23 LUFS), or a LUFS number such as -18."New value: +"youtube (-14 LUFS, default), podcast (-16), broadcast (-23), or a LUFS number."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedoverlay9 fields changed
      • changedInput schema / properties / end / description
        Previous value: -"Optional second to hide the overlay after."New value: +"Hide after this second."
      • changedInput schema / properties / height / description
        Previous value: -"Optional overlay height in px (width auto when omitted)."New value: +"Scale to this height."
      • changedInput schema / properties / overlay / description
        Previous value: -"Path to the overlay image or video (logo, watermark, picture-in-picture)."New value: +"Overlay image or video path."
      • addedInput schema / properties / shape
        Added value: +{
        +  "description": "circle: centre square masked round (webcam).",
        +  "enum": [
        +    "rect",
        +    "circle"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / start / description
        Previous value: -"Optional second to show the overlay from."New value: +"Show from this second."
      • changedInput schema / properties / width / description
        Previous value: -"Optional overlay width in px (height auto when omitted)."New value: +"Scale to this width (other side keeps aspect)."
      • changedInput schema / properties / x / description
        Previous value: -"Overlay left position in pixels."New value: +"Left, px."
      • changedInput schema / properties / y / description
        Previous value: -"Overlay top position in pixels."New value: +"Top, px."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addedpause_recording
    • Changedpipeline8 fields changed
      • addedInput schema / properties / chapters
        Added value: +{
        +  "description": "Keep the input's markers as chapters, re-timed through trims and speed.",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / dryRun / description
        Previous value: -"Return the planned ffmpeg command and output size without running it."New value: +"Return the plan (ffmpeg command, output size) without running it."
      • addedInput schema / properties / recipe
        Added value: +{
        +  "description": "Polish preset expanded to steps (see dryRun): pr_demo = cut_idle, click zoom, GIF <=10 MB; tutorial = + audio, captions, 1080p mp4; social_reel = 9:16, big captions. Given steps replace its same-op step.",
        +  "enum": [
        +    "pr_demo",
        +    "tutorial",
        +    "social_reel"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / steps / description
        Previous value: -"Edits in order, each { op, ...the same options as its tool }: trim, crop, scale, speed, redact (redact_region), callout, reframe, zoom (keyframes), and as the last step only export_preset or export_gif. Times in a step are on the timeline as it is at that step, after any earlier trim or speed change; pixel positions are in the frame as it is at that step."New value: +"Edits in order, each { op, ...its tool's options }; export_preset/export_gif only last. Times and pixels are relative to the video as it is at that step (after earlier trims, speed, crops). zoom follow:\"clicks\" plans from the event log; burn_subtitles takes subtitles or transcribe:true."
      • changedInput schema / properties / steps / items / oneOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "duration": {
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "end": {
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "op": {
        -        "const": "trim",
        -        "type": "string"
        -      },
        -      "start": {
        -        "minimum": 0,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "start"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "height": {
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "op": {
        -        "const": "crop",
        -        "type": "string"
        -      },
        -      "width": {
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "x": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "y": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "x",
        -      "y",
        -      "width",
        -      "height"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "height": {
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      },
        -      "op": {
        -        "const": "scale",
        -        "type": "string"
        -      },
        -      "width": {
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "op"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "factor": {
        -        "exclusiveMinimum": 0,
        -        "type": "number"
        -      },
        -      "op": {
        -        "const": "speed",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "factor"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "color": {
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "redact",
        -        "type": "string"
        -      },
        -      "pad": {
        -        "maximum": 9007199254740991,
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "regions": {
        -        "items": {
        -          "properties": {
        -            "end": {
        -              "description": "Optional second to stop redacting after.",
        -              "exclusiveMinimum": 0,
        -              "type": "number"
        -            },
        -            "height": {
        -              "description": "Region height in pixels.",
        -              "exclusiveMinimum": 0,
        -              "maximum": 9007199254740991,
        -              "type": "integer"
        -            },
        -            "start": {
        -              "description": "Optional second to start redacting from.",
        -              "minimum": 0,
        -              "type": "number"
        -            },
        -            "width": {
        -              "description": "Region width in pixels.",
        -              "exclusiveMinimum": 0,
        -              "maximum": 9007199254740991,
        -              "type": "integer"
        -            },
        -            "x": {
        -              "description": "Left edge in pixels.",
        -              "maximum": 9007199254740991,
        -              "minimum": 0,
        -              "type": "integer"
        -            },
        -            "y": {
        -              "description": "Top edge in pixels.",
        -              "maximum": 9007199254740991,
        -              "minimum": 0,
        -              "type": "integer"
        -            }
        -          },
        -          "required": [
        -            "x",
        -            "y",
        -            "width",
        -            "height"
        -          ],
        -          "type": "object"
        -        },
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "style": {
        -        "enum": [
        -          "box",
        -          "blur",
        -          "pixelate"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "regions"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "items": {
        -        "items": {
        -          "oneOf": [
        -            {
        -              "properties": {
        -                "color": {
        -                  "description": "Color name, #RRGGBB, or name@alpha.",
        -                  "type": "string"
        -                },
        -                "fill": {
        -                  "description": "Fill instead of outline.",
        -                  "type": "boolean"
        -                },
        -                "from": {
        -                  "description": "Show from this second (default: start).",
        -                  "minimum": 0,
        -                  "type": "number"
        -                },
        -                "height": {
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "thickness": {
        -                  "description": "Outline px (default 4).",
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "to": {
        -                  "description": "Hide after this second (default: end).",
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "type": {
        -                  "const": "box",
        -                  "type": "string"
        -                },
        -                "width": {
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "x": {
        -                  "type": "number"
        -                },
        -                "y": {
        -                  "type": "number"
        -                }
        -              },
        -              "required": [
        -                "type",
        -                "x",
        -                "y",
        -                "width",
        -                "height"
        -              ],
        -              "type": "object"
        -            },
        -            {
        -              "properties": {
        -                "background": {
        -                  "description": "Dark panel behind the text (default true).",
        -                  "type": "boolean"
        -                },
        -                "color": {
        -                  "description": "Color name, #RRGGBB, or name@alpha.",
        -                  "type": "string"
        -                },
        -                "from": {
        -                  "description": "Show from this second (default: start).",
        -                  "minimum": 0,
        -                  "type": "number"
        -                },
        -                "size": {
        -                  "description": "Font size px (default 32).",
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "text": {
        -                  "minLength": 1,
        -                  "type": "string"
        -                },
        -                "to": {
        -                  "description": "Hide after this second (default: end).",
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "type": {
        -                  "const": "text",
        -                  "type": "string"
        -                },
        -                "x": {
        -                  "type": "number"
        -                },
        -                "y": {
        -                  "type": "number"
        -                }
        -              },
        -              "required": [
        -                "type",
        -                "x",
        -                "y",
        -                "text"
        -              ],
        -              "type": "object"
        -            },
        -            {
        -              "properties": {
        -                "color": {
        -                  "description": "Color name, #RRGGBB, or name@alpha.",
        -                  "type": "string"
        -                },
        -                "from": {
        -                  "description": "Show from this second (default: start).",
        -                  "minimum": 0,
        -                  "type": "number"
        -                },
        -                "thickness": {
        -                  "description": "Shaft px (default 8).",
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "to": {
        -                  "description": "Hide after this second (default: end).",
        -                  "exclusiveMinimum": 0,
        -                  "type": "number"
        -                },
        -                "type": {
        -                  "const": "arrow",
        -                  "type": "string"
        -                },
        -                "x1": {
        -                  "description": "Tail x.",
        -                  "type": "number"
        -                },
        -                "x2": {
        -                  "description": "Head x: the point the arrow points at.",
        -                  "type": "number"
        -                },
        -                "y1": {
        -                  "description": "Tail y.",
        -                  "type": "number"
        -                },
        -                "y2": {
        -                  "description": "Head y.",
        -                  "type": "number"
        -                }
        -              },
        -              "required": [
        -                "type",
        -                "x1",
        -                "y1",
        -                "x2",
        -                "y2"
        -              ],
        -              "type": "object"
        -            }
        -          ]
        -        },
        -        "maxItems": 50,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "op": {
        -        "const": "callout",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "items"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "aspect": {
        -        "enum": [
        -          "16:9",
        -          "9:16",
        -          "1:1",
        -          "4:5"
        -        ],
        -        "type": "string"
        -      },
        -      "fit": {
        -        "enum": [
        -          "pad",
        -          "crop"
        -        ],
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "reframe",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "aspect"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "keyframes": {
        -        "items": {
        -          "properties": {
        -            "full": {
        -              "description": "Zoom back out to the whole frame.",
        -              "type": "boolean"
        -            },
        -            "height": {
        -              "exclusiveMinimum": 0,
        -              "type": "number"
        -            },
        -            "t": {
        -              "description": "Seconds: the view is fully reached at this time.",
        -              "minimum": 0,
        -              "type": "number"
        -            },
        -            "width": {
        -              "exclusiveMinimum": 0,
        -              "type": "number"
        -            },
        -            "x": {
        -              "type": "number"
        -            },
        -            "y": {
        -              "type": "number"
        -            }
        -          },
        -          "required": [
        -            "t"
        -          ],
        -          "type": "object"
        -        },
        -        "maxItems": 100,
        -        "minItems": 1,
        -        "type": "array"
        -      },
        -      "op": {
        -        "const": "zoom",
        -        "type": "string"
        -      },
        -      "transitionSec": {
        -        "exclusiveMinimum": 0,
        -        "maximum": 5,
        -        "type": "number"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "keyframes"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "fit": {
        -        "enum": [
        -          "pad",
        -          "crop"
        -        ],
        -        "type": "string"
        -      },
        -      "op": {
        -        "const": "export_preset",
        -        "type": "string"
        -      },
        -      "platform": {
        -        "enum": [
        -          "youtube",
        -          "instagram_reel",
        -          "tiktok",
        -          "x",
        -          "square",
        -          "steam_trailer",
        -          "vertical_reel"
        -        ],
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "op",
        -      "platform"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "format": {
        -        "enum": [
        -          "gif",
        -          "webp"
        -        ],
        -        "type": "string"
        -      },
        -      "fps": {
        -        "exclusiveMinimum": 0,
        -        "maximum": 30,
        -        "type": "number"
        -      },
        -      "maxBytes": {
        -        "maximum": 9007199254740991,
        -        "minimum": 10000,
        -        "type": "integer"
        -      },
        -      "op": {
        -        "const": "export_gif",
        -        "type": "string"
        -      },
        -      "width": {
        -        "maximum": 1920,
        -        "minimum": 64,
        -        "type": "integer"
        -      }
        -    },
        -    "required": [
        -      "op"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "duration": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "end": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "op": {
        +        "const": "trim",
        +        "type": "string"
        +      },
        +      "start": {
        +        "minimum": 0,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "start"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "height": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "op": {
        +        "const": "crop",
        +        "type": "string"
        +      },
        +      "width": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "x": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "y": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "x",
        +      "y",
        +      "width",
        +      "height"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "height": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      },
        +      "op": {
        +        "const": "scale",
        +        "type": "string"
        +      },
        +      "width": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "factor": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "op": {
        +        "const": "speed",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "factor"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "color": {
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "redact",
        +        "type": "string"
        +      },
        +      "pad": {
        +        "maximum": 9007199254740991,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "regions": {
        +        "items": {
        +          "properties": {
        +            "end": {
        +              "exclusiveMinimum": 0,
        +              "type": "number"
        +            },
        +            "height": {
        +              "exclusiveMinimum": 0,
        +              "maximum": 9007199254740991,
        +              "type": "integer"
        +            },
        +            "start": {
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "width": {
        +              "exclusiveMinimum": 0,
        +              "maximum": 9007199254740991,
        +              "type": "integer"
        +            },
        +            "x": {
        +              "maximum": 9007199254740991,
        +              "minimum": 0,
        +              "type": "integer"
        +            },
        +            "y": {
        +              "maximum": 9007199254740991,
        +              "minimum": 0,
        +              "type": "integer"
        +            }
        +          },
        +          "required": [
        +            "x",
        +            "y",
        +            "width",
        +            "height"
        +          ],
        +          "type": "object"
        +        },
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "style": {
        +        "enum": [
        +          "box",
        +          "blur",
        +          "pixelate"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "regions"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "fontFile": {
        +        "description": "Font: a .ttf/.otf/.ttc path or a C:\\Windows\\Fonts file name. Default: bundled Inter, with a covering system font for scripts it lacks (CJK, emoji, Arabic, ...).",
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "items": {
        +        "items": {
        +          "oneOf": [
        +            {
        +              "properties": {
        +                "color": {
        +                  "type": "string"
        +                },
        +                "fill": {
        +                  "description": "Fill instead of outline.",
        +                  "type": "boolean"
        +                },
        +                "from": {
        +                  "minimum": 0,
        +                  "type": "number"
        +                },
        +                "height": {
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "thickness": {
        +                  "description": "Outline px (default 4).",
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "to": {
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "type": {
        +                  "const": "box",
        +                  "type": "string"
        +                },
        +                "width": {
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "x": {
        +                  "type": "number"
        +                },
        +                "y": {
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "type",
        +                "x",
        +                "y",
        +                "width",
        +                "height"
        +              ],
        +              "type": "object"
        +            },
        +            {
        +              "properties": {
        +                "background": {
        +                  "description": "Dark panel behind the text (default true).",
        +                  "type": "boolean"
        +                },
        +                "color": {
        +                  "type": "string"
        +                },
        +                "from": {
        +                  "minimum": 0,
        +                  "type": "number"
        +                },
        +                "size": {
        +                  "description": "Font size px (default 32).",
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "text": {
        +                  "minLength": 1,
        +                  "type": "string"
        +                },
        +                "to": {
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "type": {
        +                  "const": "text",
        +                  "type": "string"
        +                },
        +                "x": {
        +                  "type": "number"
        +                },
        +                "y": {
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "type",
        +                "x",
        +                "y",
        +                "text"
        +              ],
        +              "type": "object"
        +            },
        +            {
        +              "properties": {
        +                "color": {
        +                  "type": "string"
        +                },
        +                "from": {
        +                  "minimum": 0,
        +                  "type": "number"
        +                },
        +                "thickness": {
        +                  "description": "Shaft px (default 8).",
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "to": {
        +                  "exclusiveMinimum": 0,
        +                  "type": "number"
        +                },
        +                "type": {
        +                  "const": "arrow",
        +                  "type": "string"
        +                },
        +                "x1": {
        +                  "type": "number"
        +                },
        +                "x2": {
        +                  "description": "Head (x2,y2) is the point the arrow points at.",
        +                  "type": "number"
        +                },
        +                "y1": {
        +                  "type": "number"
        +                },
        +                "y2": {
        +                  "type": "number"
        +                }
        +              },
        +              "required": [
        +                "type",
        +                "x1",
        +                "y1",
        +                "x2",
        +                "y2"
        +              ],
        +              "type": "object"
        +            }
        +          ]
        +        },
        +        "maxItems": 50,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "op": {
        +        "const": "callout",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "items"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "aspect": {
        +        "enum": [
        +          "16:9",
        +          "9:16",
        +          "1:1",
        +          "4:5"
        +        ],
        +        "type": "string"
        +      },
        +      "fit": {
        +        "enum": [
        +          "pad",
        +          "crop"
        +        ],
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "reframe",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "aspect"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "follow": {
        +        "const": "clicks",
        +        "type": "string"
        +      },
        +      "holdSec": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 30,
        +        "type": "number"
        +      },
        +      "keyframes": {
        +        "items": {
        +          "properties": {
        +            "full": {
        +              "type": "boolean"
        +            },
        +            "height": {
        +              "exclusiveMinimum": 0,
        +              "type": "number"
        +            },
        +            "t": {
        +              "minimum": 0,
        +              "type": "number"
        +            },
        +            "width": {
        +              "exclusiveMinimum": 0,
        +              "type": "number"
        +            },
        +            "x": {
        +              "type": "number"
        +            },
        +            "y": {
        +              "type": "number"
        +            }
        +          },
        +          "required": [
        +            "t"
        +          ],
        +          "type": "object"
        +        },
        +        "maxItems": 100,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "maxZoom": {
        +        "maximum": 6,
        +        "minimum": 1,
        +        "type": "number"
        +      },
        +      "op": {
        +        "const": "zoom",
        +        "type": "string"
        +      },
        +      "transitionSec": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 5,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "keepSec": {
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "minIdleSec": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "op": {
        +        "const": "cut_idle",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "denoise": {
        +        "enum": [
        +          "light",
        +          "medium",
        +          "strong"
        +        ],
        +        "type": "string"
        +      },
        +      "normalize": {
        +        "anyOf": [
        +          {
        +            "enum": [
        +              "youtube",
        +              "podcast",
        +              "broadcast"
        +            ],
        +            "type": "string"
        +          },
        +          {
        +            "maximum": -5,
        +            "minimum": -70,
        +            "type": "number"
        +          }
        +        ]
        +      },
        +      "op": {
        +        "const": "audio",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "op": {
        +        "const": "burn_subtitles",
        +        "type": "string"
        +      },
        +      "style": {
        +        "enum": [
        +          "clean",
        +          "social"
        +        ],
        +        "type": "string"
        +      },
        +      "subtitles": {
        +        "type": "string"
        +      },
        +      "transcribe": {
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "aspect": {
        +        "enum": [
        +          "16:9",
        +          "9:16",
        +          "1:1",
        +          "4:5"
        +        ],
        +        "type": "string"
        +      },
        +      "colors": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "maxItems": 4,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "image": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "backdrop",
        +        "type": "string"
        +      },
        +      "padding": {
        +        "maximum": 2000,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "preset": {
        +        "enum": [
        +          "desktop",
        +          "rec",
        +          "amber",
        +          "light"
        +        ],
        +        "type": "string"
        +      },
        +      "radius": {
        +        "maximum": 1000,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "shadow": {
        +        "maximum": 200,
        +        "minimum": 0,
        +        "type": "integer"
        +      },
        +      "shadowOpacity": {
        +        "maximum": 1,
        +        "minimum": 0,
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "clicks": {
        +        "type": "boolean"
        +      },
        +      "color": {
        +        "type": "string"
        +      },
        +      "events": {
        +        "type": "string"
        +      },
        +      "fontFile": {
        +        "minLength": 1,
        +        "type": "string"
        +      },
        +      "keys": {
        +        "enum": [
        +          "shortcuts",
        +          "masked"
        +        ],
        +        "type": "string"
        +      },
        +      "lingerSec": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 10,
        +        "type": "number"
        +      },
        +      "op": {
        +        "const": "keystroke_overlay",
        +        "type": "string"
        +      },
        +      "position": {
        +        "enum": [
        +          "bottom",
        +          "bottom-left",
        +          "bottom-right",
        +          "top",
        +          "top-left",
        +          "top-right"
        +        ],
        +        "type": "string"
        +      },
        +      "size": {
        +        "maximum": 400,
        +        "minimum": 8,
        +        "type": "number"
        +      },
        +      "typing": {
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "clicks": {
        +        "type": "boolean"
        +      },
        +      "events": {
        +        "type": "string"
        +      },
        +      "hideAfterSec": {
        +        "maximum": 600,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "op": {
        +        "const": "cursor",
        +        "type": "string"
        +      },
        +      "size": {
        +        "maximum": 8,
        +        "minimum": 0.25,
        +        "type": "number"
        +      },
        +      "smoothing": {
        +        "maximum": 1,
        +        "minimum": 0,
        +        "type": "number"
        +      },
        +      "spotlight": {
        +        "type": "boolean"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "fit": {
        +        "enum": [
        +          "pad",
        +          "crop"
        +        ],
        +        "type": "string"
        +      },
        +      "op": {
        +        "const": "export_preset",
        +        "type": "string"
        +      },
        +      "platform": {
        +        "enum": [
        +          "youtube",
        +          "instagram_reel",
        +          "tiktok",
        +          "x",
        +          "square",
        +          "steam_trailer",
        +          "vertical_reel"
        +        ],
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "op",
        +      "platform"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "format": {
        +        "enum": [
        +          "gif",
        +          "webp"
        +        ],
        +        "type": "string"
        +      },
        +      "fps": {
        +        "exclusiveMinimum": 0,
        +        "maximum": 30,
        +        "type": "number"
        +      },
        +      "maxBytes": {
        +        "maximum": 9007199254740991,
        +        "minimum": 10000,
        +        "type": "integer"
        +      },
        +      "op": {
        +        "const": "export_gif",
        +        "type": "string"
        +      },
        +      "width": {
        +        "maximum": 1920,
        +        "minimum": 64,
        +        "type": "integer"
        +      }
        +    },
        +    "required": [
        +      "op"
        +    ],
        +    "type": "object"
        +  }
        +]
      • removedInput schema / properties / steps / minItems
        Removed value: -1
      • changedInput schema / required
        Previous value: -[
        -  "input",
        -  "steps"
        -]New value: +[
        +  "input"
        +]
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "processes": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "steps": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "processes",
        +    "steps"
        +  ],
        +  "type": "object"
        +}
    • Removedplayer_frames
    • Changedread_events6 fields changed
      • changedInput schema / properties / from / description
        Previous value: -"Only events at or after this video time, in seconds."New value: +"Earliest video second."
      • changedInput schema / properties / input / description
        Previous value: -"Or a recording path (its sibling .events.jsonl is read) or the .events.jsonl itself."New value: +"Or a recording path, or its .events.jsonl."
      • changedInput schema / properties / limit / description
        Previous value: -"Most events to return (default 200); the result says when more matched."New value: +"Most events to return (default 200)."
      • changedInput schema / properties / to / description
        Previous value: -"Only events at or before this video time, in seconds."New value: +"Latest video second."
      • changedInput schema / properties / types / description
        Previous value: -"Only these types: down / up (mouse buttons), move (sampled cursor), wheel, key (a named shortcut), typing (a burst of typing: start and length only), gap (events may be missing). Clicks are down."New value: +"down/up (mouse buttons; clicks are down), move (sampled cursor), wheel, key (shortcut), typing (burst), gap (events may be missing)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "eventsPath": {
        +      "type": "string"
        +    },
        +    "matched": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "returned": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "summary": {
        +      "additionalProperties": {
        +        "type": "number"
        +      },
        +      "propertyNames": {
        +        "type": "string"
        +      },
        +      "type": "object"
        +    },
        +    "total": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "eventsPath",
        +    "total",
        +    "matched",
        +    "returned",
        +    "summary"
        +  ],
        +  "type": "object"
        +}
    • Changedredact_region11 fields changed
      • changedInput schema / properties / color / description
        Previous value: -"Fill color for box style (default black)."New value: +"Box fill color (default black)."
      • changedInput schema / properties / pad / description
        Previous value: -"Optional pixels to expand each region by, to cover anti-aliased edges (default 0)."New value: +"Grow each region by this many px (default 0)."
      • changedInput schema / properties / regions / description
        Previous value: -"One or more rectangles to redact. Each may be limited to a time window."New value: +"Pixel rectangles (x, y, width, height), each optionally limited to start..end seconds."
      • removedInput schema / properties / regions / items / properties / end / description
        Removed value: -"Optional second to stop redacting after."
      • removedInput schema / properties / regions / items / properties / height / description
        Removed value: -"Region height in pixels."
      • removedInput schema / properties / regions / items / properties / start / description
        Removed value: -"Optional second to start redacting from."
      • removedInput schema / properties / regions / items / properties / width / description
        Removed value: -"Region width in pixels."
      • removedInput schema / properties / regions / items / properties / x / description
        Removed value: -"Left edge in pixels."
      • removedInput schema / properties / regions / items / properties / y / description
        Removed value: -"Top edge in pixels."
      • changedInput schema / properties / style / description
        Previous value: -"box (default) draws an irreversible solid fill; blur and pixelate are softer but partially recoverable."New value: +"box (default): irreversible fill; blur/pixelate are partially recoverable."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedreframe2 fields changed
      • changedInput schema / properties / fit / description
        Previous value: -"pad (default): scale to fit and letterbox, no content lost. crop: scale to fill and center-crop."New value: +"pad (default): letterbox, nothing lost. crop: fill and center-crop."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addedresume_recording
    • Changedreview_recording1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "durationSec": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "fps": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "hasAudio": {
        +      "type": "boolean"
        +    },
        +    "height": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "input": {
        +      "type": "string"
        +    },
        +    "width": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "input",
        +    "durationSec",
        +    "width",
        +    "height",
        +    "fps",
        +    "hasAudio"
        +  ],
        +  "type": "object"
        +}
    • Changedsample_frames11 fields changed
      • changedInput schema / properties / dedupe / description
        Previous value: -"Mode 'fps': drop frames that are nearly identical to the previous one (default false)."New value: +"Mode fps: drop near-duplicate frames (default false)."
      • changedInput schema / properties / fps / description
        Previous value: -"Sample this many frames per second (mode 'fps')."New value: +"Frames per second (mode fps)."
      • changedInput schema / properties / maxFrames / description
        Previous value: -"Most frames this call may write (default 100, max 1000). In fps mode a rate that would exceed it is lowered so the frames still span the whole video."New value: +"Frame cap (default 100); fps is lowered to fit while still spanning the video."
      • changedInput schema / properties / maxImageWidth / description
        Previous value: -"Downscale inline images to at most this width (default 1280)."New value: +"Max inline image width (default 1280)."
      • changedInput schema / properties / maxInlineImages / description
        Previous value: -"How many frames to embed inline (default 8, max 20). Every frame is still written to disk and listed by path."New value: +"Frames to embed inline (default 8); all are listed by path."
      • changedInput schema / properties / mode / description
        Previous value: -"How to pick frames. 'scenes' returns only frames where the screen changed (plus the first frame), strongest changes first up to maxFrames, which is usually the cheapest way to review a recording. Defaults to 'fps' or 'timestamps' depending on which of those is given."New value: +"scenes: only frames where the screen changed (strongest first), usually the cheapest review. Default: fps or timestamps, whichever is given."
      • changedInput schema / properties / outputDir / description
        Previous value: -"Optional folder for the frames. Defaults to SCREENCAST_HOME/frames/<id>."New value: +"Optional folder for the frames (a relative path resolves under SCREENCAST_HOME/frames). Defaults to SCREENCAST_HOME/frames/<id>."
      • changedInput schema / properties / returnImages / description
        Previous value: -"Also return the frames inline as images the model can view directly (default true). Only the first maxInlineImages frames are embedded."New value: +"Return the first maxInlineImages frames inline (default true)."
      • changedInput schema / properties / sceneThreshold / description
        Previous value: -"Mode 'scenes': how much the frame must change to count, 0-1 (default 0.1; raise it to keep only big changes)."New value: +"Mode scenes: change needed to count, 0-1 (default 0.1)."
      • changedInput schema / properties / timestamps / description
        Previous value: -"Explicit second offsets to grab one frame at each (mode 'timestamps')."New value: +"Seconds to grab a frame at (mode timestamps)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "frameCount": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "frameDir": {
        +      "type": "string"
        +    },
        +    "frames": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "mode": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "frameDir",
        +    "frameCount",
        +    "frames",
        +    "mode"
        +  ],
        +  "type": "object"
        +}
    • Addedsave_replay
    • Changedscale1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedscreen_diff5 fields changed
      • changedInput schema / properties / a / description
        Previous value: -"The 'before' image (or video: its first frame is used)."New value: +"Before image (or video: first frame)."
      • changedInput schema / properties / b / description
        Previous value: -"The 'after' image (or video). Scaled to a's size if it differs."New value: +"After image (or video); scaled to a's size."
      • changedInput schema / properties / pixelThreshold / description
        Previous value: -"How different (0-255 mean) a cell of about 32x32 image pixels must be to count as changed (default 12: catches a changed label or a toast)."New value: +"Mean 0-255 difference for a ~32x32 cell to count as changed (default 12)."
      • changedInput schema / properties / returnImage / description
        Previous value: -"Also return 'b' inline with the changed regions outlined in red (default true)."New value: +"Return b inline with changes outlined (default true)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "changedFraction": {
        +      "type": "number"
        +    },
        +    "identical": {
        +      "type": "boolean"
        +    },
        +    "meanDiff": {
        +      "type": "number"
        +    },
        +    "regions": {
        +      "items": {},
        +      "type": "array"
        +    },
        +    "ssim": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "identical",
        +    "ssim",
        +    "meanDiff",
        +    "changedFraction",
        +    "regions"
        +  ],
        +  "type": "object"
        +}
    • Changedscreenshot6 fields changed
      • changedInput schema / properties / backend / description
        Previous value: -"gdigrab (default, ~0.2 s) captures what is visible on screen. 'wgc' (window: targets only, FFmpeg 8+) captures the window's own surface through Windows Graphics Capture, even when other windows cover it; slower (~1-2 s)."New value: +"gdigrab (default, ~0.2 s): what is visible. wgc (window:, FFmpeg 8+, ~1-2 s): the window even if covered."
      • changedInput schema / properties / exactTitle / description
        Previous value: -"For window: targets, match only a window whose title equals the given title (case-insensitive); never fall back to a substring match. Default false."New value: +"window: targets match the whole title only, never a substring (default false)."
      • changedInput schema / properties / maxImageWidth / description
        Previous value: -"Downscale the inline image to at most this width (default 1280)."New value: +"Max inline image width (default 1280)."
      • changedInput schema / properties / returnImage / description
        Previous value: -"Also return the screenshot inline as an image the model can view directly (default true). The PNG on disk is always full resolution."New value: +"Return the image inline (default true; the PNG on disk stays full size)."
      • changedInput schema / properties / target / description
        Previous value: -"Capture target: 'full' | 'monitor:<index>' | 'window:<title>' (or window:exe=<app.exe> / window:hwnd=<handle>) | 'region:<x>,<y>,<w>,<h>'. window: captures the on-screen rectangle the window occupies as currently displayed - it must be visible, on top, and not minimized (case-insensitive exact title, else substring; topmost match wins)."New value: +"full | monitor:<i> (0 = primary) | window:<title> (or window:exe=<app.exe> / window:hwnd=<n>) | region:<x>,<y>,<w>,<h>. Titles match exactly, else as a substring; topmost wins."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "backend": {
        +      "type": "string"
        +    },
        +    "inlineImages": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "outputPath": {
        +      "type": "string"
        +    },
        +    "target": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath",
        +    "target",
        +    "backend",
        +    "inlineImages"
        +  ],
        +  "type": "object"
        +}
    • Addedsearch_recording
    • Changedspeed1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedstart_recording16 fields changed
      • changedInput schema / properties / audio / description
        Previous value: -"Audio capture (default none, video-only). source 'system' needs a loopback device; microphone capture is not supported."New value: +"Audio (default none). No microphone capture."
      • changedInput schema / properties / audio / properties / device / description
        Previous value: -"Optional dshow loopback device name (from list_audio_devices). When omitted, a loopback device is auto-detected."New value: +"dshow loopback device (from list_audio_devices); auto-detected if omitted."
      • changedInput schema / properties / audio / properties / source / description
        Previous value: -"system captures what is playing on the machine; none is video-only."New value: +"system = what the machine plays (needs a loopback device); none = video only."
      • changedInput schema / properties / backend / description
        Previous value: -"gdigrab (default) records the screen rectangle. wgc (window: targets, FFmpeg 8+) records the window's own surface through Windows Graphics Capture: it keeps recording the window when it is covered, moved, or in the background, and frames only its client area. No audio with wgc."New value: +"gdigrab (default): the screen rectangle. wgc (window: targets, FFmpeg 8+): the window's own surface, even when covered or moved; client area only, no audio. ddagrab: one display on the GPU, low CPU."
      • changedInput schema / properties / backend / enum
        Previous value: -[
        -  "gdigrab",
        -  "wgc"
        -]New value: +[
        +  "gdigrab",
        +  "wgc",
        +  "ddagrab"
        +]
      • addedInput schema / properties / cursor
        Added value: +{
        +  "description": "events: leave the OS cursor out and log it (implies events) for the cursor tool to redraw.",
        +  "enum": [
        +    "os",
        +    "events"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / encoder
        Added value: +{
        +  "description": "auto = first working GPU encoder, else x264 (default with ddagrab; else x264).",
        +  "enum": [
        +    "auto",
        +    "x264",
        +    "nvenc",
        +    "qsv",
        +    "amf"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / events / description
        Previous value: -"Also log mouse clicks, scroll, cursor positions, and typing to <recording>.events.jsonl, timed to the video and in video pixels (default false). Read it with read_events. Adds about a second to start."New value: +"Also log clicks, scroll, cursor, and typing (video-timed, video pixels) for read_events (default false; ~1 s slower start)."
      • changedInput schema / properties / exactTitle / description
        Previous value: -"For window: targets, match only a window whose title equals the given title (case-insensitive); never fall back to a substring match. Default false."New value: +"window: targets match the whole title only, never a substring (default false)."
      • changedInput schema / properties / keys / description
        Previous value: -"With events: masked (default) logs typing only as bursts (start and length on a 0.5 s grid), never which keys or when each one was pressed. shortcuts also names chords made with Ctrl, Alt, or Win (e.g. Ctrl+S), with their times; typed text is never logged."New value: +"With events: masked (default) logs typing only as 0.5 s-grid bursts, never keys; shortcuts also names Ctrl/Alt/Win chords. Typed text is never logged."
      • changedInput schema / properties / maxDurationSec / description
        Previous value: -"Stop automatically after this many seconds, finalizing the file (default 3600, or SCREENCAST_MAX_RECORDING_SEC; at most 604800, 7 days). 0 = no cap. A safety net against a recording that is never stopped."New value: +"Auto-stop after this many seconds (default 3600 or SCREENCAST_MAX_RECORDING_SEC; max 7 days; 0 = no cap)."
      • changedInput schema / properties / output / description
        Previous value: -"Optional output .mp4 path. Defaults to a file under SCREENCAST_HOME/recordings."New value: +"Output .mp4 path (default under SCREENCAST_HOME/recordings)."
      • addedInput schema / properties / replayBufferSec
        Added value: +{
        +  "description": "Instant replay: keep only the last N s (bounded disk) for save_replay. gdigrab only.",
        +  "maximum": 3600,
        +  "minimum": 4,
        +  "type": "integer"
        +}
      • changedInput schema / properties / target / description
        Previous value: -"Capture target: 'full' | 'monitor:<index>' (0 = primary) | 'window:<title>' (or window:exe=<app.exe> / window:hwnd=<handle>, without relying on the title) | 'region:<x>,<y>,<w>,<h>' (absolute pixels). window: records the on-screen rectangle the window occupies, resolved ONCE at start (it must be visible, on top, not minimized); it does not follow a window moved or resized mid-recording."New value: +"full | monitor:<i> (0 = primary) | window:<title> (or window:exe=<app.exe> / window:hwnd=<n>) | region:<x>,<y>,<w>,<h>. With gdigrab a window's rectangle is resolved once at start (visible, on top); it does not follow the window."
      • addedInput schema / properties / webcam
        Added value: +{
        +  "description": "Also record a camera to <output>.webcam.mp4, aligned for overlay.",
        +  "properties": {
        +    "corner": {
        +      "enum": [
        +        "top_left",
        +        "top_right",
        +        "bottom_left",
        +        "bottom_right"
        +      ],
        +      "type": "string"
        +    },
        +    "device": {
        +      "description": "list_video_devices name (default: first).",
        +      "type": "string"
        +    },
        +    "shape": {
        +      "enum": [
        +        "rect",
        +        "circle"
        +      ],
        +      "type": "string"
        +    },
        +    "size": {
        +      "description": "Share of width (0.25).",
        +      "maximum": 0.5,
        +      "minimum": 0.1,
        +      "type": "number"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "backend": {
        +      "type": "string"
        +    },
        +    "outputPath": {
        +      "type": "string"
        +    },
        +    "sessionId": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "sessionId",
        +    "status",
        +    "backend",
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Addedstep_guide
    • Changedstop_recording2 fields changed
      • addedInput schema / properties / save
        Added value: +{
        +  "description": "Replay buffer: write it all to outputPath first (default: discard).",
        +  "type": "boolean"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "durationSec": {
        +      "type": [
        +        "number",
        +        "null"
        +      ]
        +    },
        +    "outputPath": {
        +      "type": "string"
        +    },
        +    "sessionId": {
        +      "type": "string"
        +    },
        +    "status": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "sessionId",
        +    "status",
        +    "outputPath",
        +    "durationSec"
        +  ],
        +  "type": "object"
        +}
    • Changedtitle_card2 fields changed
      • addedInput schema / properties / fontFile
        Added value: +{
        +  "description": "Font: a .ttf/.otf/.ttc path or a C:\\Windows\\Fonts file name. Default: bundled Inter, with a covering system font for scripts it lacks (CJK, emoji, Arabic, ...).",
        +  "minLength": 1,
        +  "type": "string"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedtranscribe2 fields changed
      • addedInput schema / properties / words
        Added value: +{
        +  "description": "One word per cue, for word timing (cut_by_transcript).",
        +  "type": "boolean"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "cues": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "srtPath": {
        +      "type": "string"
        +    },
        +    "text": {
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "srtPath",
        +    "cues",
        +    "text"
        +  ],
        +  "type": "object"
        +}
    • Changedtrim2 fields changed
      • changedInput schema / properties / exact / description
        Previous value: -"Re-encode so the cut is frame-exact and nothing before start stays in the file (default true). false stream-copies: much faster, but the cut snaps to a keyframe and the frames before start still ship in the file, hidden only by an edit list. Never use false to remove sensitive content."New value: +"Re-encode for a frame-exact cut with the removed content really gone (default true). false = fast stream copy that snaps to a keyframe and keeps hidden earlier frames; never use it to remove secrets."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedwait_for_change10 fields changed
      • changedInput schema / properties / exactTitle / description
        Previous value: -"For window: targets, match the title exactly (default false)."New value: +"window: targets match the whole title only (default false)."
      • changedInput schema / properties / intervalMs / description
        Previous value: -"Pause between checks in ms (default 250); each check itself takes ~0.2 s."New value: +"Pause between checks in ms (default 250)."
      • changedInput schema / properties / keep / description
        Previous value: -"Keep the final screenshot on disk and return its path (default false: it is only returned inline)."New value: +"Keep the final screenshot on disk and return its path (default false)."
      • changedInput schema / properties / mode / description
        Previous value: -"'change' (default) returns as soon as the target differs from when the call started (a dialog opened, a page responded). 'settle' returns once the target has stopped changing for settleSec (a build finished, a page finished loading)."New value: +"change (default): return once it differs from the start. settle: once it has been still for settleSec."
      • changedInput schema / properties / pixelThreshold / description
        Previous value: -"How different (0-255 mean) a cell of about 32x32 screen pixels must be to count as changed (default 12: catches a changed label or a toast)."New value: +"Mean 0-255 difference for a ~32x32 cell to count as changed (default 12)."
      • changedInput schema / properties / returnImage / description
        Previous value: -"Also return a screenshot of the final state inline (default true)."New value: +"Return the final state inline (default true)."
      • changedInput schema / properties / settleSec / description
        Previous value: -"Mode 'settle': how long the screen must stay still (default 1)."New value: +"Mode settle: seconds of stillness (default 1)."
      • changedInput schema / properties / target / description
        Previous value: -"What to watch: 'full' | 'monitor:<index>' | 'window:<title>' (or window:exe=<app.exe> / window:hwnd=<handle>) | 'region:<x>,<y>,<w>,<h>'."New value: +"What to watch: full | monitor:<i> | window:<title> (or exe=/hwnd=) | region:<x>,<y>,<w>,<h>."
      • changedInput schema / properties / timeoutSec / description
        Previous value: -"Give up after this many seconds (default 30). A timeout is a normal result, not an error."New value: +"Give up after this many seconds (default 30; a timeout is a result, not an error)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "elapsedSec": {
        +      "type": "number"
        +    },
        +    "mode": {
        +      "type": "string"
        +    },
        +    "origin": {
        +      "additionalProperties": {},
        +      "properties": {
        +        "x": {
        +          "type": "number"
        +        },
        +        "y": {
        +          "type": "number"
        +        }
        +      },
        +      "required": [
        +        "x",
        +        "y"
        +      ],
        +      "type": "object"
        +    },
        +    "outcome": {
        +      "type": "string"
        +    },
        +    "regions": {
        +      "items": {},
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "outcome",
        +    "mode",
        +    "elapsedSec",
        +    "regions",
        +    "origin"
        +  ],
        +  "type": "object"
        +}
    • Changedxfade_transition4 fields changed
      • changedInput schema / properties / inputA / description
        Previous value: -"Path to the first (outgoing) video."New value: +"Outgoing video."
      • changedInput schema / properties / inputB / description
        Previous value: -"Path to the second (incoming) video."New value: +"Incoming video."
      • changedInput schema / properties / transition / description
        Previous value: -"xfade transition name (default fade): fade, wipeleft, slideup, circleopen, dissolve, ..."New value: +"xfade name (default fade): fade, wipeleft, slideup, circleopen, dissolve, ..."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "outputPath": {
        +      "description": "Path of the file written.",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "outputPath"
        +  ],
        +  "type": "object"
        +}
    • Changedzoom10 fields changed
      • changedInput schema / properties / dryRun / description
        Previous value: -"Only return the planned keyframes (edit them and pass them back); write nothing."New value: +"Return the planned keyframes only (editable, pass back)."
      • changedInput schema / properties / events / description
        Previous value: -"Event log to read clicks from (default: the input's sibling .events.jsonl). Its times and pixels must match the input, so use the original recording, not a trimmed or scaled copy."New value: +"Events log (default: the input's .events.jsonl); must match the input's timing and size, so use the original recording."
      • changedInput schema / properties / follow / description
        Previous value: -"Without keyframes: clicks zooms toward each click in the recording's input event log (start_recording events: true), panning between clicks close together; changes zooms toward where the screen changed. auto (default) uses clicks when the log has any, else changes."New value: +"Without keyframes: clicks (from the events log of start_recording events: true) or changes (where the screen changed). auto (default): clicks if logged, else changes."
      • changedInput schema / properties / highlightClicks / description
        Previous value: -"Draw an expanding ring at each click from the event log (default false). Rings move with the zoom."New value: +"Ring each logged click (default false)."
      • changedInput schema / properties / highlightColor / description
        Previous value: -"Ring color: name, #RRGGBB, or name@alpha (default #FF4545)."New value: +"Ring color (default #FF4545)."
      • changedInput schema / properties / holdSec / description
        Previous value: -"Auto mode: stay zoomed this long after activity stops (default 2)."New value: +"Auto mode: stay zoomed this long after activity (default 2)."
      • changedInput schema / properties / keyframes / description
        Previous value: -"Views to animate between: each fills the frame with a source rectangle (x, y, width, height) by time t, or { t, full: true } to zoom out. Omit to plan them automatically (see follow)."New value: +"Views reached by time t: a source rectangle (x, y, width, height), or { t, full: true } to zoom out. Omit to plan them (see follow)."
      • removedInput schema / properties / keyframes / items / properties / full / description
        Removed value: -"Zoom back out to the whole frame."
      • removedInput schema / properties / keyframes / items / properties / t / description
        Removed value: -"Seconds: the view is fully reached at this time."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": {},
        +  "properties": {
        +    "keyframes": {
        +      "items": {},
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "keyframes"
        +  ],
        +  "type": "object"
        +}
  2. 9 tool updatesv0.39.0
    • Changedconcat1 field changed
      • changedInput schema / properties / inputs / description
        Previous value: -"Two or more video paths to join, in order. Inputs must share codec/format."New value: +"Two or more video paths to join, in order. Matching inputs are stream-copied; others are re-encoded."
    • Changedfind_text5 fields changed
      • addedInput schema / properties / keep
        Added value: +{
        +  "description": "For a live target: keep the captured screenshot and return its path (default false: it is deleted after reading, since it may show the secrets being looked for).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / maxFrames
        Added value: +{
        +  "description": "With scanEverySec: most frames to read (default 30); each takes about a second.",
        +  "maximum": 120,
        +  "minimum": 1,
        +  "type": "integer"
        +}
      • changedInput schema / properties / query / description
        Previous value: -"Text to look for. Case-insensitive, and tolerant of common OCR misreads (_ vs -, I vs l, O vs 0). Without a query, all recognised text is returned."New value: +"Text to look for. Case-insensitive, and tolerant of common OCR misreads (_ vs -, I vs l, O vs 0; regexes get the _ vs - tolerance). Without a query, all recognised text is returned."
      • addedInput schema / properties / scanEverySec
        Added value: +{
        +  "description": "For a video input: read a frame every N seconds across the whole clip instead of one frame, so text shown at any moment is found (use it to check a clip for secrets before sharing). Each match gets its time, and redactRegions get start/end. The interval widens to stay within maxFrames.",
        +  "exclusiveMinimum": 0,
        +  "type": "number"
        +}
      • changedInput schema / properties / timestamp / description
        Previous value: -"For a video input: the second to read (default 0)."New value: +"For a video input: the second to read (default 0). Ignored with scanEverySec."
    • Addedplayer_frames
    • Changedread_events2 fields changed
      • changedInput schema / properties / types / description
        Previous value: -"Only these types: down / up (mouse buttons), move (sampled cursor), wheel, key. Clicks are down."New value: +"Only these types: down / up (mouse buttons), move (sampled cursor), wheel, key (a named shortcut), typing (a burst of typing: start and length only), gap (events may be missing). Clicks are down."
      • changedInput schema / properties / types / items / enum
        Previous value: -[
        -  "down",
        -  "up",
        -  "move",
        -  "wheel",
        -  "key"
        -]New value: +[
        +  "down",
        +  "up",
        +  "move",
        +  "wheel",
        +  "key",
        +  "typing",
        +  "gap"
        +]
    • Addedreview_recording
    • Changedscreen_diff1 field changed
      • changedInput schema / properties / pixelThreshold / description
        Previous value: -"How different (0-255 mean per 8 px cell, at ~320 px analysis width) an area must be to count as changed (default 12)."New value: +"How different (0-255 mean) a cell of about 32x32 image pixels must be to count as changed (default 12: catches a changed label or a toast)."
    • Changedstart_recording4 fields changed
      • changedInput schema / properties / events / description
        Previous value: -"Also log mouse clicks, scroll, cursor positions, and key presses to <recording>.events.jsonl, timed to the video and in video pixels (default false). Read it with read_events. Adds about a second to start."New value: +"Also log mouse clicks, scroll, cursor positions, and typing to <recording>.events.jsonl, timed to the video and in video pixels (default false). Read it with read_events. Adds about a second to start."
      • changedInput schema / properties / keys / description
        Previous value: -"With events: masked (default) logs that a key was pressed, never which. shortcuts also names chords made with Ctrl, Alt, or Win (e.g. Ctrl+S); typed text is never logged."New value: +"With events: masked (default) logs typing only as bursts (start and length on a 0.5 s grid), never which keys or when each one was pressed. shortcuts also names chords made with Ctrl, Alt, or Win (e.g. Ctrl+S), with their times; typed text is never logged."
      • changedInput schema / properties / maxDurationSec / description
        Previous value: -"Stop automatically after this many seconds, finalizing the file (default 3600, or SCREENCAST_MAX_RECORDING_SEC). 0 = no cap. A safety net against a recording that is never stopped."New value: +"Stop automatically after this many seconds, finalizing the file (default 3600, or SCREENCAST_MAX_RECORDING_SEC; at most 604800, 7 days). 0 = no cap. A safety net against a recording that is never stopped."
      • changedInput schema / properties / maxDurationSec / maximum
        Previous value: -9007199254740991New value: +604800
    • Changedtrim1 field changed
      • addedInput schema / properties / exact
        Added value: +{
        +  "description": "Re-encode so the cut is frame-exact and nothing before start stays in the file (default true). false stream-copies: much faster, but the cut snaps to a keyframe and the frames before start still ship in the file, hidden only by an edit list. Never use false to remove sensitive content.",
        +  "type": "boolean"
        +}
    • Changedwait_for_change2 fields changed
      • addedInput schema / properties / keep
        Added value: +{
        +  "description": "Keep the final screenshot on disk and return its path (default false: it is only returned inline).",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / pixelThreshold / description
        Previous value: -"How different an 8 px cell must be to count as changed (default 12)."New value: +"How different (0-255 mean) a cell of about 32x32 screen pixels must be to count as changed (default 12: catches a changed label or a toast)."
  3. 39 tool updatesv0.32.0
    • First observedassemble_highlights
    • First observedburn_subtitles
    • First observedcallout
    • First observedclip
    • First observedcompress
    • First observedconcat
    • First observedcontact_sheet
    • First observedconvert
    • First observedcrop
    • First observedcut_idle
    • First observeddenoise
    • First observedexport_gif
    • First observedexport_preset
    • First observedextract_audio
    • First observedfind_text
    • First observedget_media_info
    • First observedget_session
    • First observedlist_audio_devices
    • First observedlist_sessions
    • First observedmusic_bed
    • First observednormalize_audio
    • First observedoverlay
    • First observedpipeline
    • First observedread_events
    • First observedredact_region
    • First observedreframe
    • First observedsample_frames
    • First observedscale
    • First observedscreen_diff
    • First observedscreenshot
    • First observedspeed
    • First observedstart_recording
    • First observedstop_recording
    • First observedtitle_card
    • First observedtranscribe
    • First observedtrim
    • First observedwait_for_change
    • First observedxfade_transition
    • First observedzoom

TDQS

B3.4/5.0

Scored across 57 tools

Disambiguation3/5

Descriptions do real work routing between near-neighbors ('For transitions use xfade_transition', 'For one segment, trim does the same'), but several clusters genuinely overlap: trim/clip/cut_idle/cut_by_transcript, concat/xfade_transition/assemble_highlights, convert/compress/export_gif/export_preset, and the many single-effect edit tools (crop, scale, speed, overlay, callout, cursor, backdrop, reframe, zoom) versus pipeline which subsumes them. An agent can usually pick correctly after reading, but with 57 options the selection cost is high and misselection is plausible.

Naming Consistency3/5

All names are lowercase snake_case, but the convention is mixed: some are verb_noun (start_recording, add_marker, export_gif, list_sessions), others are bare verbs or nouns (trim, crop, concat, compress, transcribe, chapters, pipeline, doctor, screenshot). It stays readable, but there is no single predictable pattern to infer an unseen tool's name.

Tool Count2/5

57 tools is far past the point where a flat surface stays navigable, and the descriptions themselves hint at toolsets that could be gated. The domain is broad (capture, edit, audio, export, packaging), which justifies more than a dozen tools, but not this many all exposed at once alongside a `pipeline` tool that overlaps dozens of them.

Completeness4/5

Coverage is unusually thorough: session lifecycle (start/stop/pause/resume/list/get), capture targets and devices, a full edit/audio/export toolkit, OCR/search, diagnostics (doctor), and deliverables (bug_report, step_guide). The main gap is housekeeping — no tool to delete a session or remove intermediate artifacts — a minor omission agents can work around.

Maintenance

ActivityMaintained
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables an AI agent to operate Windows applications through vision-driven UI Automation and record polished demo videos with pre-click camera zoom, narration, and cinematic effects.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to inspect UI screen recordings as token-efficient image sheets with changed regions boxed, single-frame flicker flagged, and speech aligned to frames. Exposes watch_video and zoom_video tools so agents can pull dense keyframes across any time range or one sharp full-resolution frame, all processed locally.
    0
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables coding agents to ask focused questions about local screenshots, video, audio, and music and receive compact text reports on OCR, layout, timestamps, sounds, and music description. Media stays on the machine and raw files are never loaded into the agent's context, with support for cropping, interval sampling, and durable background jobs.
    MIT