docs REFERENCE

CLI reference.

Share HTML mockups from any coding agent. Collect element-level annotations. Feed them back into the loop.

$ npm install -g peekable
v0.1.3 · package: peekable · binary: peekable · config: ~/.peekable/config.json

Quickstart

Push your first mockup to a public URL in under two minutes.

1
Install the CLI

Requires Node.js. Install globally so agents can call it directly.

$ npm install -g peekable
2
Register and get an API key

One-time setup. Requires a beta invite code.

$ peekable register --name "Ada" --email ada@example.com --invite-code abc123
Registered as Ada.
API key saved to ~/.peekable/config.json

Next step: run `peekable init` to complete setup.
3
Run init

Verifies server connectivity and installs the agent skill.

$ peekable init
Connection verified.
Claude Code /peekable skill installed.
Codex not detected — skipping skill install.
Test push verified.

Ready to go.

Installed agent skills:
- Claude Code: use the /peekable skill

Example prompts:
- "Use Peekable to share ./mockups/home.html"
- "Use Peekable to proxy localhost:3000 for review"
4
Create a session and push a file
$ peekable create "Homepage v2" --json
{"id":"8jYX99tcWr","name":"Homepage v2","mode":"static","url":"https://peekable.fyi/s/8jYX99tcWr"}

$ peekable push 8jYX99tcWr ./out.html
Pushed v1 to 8jYX99tcWr
5
Share the URL and wait for annotations

Reviewers open the URL, click elements to annotate, and submit. The agent watches for incoming feedback.

$ peekable watch 8jYX99tcWr
Watching session 8jYX99tcWr for annotations...

📝 Ada submitted annotations on v1
   Run: /peekable review 8jYX99tcWr
6
Fetch feedback, implement changes, resolve, push
$ peekable feedback 8jYX99tcWr --json
# agent reads annotations, implements them
$ peekable resolve 8jYX99tcWr ann_id1 ann_id2
Resolved 2 annotation(s).
$ peekable push 8jYX99tcWr ./out.html
Pushed v2 to 8jYX99tcWr
NOTE

Most commands support --json for machine-readable output. peekable watch streams human-readable notifications; agents should leave it running and parse review data with peekable feedback --json.

Command reference

One block per command. Options marked required are enforced at parse time.

register Register for an API key
peekable register --name <name> --email <email> [--invite-code <code>] [--url <url>] [--json]
FlagRequiredDefaultDescription
--name <name>requiredDisplay name
--email <email>requiredEmail address
--invite-code <code>$PEEKABLE_INVITE_CODEBeta invite code
--url <url>https://peekable.fyiServer URL
--jsonfalseOutput JSON
$ peekable register --name "Ada" --email ada@example.com --invite-code abc123
Registered as Ada.
API key saved to ~/.peekable/config.json

Next step: run `peekable init` to complete setup.

# --json output on success:
{"api_key": "sk-...", "url": "https://peekable.fyi", "name": "Ada"}
NOTE

Config is written to ~/.peekable/config.json. Delete this file to re-register. Invite code can also be set via the PEEKABLE_INVITE_CODE environment variable.

init Set up peekable — install Claude Code/Codex skills and verify connection
peekable init [--json]
FlagRequiredDefaultDescription
--jsonfalseOutput JSON

Checks server connectivity, installs the /peekable skill for any detected agent (~/.claude/ → Claude Code, ~/.codex/ → Codex), then runs a test push to verify end-to-end access.

$ peekable init
Connection verified.
Claude Code /peekable skill installed.
Codex not detected — skipping skill install.
Test push verified.

Ready to go.

Installed agent skills:
- Claude Code: use the /peekable skill

Example prompts:
- "Use Peekable to share ./mockups/home.html"
- "Use Peekable to proxy localhost:3000 for review"
create Create a new sharing session
peekable create <name> [--json]
FlagRequiredDefaultDescription
<name>requiredSession name (positional)
--jsonfalseOutput JSON
$ peekable create "Homepage v2"
Created session: 8jYX99tcWr
URL: https://peekable.fyi/s/8jYX99tcWr
push Push a standalone HTML file as a new version
peekable push <session-id> <file> [--json]
FlagRequiredDefaultDescription
<session-id>requiredSession ID
<file>requiredStandalone HTML file path
--jsonfalseOutput JSON

Use for complete HTML documents with their own <html>/<body> shell. Files without those tags trigger a fragment warning and a suggestion to use push-url or proxy instead. Each push creates a new version; connected viewers auto-reload.

