Receber por email
← Voltar para o catálogo

peekaboo

Drive, observe, and critique any running macOS app end-to-end via Peekaboo — the macOS-native equivalent of Playwright + visual-regression review for SwiftUI/AppKit. Use proactively whenever the user mentions UI, screens, screenshots, the app's appearance, layout, spacing, alignment, copy/labels, sidebar, panels, settings, theme, accessibility identifiers, clicking, typing, menus, file pickers, re

11estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add johnkozaris/jko-claude-plugins

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/peekaboo-johnkozaris/svg)](https://www.skillteca.com.br/skills/peekaboo-johnkozaris)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Peekaboo — drive, observe, and critique any macOS app

**The job is not "is this clickable". The job is "does it work, and does
it look right". Every screenshot deserves a critique pass.**

Peekaboo is a single Swift CLI that combines screenshot, AX-tree inspection, synthetic input, and change-aware video capture against macOS apps. It's the macOS-native equivalent of Playwright + visual-regression review.

You invoke peekaboo directly — it's a full toolkit, not a fixed menu of recipes. Build orchestration belongs to your project's task runner (Justfile, Makefile, xcodebuild, etc.); UI driving is your domain.

No external AI keys. Ever. You are the LLM. When you need to "look at" the screenshot, view the PNG yourself. Skip peekaboo agent, peekaboo see --analyze, peekaboo image --analyze, peekaboo analyze — they all require an external API key.

When to invoke this skill

  • ✅ User says "see what it looks like", "show me the UI", "verify it works",

"click X", "type Y", "take a screenshot", "drive the app", "test it end-to-end"

  • ✅ After modifying any SwiftUI/AppKit view — verify it renders, works, and

still looks intentional

  • ✅ When debugging a UI bug — capture before/after + critique each
  • ✅ Before claiming a UI feature done in autopilot mode
  • ❌ Skip if the change is purely backend / non-UI

Prerequisites

peekaboo --version                           # ≥ 3.0
peekaboo list permissions --json             # both must be granted

If peekaboo is not installed:

brew install steipete/tap/peekaboo

Then grant Screen Recording AND Accessibility to your terminal in System Settings → Privacy & Security. Both are required.

The loop (copy this checklist into your response and tick items off)

  • [ ] Build the app — use the project's task runner
  • [ ] Drive — get the app to the state under test
  • [ ] Snapshot — peekaboo see --json --annotate --path /tmp/k.png
  • [ ] CRITIQUE — view /tmp/k_annotated.png inline; score it against the

rubric. Optionally chain a design skill (critique/polish/layout)

  • [ ] Fix any findings
  • [ ] Re-verify — repeat snapshot + critique; diff against previous PNG

Discovering the target app

Before running anything, you need the bundle ID (preferred) or app name:

# Find a running app's bundle ID
peekaboo list apps --json | jq '.data.applications[]|select(.name|test("YourApp";"i"))|{name,bundleIdentifier,processIdentifier}'

# Always prefer --bundle-id over --app <DisplayName>:
#   - bundle ID is stable (e.g. com.example.myapp)
#   - the running process registers as CFBundleName, which often differs
#     from the Xcode scheme. Using the scheme name fails APP_NOT_FOUND.

Cache the bundle ID and any display-name caveats in your project's AGENTS.md / CLAUDE.md so future runs don't re-discover them.

Terminology (one-to-one with peekaboo's command names)

| Word | Means | Command | |----------------|----------------------------------------------------------|--------------------------| | Snapshot | Annotated PNG plus AX-tree JSON (the "DOM+screenshot") | peekaboo see | | Screenshot | Raw PNG only, no AX tree | peekaboo image | | Recording | Change-aware MP4 video | peekaboo capture live |

Default to snapshot (peekaboo see) — the AX JSON lets the next step click by element ID without re-parsing the screen.

Step 1 — Drive the UI

The full driving surface (run peekaboo <cmd> --help for details, or peekaboo learn for the comprehensive guide):

| Need | Command | |---------------------------------------|----------------------------------------------------------| | Launch / quit app | peekaboo app launch --bundle-id $BID --wait-until-ready<br>peekaboo app quit --app $BID | | Inspect UI (annotated PNG + JSON) | peekaboo see --app $BID --json --annotate --path /tmp/k.png > /tmp/k.json | | Click by AX identifier (most robust) | See "Click by .accessibilityIdentifier" recipe below | | Click by visible label | peekaboo click "Settings" --app $BID | | Click by element ID from see | peekaboo click --on elem_42 --snapshot $SID --app $BID | | Type text | peekaboo type "hello" --app $BID<br>(append --return to press Enter) | | Single key | peekaboo press return / peekaboo press escape | | Hotkey | peekaboo hotkey --keys "cmd,b" --app $BID | | Menu bar | peekaboo menu list --app $BID (discover)<br>peekaboo menu click --app $BID --path "View > Toggle Sidebar" | | System file/save dialog | peekaboo dialog list --app $BID<br>peekaboo dialog click --button "Open" --app $BID<br>peekaboo dialog input --text "..." --field "..." --app $BID<br>peekaboo dialog file --path "/Users/me" --select "Open" --app $BID | | Scroll inside a list / pane | peekaboo scroll --direction down --amount 5 --on elem_N | | Drag-and-drop | peekaboo drag --from elem_A --to elem_B --app $BID | | Resize/reposition window | peekaboo window set-bounds --app $BID --x 0 --y 0 --width 1024 --height 640 | | Read/write clipboard | peekaboo clipboard get / peekaboo clipboard set --text "x" | | Paste from clipboard | peekaboo paste --app $BID | | Open URL / deep link | peekaboo open "x-myapp://..." | | Replay a saved scenario | peekaboo run scripts/onboarding.peekaboo.json |

Throughout this skill, $BID is the target app's bundle ID (com.example.myapp).

Click by .accessibilityIdentifier — the killer pattern

If your SwiftUI / AppKit code tags interactive views with .accessibilityIdentifier(...), Peekaboo surfaces those exact strings as ui_elements[].identifier. Queries are then immune to copy changes:

peekaboo see --app $BID --json --annotate --path /tmp/k.png > /tmp/k.json

SID=$(jq -r .data.snapshot_id /tmp/k.json)
ID=$(jq -r '.data.ui_elements[]|select(.identifier=="header.utility.settings").id' /tmp/k.json)

peekaboo click --on "$ID" --snapshot "$SID" --app $BID

If you reach for a copy-based click (peekaboo click "Some Label") more than once on the same control, add a stable identifier in your project's chosen namespace (e.g. header.tab.sessions, panel.settings.save, row.<id>.delete). Both peekaboo queries and any XCUITest become resilient to copy changes:

Button("Settings") { … }
    .accessibilityIdentifier("header.utility.settings")

Document the namespace in your project's AGENTS.md so additions stay consistent.

Step 2 — Capture (anatomy of peekaboo see)

peekaboo see --app $BID --json --annotate --path /tmp/k.png > /tmp/k.json

This writes two PNGs:

  • /tmp/k.png — raw screenshot
  • /tmp/k_annotated.png — same image overlaid with elem_N markers

(this is the one you usually want to view)

…and prints a JSON envelope {success, data, debug_logs} where data has:

| Field | Meaning | |------------------------|--------------------------------------------------------| | snapshot_id | UUID — pass to --snapshot for click stability | | screenshot_raw | path to /tmp/k.png | | screenshot_annotated | path to /tmp/k_annotated.png | | application_name | display name (CFBundleName)

Compartilhar X LinkedIn