API and CLI

SuiteCut's fixture, capture, output, reporter, and render option objects reject unknown keys and invalid values. Playwright launch and browser-context options pass through to Playwright.

Public exports

These are every package entry point and export in the current build. Files belowsuitecut/src are internal and are not public imports.

suitecut

Playwright Test, the renderer, and the option types used by both.

TypeScript
import {
  expect,
  renderSuiteCut,
  test,
  type Milliseconds,
  type SuiteCutAnimationOptions,
  type SuiteCutAudioPlugin,
  type SuiteCutAudioPluginReference,
  type SuiteCutAudioSynthesisRequest,
  type SuiteCutBorderStyle,
  type SuiteCutCaptureOptions,
  type SuiteCutCaptureSize,
  type SuiteCutCaptureViewport,
  type SuiteCutCheckpointOptions,
  type SuiteCutColorRange,
  type SuiteCutEasing,
  type SuiteCutFixture,
  type SuiteCutHighlightMode,
  type SuiteCutHighlightOptions,
  type SuiteCutJsonValue,
  type SuiteCutNarrationOptions,
  type SuiteCutNarrationProvider,
  type SuiteCutNarrationVoice,
  type SuiteCutOutputContainer,
  type SuiteCutOutputFormat,
  type SuiteCutPointerActionOptions,
  type SuiteCutRenderConfig,
  type SuiteCutRenderFailureMode,
  type SuiteCutRenderOutputConfig,
  type SuiteCutRenderQuality,
  type SuiteCutRenderReport,
  type SuiteCutRenderRequest,
  type SuiteCutScrollAlignment,
  type SuiteCutScrollBehavior,
  type SuiteCutScrollOptions,
  type SuiteCutTypeOptions,
  type SuiteCutVisualAnimation,
  type SuiteCutZoomOptions,
} from 'suitecut'

suitecut/playwright

The runner-free recording lifecycle and all of its callback, setup, result, and option types.

TypeScript
import {
  defineSuiteCut,
  record,
  type Milliseconds,
  type SuiteCutAudioPluginReference,
  type SuiteCutBrowserName,
  type SuiteCutCaptureOptions,
  type SuiteCutCheckpointOptions,
  type SuiteCutCleanup,
  type SuiteCutDefinitionOptions,
  type SuiteCutFixture,
  type SuiteCutHighlightOptions,
  type SuiteCutNarrationOptions,
  type SuiteCutOutputOptions,
  type SuiteCutPointerActionOptions,
  type SuiteCutRecordOptions,
  type SuiteCutRecordResult,
  type SuiteCutRecorder,
  type SuiteCutRecordingCallback,
  type SuiteCutRecordingContext,
  type SuiteCutScrollOptions,
  type SuiteCutTypeOptions,
  type SuiteCutSetupContext,
  type SuiteCutZoomOptions,
} from 'suitecut/playwright'

suitecut/audio-plugin

The contract and helpers for external narration packages.

TypeScript
import {
  audioPluginReference,
  defineSuiteCutAudioPlugin,
  encodePcm16Wav,
  type SuiteCutAudioPlugin,
  type SuiteCutAudioPluginReference,
  type SuiteCutAudioSynthesisRequest,
  type SuiteCutJsonValue,
} from 'suitecut/audio-plugin'

suitecut/render

The programmatic renderer and its complete request, output, edit, and report types.

TypeScript
import {
  renderSuiteCut,
  type SuiteCutColorRange,
  type SuiteCutEditSegment,
  type SuiteCutOutputContainer,
  type SuiteCutOutputFormat,
  type SuiteCutRenderConfig,
  type SuiteCutRenderFailureMode,
  type SuiteCutRenderOutputConfig,
  type SuiteCutRenderQuality,
  type SuiteCutRenderReport,
  type SuiteCutRenderRequest,
} from 'suitecut/render'

suitecut/reporter

The Playwright reporter class and reporter configuration type.

TypeScript
import SuiteCutReporter, {
  type SuiteCutReporterOptions,
} from 'suitecut/reporter'

suitecut/types

The complete manifest, event, artifact, media, geometry, diagnostic, and identity model.

