Automated documentation screenshots for software projects.
Documentation screenshots go stale. Every UI change means manually re-capturing images, cropping them, adding drop shadows, updating the README, and committing. Most teams give up and let their docs rot.
Phantom automates the entire pipeline: launch your app, execute actions, capture screenshots, process them, and commit the results — all from a single YAML manifest.
# .phantom.yml
phantom: "1"
project: "my-app"
name: "My App"
setup:
type: web
build:
- npm ci
run:
command: "npm run dev"
ready_check:
type: http
url: "http://localhost:3000"
captures:
- id: dashboard
name: "Dashboard"
route: "/"
output: "docs/screenshots/dashboard.png"
actions:
- type: wait_for
selector: ".dashboard-loaded"
- type: set_theme
theme: darkphantom run -p ./my-apppipx install phantom-docs
# or
pip install phantom-docsFor web runner captures, install Playwright browsers:
playwright install chromiumCheck your setup:
phantom doctor# 1. Initialize a manifest (auto-detects project type)
phantom init
# 2. Edit .phantom.yml with your routes and captures
# 3. Run the pipeline
phantom run -p .The fastest way to set up Phantom for an existing project is with Claude Code. Copy the onboarding prompt into Claude Code while in your project's root directory — it will analyze your codebase and generate everything Phantom needs:
- Framework-specific demo mode playbooks (Flask, React, SDL2, Java Swing, TUI)
.phantom.ymlmanifest with progressive verification at every stage- GitHub Actions workflow for automated updates
- README sentinels for screenshot placement
- Action timing rules and screenshot quality checks
- Desktop Runner support for native GUI apps
# From your project directory:
cat path/to/phantom/docs/onboarding-prompt.md | pbcopy # macOS
# Then paste into Claude CodePhantom freezes the interface your app and CI depend on in
CONTRACT.md — currently contract-version: 1.0.0. It
covers the PHANTOM_MODE=1 boot semantics, the .phantom.yml schema
(unknown keys are always ignored, never fatal), the readiness/timeout signal,
and the docs/screenshots/ artifact directory.
Pin the package by minor range and assert on the contract version — the same
discipline as pinning a Docker image tag rather than latest:
import phantom
assert phantom.__contract_version__.startswith("1.") # contract major 1
# requirements: phantom-docs==0.4.*Phantom guarantees PHANTOM_MODE=1 in your app's environment on every capture,
across all runners. Conformance is machine-checked in
tests/contract/; the CI smoke job that consumes the
contract is specified in docs/smoke-job-spec.md.
Phantom ships with 600+ tests across unit, integration, and
contract-conformance suites.
Phantom supports multiple runner types for different kinds of applications:
| Runner | Type | Use Case | Key Tools |
|---|---|---|---|
| Web | web |
Browser-based apps | Playwright, Node |
| TUI | tui |
Terminal applications | pyte, silicon |
| Desktop | desktop |
Native GUI apps (SDL2, Qt, Swing, Electron) | Xvfb, xdotool, ImageMagick |
| Docker Compose | docker-compose |
Containerized apps | Docker |
Runners are pluggable — see Writing Runner Plugins for the extension API.
The .phantom.yml manifest has these top-level sections:
phantom: "1" # Schema version
project: "my-app" # Unique project ID (kebab-case)
name: "My App" # Display name
setup: # How to build and run the project
type: web # Runner type
build: [...] # Build commands
run: # Run configuration
command: "..."
ready_check: { ... }
capture_defaults: # Defaults applied to all captures
viewport: { width: 1280, height: 800 }
theme: dark
captures: # Screenshot definitions
- id: hero
name: "Hero screenshot"
route: "/"
output: "docs/hero.png"
actions: [...]
processing: # Image processing pipeline
format: png
border:
style: drop-shadow
publishing: # Git commit settings
branch: main
strategy: direct # or "pr"
readme_update: trueSee docs/manifest-reference.md for the complete field reference.
| Command | Description |
|---|---|
phantom run -p <path> |
Run the capture pipeline |
phantom validate <manifest> |
Validate a manifest file |
phantom init |
Scaffold a new .phantom.yml |
phantom analyze -p <path> |
Generate a manifest from your code via the AI Analyst |
phantom doctor |
Check system dependencies |
phantom status |
Show run history |
phantom snapshots |
List recent screenshot snapshots |
phantom rollback |
Roll screenshots back to a previous snapshot |
phantom diff |
Show what changed since the last AI analysis (no API calls) |
phantom costs |
Show AI Analyst cost summary |
phantom serve |
Start webhook listener + scheduler |
phantom gc |
Clean up stale workspaces |
| Option | Description |
|---|---|
--dry-run |
Run pipeline without git commits |
--capture <id> |
Run a single capture |
--group <name> |
Run a named group of captures |
--skip-publish |
Capture and process, skip git |
--force |
Commit even if below diff threshold |
--if-changed |
Skip if repo HEAD unchanged |
--ai-analyst |
Generate the manifest via AI instead of reading .phantom.yml |
--ai-document |
Use AI to update the README with screenshots after capture |
--ai-auto |
Full autonomous pipeline: AI analyze + capture + document |
--review |
Send screenshots to a vision model for quality review |
--verbose / -v |
Enable debug logging |
Phantom can read your codebase and generate a capture plan for you — no hand-written manifest required. Install the optional extra and set an Anthropic API key:
pip install 'phantom-docs[ai]'
export ANTHROPIC_API_KEY=sk-ant-...# Generate a .phantom.yml from your project
phantom analyze -p . --max-cost 0.50
# Or run the whole pipeline autonomously: analyze + capture + update README
phantom run -p . --ai-autoEvery AI run is cost-capped (--max-cost, default $0.50) and tracked — use
phantom costs for a running total and phantom diff to preview what changed
before spending anything.
.phantom.yml
│
▼
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Validate │────▶│ Build │────▶│ Launch │────▶│ Capture │
│ Manifest │ │ Project │ │ App │ │ Screenshots│
└──────────┘ └──────────┘ └──────────┘ └──────────┘
│
┌───────────────────────────────────────────────────┘
▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Darkroom │────▶│ README │────▶│ Git │
│ Process │ │ Update │ │ Publish │
└──────────┘ └──────────┘ └──────────┘
- Validate — Parse and validate the manifest with Pydantic
- Build — Run build commands (
npm ci,cargo build, etc.) - Launch — Start the app and wait for ready check
- Capture — Execute actions and take screenshots
- Darkroom — Process images (crop, borders, optimize, diff)
- README — Update sentinel regions with new image tags
- Publish — Commit and push (or open a PR)
| Variable | Description |
|---|---|
PHANTOM_MODE |
Set to 1 in your app's environment by Phantom on every capture; your app switches to deterministic demo mode. See CONTRACT.md. |
PHANTOM_WEBHOOK_SECRET |
HMAC secret for webhook verification |
PHANTOM_MANIFEST_MAP |
Repo-to-manifest mapping for serve mode |
ANTHROPIC_API_KEY |
API key for the optional AI Analyst (analyze, --ai-*). See AI Analyst. |
Add markers to your README for automatic image updates:
<!-- phantom:hero -->
<!-- /phantom:hero -->Phantom will inject the <img> tag between these markers when a capture with readme_target: hero changes.
Phantom's product security model — webhook HMAC verification and the zero-outbound
network posture — is documented in
docs/SECURITY-PRACTICES.md. To report a
vulnerability, see SECURITY.md.
See CONTRIBUTING.md for development setup, running tests, and contribution guidelines.
MIT — Copyright 2026 Will Buscombe