| name | harness:screenshot |
| description | Screenshot capture skill for recording application state as a visual artifact. Captures browser pages, desktop windows, or terminal output and saves them as timestamped PNG files (or base64-encoded inline artifacts). Use when: (1) documenting the visual state of a running web application, (2) capturing a UI before/after a code change, (3) recording terminal or CLI output as an image, (4) producing evidence artifacts for a bug report or test run, (5) snapshotting intermediate UI states during an automated agent workflow, (6) comparing layouts across breakpoints or themes. Triggers on: take a screenshot, capture the screen, screenshot the app, record the UI, capture application state, visual snapshot, screenshot artifact, capture browser, capture window, harness screenshot. |
harness:screenshot
Workflow
Do you want a quick one-shot capture?
→ Run the CLI
Do you want to embed captures inside an agent pipeline?
→ Programmatic usage
Do you want Claude to decide when to capture?
→ Agent-driven capture
Overview
The screenshot skill captures the visual state of a running application and
saves it as a timestamped PNG artifact. It supports three capture backends,
selected automatically based on what is available:
| Backend | Target | Dependency |
|---|
playwright | Browser pages (Chromium / Firefox / WebKit) | playwright Python package |
pillow | Full desktop or specific window (X11 / macOS / Win) | Pillow + python-xlib or pygetwindow |
terminal | Terminal / CLI output rendered to image | Pillow + pyte |
All backends produce the same output shape — a ScreenshotArtifact — so the
rest of the pipeline never needs to know which backend ran.
CLI Usage
python skills/screenshot/scripts/capture_screenshot.py \
--url http://localhost:3000 \
--out .artifacts/screenshots/
python skills/screenshot/scripts/capture_screenshot.py \
--desktop \
--out .artifacts/screenshots/
python skills/screenshot/scripts/capture_screenshot.py \
--url http://localhost:3000 \
--base64
python skills/screenshot/scripts/capture_screenshot.py \
--url http://localhost:3000 \
--label "after-nav-refactor" \
--out .artifacts/screenshots/
python skills/screenshot/scripts/capture_screenshot.py \
--url http://localhost:3000 \
--width 1280 \
--height 800 \
--out .artifacts/screenshots/
python skills/screenshot/scripts/capture_screenshot.py \
--url http://localhost:3000 \
--wait-for "#app.ready" \
--out .artifacts/screenshots/
Programmatic Usage
1 — Simple browser capture
from harness_skills.screenshot import capture_url, ScreenshotOptions
artifact = capture_url(
url="http://localhost:3000",
options=ScreenshotOptions(width=1280, height=800, label="home-page"),
out_dir=".artifacts/screenshots/",
)
print(artifact.path)
print(artifact.label)
print(artifact.timestamp)
print(artifact.size_bytes)
2 — Desktop / window capture
from harness_skills.screenshot import capture_desktop, capture_window
artifact = capture_desktop(out_dir=".artifacts/screenshots/")
artifact = capture_window(title="My App", out_dir=".artifacts/screenshots/")
3 — Base64 inline artifact (no file written)
from harness_skills.screenshot import capture_url_base64
b64 = capture_url_base64("http://localhost:3000")
html = f'<img src="data:image/png;base64,{b64}" />'
4 — Sequence capture (before / after)
from harness_skills.screenshot import SequenceCapture
with SequenceCapture(label="nav-refactor", out_dir=".artifacts/screenshots/") as seq:
before = seq.snap("before", url="http://localhost:3000/nav")
after = seq.snap("after", url="http://localhost:3000/nav")
print(seq.diff_summary())
Agent-Driven Capture
Wire screenshot_tool into a Claude agent session so Claude can decide when to
take a screenshot:
import asyncio
from harness_skills.screenshot_agent import build_screenshot_tools, run_screenshot_agent
from claude_agent_sdk import ClaudeAgentOptions
server = build_screenshot_tools(out_dir=".artifacts/screenshots/")
options = ClaudeAgentOptions(
mcp_servers={"screenshot": server},
allowed_tools=["take_screenshot", "list_screenshots"],
)
result = asyncio.run(
run_screenshot_agent(
prompt="Take a screenshot of http://localhost:3000 before and after clicking the login button.",
out_dir=".artifacts/screenshots/",
model="claude-opus-4-6",
max_turns=8,
)
)
print(result)
MCP Tools exposed to Claude
| Tool | Description |
|---|
take_screenshot | Captures a URL, desktop, or window. Accepts url, label, width, height, wait_for, desktop (bool). Returns ScreenshotArtifact JSON. |
list_screenshots | Lists all PNG artifacts in out_dir with metadata (label, timestamp, size). |
Output Artifact
Every capture returns a ScreenshotArtifact:
@dataclass
class ScreenshotArtifact:
path: Path
filename: str
label: str
timestamp: datetime
size_bytes: int
backend: str
base64: str | None
metadata: dict
Artifacts are written to out_dir (default: .artifacts/screenshots/) with the
naming pattern:
{label}_{ISO-8601-timestamp}.png
where timestamp colons are replaced with hyphens for filesystem compatibility.
Backend Detection & Fallback
The capture functions probe available backends at import time:
playwright — preferred for URL captures; falls back to pillow if not installed.
pillow — used for desktop / window captures; required for terminal captures.
terminal — activated only when --terminal / capture_terminal() is called.
Install the recommended extras:
uv add playwright && playwright install chromium
uv add Pillow python-xlib
uv add Pillow pygetwindow
uv add Pillow pyte
Key Files
| Path | Purpose |
|---|
harness_skills/screenshot.py | Core capture logic — ScreenshotArtifact, ScreenshotOptions, SequenceCapture, all capture_* helpers. |
harness_skills/screenshot_agent.py | Agent SDK interface — build_screenshot_tools, run_screenshot_agent, MCP tool definitions. |
skills/screenshot/scripts/capture_screenshot.py | Standalone CLI helper; runs without installing the package. |