$ peekable push 8jYX99tcWr ./out.html
Pushed v2 to 8jYX99tcWr
push-url Fetch an HTML response from a URL and push it as a new version
peekable push-url <session-id> <url> [--allow-remote] [--allow-private] [-y] [--json]
FlagRequiredDefaultDescription
<session-id>requiredSession ID
<url>requiredURL that returns an HTML response
--allow-remotefalseAllow snapshotting a non-localhost URL
--allow-privatefalseAllow snapshotting a private-network URL
-y, --yesfalseConfirm the fetched HTML can be uploaded
--jsonfalseOutput JSON
NOTE

Does not execute JavaScript, use browser cookies, or inline external assets. Fetch timeout: 30 s. Max response: 5 MB. Remote URLs require --allow-remote --yes because the fetched HTML is uploaded to the session.

$ peekable push-url 8jYX99tcWr http://localhost:3000/dashboard
Pushed v3 to 8jYX99tcWr from http://localhost:3000/dashboard
proxy Proxy a local dev server through a peekable share URL
peekable proxy <port> [--name <name>] [--session <id>] [--watch <dir>] [--takeover] [--json]
FlagRequiredDefaultDescription
<port>requiredLocal port (1–65535)
--name <name>"Proxy"Session name
--session <id>Reuse an existing session ID
--watch <dir>Watch directory and trigger reload on file changes
--takeoverfalseTake over an existing relay connection
--jsonfalseOutput JSON: {"id":"...","url":"..."}

Tunnels HTTP requests from the public share URL to your local port in real time via a WebSocket relay. Useful for React, Vite, Next.js, and other dev servers with routes and client-side assets. File change debounce: 500 ms. Proxy response cap: 25 MB.

# With --json: only the JSON line is emitted (status lines are suppressed)
$ peekable proxy 3000 --name "Dashboard preview" --watch ./src --json
{"id":"xK9m2qHpLc","url":"https://xK9m2qHpLc.peekable.fyi"}

# Without --json: human-readable status lines follow
$ peekable proxy 3000 --name "Dashboard preview" --watch ./src
Share URL: https://xK9m2qHpLc.peekable.fyi
Relay connected. Waiting for viewers...

File change detected, reload triggered.
watch Watch for annotation notifications on a session
peekable watch <session-id>
FlagRequiredDefaultDescription
<session-id>requiredSession ID to watch

Opens a persistent WebSocket connection. Prints a notification and run-hint when a reviewer submits annotations. Reconnects automatically on disconnect with exponential backoff (1 s → 30 s max).

$ peekable watch 8jYX99tcWr
Watching session 8jYX99tcWr for annotations...

📝 Ada submitted annotations on v1
   Run: /peekable review 8jYX99tcWr

Disconnected. Reconnecting in 1s...
feedback Fetch feedback for a session
peekable feedback <session-id> [--json]
FlagRequiredDefaultDescription
<session-id>requiredSession ID
--jsonfalseOutput JSON (merged annotations + choice events)

Fetches both element-level annotations and data-choice click events in parallel, grouped by version. Use --json for structured agent consumption; the JSON output includes element_context (selector, computed styles, bounding box) alongside each annotation note.

$ peekable feedback 8jYX99tcWr

Annotations:

--- Version 1 ---
  [Ada] Button (.btn-primary)
    "The contrast ratio is too low here."
    Styles: background-color: #ccc, color: #fff
resolve Mark annotations as resolved
peekable resolve <session-id> <annotation-ids...> [--json]
FlagRequiredDefaultDescription
<session-id>requiredSession ID
<annotation-ids...>requiredOne or more annotation IDs (variadic)
--jsonfalseOutput JSON

Resolve before pushing — the server broadcasts annotations_resolved to all connected viewers, which updates their overlay pins in real time.

$ peekable resolve 8jYX99tcWr ann_id1 ann_id2
Resolved 2 annotation(s).
list List active sessions
peekable list [--json]
FlagRequiredDefaultDescription
--jsonfalseOutput JSON
$ peekable list
Active sessions (2 / 3):
  8jYX99tcWr  Homepage v2  (6/15/2026)
  xK9m2qHpLc  Dashboard preview  (6/28/2026)
close Close a session
peekable close <session-id> [--json]
FlagRequiredDefaultDescription
<session-id>requiredSession ID
--jsonfalseOutput JSON: {"ok":true}
$ peekable close 8jYX99tcWr
Closed session 8jYX99tcWr
doctor Print a support snapshot for debugging Peekable setup
peekable doctor [--json] [--test-push]
FlagRequiredDefaultDescription
--jsonfalseOutput JSON report
--test-pushfalseCreate, push, and close a temporary test session

