Stop being your AI's eyes and hands: pwa-debug lets Claude debug your live, logged-in browser

2026-11-04来源 dev.toEnglish

If you've debugged a web app with an AI assistant, you know the loop:

  1. The AI asks what the console says. You copy and paste it.
  2. It asks what the component's state is. You open React DevTools and describe it.
  3. It asks you to click the button and report what happens. You click it.
  4. It asks for a screenshot. You take one.

You end up as the AI's eyes and hands. That's slow, it loses information, and it doesn't work at all for the bugs that hurt most in PWAs: stale caches, service workers that won't update, install failures, and version skew after a deploy.

I built pwa-debug to remove that loop. It's an open-source (MIT) MCP server plus a browser extension that gives an AI agent like Claude Code direct, structured access to your live, logged-in browser. That covers the DOM, console, network, framework state, store state, service workers, caches, and storage, and the agent can also interact with the page.

npx -y @aryanduntley/pwa-debug@latest 

The questions it answers

These are the PWA problems people search for most. pwa-debug answers them by reading the runtime directly, without screenshots or OCR:

You ask The agent calls
Why won't my service worker update? Why are some users on old code? sw_status, pwa_update_analyze (waiting-vs-active versions, version-skew verdict)
Why is my cache stale? Why are chunks 404ing after a deploy? cache_list / cache_inspect / cache_match (entries with age, size, cache-control)
Why won't my PWA install? pwa_installability (structured { gaps[], fixes[] }, not just "manifest invalid")
What's actually in IndexedDB right now? idb_list / idb_query, storage_get
Why does this component have the wrong state? react_get_state, vue_get_state, store_get_state, redux_get_state
Does anything break at 360px, in dark mode, in Spanish? layout_sweep (one call, every page × width × scheme × state)

Highlights

🔐 It runs in your real browser profile

Google's chrome-devtools-mcp is great, but it starts a fresh automated Chrome. That browser has none of your cookies, sessions, or extensions, and none of your real service-worker state. If your app sits behind a login, that's a problem.

pwa-debug attaches to your normal profile by default, so the agent sees what you see: authenticated sessions, your real SW and cache state, and your extensions.

⚛️ Framework and store state that CDP can't reach

A script injected into the page's MAIN world reads each framework through its own devtools hooks:

  • React fiber tree, props, state, and hooks
  • Vue 3 component tree and reactive state
  • Svelte components with source locations
  • Solid detection and element lookup
  • Redux, Zustand, Pinia, Jotai: read, subscribe to change deltas, and (opt-in) dispatch

Every framework also supports find-by-text and find-by-role, so the agent can locate "the Submit button inside <CheckoutForm>" without guessing selectors.

🛠️ The full PWA diagnostics suite

This is the part the project is named for. It covers service-worker lifecycle and versions, CacheStorage contents and age, installability gaps with per-gap fixes, a live capability matrix (Push, Background Sync, Periodic Sync, Badging, File System Access, Window Controls Overlay), IndexedDB and web storage, and pwa_update_analyze. That last tool combines SW status, cache ages, and recent 404s into a verdict such as "cached HTML is older than the JS it references", which is the classic cause of "why are some users on old code."

pwa_snapshot produces one capped blob of the whole runtime state, which is useful for repros and bug hand-offs.

👆 The agent drives the page itself

pdl_click, pdl_fill, pdl_submit, pdl_key_press, pdl_type_sequence, pdl_navigate, and pdl_new_tab are available, along with touch gestures: tap, double-tap, long-press, swipe, drag, scroll, and pinch. Events are dispatched as native-event sequences, so React's and Vue's delegated event systems fire properly. Targets use one locator format (selector, role, text, or a framework component id).

📱 Android phones over adb

The extension can't run in Android Chrome, so pwa-debug connects to phones over adb and CDP and injects the same page-world code there. One call does the setup:

pdl_android_attach({ open_url: "http://localhost:5173", reverse_ports: [5173] // phone's localhost:5173 → your dev server }) → { connectionId: "cdp:127.0.0.1:<port>:<tab>" } 

After that, every page tool works on the phone tab, including React state, stores, PWA diagnostics, gestures, and console and network capture, and you can watch it happen on the device. I verified this live on a Galaxy S24 Ultra (Android 16, Chrome 156).

📐 Responsive layout sweep

One layout_sweep call goes through a matrix of pages × viewport widths × color schemes × app states (plus extra dimensions such as language). For each view it emulates the viewport over CDP and measures the page for:

  • horizontal page overflow and off-screen elements
  • tap targets below WCAG 2.2 minimums
  • clipped or ellipsized text (useful when testing longer translations)
  • fixed bars that aren't fully on screen
  • clipped focus and selection rings
  • unresolved copy like {{name}}, undefined, NaN, [object Object]
  • page errors during the view, plus optional WCAG AA contrast

It groups the results into distinct problems, so 150 raw findings that come from two root causes are reported as two groups, with screenshots if you ask for them. You can also pass your own custom_checks expressions. In the largest real test it swept an 83-page prototype across 4,812 views.

🔌 Library popups, replay, and source maps

  • WalletConnect, RainbowKit, and SDK modals that live in shadow roots or nested iframes can be recorded, replayed, and correlated with the console errors and failed requests that occurred while they were open (popup_failures).
  • rrweb session recording and replay, plus persistent ring buffers that survive navigations and reloads.
  • source_map_resolve maps minified stack frames back to src/file.ts:line:col.

🤖 Built for agents, not humans

Every tool returns { ok, data, error?, next_steps[] }. The next_steps field tells the agent what to call next based on the actual result, so it recovers from setup gaps and errors without you stepping in. pdl_help serves the whole usage guide as data, and filters keep each response to the slice the agent asked for instead of dumping the full DOM.

Works with chrome-devtools-mcp, doesn't replace it

pwa-debug is complementary to chrome-devtools-mcp, and the two tool sets don't overlap. pwa-debug launches a browser with a live debug port, and chrome-devtools-mcp attaches to that same port. Both then drive the same tab over separate channels: CDP for one, extension and page-world injection for the other.

pdl_launch_browser({ browser: "brave", mode: "sandbox-persistent" }) pdl_register_chrome_devtools() // pins chrome-devtools-mcp to the right port for you 

Getting started

As a Claude Code plugin (no clone, no build)

/plugin marketplace add aryanduntley/pwa-debug-layer /plugin install pwa-debug@pwa-debug /reload-plugins 

Or with any MCP client

claude mcp add pwa-debug --scope user -- npx -y @aryanduntley/pwa-debug@latest 

Then tell your agent:

Set up pwa-debug and open my app at http://localhost:5173.

The setup is agent-driven. It runs pdl_check_setup, registers the native-messaging host, launches a browser with the extension preloaded, and confirms the round-trip with session_ping. Each step's next_steps tells it what to do next.

Browser support: Chromium-family browsers (Chrome, Chromium, Brave, Edge, Vivaldi, Opera) and Android Chrome over adb. Brave and Chromium give the smoothest experience, because Google Chrome 142+ removed --load-extension and so needs one manual "Load unpacked" step.

How it works

Claude Code ──MCP──► Native host (MCP server, ring buffers, replay store) │ native messaging ▼ Extension service worker │ ┌─────────────┴──────────────┐ ▼ ▼ Content script Page-world script (MAIN world) DOM observe, actions React/Vue hooks, fetch/XHR patch, stores 
  • The extension handles the page: DOM, content scripts, and page-world hooks injected on every load.
  • The native host handles persistence and the MCP server.
  • MCP is the contract with the AI.

The whole codebase is TypeScript written in a strict functional style: pure functions, immutable data, no classes, and side effects kept at the edges.

Help wanted 🙏

Development happens on Linux, where everything is live-tested. The macOS and Windows code paths (browser detection, profile paths, native-messaging registration) are written and unit-tested but have never run on real hardware. If you're on a Mac or a Windows machine, trying it and opening an issue with the output would help more than anything else right now.

Firefox support is on the roadmap (via WebDriver BiDi). Stars, issues, and PRs are all welcome.

If you try it on a PWA bug, I'd like to hear how it went in the comments, whether it worked or not.

原文:https://www.a8q9.cn/en/article/stop-being-your-ai-s-eyes-and-hands-pwa-debug-lets-claude-debug-your-live-logged-73b37b.html

相关文章