simulator-automation
Automate the EvenHub glasses simulator via its HTTP API. Use when testing or controlling the simulator programmatically — sending glasses input (up, down, click, double click), capturing screenshots, or reading browser console logs.
How do I install this agent skill?
npx skills add https://github.com/even-realities/everything-evenhub --skill simulator-automationIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill facilitates automation of the EvenHub simulator via a local HTTP API. The primary security concern is the potential for indirect prompt injection, as the agent processes untrusted console logs and screenshots from simulated web applications.
- Socketpass
No alerts
- Snykpass
Risk: LOW · No issues
What does this agent skill do?
EvenHub Simulator Automation
The simulator exposes an HTTP API on localhost when launched with --automation-port <PORT>.
evenhub-simulator https://my-app.example.com --automation-port 9898
Base URL: http://127.0.0.1:<PORT>
API Reference
Health check
GET /api/ping
→ "pong"
Glasses screenshot
Returns the current LVGL framebuffer as image/png (576×288, RGBA).
GET /api/screenshot/glasses
→ image/png binary (RGBA)
RGBA format — critical for image analysis:
- Background pixels:
(R=0, G=255, B=0, A=0)— transparent (alpha = 0) - Lit/text pixels:
(R=0, G=255, B=0, A=255)— opaque (alpha = 255)
Always work in RGBA mode. Do NOT convert to RGB — it drops the alpha channel and makes background pixels indistinguishable from text pixels (both appear as pure green).
from PIL import Image
img = Image.open('glasses.png') # keep as RGBA — do NOT call img.convert('RGB')
pixels = img.load()
# Lit pixel test:
is_lit = lambda px: px[3] > 0 # alpha > 0
Webview screenshot
Captures the main browser webview using html2canvas. Returns image/png. May take a few seconds; times out after 10s.
GET /api/screenshot/webview
→ image/png binary
Console logs
Returns captured console.* output, uncaught exceptions, unhandled promise rejections, and failed fetch calls from the main webview.
GET /api/console
→ { "entries": [...], "total": N }
Each entry:
{ "id": 0, "level": "log|warn|error|info|debug|trace", "message": "...", "ts": 1712150400000 }
Prefixes for non-console sources:
[uncaught] ...— uncaught exception[unhandledrejection] ...— unhandled promise rejection[fetch] ...— failed fetch (non-ok status or network error)
Poll for new entries only:
GET /api/console?since_id=42
→ entries with id > 42
since_id must be a non-negative integer. Passing a negative value (e.g. -1) causes
the server to return an error, not an empty list. For the first poll, omit the parameter
entirely to retrieve all current entries, then track last_id from the response:
# First poll — no since_id
resp = requests.get(f"{BASE_URL}/api/console")
entries = resp.json()["entries"]
last_id = max((e["id"] for e in entries), default=0)
# Subsequent polls
resp = requests.get(f"{BASE_URL}/api/console?since_id={last_id}")
Clear the buffer:
DELETE /api/console
Timing caution: Startup logs (e.g. a "ready" signal) are emitted once and lost if you clear the buffer before reading them. Pattern: poll for the ready signal first, then clear if needed.
# Safe: check for ready signal BEFORE clearing
poll_until(target="APP_READY")
requests.delete(f"{BASE_URL}/api/console") # only if you need a clean slate after
Glasses input
Send a touchpad action to the glasses display.
POST /api/input
Content-Type: application/json
{ "action": "up" | "down" | "click" | "double_click" }
Response: { "ok": true }
Actions map to the glasses touchpad:
up/down— scroll through list items or textclick— select the current itemdouble_click— triggers a system-level double-click event (typically "back" or "dismiss")
Automation workflow
- Verify the server is running:
GET /api/ping - Poll for app ready (without clearing console first): look for a known log message.
- Observe: Use
/api/screenshot/glasses(RGBA) or/api/consoleto check state. - Act: Send input via
POST /api/input. After each action, wait briefly (~300ms) then confirm state changed. - Iterate: Use
since_idwhen polling console to avoid re-reading old entries.
Tips
- The glasses display is 576×288 pixels, monochrome green. Screenshots are RGBA PNGs.
- Input only works when the app has created an active event container. If no container is active, input is silently ignored.
double_clickis typically used to go back or dismiss the current view.- Allow 4+ seconds after launching the simulator before polling — SDK init and
createStartUpPageContainertake time.
Task
$ARGUMENTS
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/even-realities/everything-evenhub/simulator-automation">View simulator-automation on skillZs</a>