Safe for pasting in support requests — output redacts config paths to ~ and never includes API keys, HTML payloads, or annotation text.

$ peekable doctor --test-push
Peekable CLI: 0.1.4
Node: v22.4.0
Config: ~/.peekable/config.json
Server: https://peekable.fyi reachable
Auth: valid
Active sessions: 2 / 3
Test push: ok
report Report a problem or send feedback to the Peekable team
peekable report [message...] [--no-diagnostics] [--json]
FlagRequiredDefaultDescription
[message...]promptMessage to send. If omitted, prompts on stdin.
--no-diagnosticsdiagnostics onOpt out of sending the scalar doctor snapshot
--jsonfalseOutput JSON

Requires registration. Peekable prints the exact payload (message + scalar diagnostics) before sending. Diagnostics are scalar-only (statuses, versions, os/arch/node) — no raw error messages, emails, or paths.

$ peekable report "watch reconnects every few seconds"
Sending report:
{
  "message": "watch reconnects every few seconds",
  "diagnostics": { "cli_version": "0.1.5", "os": "darwin", "arch": "arm64", ... }
}
Report submitted. Thanks — we read every one.
uninstall Remove local Peekable config and installed Claude Code skill
peekable uninstall [--json]
FlagRequiredDefaultDescription
--jsonfalseOutput JSON

Removes ~/.peekable/, ~/.claude/skills/peekable/, and ~/.codex/skills/peekable/. Does not delete hosted sessions or account data. To also remove the CLI package, run npm uninstall -g peekable afterward.

$ peekable uninstall
# Paths are printed in full (no redaction) — exact value differs per user
Peekable config: removed (/Users/you/.peekable)
Claude Code skill: removed (/Users/you/.claude/skills/peekable)
Codex skill: not found (/Users/you/.codex/skills/peekable)

To remove the CLI package, run: npm uninstall -g peekable
This only removes local Peekable files. It does not delete hosted sessions or account data.
For hosted account or data deletion, contact support.

Agent integration

What peekable init installs, how agents discover the skill, and the full review loop.

Skill detection and install

Running peekable init copies SKILL.md from the npm package into the detected agent's skill directory:

Claude Code

Detected when ~/.claude/ exists. Skill installed to ~/.claude/skills/peekable/SKILL.md. Invoke with /peekable.

Codex

Detected when ~/.codex/ exists. Skill installed to ~/.codex/skills/peekable/SKILL.md. Invoke with $peekable.

Trigger keywords

The skill activates when the user says any of:

"share this"  ·  "share with"  ·  "/share"  ·  "/peekable"  ·  "peekable"
or when the user wants a collaborator to review a mockup

The review loop

The skill encodes a deterministic push → watch → review → resolve → push cycle:

1
Share

Agent creates a session (or reuses one for the same topic), inspects the file, then pushes: push for standalone documents with <html>/<body>, push-url for fragments backed by a running page, proxy for live dev servers.

$ peekable create "Nav redesign" --json
{"id":"8jYX99tcWr","name":"Nav redesign","mode":"static","url":"https://peekable.fyi/s/8jYX99tcWr"}
$ peekable push 8jYX99tcWr ./nav.html --json
{"version":1}
2
Watch

Agent runs peekable watch <session-id> and waits. When a reviewer submits annotations, a notification fires.

📝 Ada submitted annotations on v1
   Run: /peekable review 8jYX99tcWr
3
Review

Agent fetches feedback and presents annotations grouped by reviewer with element name, CSS selector, note, and computed styles. Prompts the developer to approve all, one by one, or skip.

$ peekable feedback 8jYX99tcWr --json
{"feedback":[],"annotations":[{"version":1,"items":[{"id":"ann_id1","selector":".btn-primary","element_name":"Button","note":"Contrast too low","element_context":{...},"viewer":"Ada","created_at":"..."}]}]}
4
Resolve then push

For each implemented annotation, agent calls resolve before pushing the next version. Viewers' overlay pins update in real time. Then push — browser auto-reloads. Agent prints a summary like: "Pushed v3 with 2 changes. 1 annotation skipped."

$ peekable resolve 8jYX99tcWr ann_id1
Resolved 1 annotation(s).
$ peekable push 8jYX99tcWr ./nav.html --json
{"version":2}
TIP

