6.6 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Overview
WebShot is a CLI tool built with Node.js and Puppeteer for capturing screenshots, videos, and full HTML snapshots of websites. It features an interactive "shoot mode" with pastel-themed terminal UI, custom automation scripts, and support for multiple export formats (PNG, JPG, WEBP, PDF, MP4, HTML).
Architecture
Core Components
Main executable (webshot):
- Single-file CLI application with shebang (
#!/usr/bin/env node) - Self-contained with all functionality in ~800 lines
- Uses Puppeteer for browser automation
- Built-in debug mode with Node.js inspector support (restarts process with
--inspect)
Key architectural patterns:
- Spinner class (webshot:79-114): Animated terminal progress indicator with rotating frames and pastel colors
- Export functions (webshot:202-470): Modular export handlers for each format (PNG, JPG, WEBP, PDF, MP4, HTML)
- MP4 recording (webshot:243-400): Fast screenshot-loop method that captures JPEG frames and uses ffmpeg to create video (supports both MP4 with H.264 and WebM with VP9)
- HTML export (webshot:403-470): Downloads complete page with all assets (images, CSS, JS) into
assets/subdirectory - Interactive shoot mode (webshot:149-200): Race between spacebar press and countdown timer
Custom Script System
WebShot supports custom Puppeteer automation scripts via -s/--script flag. Scripts are evaluated with access to the page object and can manipulate the page before capture.
Example scripts (examples/):
scroll-animation.js- Smoothly scrolls to bottom and back to topdark-mode.js- Attempts to enable dark mode using multiple detection methodsinteract-form.js- Fills out forms with demo datahover-effects.js- Simulates hover states on interactive elementsmobile-view.js- Switches to mobile viewport (375x667, iPhone SE)animated-sections.js- Scrolls through sections to trigger scroll-based animations
Scripts are executed via eval() in an async context with access to page, console, and other webshot internals (webshot:722-727).
Commands
Basic Usage
# Install dependencies
pnpm install
# Make executable (if needed)
chmod +x webshot
# Run from anywhere (if in PATH)
webshot -u https://github.com --help
Common Workflows
# Screenshot with interactive shoot mode
webshot -u https://example.com
# Screenshot without delay
webshot -u https://example.com --no-delay
# High quality WEBP
webshot -u https://example.com -f webp --quality 95
# Record 10 second video (MP4)
webshot -u https://bruno-simon.com -f mp4 --duration 10000 --fps 30
# Record as WebM instead
webshot -u https://bruno-simon.com -f mp4 -o output.webm --duration 10000
# Export as PDF
webshot -u https://github.com/features -f pdf
# Download complete HTML with assets
webshot -u https://stripe.com -f html -o stripe/index.html
# Use custom automation script
webshot -u https://example.com -s examples/dark-mode.js
# Custom viewport
webshot -u https://example.com -w 1280 -h 720
# Custom shoot delay (5 seconds)
webshot -u https://example.com 5000
Debug Mode
# Enable debug logging and Node.js inspector
webshot -u https://example.com --debug
# Connect debugger on custom port
DEBUG_PORT=9230 webshot -u https://example.com --debug
# Debug with specific wait strategy (for slow sites)
webshot -u https://example.com --debug --wait-until load --timeout 60000
Debug mode:
- Prints detailed logs prefixed with
[DEBUG]in magenta (webshot:36-40) - Enables Puppeteer dumpio for browser console output (webshot:669)
- Listens for page console messages, errors, and failed requests (webshot:677-682)
- Restarts process with
--inspectif not already in debug mode (webshot:7-19)
Wait Strategies
The --wait-until flag controls when navigation is considered complete:
load- Wait for window.load event (fastest, may miss dynamic content)domcontentloaded- Wait for DOM to be readynetworkidle2(default) - Wait until 2 or fewer network connections remain for 500msnetworkidle0- Wait until 0 network connections remain (slowest, most complete)
Use --timeout <ms> to increase navigation timeout for slow sites (default: 30000ms).
Format-Specific Details
MP4/WebM Video Recording
Video recording uses a fast screenshot-loop method:
- Captures JPEG screenshots as fast as possible (quality: 60 for speed)
- Saves frames to temporary directory (
.webshot-frames-<timestamp>/) - Uses ffmpeg to convert frames to video
- Automatically detects output format based on file extension (
.mp4→ H.264,.webm→ VP9) - Duplicates frames to reach target FPS using ffmpeg
-rflag - Cleans up temporary frames after conversion
Requires ffmpeg to be installed and available in PATH.
HTML Export
HTML export downloads a complete snapshot:
- Extracts all resource URLs (images, CSS, JS, favicon)
- Downloads each resource using Puppeteer's page.goto()
- Saves resources to
assets/subdirectory relative to output file - Rewrites HTML to use local asset paths
- Returns to original page after downloading
Package Structure
- Package manager: pnpm (uses pnpm-workspace)
- Main entry:
webshot(executable script, also set as bin in package.json) - Only dependency:
puppeteer(uses bundled Chromium) - Keywords: pupeteer (sic), cli, record, screeencast (sic), shoot
Color Palette
Terminal UI uses pastel ANSI colors defined in colors object (webshot:43-63):
- Pastels: pink (217), lavender (183), mint (158), peach (223), sky (153), coral (210), sage (151)
- Standard: green, yellow, red, cyan, gray
- Modifiers: bright, dim, reset
ASCII banner uses mint → sky → lavender gradient (webshot:66-76).
Important Notes
- Single file architecture: All code lives in the
webshotexecutable - no separate modules - No README: Project lacks a README.md file, all documentation is in
--helpoutput - No tests: No test directory or test files present
- Script evaluation security: Custom scripts are evaluated with
eval()and have full access to Node.js APIs - only use trusted scripts - ffmpeg dependency: MP4/WebM recording requires ffmpeg to be installed separately
- Viewport defaults: 1920x1080 at 2x device scale factor (webshot:684-688)
- Interactive mode: Uses raw terminal input with keypress events (webshot:152-154)
- File overwrite: Always prompts before overwriting existing files (webshot:129-146)
- Fonts ready: Waits for document.fonts.ready before capturing (webshot:716)