TypeScript
import {
  SUITECUT_EVENT_ATTACHMENT,
  type EpochMilliseconds,
  type FilePath,
  type ISODateTime,
  type Milliseconds,
  type MimeType,
  type SuiteCutActiveScreencast,
  type SuiteCutAnimationOptions,
  type SuiteCutArtifact,
  type SuiteCutArtifactId,
  type SuiteCutArtifactRole,
  type SuiteCutAttempt,
  type SuiteCutAttemptClock,
  type SuiteCutAttemptId,
  type SuiteCutAudioStream,
  type SuiteCutBorderStyle,
  type SuiteCutCapturedArtifact,
  type SuiteCutCapturedCheckpointArtifact,
  type SuiteCutCapturedNarrationArtifact,
  type SuiteCutCapturedVideo,
  type SuiteCutCheckpointEvent,
  type SuiteCutCheckpointOptions,
  type SuiteCutDiagnostic,
  type SuiteCutDiagnosticCode,
  type SuiteCutDiagnosticLevel,
  type SuiteCutEasing,
  type SuiteCutError,
  type SuiteCutEvent,
  type SuiteCutEventAttachment,
  type SuiteCutEventBase,
  type SuiteCutEventId,
  type SuiteCutExecutionStep,
  type SuiteCutFixture,
  type SuiteCutHighlightEvent,
  type SuiteCutHighlightMode,
  type SuiteCutHighlightOptions,
  type SuiteCutHoldEvent,
  type SuiteCutHoldReason,
  type SuiteCutManifest,
  type SuiteCutMedia,
  type SuiteCutMediaId,
  type SuiteCutMediaStream,
  type SuiteCutNarrationEvent,
  type SuiteCutNarrationOptions,
  type SuiteCutNarrationProvider,
  type SuiteCutNarrationVoice,
  type SuiteCutPage,
  type SuiteCutPageEventBase,
  type SuiteCutPageId,
  type SuiteCutPageKind,
  type SuiteCutPathKind,
  type SuiteCutPoint,
  type SuiteCutPointerButton,
  type SuiteCutPointerButtonEvent,
  type SuiteCutPointerMoveEvent,
  type SuiteCutPointerType,
  type SuiteCutRecordingSession,
  type SuiteCutRect,
  type SuiteCutRunStatus,
  type SuiteCutScrollAlignment,
  type SuiteCutScrollBehavior,
  type SuiteCutScrollOptions,
  type SuiteCutSize,
  type SuiteCutSourceLocation,
  type SuiteCutStepCategory,
  type SuiteCutStepId,
  type SuiteCutStepOutcome,
  type SuiteCutTest,
  type SuiteCutTestId,
  type SuiteCutTestStatus,
  type SuiteCutTypeOptions,
  type SuiteCutVideoStream,
  type SuiteCutVideoTiming,
  type SuiteCutViewport,
  type SuiteCutVisualAnimation,
  type SuiteCutZoomEvent,
  type SuiteCutZoomOptions,
} from 'suitecut/types'

Playwright Test

test extends Playwright Test with the suitecut fixture and two options.expect is Playwright's normal assertion API.

  • suitecut: the recording controls documented below.
  • suitecutCapture: viewport, source size, frame rate, quality, and narration tail.
  • suitecutAudioPlugins: external provider references loaded in the narration worker.

Fixture methods

TypeScript
interface SuiteCutFixture {
  selectPage(page: Page): void
  narrate(text: string, options?: SuiteCutNarrationOptions): Promise<void>
  checkpoint(label: string, options?: SuiteCutCheckpointOptions): Promise<void>
  hold(durationMs: number): Promise<void>
  highlight(locator: Locator, options?: SuiteCutHighlightOptions): Promise<void>
  zoom(locator: Locator, options?: SuiteCutZoomOptions): Promise<void>
  hover(locator: Locator, options?: SuiteCutPointerActionOptions): Promise<void>
  click(locator: Locator, options?: SuiteCutPointerActionOptions): Promise<void>
  type(locator: Locator, text: string, options?: SuiteCutTypeOptions): Promise<void>
  scrollTo(locator: Locator, options?: SuiteCutScrollOptions): Promise<void>
  scrollTop(options?: SuiteCutScrollOptions): Promise<void>
}

selectPage(page): void

Selects the main page, popup, or secondary page used by later narration, checkpoints, holds, andscrollTop(). Locator methods select their locator's page automatically. Closing a selected popup returns selection to its opener when possible.

narrate(text, options?): Promise<void>

