Introspection is a Playwright-integrated tracing framework. A trace records a stream of typed trace events — network requests and responses, JS errors with scope locals, DOM snapshots, Playwright actions — and their associated assets to disk as NDJSON. Plugins are the unit of feature capture, each subscribing to Chrome DevTools Protocol (CDP) events or page state.
When an end-to-end test fails, the usual debugging loop is: read the error, guess what the app was doing, add more logs or breakpoints, re-run. With a trace on disk, you can query the recorded trace instead of re-running the test.
Introspection is built primarily for AI-assisted debugging — the trace gives a model the full execution context to reason about — but the same trace is queryable by humans too, via the introspect CLI or programmatically through @introspection/read.
attach(page, { plugins }) opens a CDP trace alongside the Playwright test. Plugins contribute to the event stream by subscribing to CDP events and/or injecting scripts in the browser.
| Package | Description |
|---|---|
introspect |
CLI for querying traces: summary, events, list, plugins |
@introspection/playwright |
Attach tracing to a Playwright page — the main integration point |
@introspection/read |
Programmatic access to traces — adapter-based, environment-agnostic |
@introspection/write |
Trace recording — creates traces, appends events, writes assets |
@introspection/utils |
Shared utilities: CDP normalizers, event bus, debug, snapshot |
@introspection/types |
Shared TypeScript types for events, plugins, and trace format |
Every capability is a plugin. If you don't wire it up, it won't log. Pass the plugins you want to attach() via the required plugins option.
| Plugin | Package | What it captures |
|---|---|---|
cdp() |
@introspection/plugin-cdp |
Raw Chrome DevTools Protocol commands and events (advanced instrumentation) |
consolePlugin() |
@introspection/plugin-console |
Browser console output |
debuggerPlugin() |
@introspection/plugin-debugger |
Debugger pauses with scope locals and call stack |
defaults() |
@introspection/plugin-defaults |
Composition: [network(), jsError(), debuggerPlugin(), consolePlugin()] |
jsError() |
@introspection/plugin-js-error |
JS exceptions and unhandled rejections |
network() |
@introspection/plugin-network |
HTTP requests, responses, and response bodies |
performance() |
@introspection/plugin-performance |
Core Web Vitals, resource timing, long tasks, layout shifts, and paint |
webgl() |
@introspection/plugin-webgl |
WebGL state, uniforms, draw calls, textures, and canvas PNGs |
| Plugin | Package | What it captures |
|---|---|---|
reactScanPlugin() |
@introspection/plugin-react-scan |
React component renders and reconciler commits, via react-scan |
redux() |
@introspection/plugin-redux |
Store dispatches from Redux, Zustand, Valtio, and other Redux DevTools–compatible libraries, with optional state snapshots |
solidDevtools() |
@introspection/plugin-solid-devtools |
SolidJS component structure, reactive updates, and dependency graph |
pnpm add -D @introspection/playwright introspectimport { attach } from "@introspection/playwright";
import { defaults } from "@introspection/plugin-defaults";
test("checkout flow", async ({ page }) => {
const handle = await attach(page, {
testTitle: "checkout flow",
plugins: defaults(),
});
await handle.page.goto("/cart");
await handle.page.getByRole("button", { name: "Checkout" }).click();
await handle.detach();
});After the test runs, query the trace:
introspect summary
introspect events --type js.error
introspect events --type network.* # Prefix matching: all network.* events
introspect events --type network.response --filter 'event.metadata.status >= 400'Full documentation:
@introspection/playwright—attach()fixture and optionsintrospectCLI —debug,summary,events,network,assetscommands@introspection/plugin-*— Available plugins and their options
Each test produces a trace directory:
.introspect/
<trace-id>/
meta.json ← id, startedAt, endedAt, label
events.ndjson ← one JSON event per line
assets/ ← response bodies, DOM snapshots, plugin captures
TraceEvents are plain JSON objects with a unique id, type, timestamp (ms since test start), references to corresponding assets and event-specific metadata.
Every push to main publishes preview builds via pkg.pr.new. You can install any commit's build directly without waiting for a versioned release — useful for trying unreleased fixes or features.
The full list of published previews is tracked on the releases branch, with install commands for each package at every commit and a JSON list for use in package.json overrides (e.g. in a monorepo).