screen recorder for agents
yyoreel can send a one-time video_verified activation after a local MP4 exists, is non-empty, and all optional audio and video streams decode through its ffmpeg runtime. Telemetry requires a non-empty runtime YYOREEL_POSTHOG_KEY. Missing configuration is a no-op, and YYOREEL_TELEMETRY=0 completely opts out before state or SDK access. Delivery is always best effort, runs in a bounded detached process, and cannot change recording success, delay CLI exit, or print SDK failures.
After a verified recording, agents may privately submit a voluntary numeric rating with yyoreel feedback <rating> [category], where the rating is an integer from 1 through 5 and the optional category is setup, browser, recording, verification, or other. yyoreel never accepts or transmits free-text feedback. See the CLI package documentation for the complete event and privacy contract.
yyoreel can send a one-time video_verified activation after a local MP4 exists, is non-empty, and all optional audio and video streams decode through its ffmpeg runtime. Published packages include a write-only public PostHog project token intended for public apps. A non-empty YYOREEL_POSTHOG_KEY overrides that token, and YYOREEL_TELEMETRY=0 completely opts out. Telemetry is always best effort, runs in a bounded detached process, and cannot change recording success, delay CLI exit, or print SDK failures.
After a verified recording, agents may privately submit a voluntary numeric rating with yyoreel feedback <rating> [category], where the rating is an integer from 1 through 5 and the optional category is setup, browser, recording, verification, or other. yyoreel never accepts or transmits free-text feedback. See the CLI package documentation for the complete event and privacy contract.
Define steps in a JSON config (clicks, key presses, drags, pauses) and yyoreel drives a headless Chrome instance, streams lossless PNG frames from Chrome on a fixed output clock, and encodes the result with ffmpeg.
Chrome and ffmpeg are downloaded automatically on first use to ~/.yyoreel if not already installed.
npm install @yyopc/yyoreel
npx yyoreel init --name my-video --url https://example.com
npx yyoreel recordcustom-theme - Demonstrates fully customizing the cursor overlay and keystroke HUD appearance using a code editor page.
drag-and-drop - Demonstrates dragging elements between positions on a kanban board.
form-filling - Demonstrates typing into form fields and clicking a submit button, simulating a login flow.
gif-output - Demonstrates outputting the recording as an animated GIF instead of the default MP4.
hello-world - The simplest possible yyoreel example. Opens a landing page and clicks the call-to-action button.
keyboard-shortcuts - Demonstrates pressing key combos and displaying them in the keystroke HUD overlay. Uses a code editor page as the target.
mobile-viewport - Demonstrates recording at mobile device dimensions using a finance app interface.
modifier-clicks - Demonstrates clicking elements with modifier keys held down, simulating multi-select in a file manager.
multi-demo - Demonstrates defining multiple videos in a single config file, each producing its own output from the same page.
page-scrolling - Demonstrates scrolling the page and scrolling within a specific container element on a blog post layout.
screenshots - Demonstrates capturing PNG screenshots at specific points during a recording. Useful for generating static marketing assets or documentation images alongside videos.
shared-steps - Demonstrates using include to share common setup steps across videos. The shared steps dismiss a cookie consent banner before the main video steps run.
webm-output - Demonstrates outputting the recording as a WebM video using VP9 encoding.
Scaffold a new config file:
yyoreel init
yyoreel init --name login-flow --url https://myapp.com
yyoreel init --name hero -o hero.config.jsonThis creates a yyoreel.config.json with a $schema for IDE autocompletion:
{
"$schema": "https://yyoreel.com/schema/v1.json",
"videos": {
"my-video": {
"url": "https://example.com",
"defaultDelay": 500,
"steps": [
{ "action": "pause", "ms": 500 },
{ "action": "click", "text": "Get Started" },
{ "action": "key", "key": "cmd+a", "delay": 1000 }
]
}
}
}When viewport is omitted on macOS, webreel uses the main display's usable area in logical CSS pixels. On unsupported platforms or when display discovery is unavailable, it falls back to a 1080x1080 CSS viewport. Set an explicit { "width": ..., "height": ... } value or a named preset to override automatic sizing.
Record videos:
yyoreel record
yyoreel record hero login
yyoreel record -c custom.config.json
yyoreel record --watch
yyoreel record --verboseSet YYOREEL_CDP_ENDPOINT to record or preview against an already-running Chrome
remote debugging endpoint:
YYOREEL_CDP_ENDPOINT=http://127.0.0.1:9222 yyoreel recordThe value can be an HTTP(S) endpoint, a raw WebSocket debugger URL, or a port
such as 9222. yyoreel skips its Chrome download and launch path, creates a
dedicated page target, and closes only that target when the run ends. The
existing browser remains running.
Attach mode uses the same capture pacing, Retina quality, autozoom, backgrounds, cursor overlays, and HUD pipeline as launch mode. The configured viewport is applied to the dedicated target with CDP device emulation. It controls the page and recording dimensions, but it does not resize the existing browser window.
Run a video in a visible browser window without recording:
yyoreel preview
yyoreel preview hero
yyoreel preview hero --verboseRe-composite videos from stored raw recordings and timelines without re-recording:
yyoreel composite
yyoreel composite heroDownload Chrome and ffmpeg to ~/.yyoreel. Both are also auto-downloaded on first run. Use --force to fix corrupted or broken binaries.
yyoreel install
yyoreel install --forceCheck config files for errors without running them:
yyoreel validate
yyoreel validate -c custom.config.jsonyyoreel --help
yyoreel --version
yyoreel record --help| Action | Fields | Description |
|---|---|---|
pause |
ms |
Wait for a duration |
click |
text or selector, optional within, modifiers |
Move cursor to an element and click |
key |
key (e.g. "cmd+z"), optional label |
Press a key or key combo |
type |
text, optional target, charDelay |
Type text character by character |
scroll |
optional x, y, selector |
Scroll the page or an element |
wait |
selector or text, optional timeout |
Wait for an element to appear |
screenshot |
output |
Capture a PNG screenshot |
drag |
from and to (each with text/selector/within) |
Drag from one element to another |
moveTo |
text or selector, optional within |
Move cursor to an element |
navigate |
url |
Navigate to a new URL mid-video |
hover |
text or selector, optional within |
Hover over an element (triggers CSS) |
select |
selector, value |
Select a value in a dropdown |
All steps (except pause) accept an optional delay field (ms to wait after the step). Use defaultDelay at the top-level or per-video to set a default.
| Field | Default | Description |
|---|---|---|
$schema |
- | JSON Schema URL for IDE autocompletion |
outDir |
videos/ |
Default output directory for videos |
baseUrl |
"" |
Prepended to relative video URLs |
viewport |
main display | Main display's usable logical area on macOS, with a 1080x1080 fallback |
theme |
- | Default recording background, cursor, and HUD customization |
include |
- | Array of step files prepended to all videos |
defaultDelay |
- | Default delay (ms) after each step |
videos |
required | Object mapping video names to their configs |
| Field | Default | Description |
|---|---|---|
url |
required | URL to navigate to |
baseUrl |
inherited | Prepended to relative URLs |
viewport |
inherited | Explicit dimensions or preset override |
zoom |
- | CSS zoom level applied to the page |
autoZoom |
true |
Spring-zoom the recording card around related clicks |
fps |
60 |
Recording frame rate |
quality |
80 |
Final quality and 1x or 2x physical pixel density |
waitFor |
- | CSS selector to wait for before start |
output |
<name>.mp4 |
Output file path (.mp4, .gif, or .webm) |
thumbnail |
{ time: 0 } |
Object with time (seconds) or enabled: false |
include |
inherited | Array of paths to JSON files whose steps are prepended |
theme |
inherited | Recording background, cursor, and HUD customization |
defaultDelay |
inherited | Default delay (ms) after each step |
quality controls both physical capture density and final compression. Values from 80 through 100 preserve the resolved CSS viewport while doubling the output width and height. Values from 1 through 79 retain 1x output dimensions. If a 1x viewport has an odd dimension, webreel keeps its CSS layout and pads that output edge by one pixel for compatible 4:2:0 video. On a 2x Retina Mac, the default quality of 80 therefore matches native display density, but capture density still comes from quality, not the display's device pixel ratio. Chrome supplies lossless PNG screencast frames. During capture, webreel remuxes those frames so video encoding cannot slow the output clock. Once capture stops, it compacts the retained raw with lossless ultrafast QP0 H.264 RGB while preserving the source RGB samples. A fixed output clock reuses the latest source frame when necessary to maintain the requested frame rate. For MP4 output, the final H.264 encode is the only lossy generation, using the quality-to-CRF mapping, the veryfast preset, and compatible 4:2:0 output. WebM and GIF exports apply their format-specific delivery encode after composition.
Set theme.cursor.animationStyle to "smooth", "medium", "rapid", or "none". The default is "medium", which preserves the original humanized cursor motion. Only these named presets are accepted. The "none" preset teleports pointer moves while keeping the intermediate events needed for drag actions.
Cap-style autozoom is enabled by default for recordings. Related clicks form one continuous spring-driven segment, and meaningful cursor movement re-aims the view without zoom pumping. With a recording background, the complete rounded card and its shadow scale and pan over the fixed canvas, so the surrounding padding naturally shrinks or disappears. The cursor moves with the card, while keystroke HUD labels remain fixed to the output frame. Existing zoom is applied during capture first, then autozoom operates on the captured frames. Set autoZoom to false on a video to disable it.
Set theme.background to "none" (the default), a hex color such as "#8b5cf6", or a local image path such as "./assets/background.png". Colors and images place the recording on a centered, rounded card with a subtle shadow. During autozoom, that card expands and pans over the fixed background rather than keeping constant padding. Image paths resolve relative to the config file and use center-cropped cover scaling. The output dimensions remain unchanged, and the keystroke HUD stays at canvas level above the card.
Set theme.hud.enabled to false to hide the keystroke and shortcut HUD in previews and recorded output. It defaults to true. Disabled recordings omit HUD state from the timeline, so MP4, WebM, GIF, autozoom, and background-inset output all remain HUD-free.
The contrast-safe built-in arrow remains the cursor through movement, hover, and click press. A custom theme.cursor.image likewise remains unchanged while clicking. Click press and release use a 100ms cubic ease-out scale transition, reaching 0.75 at full press without swapping cursor artwork.
pnpm install
pnpm build| Package | Description |
|---|---|
@yyopc/yyoreel |
SDK and CLI for recording browser flows |
Apache-2.0