Always use --json in agent contexts and parse the result. Reuse existing sessions when iterating on the same topic — each push creates a new version and auto-reloads viewers. If session creation returns a limit error, run peekable list --json, close stale sessions, and retry.

Telemetry

Peekable CLI sends anonymous usage/failure telemetry to improve reliability. Opt out by setting PEEKABLE_NO_TELEMETRY=1.

Environment variable config

SHARE_URL and SHARE_API_KEY are both required to override ~/.peekable/config.json; SHARE_NAME is optional and defaults to "User":

SHARE_URL=https://peekable.fyi
SHARE_API_KEY=sk-...
SHARE_NAME=Ada  # defaults to "User" if absent

Sessions & versions

The core data model behind every push, proxy, and public URL.

Static session

Created by create + push / push-url. Each push appends a version (v1, v2, ...). The server always serves the latest version. Viewers auto-reload on push via WebSocket.

URL: peekable.fyi/s/<id>
ID: 10-char nanoid

Proxy session

Created by proxy <port>. Requests are relayed in real time via WebSocket tunnel — no version concept. Cannot accept push.

URL: <id>.peekable.fyi
ID: 10-char lowercase alphanumeric

Versions

Static sessions only. Auto-incrementing integer per push. Annotations are scoped to a version. Viewers always see the latest version and receive a live reload when a new one arrives.

Injected status bar shows current version.
Annotations: stored per version.

Session lifecycle

Sessions remain open until explicitly closed. Closing returns HTTP 410 to viewers. No automatic expiry. Close stale sessions to stay within your active session limit.

peekable close <session-id>

Feedback model

Two parallel mechanisms: element-level annotations and data-choice click events.

Annotations

Reviewers enter annotate mode in the injected overlay, click an element, type a note, and submit. Each annotation captures the CSS selector, element name, note text, computed styles, bounding box, and viewport context.

Max 50 annotations per batch.
Note: max 2000 chars.
Status: pending → resolved.

Choice events

Elements marked with data-choice attributes record a click event when a viewer interacts with them. Useful for A/B feedback ("which layout?") on static mockups.

Retrieved via: peekable feedback <id>
Stored in events table, grouped by version.

Draft persistence

Annotation drafts are stored in the reviewer's browser localStorage keyed by session ID and version. Drafts older than 7 days are pruned automatically on load.

Key: peekable-annotations-{sessionId}-v{version}
Cleared after successful batch submit.

Real-time sync

On submission, the server broadcasts annotations_submitted to all WebSocket viewers — this is what peekable watch listens for. After resolve, annotations_resolved updates the overlay pins for all viewers.

peekable watch <id>

View secrets & API keys

How access to shared sessions is controlled.

View secrets

Static sessions can be protected with a view secret. The secret is encoded in the share URL fragment — it never reaches the server in the URL path:

https://peekable.fyi/s/<id>#k=<secret>

The browser reads the fragment, auto-submits it to the unlock endpoint, and receives a signed cookie valid for 24 hours. Rotating the secret immediately invalidates all existing viewer cookies and disconnects active viewers. View secrets apply to static sessions only; proxy sessions do not support them.

API keys

Generated at registration as sk- + 32 random characters. Passed as a bearer token on all owner-authenticated requests. Stored in ~/.peekable/config.json. Do not share your API key — it grants full owner access to all your sessions.

Invite codes

Registration is invite-gated during early access. Codes are single-use. Supply yours with --invite-code or via the PEEKABLE_INVITE_CODE environment variable.

Limits

Default limits for the hosted service during early access.

Limit Value Notes
Active sessions per user 3 HTTP 403 (active_session_limit_reached) when exceeded. Founding Creator plan: unlimited.
Concurrent viewers per session 2 HTTP 423 (HTTP) or 503 (WebSocket) when at capacity.
push-url max response size 5 MB CLI enforced. Fetch timeout: 30 s.
Proxy response cap 25 MB Per upstream response relayed to viewer.
Annotations per batch 50 Server enforced. One batch per "Submit" click.
Annotation note length 2 000 chars Per annotation.
View secret length 8–200 chars Auto-generated: 24 URL-safe characters.
Proxy in-flight requests 100 Per relay session. Per-request timeout: 30 s.
Session TTL none Sessions remain open until explicitly closed.
TIP

If create or proxy returns a session limit error, run peekable list --json, identify stale sessions, and close them with peekable close <id>. Run peekable doctor to see your current usage at a glance.