Synthesizes speech locally, records its audio, displays a caption, and waits for the measured clip plus the configured narration tail. Synthesis time is excluded from the recording clock. Thetext must not be empty.

  • provider: kokoro by default, macos-say, or a configured audio plugin ID.
  • voice: af_heart for Kokoro; the native provider uses its system default when omitted.
  • speed: 0.5 through 2; default 1.
  • caption: override the spoken text shown on screen. Use an empty string to hide the caption without removing audio.

checkpoint(label, options?): Promise<void>

Captures an attached PNG and records it in the manifest. The label must not be empty.fullPage captures the full scrollable document; default false captures the viewport.

hold(durationMs): Promise<void>

Keeps the selected browser page recording its current state. The duration is in milliseconds and must be greater than zero.

highlight(locator, options?): Promise<void>

Measures a visible locator and records the complete highlight animation in the selected browser. Hidden or geometry-less locators fail clearly.

  • durationMs: total duration; default 1200.
  • mode: outline by default, fill, or spotlight.
  • paddingPx: 8; borderWidthPx: 4.
  • borderStyle: solid by default, or dashed.
  • borderColor: #7C3AED; borderRadiusPx: 10.
  • fillColor: #7C3AED; fillOpacity: 0.08.
  • backdropColor: #000000; backdropOpacity: 0.45.
  • label: optional text displayed above the target.
  • enter: default { type: 'fade-scale', durationMs: 180, easing: 'ease-out' }.
  • exit: default { type: 'fade', durationMs: 140, easing: 'ease-in' }.

Animation type accepts none, fade, scale, orfade-scale. Easing accepts linear, ease-in,ease-out, or ease-in-out. A none phase is instantaneous.

zoom(locator, options?): Promise<void>

Scrolls the locator into view and records an output-frame-sampled camera crop. SuiteCut keeps the crop inside the browser frame and limits the requested scale when necessary to retain all available target padding. Concurrent zoom calls run in call order.

  • scale: 1 through 1.25; default 1.15.
  • paddingPx: minimum retained target padding; default 24.
  • holdMs: time at the closest scale; default 900.
  • enter: default { type: 'scale', durationMs: 260, easing: 'ease-out' }.
  • exit: default { type: 'scale', durationMs: 220, easing: 'ease-in-out' }.

Zoom accepts the same animation values as highlight. none disables a phase;fade, scale, and fade-scale use eased camera interpolation.

hover(locator, options?): Promise<void>

Scrolls the locator into view, moves the recorded cursor to its center, performs a real Playwright hover, waits for resulting application animations by default, and settles.

  • moveDurationMs: 450.
  • settleMs: 120.
  • waitForAnimations: true.
  • animationTimeoutMs: 2000.

click(locator, options?): Promise<void>

Uses the same options as hover(), performs a real click, and records a 280 ms ripple. The ripple and optional application-animation wait run together. Click-driven navigation is supported.

type(locator, text, options?): Promise<void>

Scrolls the field into view and enters text one character at a time through Playwright's keyboard events. The source recording shows each character as it appears. The text must contain at least one character.

  • delayMs: time between characters; default 70.
  • settleMs: wait after the last character; default 250.
  • clearExisting: replace the current value before typing; default true. Set it to false to type at the current caret.

scrollTo(locator, options?): Promise<void>

Calls native scrollIntoView() and waits for the target to remain stable for three animation frames.

  • behavior: smooth by default, or auto.
  • block: center by default; also start, end, or nearest.
  • inline: nearest by default; also start, center, or end.
  • timeoutMs: 2000; settleMs: 120.

scrollTop(options?): Promise<void>

Scrolls the selected window to the origin. It uses behavior, timeoutMs, andsettleMs with the defaults above. block and inline are accepted for the shared options type but do not affect a window-to-origin scroll.

Capture options

Set suitecutCapture through test.use() or Playwright Test configuration. Plain Playwright scripts pass the same object as capture to record() ordefineSuiteCut().

  • viewport: default 1600x900; maximum 7680x4320.
  • size: encoded source size, defaulting to the viewport. A larger proportional size uses a matching layout scale. For example, a 1920x1080 viewport with a3840x2160 size keeps HD composition on a native 4K surface. Both size dimensions must be even and no larger than 7680x4320.
  • framesPerSecond: 30 or 60; default 60.
  • quality: screencast JPEG quality 1 through 100; default 100.
  • narrationTailMs: non-negative post-narration pause; default 350.

Reporter options

  • outputFile: default .suitecut/latest-run.json. TheSUITECUT_MANIFEST_PATH environment variable takes precedence.
  • pathKind: absolute by default, or manifest-relative.
  • includeStepCategories: optional allowlist of hook, fixture,pw:api, expect, test.step, test.attach, orunknown. Retained descendants reconnect to the nearest retained ancestor.

