Use Peekaboo for native macOS capture, UI inspection, and automation. Prefer its
native app, window, Accessibility, and input commands over AppleScript or
osascript whenever Peekaboo exposes the operation.
Binary
- Prefer
~/bin/peekaboowhen present; it is Peter's signed local release copy. - Otherwise use
peekaboofromPATH. - Check the selected binary before relying on syntax or installed state.
PB="${PEEKABOO_BIN:-$HOME/bin/peekaboo}"
[ -x "$PB" ] || PB="$(command -v peekaboo)"
"$PB" --version
Runtime host and permissions
- Launch
Peekaboo.appwithout taking focus when a GUI Bridge host is needed:open -gj -a Peekaboo. - The app owns its TCC grants and serves
~/Library/Application Support/Peekaboo/bridge.sock. The reusable daemon has separate permissions and servesdaemon.sock;daemon startis not an app launch. - Ordinary runtime selection prefers a healthy reusable daemon, then the GUI
host, before starting a daemon. Implicit screen-capture observation, AX-tree
inspection, browser, and snapshot-state commands instead prefer and may
auto-start the current CLI build's exact build-scoped daemon before the GUI
host. Use
bridge status --verbose --jsonto inspect candidates, but remember that operation requirements can change their order. When app-held TCC is required, pass--bridge-socket "$HOME/Library/Application Support/Peekaboo/bridge.sock"and verifyhostKind: guiinstead of assuming the app was selected. - Check
permissions status --all-sources --json. Grant Screen Recording, Accessibility, and Event Synthesizing to the process reported as the selected source, not merely to the invoking terminal. - Prefer Bridge capture from SSH, LaunchAgent, Codex, and other background
sessions.
--no-remote --capture-engine cgis a local-debug override and can return wallpaper-only pixels outside the active Aqua session. - Never run an unsigned or ad-hoc build against saved TCC or Keychain state.
Background-first safety
- Keep the user's foreground app, keyboard focus, and physical cursor untouched
by default. Supply an exact
--app,--pid,--window-id, or fresh snapshot target and use Peekaboo's background delivery. - Never add
--foregroundmerely to make a command work speculatively. Add it only when the user authorized foreground interaction or the target demonstrably rejects background delivery. - Shared-cursor and targetless global input must use explicit foreground mode.
This includes
move,drag, targetless/smooth scroll, and targetless keyboard input;click --long-pressis foreground-only. Foreground mode can interrupt the user. - Background type and paste need a resolvable app/PID, a complete inventory with
at most one eligible window, and Event Synthesizing permission. Raw
pressadditionally requires an exact window selector or fresh exact-window snapshot; app/PID-only chords require explicit foreground mode. - Do not click, type, paste, quit, or otherwise mutate UI unless the user asked or the target is a controlled test. Re-observe after mutations; never replay an indeterminate input blindly.
v4 command names
- Inventory:
app list,window list, andscreen list; there is no top-levellistcommand. - Screenshots and UI inspection:
see --no-elementsfor pixels, orsee --tree --no-screenshotfor AX-only text; do not use the removedimageorinspect-uiCLI commands. - Keyboard chords:
press; do not use the removedhotkeycommand. - Named Accessibility actions:
action; do not useperform-action. - Coordinate clicks:
click --at x,y; do not use--coords.
Common commands
"$PB" permissions status --all-sources --json
open -gj -a Peekaboo
"$PB" bridge status --verbose --json
"$PB" screen list --json
"$PB" app list --include-hidden --include-background --json
"$PB" window list --app Safari --json
# Screenshot only; observation does not activate the target app.
"$PB" see --no-elements --mode screen --path /tmp/screen.png --json
# Interactive map plus a directly accessible image artifact.
"$PB" see --app Safari --annotate --path /tmp/safari-see.png --json
# AX-only inspection, with no pixel capture or screenshot artifact.
"$PB" see --app Safari --tree --no-screenshot --json
# Use IDs and the snapshot returned by a fresh `see`.
"$PB" click --on "$ELEMENT_ID" --snapshot "$SNAPSHOT_ID" --json
# Generic `action AXPress` requires explicit foreground consent; use the
# dedicated exact-target `click` route above for background button activation.
# Process-targeted background keyboard delivery.
"$PB" type "text" --app TextEdit --json
"$PB" press Return --app TextEdit --window-id 1234 --json
"$PB" paste "text" --app TextEdit --json
"$PB" tools --json
"$PB" tools describe click --json
Click coordinates safely
Screenshot pixels are not automatically click coordinates. click --at uses
logical points. With target flags, coordinates are relative to the resolved
window; without them they are global screen coordinates. Add --global to make
targeted coordinates use the global logical space. Use screen list --json for
display bounds and scale factors when converting Retina pixels.
A background coordinate click requires an explicit snapshot from a fresh exact-window observation. First resolve the canonical window ID, then observe that exact window and use both its window ID and returned snapshot ID:
"$PB" window list --app Safari --json
"$PB" see --app Safari --window-id 12345 --path /tmp/safari.png --json
"$PB" click --window-id 12345 --at 20,40 --snapshot "$SNAPSHOT_ID" --json
Peekaboo revalidates the captured PID, process generation, window ID, and bounds
before dispatch. If the exact receipt cannot be established, background input
must fail instead of guessing. Use --foreground only when visible shared-pointer
interaction is intentional. Background right/double click can be dispatched to
an exact route but remains effect-unverifiable; run a fresh see before retrying.
For element work, prefer IDs from a fresh see and pass the snapshot explicitly.
Queries and the implicit latest snapshot are convenient but less deterministic.
After an action changes UI, capture a new snapshot rather than reusing stale IDs.
Workflow
- Resolve
PB, confirm its version, and launch the signed GUI host in the background when app-held TCC is needed. - Verify the selected Bridge host and compare permissions across sources.
- Resolve the target with
app listorwindow list; prefer PID/window ID over a broad name or title when cleanup or mutation must be exact. - Observe without focus theft: use
see --no-elementsfor a screenshot, ordinaryseefor element IDs, orsee --tree --no-screenshotfor AX-only inspection. Pass--pathwhen the caller needs the image file. - Interact in the background with an exact target and fresh snapshot. Prefer
actionor an element click over coordinate input. - Verify every mutation with a new
seeor a purpose-built read-only command. - Escalate to explicit
--foregroundonly for authorized shared cursor/global input or a confirmed application limitation; never silently promote modes. - Use
capture livefor change-aware capture,capture videofor video frame sampling,tools describe <name>for MCP schemas, and<command> --helpfor current CLI syntax. - Verify image artifacts with
sips -g pixelWidth -g pixelHeight <path>or view them locally.
Source of truth: ~/Projects/peekaboo/docs/commands/ and the selected binary's
--help output.