A CLI that takes a YAML script and outputs a browser recording. Designed to be called by AI agents that need to generate demo videos of UI changes — not a full platform, just the sharp tool that does one thing well.
npm install -g @jfenc91/reenact
click to copy
$ reenact examples/login_flow.yaml -o demo.webm Running 9 steps... ✓ navigate → the-internet.herokuapp.com/login ✓ type → #username "tomsmith" @ 65 wpm ✓ type → #password "SuperSecret..." @ 55 wpm ✓ click → button[type='submit'] ✓ wait → 2s ✓ scroll → down Video saved to demo.webm
Your AI agent can read a diff and write a YAML script. reenact turns that script into a real browser recording.
YAML in, video out. The format is trivial for any LLM to generate — your agent reads the diff, writes the script, calls the CLI.
No platform, no dashboard, no account. One binary, one command: reenact script.yaml -o video.mp4. Pipe it into whatever workflow you want.
Playwright drives actual Chromium — WebGL, SPAs, auth flows all work. Output is WebM or MP4, ready to share.
Bezier mouse curves, variable-speed typing, smooth scrolling. Recordings look like a person used the app, not a bot.
Describe what to click, type, and scroll in plain YAML. Version-controlled, diffable, and easy for humans and AI to read and write.
Pipe into gh pr comment, attach to Slack, embed in docs. reenact makes the video — you decide where it goes.
Your AI agent reads the code change and generates a YAML script describing how to demo it.
reenactOne shell command. Headless Chromium runs the steps and records a video with realistic interactions.
The agent takes the output file and posts it wherever it needs to go — PRs, Slack, docs, tickets.
Node.js 18+
$ npm install -g @jfenc91/reenact
Create demo.yaml:
url: https://example.com steps: - wait: 1s - click: "h1" - scroll: down
Run it:
$ reenact demo.yaml -o demo.webm
Copy any of these, swap the URLs and selectors for your app, and run.
# Record a realistic login interaction name: Login Flow url: https://the-internet.herokuapp.com/login viewport: width: 1280 height: 720 steps: - wait: 1s # Type credentials naturally - type: selector: "#username" text: "tomsmith" wpm: 65 - wait: 300ms - type: selector: "#password" text: "SuperSecretPassword!" wpm: 55 - wait: 500ms - click: "button[type='submit']" - wait: 2s - scroll: down
# Search Wikipedia and browse a result name: Wikipedia Search url: https://en.wikipedia.org viewport: width: 1280 height: 800 steps: - wait: 1s # Type a search query - type: selector: "#searchInput" text: "bezier curve" wpm: 60 - wait: 600ms - click: ".cdx-search-input__end-button" - wait: 2s # Scroll through the article - scroll: down - wait: 800ms - scroll: down - wait: 800ms - scroll: down - wait: 1s
# Record a WebGL Three.js demo name: WebGL Demo url: https://threejs.org/examples/#webgl_animation_keyframes viewport: width: 1280 height: 720 steps: - wait: 3s # Move mouse around the 3D scene - move_to: x: 640 y: 360 duration: 500 - wait: 500ms - move_to: x: 800 y: 300 duration: 600 - wait: 500ms - move_to: x: 400 y: 400 duration: 600 - wait: 1s # Scroll to zoom - scroll: down - wait: 500ms - scroll: up - wait: 1s
# Minimal example: visit a page, scroll around name: Basic Navigation url: https://example.com viewport: width: 1280 height: 720 steps: - wait: 1s - scroll: down - wait: 500ms - scroll: up - wait: 1s
Every step you can use in a script.
- click: "#btn"
Smooth mouse move to element, then click at a random point within its bounds.
- type:
selector: "#input"
text: "hello"
wpm: 70
Type character by character at natural speed. wpm controls pace (default 70).
- hover: ".menu-item"
Move the cursor over an element without clicking. Great for tooltips and menus.
- scroll: down
- scroll:
direction: up
amount: 500
Smooth incremental scroll. Direction is up or down, amount in pixels (default 300).
- wait: 2s
- wait: "#loaded"
Pause for a duration (ms, s, m) or wait until a selector appears.
- wait_for:
selector: ".modal"
state: visible
timeout: 10s
Wait for an element to reach a state: visible, attached, hidden, detached.
- navigate: https://example.com
Navigate to a new URL. Waits for DOM content to load.
- key: Enter
- key: Control+A
Press a keyboard key or combination.
- fill:
selector: "#bio"
text: "long content..."
Instantly fill a field (non-humanized). Use for long text where typing would be slow.
- select:
selector: "#country"
value: "US"
Choose a value from a <select> dropdown.
- clear: "#search"
Clear the contents of an input field.
- screenshot: output.png
Capture a screenshot mid-recording. Useful for debugging or docs.
- back
- forward
- reload
Browser history navigation and page reload.
- move_to:
x: 500
y: 300
duration: 600
Move cursor to exact coordinates with smooth bezier motion.
Top-level YAML keys that configure the recording environment.
# 1. Create a script $ cat > demo.yaml <<EOF url: https://your-app.com steps: - wait: 1s - click: ".get-started" - wait: 2s EOF # 2. Record it $ reenact demo.yaml -o demo.webm # 3. That's it. You have a video.