Plain Playwright options

Import record or defineSuiteCut from suitecut/playwright. Each call owns one browser, context, main page, and recording. It writes one manifest attempt with no test steps.

TypeScript
record(
  name: string,
  callback: SuiteCutRecordingCallback,
  options?: SuiteCutRecordOptions,
): Promise<SuiteCutRecordResult>

defineSuiteCut<Extensions extends object = object>(
  defaults?: SuiteCutDefinitionOptions<Extensions>,
): SuiteCutRecorder<Extensions>
  • browserName: chromium, firefox, or webkit.
  • launch: Playwright launch options.
  • context: Playwright browser context options. Do not set recordVideo; SuiteCut owns the page screencasts.
  • capture: the capture options listed above.
  • output.directory: artifact directory. The default is a unique directory under.suitecut/recordings.
  • output.manifestPath: default .suitecut/latest-run.json.
  • output.pathKind: absolute by default, or manifest-relative.

SuiteCutRecordResult

A successful recording returns attemptId, testId, the decodedmanifest, its manifestPath, and the outputDirectory.defineSuiteCut() can add typed setup values and reverse-order cleanup callbacks.

Renderer

renderSuiteCut(request) selects one recorded attempt, invokes FFmpeg, writes the requested video, and writes <output>.suitecut.json. It returns the same render report.

TypeScript
const report = await renderSuiteCut({
  manifestPath: '.suitecut/latest-run.json',
  outputPath: '.suitecut/videos/tour.mp4',
  selection: { testId, retry: 0 },
  config: {
    narrationEnabled: true,
    resultHoldMs: 500,
    failureMode: 'strict',
    output: {
      container: 'mp4',
      width: 3840,
      height: 2160,
      framesPerSecond: 60,
      quality: 'high',
    },
  },
})

The request accepts manifestPath, outputPath, optional test and retry selection, and optional render configuration. The report includes timing edits, diagnostics, selected IDs, output status, and the FFmpeg command result.

Audio plugin helpers

  • defineSuiteCutAudioPlugin(plugin) preserves the plugin type without wrapping the runtime object.
  • audioPluginReference(reference) validates a provider ID, module name, and optional JSON settings before the worker loads them.
  • encodePcm16Wav(samples, sampleRate) converts a mono Float32Array into a 16-bit PCM WAV byte array.
  • SuiteCutAudioPlugin.synthesize(request) receives text, voice, speed, output path, and plugin settings. It resolves after writing the WAV file.

The audio plugin guide shows package installation and provider setup.

Command-line flags

suitecut test [--manifest path] -- [Playwright options] forwards Playwright arguments and installs the SuiteCut reporter. suitecut render requires--manifest <path> and --output <path>.

  • --test-id <id>: select a test; default is the first.
  • --retry <number>: select an attempt; default is the latest.
  • --container <mp4|webm|mov|mkv>: default comes from the output extension.
  • --format: deprecated alias for --container.
  • --video-codec: default libvpx-vp9 for WebM, libx264 otherwise.
  • --audio-codec: default libopus for WebM, aac otherwise.
  • --pixel-format: default yuv422p10le for ProRes, yuv420p otherwise.
  • --color-range <auto|full|limited>: default auto.
  • --width and --height: default 3840x2160; supply both, even, maximum 7680x4320.
  • --fps <30|60>: default 60.
  • --quality <standard|high|master>: default high.
  • --result-hold-ms: non-negative final-frame hold; default 0.
  • --background-color: default #0B1020; three- or six-digit hex or the basic names black, white, red, green, blue, and yellow.
  • --failure-mode <strict|best-effort>: default strict. Best-effort can omit unavailable narration and records an OPTIONAL_TRACK_OMITTED warning; required video failures remain fatal.
  • --ffmpeg-path: explicit FFmpeg executable path.
  • --no-narration: omit narration audio; recorded captions remain.

A recorded test

TypeScript
test('opens the account', async ({ page, suitecut }) => {
  await page.goto('/account')
  await suitecut.narrate('The account page is open.')

  const billing = page.getByRole('link', { name: 'Billing' })
  await suitecut.highlight(billing, { label: 'Open billing' })
  await suitecut.click(billing)
  await suitecut.hold(500)
  await suitecut.checkpoint('Billing page')
})