Skip to main content

Let AI agents see your UI — point at elements, annotate, and get instant visual context for AI-powered code editing.

Project description

Peek

Point at your UI. Your AI agent sees it.

Why

AI coding agents can edit code, but they can't see your page. You end up describing layouts in words, copy-pasting HTML, or dragging screenshots into chat.

Peek fixes this. Your AI agent can screenshot any local page on its own. You can also point at specific elements with a bookmarklet, and the agent gets the screenshot plus element data (selectors, styles, bounding boxes).

Quick Start

Claude Code (CLI or VS Code) — recommended

# 1. Install uv (one-time, manages Python for you)
brew install uv
# or: curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. Install peek (uv auto-downloads a compatible Python)
uv tool install peek-mcp

# 3. One-shot setup
peek setup

peek setup is one-shot: installs Playwright Chromium, registers Peek as an MCP server in Claude Code (user scope, all projects), drops the bookmarklet page at ~/.peek/bookmarklet.html and opens it in your browser. Drag the blue button to your bookmark bar and you're done — the command exits on its own. Nothing to keep running.

From then on: open Claude Code and use it normally. It auto-launches Peek in the background whenever the agent uses a Peek tool.

Using pip directly? pip install peek-mcp works too, but requires Python 3.10+ already installed. uv tool install avoids the version-mismatch headache.

Upgrading

uv tool upgrade peek-mcp
pkill -f "peek mcp"            # or: quit + reopen Claude Code
# then: reload any browser tab that had Peek loaded

Three steps because three layers hold a copy of the code: disk (fixed by uv tool upgrade), the running peek mcp process (fixed by the kill/restart), and any browser page that already loaded the old inspector.js (fixed by a page reload). From v0.5.0 onward, Peek detects a stale inspector.js automatically and alerts you to reload — so if you forget step 3, you'll see a prompt the next time you click the bookmarklet.

Don't run peek setup to upgrade. peek setup is for first-time installs. From v0.5.4 it detects an existing install and exits cleanly, but earlier versions would re-walk you through the bookmarklet drag flow unnecessarily.

Upgrading from v0.4 → v0.5.x: re-drag the blue button from ~/.peek/bookmarklet.html (or re-run peek setup, which opens it for you) once. The v0.4 bookmarklet JS had a caching gate that v0.5 removed. Future upgrades within the v0.5 line do not require re-dragging.

Other AI tools (Cursor / Windsurf / Claude Desktop)

uv tool install peek-mcp
playwright install chromium   # ~150 MB, one-time

Add to your MCP config file (e.g. .cursor/mcp.json, ~/.codeium/windsurf/mcp_config.json, or claude_desktop_config.json):

{
  "mcpServers": {
    "peek": {
      "command": "/absolute/path/to/peek",
      "args": ["mcp"]
    }
  }
}

Run which peek in your terminal to get the absolute path. Drag the bookmarklet from ~/.peek/bookmarklet.html (peek setup creates it) — no server needed.

Recommended: tell your agent your dev port

Add this to your project's CLAUDE.md (or .cursorrules, etc.):

Dev server runs on http://localhost:3000

When using Peek's screenshot tool and you don't know the dev server URL, ask me which port the app is running on before taking a screenshot.

Replace 3000 with your actual port. This prevents your agent from guessing the wrong port.

Use it

Agent-driven screenshots (no bookmarklet needed):

Just ask your agent — "screenshot the page", "take a look at localhost:3000", "check if the button looks right". The agent calls screenshot(url) directly.

