Introduce a first-class ghost cursor system for recordings and screenshots with namespace APIs (, ) while preserving backward-compatible top-level recording helpers.
Improve reliability after relay restarts by consolidating extension wait logic around , reducing false disconnected states during and execute flows.
Refactor recording glue into dedicated modules (, in ) to keep executor orchestration thin and make cursor lifecycle state explicit and testable.
Build-time script generates tiny 32px-wide versions of all images in
public/ using sharp. At runtime, PixelatedImage component renders these
with CSS image-rendering: pixelated (nearest-neighbor / point sampling)
for a crisp mosaic effect, then fades in the real image on load.
- Auto-discovers images in public/, skips placeholder- prefixed files
- Mtime check skips regeneration when placeholder is newer than source
- Callback ref handles cached images where onLoad fires before mount
- Explicit z-index prevents placeholder from covering the real image
- Runs automatically as part of pnpm build in website package
Add explicit guidance to use playwriter first for JS-rendered websites and blocking overlays, based on repeated failures where webfetch/curl returned empty shells and screenshots were used too early.
Key updates:\n- Add a hard 'when to use playwriter vs webfetch/curl' rule in the main skill docs\n- Add a 'snapshot before screenshot' rule to prevent slow image-first debugging loops\n- Add a concrete anti-pattern for JS-rendered sites in common mistakes\n- Add obstacle-handling flow for cookie/login/age-gate overlays\n- Add media extraction/download pattern using evaluate + Node fetch/fs\n- Update skill frontmatter description (and well-known discovery copies) so context-loaded summaries also include the JS-heavy-site rule
- Replace favicon.ico with transparent PNG favicons (32px, 16px) generated
from the gray extension icon, preserving alpha channel
- Move favicon links from hardcoded JSX to typed LinksFunction export in
root.tsx, rendered via <Links /> component
- Type liveline meta export as MetaFunction
- Add properly sized OG image (1200x630) for X/Slack/Discord previews,
update meta tags to reference it
Fixes:
- Bug: page.screenshotWithAccessibilityLabels was called as method on page,
fixed to standalone function call
- Removed duplicate 'debugging playwriter issues' section at end of file
(identical to the detailed one earlier)
- Softened waitForTimeout rule: short waits (1-2s) now acknowledged as
acceptable for non-deterministic events like popups/animations
- Fixed download example path from /tmp/ to ./
- Added note that bare 'page' in examples is for brevity, real automation
should use state.myPage
- Consolidated diff behavior explanation to one place in snapshot section
(was repeated 3 times with slight inconsistencies)
- Trimmed redundant 'prefer snapshots' advice to reference the dedicated
'choosing between snapshot methods' section
- Consolidated cmd+click popup advice (was in both mistakes and common
patterns with duplicate examples)
- Cross-referenced iframe approaches: frameLocator for locator chaining,
contentFrame for Frame objects needed by snapshot()
- Clarified require is the only option in sandbox (ESM import unavailable)
The observe step now has an inner loop — if the page isn't ready (still
loading, wrong URL, expected content missing), the agent loops back to
observe again instead of acting on stale state. The ASCII diagram shows
the 'not ready' branch looping back to observe.
Every observe step in the example now prints page.url() before the
snapshot so the agent always knows the current URL. This catches
redirects and unexpected navigation between actions.
Add a 'computer use' section to skill.md showing how Playwriter covers all
actions from the Anthropic computer_20250124 tool and the Claude Chrome
extension's custom computer tool, using Playwright APIs instead of
screenshot-based coordinate clicking.
Each subsection shows the declarative locator-based approach first (preferred)
with coordinate-based fallback for canvas/maps/custom widgets.
Also adds docs/claude-extension-tools.json with all 16 tool schemas extracted
from the Claude Chrome extension v1.0.39 (minified source) for reference.
Add observe → act → observe feedback loop section with ASCII diagram
and Framer command palette example. Agents must take a snapshot after
every action to verify the result before proceeding.
Also change page creation pattern to reuse existing about:blank tabs
instead of always creating new ones, with a note to navigate immediately
in the same execute call to prevent concurrent agents from grabbing the
same tab.
When the Playwriter extension can't connect because Chrome isn't running,
agents now have platform-specific commands (macOS, Linux, Windows) to start
Chrome from the CLI. Also documents the --allowlisted-extension-id and
--auto-accept-this-tab-capture flags for enabling automatic tab capture
for screen recording without manual extension clicks.
Closes#48
Switch from getCDPSessionForPage (creates a new WS via Target.attachToTarget)
to getExistingCDPSessionForPage which reuses Playwright's internal CRSession.
This is critical for the relay server where Target.attachToTarget is intercepted
and cannot create real new sessions.
Also add FrameLocator support in accessibilitySnapshot — FrameLocator (from
locator.contentFrame()) is now auto-resolved to the real Frame object needed
for OOPIF CDP session attachment.
- New PlaywrightCDPSessionAdapter wrapping Playwright's CDPSession as ICDPSession
- New getExistingCDPSessionForPage() using context.getExistingCDPSession()
- resolveFrame() helper converts FrameLocator to Frame via elementHandle().contentFrame()
- getAriaSnapshot() frame param now accepts Frame | FrameLocator
- Executor CDP cache uses ICDPSession, borrowed sessions detach as no-op
- Test for getExistingCDPSession through the relay
- Updated framer iframe guide with alternative page.frames() example
- Bump playwright submodule to @xmorse/playwright-core@1.59.2
- Fix styles-api.md import path
- Consolidate build scripts into single build-client-bundles.ts
- Add @mozilla/readability for Firefox Reader View content extraction
- New getPageMarkdown() utility extracts main page content as plain text
- Supports search and diff-since-last-call like other utilities
- Add test with file snapshot
- Move skills/playwriter/SKILL.md to playwriter/src/skill.md (source of truth)
- Add 'playwriter skill' CLI command to output full docs
- Make skills/playwriter/SKILL.md a lightweight stub pointing to CLI
- Generate prompt.md to dist/ instead of src/
- Strip CLI-only content from MCP prompt
- Add build-resources.ts script to generate markdown API docs
- Resources now use https://playwriter.dev/resources/*.md URLs
- Output to both playwriter/dist/ and website/public/resources/
- Simplify mcp.ts resource handlers to read pre-built files