claude/ai-resources-plugin/skills/web-debugger/SKILL.md
Debug a running web app via the web-debugger SDK: app logs, application state, runtime snapshots, React state, query cache.
npx skillsauth add amhuppert/my-ai-resources web-debuggerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Runtime debugging for web applications via the web-debugger-mcp server. Provides structured logs and on-demand state snapshots from both browser and server — all saved to files for context-efficient consumption.
┌─────────────┐ WebSocket ┌──────────────────┐ stdio ┌───────────┐
│ Web App │────────────→│ web-debugger-mcp │←────────→│ Claude │
│ (SDK) │ port 7600 │ (MCP server) │ │ (agent) │
└─────────────┘ └──────────────────┘ └───────────┘
The web app uses the client SDK to send logs and register state providers. The MCP server receives these over WebSocket, writes them to .web-debugger/, and exposes three MCP tools for the agent.
| Tool | Purpose | Returns |
|------|---------|---------|
| get_logs | Get path to current session's JSONL log file | { logFile: "<path>" } |
| get_snapshot | Request state snapshot from a provider | { snapshotFile: "<path>", provider: "<name>" } |
| list_providers | List all registered state providers | { providers: [{ name, source }] } |
The MCP server is bundled with the ai-resources plugin. When the plugin is installed, the web-debugger MCP server starts automatically — no manual claude mcp add needed.
The server listens on WebSocket port 7600 (override with WEB_DEBUGGER_PORT env var). Output directory defaults to .web-debugger/ (override with WEB_DEBUGGER_DIR env var).
After building (cd web-debugger-mcp && bun run build), the binary is placed in the plugin's servers/ directory.
The web app must integrate the client SDK. This is done by the app developer, not the agent.
import { createDebugger } from "web-debugger-mcp/client";
const dbg = createDebugger();
// Log events
dbg.log("info", "User logged in", { userId: "abc123" });
// Register state providers for on-demand snapshots
dbg.registerProvider("app-state", () => store.getState());
dbg.registerProvider("react-query", () => queryClient.getQueryCache().getAll());
The SDK auto-detects browser vs server environment, silently degrades when the MCP server isn't running, and is a no-op in production (NODE_ENV explicitly set to non-development).
Always start by discovering what state the app exposes:
list_providers → see what's available
Get the log file path and read it to understand what happened:
get_logs → { logFile: ".web-debugger/logs/session-20260330-143022-a1b2.jsonl" }
Then read the file. Each line is a JSON object:
{"timestamp":"2026-03-30T14:30:22.000Z","level":"error","source":"server","message":"Failed to fetch user","context":{"userId":"abc","statusCode":500}}
Log fields: timestamp, level (info/warn/error/debug), source (browser/server), message, context (optional structured data).
Request a snapshot from a specific provider to inspect runtime state:
get_snapshot → provider: "app-state"
→ { snapshotFile: ".web-debugger/snapshots/app-state-20260330-143045-c3d4.json" }
Then read the snapshot file. Snapshots are pretty-printed JSON.
For full debugging, combine with browser automation:
get_logs to check what errors occurred during the interactionget_snapshot to inspect application state at the point of failureSee /browser-automation for Playwright tool usage.
Snapshots automatically serialize non-JSON-native types. When reading snapshot files, recognize these tagged objects:
| Type | Serialized Form |
|------|----------------|
| Set | { "__type": "Set", "values": [...] } |
| Map | { "__type": "Map", "entries": [[key, value], ...] } |
| Date | { "__type": "Date", "value": "2026-03-30T..." } |
| RegExp | { "__type": "RegExp", "source": "\\d+", "flags": "gi" } |
| Error | { "__type": "Error", "name": "TypeError", "message": "...", "stack": "..." } |
| BigInt | { "__type": "BigInt", "value": "12345" } |
| undefined | { "__type": "undefined" } |
| Function | { "__type": "Function", "name": "myFunc" } |
| Circular ref | { "__type": "circular" } |
All output is under .web-debugger/ (relative to the project root):
.web-debugger/
├── logs/
│ └── session-YYYYMMDD-HHmmss-XXXX.jsonl # one per server connect
└── snapshots/
└── <provider>-YYYYMMDD-HHmmss-XXXX.json # one per snapshot request
get_logs returns "No active session" — The web app hasn't connected yet. Start the dev server and ensure the SDK is initialized.list_providers returns empty — No providers registered. The app must call debugger.registerProvider().get_snapshot returns "provider_not_found" — The provider name doesn't match. Use list_providers to check exact names.get_snapshot returns "snapshot_timeout" — The provider took >10s to respond. The app may be frozen or the provider callback is hanging.development
Debug a running web app via the web-debugger SDK: app logs, application state, runtime snapshots, React state, query cache.
development
Thoroughly understand a software development objective before implementation: research, identify ambiguities, ask clarifying questions. Use before starting implementation of a non-trivial or ambiguously specified feature, or when requirements leave open design decisions.
development
Locate the on-disk Claude Code transcript file (.jsonl under ~/.claude/projects/) for the current or a specified conversation.
development
Reflect on codebase navigation effectiveness at end of conversation. Surfaces dead ends, inefficiencies, missing context. Does not write files — pair with /kiro:steering-custom to persist.