CLI reference.
Share HTML mockups from any coding agent. Collect element-level annotations. Feed them back into the loop.
Quickstart
Push your first mockup to a public URL in under two minutes.
Requires Node.js. Install globally so agents can call it directly.
One-time setup. Requires a beta invite code.
Registered as Ada.
API key saved to ~/.peekable/config.json
Next step: run `peekable init` to complete setup.
Verifies server connectivity and installs the agent skill.
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"
{"id":"8jYX99tcWr","name":"Homepage v2","mode":"static","url":"https://peekable.fyi/s/8jYX99tcWr"}
$ peekable push 8jYX99tcWr ./out.html
Pushed v1 to 8jYX99tcWr
Reviewers open the URL, click elements to annotate, and submit. The agent watches for incoming feedback.
Watching session 8jYX99tcWr for annotations...
📝 Ada submitted annotations on v1
Run: /peekable review 8jYX99tcWr
# 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
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.
| Flag | Required | Default | Description |
|---|---|---|---|
| --name <name> | required | — | Display name |
| --email <email> | required | — | Email address |
| --invite-code <code> | $PEEKABLE_INVITE_CODE | Beta invite code | |
| --url <url> | https://peekable.fyi | Server URL | |
| --json | false | Output JSON |
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"}
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.
| Flag | Required | Default | Description |
|---|---|---|---|
| --json | false | Output 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.
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"
| Flag | Required | Default | Description |
|---|---|---|---|
| <name> | required | — | Session name (positional) |
| --json | false | Output JSON |
Created session: 8jYX99tcWr
URL: https://peekable.fyi/s/8jYX99tcWr
| Flag | Required | Default | Description |
|---|---|---|---|
| <session-id> | required | — | Session ID |
| <file> | required | — | Standalone HTML file path |
| --json | false | Output 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.
Pushed v2 to 8jYX99tcWr
| Flag | Required | Default | Description |
|---|---|---|---|
| <session-id> | required | — | Session ID |
| <url> | required | — | URL that returns an HTML response |
| --allow-remote | false | Allow snapshotting a non-localhost URL | |
| --allow-private | false | Allow snapshotting a private-network URL | |
| -y, --yes | false | Confirm the fetched HTML can be uploaded | |
| --json | false | Output JSON |
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.
Pushed v3 to 8jYX99tcWr from http://localhost:3000/dashboard
| Flag | Required | Default | Description |
|---|---|---|---|
| <port> | required | — | Local 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 | |
| --takeover | false | Take over an existing relay connection | |
| --json | false | Output 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.
$ 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.
| Flag | Required | Default | Description |
|---|---|---|---|
| <session-id> | required | — | Session 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).
Watching session 8jYX99tcWr for annotations...
📝 Ada submitted annotations on v1
Run: /peekable review 8jYX99tcWr
Disconnected. Reconnecting in 1s...
| Flag | Required | Default | Description |
|---|---|---|---|
| <session-id> | required | — | Session ID |
| --json | false | Output 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.
Annotations:
--- Version 1 ---
[Ada] Button (.btn-primary)
"The contrast ratio is too low here."
Styles: background-color: #ccc, color: #fff
| Flag | Required | Default | Description |
|---|---|---|---|
| <session-id> | required | — | Session ID |
| <annotation-ids...> | required | — | One or more annotation IDs (variadic) |
| --json | false | Output JSON |
Resolve before pushing — the server broadcasts annotations_resolved to all connected viewers, which updates their overlay pins in real time.
Resolved 2 annotation(s).
| Flag | Required | Default | Description |
|---|---|---|---|
| --json | false | Output JSON |
Active sessions (2 / 3):
8jYX99tcWr Homepage v2 (6/15/2026)
xK9m2qHpLc Dashboard preview (6/28/2026)
| Flag | Required | Default | Description |
|---|---|---|---|
| <session-id> | required | — | Session ID |
| --json | false | Output JSON: {"ok":true} |
Closed session 8jYX99tcWr
| Flag | Required | Default | Description |
|---|---|---|---|
| --json | false | Output JSON report | |
| --test-push | false | Create, 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 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
| Flag | Required | Default | Description |
|---|---|---|---|
| [message...] | prompt | Message to send. If omitted, prompts on stdin. | |
| --no-diagnostics | diagnostics on | Opt out of sending the scalar doctor snapshot | |
| --json | false | Output 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.
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.
| Flag | Required | Default | Description |
|---|---|---|---|
| --json | false | Output 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.
# 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:
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:
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.
{"id":"8jYX99tcWr","name":"Nav redesign","mode":"static","url":"https://peekable.fyi/s/8jYX99tcWr"}
$ peekable push 8jYX99tcWr ./nav.html --json
{"version":1}
Agent runs peekable watch <session-id> and waits. When a reviewer submits annotations, a notification fires.
Run: /peekable review 8jYX99tcWr
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.
{"feedback":[],"annotations":[{"version":1,"items":[{"id":"ann_id1","selector":".btn-primary","element_name":"Button","note":"Contrast too low","element_context":{...},"viewer":"Ada","created_at":"..."}]}]}
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."
Resolved 1 annotation(s).
$ peekable push 8jYX99tcWr ./nav.html --json
{"version":2}
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_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.
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.
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.
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.
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.
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.
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.
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.
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:
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. |
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.