Query Your Visitors From the CLI (No Dashboard Required)
The Eyepup CLI is a single binary you install once and run from any terminal. It exposes the same per-visitor AI dossier data as the dashboard — list visitors, fetch a dossier, list friction patterns, get the evidence video, watch live traffic — all as plain shell commands. It works inside any AI agent that can run shell (Claude Code, Cursor, Aider, Continue, plain ChatGPT-with-shell-access).
Key takeaways
- The CLI is the lowest-friction surface for agent integration — anything that runs
bashcan runeyepup. - Same data as the dashboard. Same auth as the dashboard. Different surface.
- Designed to be piped, scripted, and chained —
--jsonoutput, exit codes, no decorations. - Free during private beta. Open-source CLI on GitHub.
Install
npm install -g eyepup
(The CLI is a single Node.js package — Node 18 or newer. Brew tap and one-line installer are coming.)
Verify:
$ eyepup --version
eyepup 0.4.2
Authenticate
$ eyepup login
✓ Open https://eyepup.com/cli-auth?code=ABCD-EFGH in your browser
✓ Logged in as eduard@eyepup.com (team: Eyepup)
The CLI uses device-flow auth — no manual API key needed. Tokens are stored in ~/.config/eyepup/credentials.json (mode 0600) and rotate automatically.
Command reference
eyepup whoami
$ eyepup whoami
team: Eyepup (acme-prod)
user: eduard@eyepup.com
role: admin
sites: eyepup.com, app.eyepup.com
eyepup visitors
List visitors with filters.
# Last 24h, filtered to "blocked by price"
$ eyepup visitors --recent 24h --filter blocked-by:price
# Filter by site
$ eyepup visitors --site eyepup.com
# Filter by email
$ eyepup visitors --filter email:sarah@acme.com
# JSON output for scripting
$ eyepup visitors --recent 7d --json | jq '.[] | .blocked_by'
# Pipe to fzf for interactive picking
$ eyepup visitors --recent 24h | fzf | awk '{print $1}' | xargs eyepup dossier
eyepup dossier <id>
Fetch one visitor's full AI dossier.
$ eyepup dossier 0xae1b
Visitor 0xae1b… landed on /pricing from a Reddit referral.
Spent 92s on the page, hovered the annual toggle 3× without
clicking it, opened the FAQ once, scrolled to the bottom, then
back to the hero CTA, then left.
Blocked-by: price uncertainty (medium confidence)
Suggested fix: surface the annualized price next to the monthly
price by default
Channel: organic / Reddit
Heat score: 72 / 100
Sessions: 1
Evidence: eyepup evidence 0xae1b (28s mp4)
eyepup patterns
Aggregated friction patterns across all visitors.
$ eyepup patterns --week-over-week
Top friction patterns this week:
▲ +12 price uncertainty (47 visitors)
▼ -3 form length (12 visitors)
▲ +5 mobile CTA hidden (8 visitors)
↔ 0 trust signal weak (6 visitors)
# JSON output for scripting
$ eyepup patterns --since 30d --json
eyepup paths
Most-traveled friction paths.
$ eyepup paths --since 7d --top 5
1. /landing → /pricing → bounce (124 visitors, 38% drop)
2. /signup → step 2 → bounce ( 71 visitors, 22% drop)
3. /pricing → /pricing → /pricing → bounce ( 44 visitors, "thrash" pattern)
4. /demo → /pricing → bounce ( 31 visitors, message mismatch)
5. /home → /features → /pricing → bounce ( 28 visitors, FOMO bail)
eyepup evidence <session-id>
Print the URL of the rendered MP4 the AI watched.
$ eyepup evidence 0xae1b
https://evidence.eyepup.com/<presigned-url>.mp4
# Open in default video player
$ eyepup evidence 0xae1b --open
# Pipe through ffmpeg, mpv, etc.
$ eyepup evidence 0xae1b --json | jq -r .url | xargs mpv
eyepup live
Stream new visitors as they arrive.
$ eyepup live
[14:32:01] new visitor 0xc4e8 /pricing from /
[14:32:14] new visitor 0xa19a /home from twitter.com
[14:33:02] friction 0xc4e8 hovered annual toggle, 4s dwell
[14:33:18] dossier 0xc4e8 blocked by price uncertainty
[14:34:01] conversion 0x99fb signed up (sarah@acme.com)
eyepup funnels
Funnel-level metrics.
$ eyepup funnels signup
Funnel: signup (last 7d)
Step 1 — landing : 1,247 visitors
Step 2 — clicked CTA : 894 (71.7%)
Step 3 — form opened : 612 (49.0%)
Step 4 — submitted : 328 (26.3%)
Step 5 — verified : 247 (19.8%)
Top friction at step 3 → 4: form length (47 visitors)
eyepup config
Manage local CLI settings.
$ eyepup config get default-site
$ eyepup config set default-site eyepup.com
$ eyepup config list
Workflows
Workflow 1 — agent-driven debugging
# Inside Claude Code
You: A customer says they couldn't sign up. Email: sarah@acme.com.
Claude: $ eyepup visitors --filter email:sarah@acme.com --json
$ eyepup dossier <her-id>
Found her: stuck on company-size dropdown, hidden below
the fold on mobile. Bug at /signup line 84.
Workflow 2 — CI sanity check
A GitHub Action that fails the build if a regression-class friction pattern shows up after deploy:
# .github/workflows/post-deploy.yml
- name: Wait 10 minutes for traffic
run: sleep 600
- name: Check for regression patterns
run: |
NEW_PATTERNS=$(eyepup patterns --since 30m --json \
| jq '[.[] | select(.delta > 5)] | length')
if [ "$NEW_PATTERNS" -gt 0 ]; then
echo "::error::Detected $NEW_PATTERNS new friction patterns"
eyepup patterns --since 30m
exit 1
fi
Workflow 3 — Slack standup digest
Cron job that posts the previous day's friction patterns to Slack:
#!/usr/bin/env bash
set -euo pipefail
DIGEST=$(eyepup patterns --since 24h --week-over-week)
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"\`\`\`$DIGEST\`\`\`\"}" \
"$SLACK_WEBHOOK_URL"
Workflow 4 — pipe into fzf for human review
$ eyepup visitors --recent 7d \
| fzf --preview 'eyepup dossier {1}' \
| awk '{print $1}' \
| xargs eyepup evidence --open
Picks a visitor interactively, previews the dossier, and opens the evidence MP4.
Output formats
All commands support --json for machine output:
$ eyepup visitors --recent 24h --json | jq '.[] | select(.heat > 80)'
$ eyepup patterns --since 7d --json > patterns.json
$ eyepup dossier 0xae1b --json | jq -r '.suggested_fix'
Default output is human-readable, color-aware, and respects NO_COLOR=1 for CI logs.
Authentication and security
- Tokens stored in
~/.config/eyepup/credentials.json, mode 0600 - Tokens rotate automatically; manual rotate with
eyepup login --force - Tokens inherit role of the user who created them
- All traffic to
api.eyepup.comover HTTPS eyepup logoutclears local credentials and revokes the token server-side
Frequently asked questions
Does the CLI need Eyepup-specific authentication?
The first time you run eyepup login, it opens a browser for a device-flow handshake — same OAuth pattern as vercel login or gh auth login. After that, every command uses the locally cached token. No manual API key copying.
Can I use it inside Docker / GitHub Actions?
Yes. Generate a long-lived API token from the dashboard (Settings → API tokens), set EYEPUP_API_KEY=<token> in the env, and the CLI uses it instead of the device-flow credentials. Works in CI.
Is there a Python or TypeScript SDK?
Not yet — the CLI plus a stable HTTP API covers most use cases. SDKs are on the roadmap.
Why a CLI instead of just a REST API?
Because every AI coding agent already knows how to run bash. None of them know how to call your custom REST API without you teaching them. A CLI is the lowest-friction agent surface on the planet.
Can I script live alerts?
Yes — eyepup live streams events as they arrive, one per line, machine-readable with --json. Pipe into awk, jq, or any alert system.
Can I use the CLI without an AI agent?
Of course. Plenty of humans run eyepup live in a terminal pane while debugging. Some teams use it as a literal "live ops feed" during launches.