User-pointed captures (bookmarklet):

  1. One-time: drag the blue button from ~/.peek/bookmarklet.html (or any other browser's copy of it) to your bookmark bar
  2. Start your AI tool (Claude Code / Cursor / etc.) — it launches peek in the background
  3. Open your app, click the bookmarklet, pick a mode:
Mode Shortcut You do Agent gets
Region Alt+R Drag a rectangle Screenshot + elements in that area
Element Alt+S Click an element Screenshot + selector, styles, HTML
Annotate Alt+A Draw (pen, box, arrow) Screenshot + your drawings + elements
  1. Tell your agent: "check what I just selected" — it calls get_user_selection()

Supported URLs

Peek works with local and LAN addresses:

URL Supported
http://localhost:3000 Yes
http://127.0.0.1:8080 Yes
http://0.0.0.0:5000 Yes
http://192.168.1.5:3000 Yes (LAN)
http://myapp.local:3000 Yes (.local domain)
http://myapp.test:8080 Yes (.test domain)
https://google.com No (public URLs blocked)

MCP Tools

Tool When to use
screenshot(url) Default — agent fetches any local/LAN URL in a fresh headless browser. Use for general "look at the page" requests, verifying code changes, etc.
get_user_selection() Reads what you captured with the bookmarklet — a region, element, or annotation. Use when you want the agent to see exactly what you pointed at, including any state that requires your interaction (login, uploaded data, clicked buttons).

For Element mode captures, the agent gets structural context to find the right code:

  • ancestor chain (body > main > section.settings > div.flex)
  • sibling position (2 of 3 <button> siblings)
  • nearest heading (h2: Settings)
  • parent layout (flex, row)

This means when you point at a button, the agent knows which button on which section — no guessing.

How It Works

Your AI agent calls screenshot(url)
    -> Playwright takes a fresh headless screenshot (stateless view)
    -> Agent sees the default render of the page

You point at something with the bookmarklet
    -> Bookmarklet renders your CURRENT browser view to PNG client-side
       (so login, uploaded data, clicked buttons are all preserved)
    -> Peek also grabs element metadata (selector, styles, DOM context)
    -> Agent calls get_user_selection() and sees what you see
    -> "The chart legend overlaps the bars. Fixing the CSS..."

One process, two jobs: MCP server talks to your AI agent over stdio, bridge server receives bookmarklet data on port 8899. peek mcp runs both.

Client-side rendering uses modern-screenshot (MIT, vendored at static/modern-screenshot.js). If it fails on an exotic page, the bridge falls back to the old Playwright re-fetch automatically. To force fallback globally, set PEEK_DOM_SNAPSHOT=0.

Troubleshooting

Playwright Chromium is not installed

Run playwright install chromium. This downloads the headless browser engine (~150 MB). Only needed once.

ERR_CONNECTION_REFUSED when taking a screenshot

Your dev server isn't running on that port. Start your dev server first, then ask the agent to screenshot. If you see this repeatedly, make sure the port in your CLAUDE.md matches your actual dev server.

Agent screenshots the wrong port

Add the CLAUDE.md snippet from step 3 above. Without it, the agent will guess.

Bookmarklet click does nothing

Peek's bridge server (which the bookmarklet talks to at localhost:8899) isn't running. Usually this means Claude Code isn't open — Claude Code is what launches peek mcp in the background. Options:

  • Open Claude Code. Once it starts, it auto-launches peek mcp. Reload your page, click the bookmarklet again.
  • Or run peek mcp in a terminal manually. Keep the terminal open while you use Peek. Ctrl+C when done.

To see what state Peek is in, run peek with no arguments — it prints install status and tells you what, if anything, to do next.

Need the bookmarklet page again

It lives at ~/.peek/bookmarklet.html after peek setup. Open that file in any browser and drag the blue button — no server required.

peek: command not found after install

If you used uv tool install peek-mcp, make sure ~/.local/bin is in your PATH. Run uv tool update-shell to fix it automatically, then open a new terminal.

If you used pip install peek-mcp, your Python scripts directory may not be in PATH. Find it with pip show peek-mcp | grep Location.

No matching distribution found for peek-mcp

Your Python is older than 3.10 (common on macOS system Python). Switch to uv tool install peek-mcp — uv downloads a compatible Python for you.

Using Peek from Safari, Firefox, or a different Chrome profile

The bookmarklet lives in each browser's bookmark bar independently — there's no cross-browser sync. To use it in another browser, open ~/.peek/bookmarklet.html in that browser and drag the blue "Peek" button to its bookmark bar. One-time setup per browser, and no server needed — it's a local file. The screenshot tool itself is browser-agnostic (it uses Playwright's own headless Chromium), so it works regardless of which browser you develop in.

