@srinivasa314/ovid
v0.0.6
Published
A minimal coding-agent layer on pi that records terminal+browser test videos onto PRs
Maintainers
Readme
ovid
ovid makes your coding agent verify the features it builds and record a polished terminal + browser video of each verification onto your PR. The verifications are ordinary code (assertions decide pass/fail), so re-running them is cheap and no LLM is needed.
Works on any-language projects (Node is only needed to run ovid). It plugs into the pi and Claude Code coding agents and support for others (e.g. Codex) may come later.
Quick start
Ovid works on macOS and Linux. On Linux you also need a C/C++ toolchain (build-essential + python3), Chromium's system libs (npx playwright install --with-deps chromium), and a system ffmpeg with the drawtext filter (apt-get install -y ffmpeg) as the bundled ffmpeg-static lacks drawtext there. Run npx ovid doctor before installing ovid to check.
cd your-project
npm i -D @srinivasa314/ovid # Node ≥20; also needs Chromium (`npx playwright install chromium`) and `gh`
npx ovid init # scaffolds config, the spec guide, and the agent integration(s)npx ovid init sets up both the pi and Claude Code integrations by default. It can be narrowed with --agent pi or --agent claude.
You can then use your agent as normal. When you ask it to build something and open a PR, it will, on its own:
- write and run an ovid e2e test for the change,
- review the recorded keyframes
- attach the terminal+browser video + per-step notes to the PR
New tests are always shown with a video; tests it only modified are included at its discretion.
pi: you have to trust the project the first time so the extension loads (or pass -a in headless/CI).
Claude Code: the integration is a project skill plus two hooks in .claude/ and a Bash(npx ovid:*) permission. Approve the project on your first interactive claude run so the permission applies and npx ovid runs without prompts. The skill and hooks work in headless claude -p even before that, but until the workspace is trusted the permission entry is ignored, so in headless runs either trust the workspace first or pass --allowedTools/--dangerously-skip-permissions.
Example
pi opened this PR for the sample app, adding full-text search across the API, web UI, and flask notes CLI. It attached this video of its own e2e test (multiple terminals plus the browser, on one timeline):

Features
- Terminal + browser in one video, stitched on a shared timeline as a focus-cut (cuts to whichever surface is active).
- Multiple terminals (named, long-lived shells) and multiple browser tabs/pages in a single test.
- Polished output: mac window chrome, titlebar labels, lower-third captions, a moving cursor + click-ripple, readable pacing
- configurable (viewport, video size/fps, pacing) via
ovid.config.ts. - Lazy rendering: videos are produced only when you need them, like when a PR is created or a test fails so passing runs stay fast.
Using the ovid CLI (without an agent)
You can drive ovid yourself too but its primarily for agents. Write specs in ovid/*.spec.ts, use ovid.terminal(cmd, opts) for shells and ovid.browser(caption, fn) for a Playwright page. The full docs are in ovid/WRITING-OVID-E2E-TESTS.md.
| Command | What it does |
| --- | --- |
| npx ovid init [--agent pi\|claude\|both] | Scaffold config, guide, .gitignore, and agent integration(s) — default both |
| npx ovid test [filter] | Run specs (records raw artifacts; videos render lazily — only on failure) |
| npx ovid render [filter] | Render saved runs into final.mp4/.gif (e.g. to view a passing run) |
| npx ovid publish [--apply] | Extract keyframes / upload media + create-or-update the PR |
| npx ovid doctor | Check external components (Chromium, ffmpeg, git, gh) |
How it works
A generated spec looks like this:
import { test, expect } from "@srinivasa314/ovid/test";
test("note persists", async ({ ovid }) => {
await ovid.terminal("flask --app api/app.py run -p 3001", { name: "API", waitFor: /Running on/ });
await ovid.browser("Create a note", async (page) => {
await page.goto("http://localhost:3000");
await page.getByRole("button", { name: "Save" }).click();
await expect(page.getByText("Buy milk")).toBeVisible();
});
});A spec drives terminals and browsers and asserts behavior in code. ovid runs it while recording the real shell and the live browser against a shared timeline, then stitches a video showing them, then overlays window chrome, captions, and a cursor.
Built with: node-pty + an asciinema cast replayed in headless xterm.js (terminal), @playwright/test + playwright-recorder-plus (browser), a timeline-driven focus-cut composited with ffmpeg.
Sample
examples/notes/ a Flask API + SQLite + vanilla web UI application and a flask notes CLI, with ovid specs covering both multi-server and mixed terminal+browser flows.
Scope
v0 targets macOS and Linux, local, single-machine. Parallel execution, CI, and remote runs are future work.
