Application Resolution in Peekaboo
This document explains how Peekaboo resolves applications across commands that accept an application parameter.
#Overview
Peekaboo supports multiple ways to identify and target applications:
- Application Name - Human-readable name (e.g., "Safari", "Google Chrome")
- Bundle ID - Unique application identifier (e.g., "com.apple.Safari")
- Process ID (PID) - Numeric process identifier
- Fuzzy Matching - Partial name matching for convenience
#Command Line Parameters
Most commands that work with applications support two parameters:
--app- Application name, bundle ID, or PID in format "PID:12345"--pid- Direct process ID as a number
#Examples
# By application name
peekaboo see --no-elements --app Safari
# By bundle ID
peekaboo window close --app com.apple.Safari
# By PID using --app parameter
peekaboo menu list --app "PID:12345"
# By PID using --pid parameter
peekaboo app quit --pid 12345
# Both parameters on a legacy window command (when they refer to the same app)
peekaboo window focus --app Safari --pid 12345
#Resolution Methods
#1. Application Name
The most common method - uses the localized application name:
peekaboo see --no-elements --app "Google Chrome"
peekaboo window list --app TextEdit
Features:
- Case-insensitive matching
- Supports spaces in names
- Uses localized names (what you see in the UI)
#2. Bundle Identifier
More precise than names, bundle IDs are unique:
peekaboo app launch --app com.microsoft.VSCode
peekaboo window close --app com.google.Chrome
Features:
- Exact matching only
- Always lowercase
- Guaranteed unique per application
#3. Process ID (PID)
Direct process targeting using numeric IDs:
# Using --pid parameter
peekaboo app quit --pid 67890
# Using --app parameter with PID: prefix
peekaboo window focus --app "PID:67890"
# Finding PIDs
peekaboo app list --include-hidden --include-background # Shows all PIDs
Features:
- Most precise targeting method
- Works even if app name is unknown
- Useful for scripting and automation
#4. Fuzzy Name Matching
Peekaboo supports partial name matching for convenience:
# Matches "Visual Studio Code"
peekaboo see --no-elements --app "visual"
peekaboo see --no-elements --app "code"
peekaboo see --no-elements --app "studio"
# Matches "Google Chrome"
peekaboo window list --app chrome
Algorithm:
- First tries exact match (case-insensitive)
- Then tries "contains" match
- Prioritizes running applications
- Falls back to installed applications
#Selector safety and legacy leniency
V4 interaction and observation commands fail closed: use either --app or --pid, never both. This rule covers see and commands that use the shared interaction target such as action, click, drag, press, set-value, and type. These commands may observe, focus, and mutate through different services, so a redundant-looking pair is unsafe when those services resolve it differently.
Some legacy app/window management commands retain lenient parameter handling as a compatibility contract. For those commands, redundant app/PID information is accepted; a textual app selector remains authoritative because the synchronous resolver cannot reliably cross-check it against the PID.
#Mutation inventory completeness
App mutations require an exact name, exact bundle ID, or explicit PID. Name and bundle selection must prove uniqueness from a complete mutation inventory. Helpers with prohibited activation policy remain selectable by exact name or bundle when the runtime host can read their process generation, including helpers owned by another user when the host has that access. Duplicate readable helpers still make a matching name or bundle ambiguous.
The native mutation inventory excludes an unreadable helper without marking the inventory partial only when repeated observations agree: activation policy is explicitly prohibited, an exact-sized short-BSD response identifies the expected PID with an effective UID different from the runtime host, and full process-generation reads actually fail with EPERM. UID alone never predicts denial, and short BSD never supplies a generation receipt. Unknown policy, other failures, changing evidence, and a readable generation that disappears or changes all remain fail-closed. These checks share the inventory's one-second off-MainActor budget and retained native worker; they do not change read-only discovery or generation-pinned explicit-PID lifecycle targeting.
#Allowed Redundancy
These legacy management forms are valid and equivalent:
# Redundant PID specifications
peekaboo window close --app "PID:12345" --pid 12345
# Legacy compatibility: the textual app selector is authoritative
peekaboo window focus --app Safari --pid 67890
#Conflict Detection
This produces an error:
# Different PIDs
peekaboo window close --app "PID:12345" --pid 67890
A textual app/PID mismatch is not synchronously detectable in the legacy resolver. This is why interaction and observation commands reject the pair instead of choosing one.
#Implementation Details
#ApplicationResolvable Protocol
Commands with application parameters can conform to the ApplicationResolvable protocol:
protocol ApplicationResolvable {
var app: String? { get }
var pid: Int32? { get }
}
Safety-sensitive interaction call sites add stricter selector validation before invoking this resolver.
#Resolution Priority
When a legacy-compatible command accepts both --app and --pid:
- If
--appusesPID:<pid>, validate that it matches--pid - Otherwise, prefer the textual app or bundle identifier for the operation
- Do not infer that an accompanying PID proves the textual app's identity
#Error Messages
Clear error messages help users understand issues:
"No application found with name 'Safarii'"- Typo in name"Application 'Safari' is not running"- App not launched"Process with PID 12345 not found or terminated"- Invalid PID"Application mismatch: --app 'Safari' does not match PID 12345 (Chrome)"- Conflict
#Best Practices
#For Users
- Use names for readability:
--app Safariis clearer than--app "PID:12345" - Use PIDs for precision: When scripting or targeting specific instances
- Use bundle IDs for reliability: When app names might be ambiguous
#For Scripts
# Get PID for scripting
PID=$(peekaboo app list --json --include-hidden --include-background | jq '.data.apps[] | select(.name=="Safari") | .pid')
peekaboo window close --pid $PID
# Or use bundle ID
peekaboo app launch --app com.apple.Safari
#For AI Agents
AI agents should provide exactly one of --app or --pid. Use PID:<pid> in --app only when a schema lacks a separate PID field. Do not send both unless the specific legacy command documents that compatibility form.
#Common Patterns
#Finding Applications
# List all running apps with PIDs
peekaboo app list --include-hidden --include-background
# Find specific app
peekaboo app list --include-hidden --include-background | grep -i safari
#Window Management
# List windows for an app
peekaboo window list --app Safari
# Focus specific window
peekaboo window focus --app Safari --window-title "GitHub"
#Cross-Space Operations
# Move window to current space (finds app by any method)
peekaboo space move-window --app Terminal --to-current
peekaboo space move-window --pid 12345 --to 2
#Troubleshooting
#Application Not Found
Symptoms:
"Application 'X' not found""No running application matches 'X'"
Solutions:
- Check spelling:
peekaboo app list --include-hidden --include-background - Try partial name:
--app chromeinstead of--app "Google Chrome" - Use bundle ID:
--app com.google.Chrome - Use PID directly: Find it with
peekaboo app list --include-hidden --include-background, then use--pid
#PID Issues
Symptoms:
"Process with PID X not found""Invalid PID format"
Solutions:
- Verify PID is current:
peekaboo app list --include-hidden --include-background - Check format:
--app "PID:12345"needs quotes and prefix - Use
--pid 12345for direct numeric PIDs
#Multiple Matches
Symptoms:
- Fuzzy matching finds wrong app
- Multiple apps with similar names
Solutions:
- Use full name:
--app "Visual Studio Code"not--app code - Use bundle ID for precision
- Use PID for exact targeting
#See Also
- Command index - Full command documentation
- Agent chat - Using Peekaboo with AI agents
- Automation guide - Scripting and automation patterns