Screenshot shows a blank or default page instead of what I see

screenshot(url) renders in a fresh headless session with no cookies or session data — it shows what an anonymous visitor would see, not your current view. If your page requires login, upload, or any user interaction to show its real content:

  • Click the Peek bookmarklet on the page you want captured, then ask the agent to check your selection. The bookmarklet renders your actual browser view to PNG client-side (since v0.5), so post-login / post-upload / post-interaction state is preserved.
  • If the bookmarklet capture itself looks off on an unusual page, try PEEK_DOM_SNAPSHOT=0 peek mcp to force the old Playwright re-fetch path. Or take an OS screenshot (Cmd+Shift+4 on macOS) and paste it directly into your chat.

Agent returns a screenshot that doesn't match what I'm looking at

get_user_selection returns the last bookmarklet capture, which could be from hours or days ago. The metadata includes an age_seconds field — if that number is large, the agent should recognize it and fall back to screenshot(url). To force a fresh capture, click the bookmarklet again on your current page.

Limitations

  • Local/LAN only. Public URLs are blocked for security (SSRF prevention).
  • screenshot(url) is stateless. It opens a fresh headless browser — no cookies, no login. For your actual session state, use the bookmarklet → get_user_selection().
  • Bookmarklet capture quality depends on the page. Most CSS renders faithfully; exotic features (WebGL, cross-origin iframes, playing videos) may render with gaps. Set PEEK_DOM_SNAPSHOT=0 to fall back to the Playwright re-fetch path if needed.
  • Peek does not survive a full page navigation. If you click a link that loads a new URL (not an in-place SPA route change), the bookmarklet-injected script is gone. Click the bookmarklet again on the new page to re-activate Peek. This is a fundamental property of bookmarklets — switching to a browser extension would remove this limitation (not planned).
  • Captures may contain sensitive data. Passwords and hidden inputs are redacted, but visible text and screenshots are saved as-is to ~/.peek/captures/. Peek keeps the 50 most recent captures automatically; older ones are pruned.

CLI

peek                      # status + next step (most users just need this)
peek setup                # one-shot: install, register MCP, drop bookmarklet page
peek mcp                  # advanced — Claude Code auto-launches this
peek mcp --port 9000      # advanced — different bridge port

Requirements

  • uv (recommended — manages Python for you) or Python 3.10+
  • Playwright Chromium (auto-installed by peek setup, or run playwright install chromium manually)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

peek_mcp-0.5.8.tar.gz (77.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

peek_mcp-0.5.8-py3-none-any.whl (47.6 kB view details)

Uploaded Python 3

File details

Details for the file peek_mcp-0.5.8.tar.gz.

File metadata

  • Download URL: peek_mcp-0.5.8.tar.gz
  • Upload date:
  • Size: 77.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for peek_mcp-0.5.8.tar.gz
Algorithm Hash digest
SHA256 c3c8654604c5affe942c9deacd12b55bf51666d2bd35afbfcca9f011bcb27e7a
MD5 bc66cd21d7fbbff76bb277443748f31f
BLAKE2b-256 9635187396abb97c5d982da32c718a98917635bd5d602f29ff5c574ae040be10

See more details on using hashes here.

File details

Details for the file peek_mcp-0.5.8-py3-none-any.whl.

File metadata

  • Download URL: peek_mcp-0.5.8-py3-none-any.whl
  • Upload date:
  • Size: 47.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for peek_mcp-0.5.8-py3-none-any.whl
Algorithm Hash digest
SHA256 97f7e1b6ea8f39c04251022fa2bb52c51510e6d306788179bf3257fec78039ec
MD5 55be480bbb411e200d4aa339705b3f9d
BLAKE2b-256 cd65ae748c8d4540cfe85615be04455c1ff5768203da3df8b68f13d143994c64

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page