
Positron Demo Video
- 2 installs
- 4.2k repo stars
- Updated August 5, 2026
- posit-dev/positron
positron-demo-video is a Claude Code skill for ai & agent building.
About
Walks through researching a feature, proposing a caption script, writing a Playwright demo test, recording it, and trimming the output for a PR. A Positron contributor uses it to produce a feature walkthrough video to attach to a pull request.
- Collaborative research-to-record workflow gated on script approval
- Records 1080p Playwright demos with overlays, then trims/converts via ffmpeg
Positron Demo Video by the numbers
- 2 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,294 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/posit-dev/positron --skill positron-demo-videoAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 4.2k |
| Last updated | August 5, 2026 |
| Repository | posit-dev/positron ↗ |
How do I helps with ai & agent building tasks during AI-assisted development.?
Creates demo videos of Positron features via a script-then-record workflow that generates a Playwright test, records it, and trims to MP4.
Who is it for?
A solo builder working on ai & agent building tasks who needs structured help with positron demo video.
Skip if: Teams with no ai & agent building needs, or anyone wanting a generic chat assistant without this specific workflow.
When should I use this skill?
When you need to helps with ai & agent building tasks during AI-assisted development., or when positron-demo-video is a claude code skill for ai & agent building.
What you get
Structured output aligned to positron-demo-video: positron-demo-video, AI & Agent Building.
Files
Positron Demo Video Generator
Creates polished demo videos of Positron features through a collaborative script-then-record workflow.
When to Use
- User asks to create a demo video for a PR
- User wants to record a feature walkthrough
- User says "generate a video", "record a demo", "make a video for the PR"
Prerequisites
- Positron must be built (
npm run build-psto check) - ffmpeg installed for MP4 conversion (optional but recommended)
Workflow
This is a collaborative process. Do NOT jump straight to writing code.
Research -> Propose Script -> Iterate -> Record -> Review -> IteratePhase 1: Research
Understand what to demo by examining the current branch:
1. Read recent commits (git log --oneline main..HEAD) 2. Look at changed files to understand the feature 3. Check for existing e2e tests that exercise the feature (may provide page object methods) 4. If adapting an existing test, read it fully
Phase 2: Propose a Script
Present a plain-text "script" to the user -- a numbered list of what the video will show, step by step. Include:
- What the viewer sees at each step
- Overlay text for each section (the narration captions)
- Estimated duration per section
Example format:
Demo Script: Notebook Cell Drag to Reorder
1. [2s] Notebook with 5 cells visible, clean layout
Overlay: "Drag and drop: grab the handle to reorder cells"
2. [3s] Hover over Cell 0 to reveal drag handle, then drag it to position 2
Overlay: (same, persists)
3. [4s] Select Cell 4, move it up 3 times with Alt+ArrowUp
Overlay: "Keyboard: Alt+Arrow to move cells up/down"
4. [4s] Multi-select cells 1-3 with Shift+Arrow, drag to end
Overlay: "Multi-select: Shift+Arrow to select, then drag together"
5. [3s] Undo 3 times to restore original order
Overlay: "Undo: Ctrl/Cmd+Z restores previous order"
Total: ~16s of action (+ ~12s trimmed initialization)Ask the user for feedback. Common adjustments:
- Reorder steps for better narrative flow
- Add/remove steps
- Change overlay wording
- Adjust which features to highlight
Phase 3: Iterate on Script
Revise the script based on feedback. Keep presenting the updated script until the user approves. Only then move to implementation.
Phase 4: Record
Once the script is approved:
1. Write the demo test -- translate the script into a Playwright test at test/e2e/demos/<name>.demo.test.ts
- Use
setupDemoLayout()to collapse panels and enable screencast mode - Include
...DEMO_SCREENCAST_SETTINGSin the test'ssettingsFile.append() - Use
narrate()/showOverlay()for captions - Use
pause()between actions for pacing - See
references/demo-patterns.mdfor code patterns
2. Run it:
DEMO_RECORD_VIDEO=1 npx playwright test test/e2e/demos/<name>.demo.test.ts \
--project e2e-electron --reporter list --timeout 3000003. Trim and convert -- use a subagent to find the start trim point (where initialization ends) and end trim point (where cleanup begins), then:
ffmpeg -ss <START_SECONDS> -t <DURATION> -i demo-videos/<hash>.webm \
-c:v libx264 -crf 20 -preset slow -an demo-videos/<name>.mp4-ss: skip initialization (typically ~10s)-t: duration to keep (cut before editor-close cleanup frames)
Phase 5: Verify and Deliver
After trimming/converting, delegate verification to a subagent to avoid polluting the main context window with large image data.
Launch a subagent (using the Agent tool) with a prompt like:
Verify the demo video at demo-videos/<name>.mp4.Extract thumbnail frames at key moments and read them to confirm overlays are visible, layout looks correct, and pacing is reasonable.
Report back: duration, file size, and a brief description of what each section shows.
Flag any issues (missing overlays, bad cropping, blank frames, etc.).
>
Commands to use:
```bash
# Get duration and file size
ffprobe -v error -show_entries format=duration,size -of csv=p=0 demo-videos/<name>.mp4
>
# Extract frames at key moments
for t in 1 5 10 15 20; do
ffmpeg -y -ss $t -i demo-videos/<name>.mp4 -frames:v 1 /tmp/frame_${t}s.jpg 2>/dev/null
done
```
Then read each /tmp/frame_*.jpg to visually inspect the frames.Once the subagent reports back, relay the results to the user:
- The video file path (for drag-and-drop into PR)
- Duration and file size
- A brief summary of what each section shows
- Any issues the subagent flagged
Ask the user to watch the video and let you know if they want changes.
Phase 6: Iterate
If the user wants changes, go back to the appropriate phase:
- Script changes (different steps, reordering) -> Phase 2
- Pacing/overlay tweaks (timing, wording) -> Phase 4
- Approved -> done, user has the video path
Technical Reference
Demo test files live in test/e2e/demos/. See demo-utils.ts for available helper functions (overlay text, human-speed typing/clicking, zoom, pacing, etc.) and existing .demo.test.ts files for examples. See references/demo-patterns.md for common demo patterns.
Video Output
- Records at 1920x1080 (1080p) for crisp output on retina displays
- GitHub free: 10MB limit / paid: 100MB limit
- First ~10-15s is initialization (always trimmed)
- WebM works on GitHub; MP4 has better Safari compat
Demo Patterns
Common patterns for writing demo scripts.
Basic Structure
Every demo script follows this template:
import { test as base, TestFixtures, WorkerFixtures } from '../tests/_test.setup';
import { pause, humanType, humanClick, setupDemoLayout, DEMO_SCREENCAST_SETTINGS } from './demo-utils';
const test = base.extend<TestFixtures, WorkerFixtures>({
beforeApp: [
async ({ settingsFile }, use) => {
settingsFile.append({ ...DEMO_SCREENCAST_SETTINGS });
await use();
},
{ scope: 'worker' }
],
});
test.use({
suiteId: __filename,
});
test.setTimeout(300_000);
test.describe('Demo: <Feature Name>', () => {
test('walkthrough', async function ({ app, page }) {
await setupDemoLayout(app, page); // Collapse panels + enable screencast mode
await pause(page, 2000); // Let app settle
// ... demo steps ...
await pause(page, 2000); // Hold on final state
});
});Console Demo
test('console demo', async function ({ app, page, python }) {
const cons = app.workbench.console;
await pause(page, 1500);
// Type and execute code
await humanType(page, cons.activeConsole, 'import pandas as pd');
await pause(page, 500);
await page.keyboard.press('Enter');
await pause(page, 1500);
await humanType(page, cons.activeConsole, 'df = pd.read_csv("data.csv")');
await pause(page, 500);
await page.keyboard.press('Enter');
await pause(page, 2000);
});Notebook Demo
test('notebook demo', async function ({ app, page, openFile }) {
const notebooks = app.workbench.notebooks;
await openFile('workspaces/example/notebook.ipynb');
await pause(page, 2000);
// Click into a cell
await humanClick(page, page.locator('.cell').first());
await pause(page, 800);
// Type code
await humanType(page, page.locator('.cell .native-edit-context'), 'print("hello")');
await pause(page, 1000);
// Run cell
await page.keyboard.press('Shift+Enter');
await pause(page, 2000); // Wait for output to appear
});Data Explorer Demo
test('data explorer demo', async function ({ app, page, python }) {
const cons = app.workbench.console;
const variables = app.workbench.variables;
// Create a dataframe
await cons.executeCode('Python', 'import pandas as pd\ndf = pd.DataFrame({"a": [1,2,3], "b": [4,5,6]})');
await pause(page, 1500);
// Open in data explorer
await variables.doubleClickVariableRow('df');
await pause(page, 2000);
// Interact with the data explorer
// ... clicks, sorts, filters ...
});Drag and Drop Demo
test('drag and drop demo', async function ({ app, page }) {
// Get source and target elements
const source = page.locator('.draggable-item').nth(2);
const target = page.locator('.draggable-item').nth(0);
await pause(page, 1000);
// Hover over source first (shows intent)
await source.hover();
await pause(page, 500);
// Perform the drag
await source.dragTo(target);
await pause(page, 1500); // Let viewer see the result
});Zoom to Area of Interest
import { zoomTo, zoomReset, showOverlay, pause } from './demo-utils';
// Zoom into a UI element to highlight detail
await showOverlay(page, 'The outline shows your notebook structure');
await zoomTo(page, page.locator('.outline-tree'), { scale: 2 });
await pause(page, 3000); // Hold so viewer can read
await zoomReset(page);- Uses CSS transform on
.monaco-workbench-- text stays sharp - Automatically centers the target in the viewport (no left/right cutoff)
- Default: 2x scale, 600ms ease-in-out animation
- At 1920x1080, a 2x zoom still gives 960x540 effective resolution
Tips
Pacing
- More pauses = easier to follow
- 800ms minimum between any two actions
- 1500-2000ms after visual changes (output appearing, panels opening)
- 2000ms at start and end
Viewport
- Default video size is 1920x1080
- If the feature needs more space, adjust in the DEMO_RECORD_VIDEO setup
Multiple Steps
- Use
test.step()to label sections (helps with debugging, not visible in video) - Consider splitting very long demos into multiple test cases
Adapting Existing Tests
When adapting an e2e test: 1. Copy the test file to test/e2e/demos/<name>.demo.test.ts 2. Change imports to include demo-utils 3. Add test.setTimeout(300_000) 4. Insert pause() calls between each action 5. Replace locator.fill() with humanType() for visible typing 6. Remove assertions that aren't needed (or keep them -- they won't affect the video)
Related skills
FAQ
What does positron-demo-video do?
positron-demo-video is a Claude Code skill for ai & agent building.
When should I use positron-demo-video?
When you need to helps with ai & agent building tasks during AI-assisted development., or when positron-demo-video is a claude code skill for ai & agent building.
What are the main capabilities?
positron-demo-video; AI & Agent Building; AI-coding skill.