debug-capture-system
User needs to capture console logs, DOM snapshots, and screenshots from a web application for debugging or monitoring
Changelog
260428: reclassify pattern label
- Reclassified self-improvement pattern P4 (Compiler Wiki) to substrate infrastructure per consolidated vault audit 2026-04-27.
260420: multiple edits
- v_migrate: Changelog migrated from table to YYMMDD H3 format per versioning-standard rule 2 (V1.6 of skills upgrade plan)
- v6: Added license, sources per V6.1/V6.2 of skills upgrade plan.
- v1.5: Added
## Quality Checkssection per V1.5 of ~/vault/plans/2026-04-20-vault-skills-upgrade-plan.md
260403: Added Visual Enrichment section + self-improving-agent-patterns cross-reference
260331: Initial creation
Description
Three-layer debug capture system originally developed for projects/dakka/_index (parallel Claude Code orchestrator running inside topics/electron-desktop-apps). Solves the fundamental problem of debugging an Electron app that renders multiple parallel terminal sessions: you cannot attach DevTools to every window, and black-screen crashes leave no trace without proactive capture.
The pattern was borrowed from the mycraft project and has since been reused in projects/bloomnet/_index for automated screenshot verification of UI changes (via Puppeteer rather than html2canvas, but the storage/pruning layer is identical).
The system has three independent layers that compose together: console log interception (Layer 1), DOM-to-PNG screenshot capture (Layer 2), and server-side persistence with FIFO pruning (Layer 3). A bonus fourth layer handles multiplexed PTY output for parallel terminal sessions.
Interface
Trigger: Building an Electron app, multi-panel web app, or any application where DevTools may be inaccessible and you need a rolling history of console state and UI state.
Inputs:
target_app: the web application to instrumentcapture_interval: screenshot frequency in milliseconds (default 3000ms)log_buffer_size: max in-memory log entries before trim (default 2000)max_frames_per_tab: screenshot retention per tab (default 40 = 2 minutes at 3s intervals)
Outputs:
console_log_file: timestamped log entries atlogs/consolelog(append-only, session-header on first write)screenshot_frames: PNG files atlogs/screenshots/{tab}/(FIFO, pruned to max_frames)dom_snapshots: clone-and-reveal captures of each tab in isolation
Three Layers
Layer 1 (Logger.ts): Singleton monkey-patches all five console.* methods. Buffers entries as { timestamp, level, message }, flushes every 2 seconds via POST to /api/logs. On fetch failure, re-queues via unshift (never drops). Catches window.error and unhandledrejection as [UNCAUGHT] and [UNHANDLED PROMISE].
Layer 2 (ScreenCapture.ts): Captures all tabs via html2canvas every 3 seconds. The clone-and-reveal technique: onclone callback hides all [data-screencap] sections in the cloned DOM, then reveals only the target tab and its ancestor chain. Handles xterm WebGL canvas taint by drawing each canvas onto its clone via ctx.drawImage() with try/catch. Adds timestamp overlay before sending PNG via FormData POST.
Layer 3 (Vite plugin): Three HTTP endpoints as dev server middleware: /api/logs (append to consolelog), /__debug_screenshot (save PNG + prune to max_frames via lexicographic sort), /__debug_clear_screenshots (wipe all frames on startup). Log persistence uses writeFileSync for session header, then appendFileSync for all subsequent entries: see topics/pitfalls/log-session-header-write-mode.
Bonus (multiplexed PTY): For N parallel terminal sessions, binary WebSocket framing: [1 byte: boyId length][N bytes: boyId][PTY data]. One node-pty process per agent. External sessions watched via .jsonl file polling at 2-second intervals.
Provenance
Developed for projects/dakka/_index, the parallel Claude Code orchestrator. The original pattern comes from the mycraft project (/Users/pluto/Documents/mycraft) which had Logger.ts, FrameCapture.ts, DebugLog.ts, and DebugOverlay.ts. Dakka adapted and simplified it to two files (Logger + ScreenCapture) plus the Vite plugin.
Also used in projects/bloomnet/_index for automated screenshot verification of dashboard UI changes. BloomNet uses Puppeteer scripts (screenshot-loop.mjs, screenshot-garden.mjs) instead of html2canvas, but stores frames in the same logs/screenshots/ directory structure.
Related topics: topics/electron-desktop-apps, topics/chrome-devtools-protocol.
Usage Notes
When to apply this pattern:
- Electron apps where DevTools may not be accessible (black screen, crash loops)
- Any web app where you need a rolling visual history of UI state
- Multi-panel/tab UIs where you need to capture hidden views without switching tabs
- Parallel process orchestration where stdout from N processes must be multiplexed
Adapting to a new project:
- Copy
Logger.tsandScreenCapture.tsinto your utils directory - Add
html2canvasas a dependency (npm install html2canvas) - Mark capturable sections with
data-screencap="section-name"attributes - Update
TAB_LABELSarray to match your section names - Add the
dakkaDebugPlugin(or equivalent) to your dev server: the three endpoints are framework-agnostic HTTP handlers - Call
initLogger()andstartScreenCapture()early in your app entry point
Tuning parameters:
CAPTURE_INTERVAL_MS(default 3000): Lower = more granular history but higher CPU. Below 1000ms is impractical with html2canvasMAX_PER_TAB(default 40): Retention window =MAX_PER_TAB * interval. 40 frames at 3s = 2 minutesmaxBufferSize(default 2000): In-memory log cap. Rarely needs changing since buffer flushes every 2shtml2canvas scale(default 1): Set to 0.5 for lower-res captures if performance is an issue
Debugging the debugger:
- If screenshots are blank, check that
document.getElementById('root')has children (the guard incaptureTab) - If xterm terminals appear blank in screenshots, the canvas compositing failed: check for tainted canvas errors in the console
- Log file not appearing? Verify the
logs/directory exists and has write permissions. The plugin creates it on startup but race conditions with other file watchers can interfere
Quality Checks
- Console logs captured per session. One log file per session with non-zero size. Session with zero log = capture broken.
- Screenshots saved with unique timestamp-based filenames. No collisions. Format:
YYYY-MM-DDTHH-mm-ss-event.png. - DOM snapshots include interactive elements.
grep -c '<button\|<input\|<select' snapshot.html> 0 for pages with UI. - Network requests logged with response bodies. Non-binary response bodies persisted; binary logged with size + content-type only.
- Captures persisted beyond session. Files symlinked or copied to
~/.rusty-data/debug-captures/for post-mortem. - Sensitive data redacted. Authorization headers, cookies, and tokens scrubbed before logging.
Visual Enrichment
When this skill produces output that benefits from visualization:
| Finding Type | Tool | Specification |
|---|---|---|
| Log volume vs screenshot count over time | R viz (skills/r-visualization-pipeline) | Family: TS, Template: Journal |
| 3-layer capture flow | Figma MCP (generate_diagram) | Type: Sequence diagram |
See topics/visual-output-routing for the full routing decision framework.
Self-improvement context: This skill is substrate infrastructure: it captures data for P4 (Compiler Wiki) systems but has no compile/lint/heal loop of its own. Reclassified from P4 per consolidated vault audit 2026-04-27. See skills/self-improving-agent-patterns.