Peek

Date
2026-05-02
Status
Shipped — released and in use
Source
github.com/richardsummerville/peek-mcp

A small Swift binary that does one thing — take a screenshot of a display, a window, or a region — and exposes it through two interfaces. As a CLI for terminal use, and as a Model Context Protocol server so Claude (Code, Desktop, Cursor) can see your screen and ask follow-up questions about what’s there. Captures come back to the model as inline image content; no temporary files, no path round-trips.

Built on ScreenCaptureKit, the modern macOS capture API. Single Swift package, one external dependency (swift-argument-parser). MIT licensed.

Why this exists

Working with Claude on UI is the obvious case. The model can read the code and predict what should render, but only a screenshot tells you what actually renders. Before Peek, that gap was filled by manually screenshotting, copying into the conversation, describing context. Now the model just calls capture_window and gets the answer.

Beyond UI work, the same primitive is useful for asking the model to read what’s on screen — Obsidian, a Figma frame, a browser tab, a PDF in Preview — without leaving the terminal.

Capabilities

The MCP server advertises five tools:

ToolArgsReturns
list_windowsinclude_offscreen?JSON list
list_displaysJSON list
capture_windowwindow_id or app_name, plus hide_cursor?, force?, format?inline image
capture_displaydisplay_id?, hide_cursor?, format?inline image
capture_regionx, y, width, height, display_id?, hide_cursor?, format?inline image

The CLI mirrors the same surface: peek windows, peek displays, peek window <app>, peek display, peek region. PNG by default; JPEG via --format or environment.

Quality presets

Lossless PNG is the default — sharp UI text, no JPEG artifacts — at the cost of larger responses. For interactive use where speed matters more than fidelity, the PEEK_QUALITY environment variable swaps presets:

  • fast — JPEG q=0.5, 768 px cap, ~80 KB per capture
  • balanced — JPEG q=0.7, 1024 px cap, ~150 KB
  • lossless — PNG, 2048 px cap, ~1 MB (default)

Per-call overrides via the format argument supersede the preset.

Install + setup

brew install richardsummerville/tap/peek
peek install            # wires Peek into Claude Code and Claude Desktop config

peek install writes the right mcpServers entry into ~/.claude.json and Claude Desktop’s config file. After that, restart the Claude host fully (Cmd-Q + reopen) and grant Screen Recording permission to the host application — not to the Peek binary itself, since ScreenCaptureKit checks the launching process.

peek doctor runs a diagnostic that reports permission status, host configuration, and the active quality preset, with a --open-settings flag that jumps straight to the Privacy panel.

Audit and observability

Every capture (CLI or MCP) is logged as a JSONL entry under the user’s data directory — useful when an agent has been running unattended and you want to see what it actually saw. A menu-bar status item shows the last capture, the five most recent, and a shortcut to the audit log.

peek log tail, peek log tail -n 100, peek log path, peek log clear --yes are the relevant CLI commands.

Implementation notes

  • Single Swift package — no Xcode project file. make install builds release and copies to /usr/local/bin. Homebrew formula is the recommended path.
  • A small deny-list (1Password, Keychain Access, Authy, etc.) blocks window captures of sensitive apps by default; force: true overrides per call.
  • TCC quirks around Homebrew binaries are handled in peek doctor — when macOS treats the brewed binary as a distinct TCC subject, the diagnostic prints the exact resolution steps.
  • The MCP transport is stdio. The same binary serves the CLI and the MCP server; mode is selected by command (peek serve for MCP).