Peekaboo is a macOS CLI & optional MCP server that enables AI agents to capture screenshots of applications, or the entire system, with optional visual question answering through local or remote AI models.
This report summarizes scanner evidence for openclaw/Peekaboo, a Swift project with 5,420 GitHub stars. SynthScan examined 709,225 lines of code across 2417 source files, recording 404 pattern matches distributed across 15 syntactic categories. The legacy adjusted pattern signal is 0.7 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 367 finding(s).
Are imports declared and package/API names verified? 15 finding(s).
Are wrappers, guards, and repeated structures necessary? 45 finding(s).
Which changes need focused human review? 404 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 404 distinct pattern matches across 15 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …ts/PeekabooAutomationKitTests/AsyncAXTypingTests.swift | 201 | fixture.selection = CFRange(location: alreadyDesired ? 2 : 0, length: 0) | COMMENT |
| LOW | …ts/PeekabooAutomationKitTests/AsyncAXTypingTests.swift | 301 | #expect(!precomposed.utf16.elementsEqual(decomposed.utf16)) | COMMENT |
| LOW | …ts/PeekabooAutomationKitTests/AsyncAXTypingTests.swift | 381 | COMMENT | |
| LOW | …ts/PeekabooAutomationKitTests/AsyncAXTypingTests.swift | 421 | COMMENT | |
| LOW | …ts/PeekabooAutomationKitTests/AsyncAXTypingTests.swift | 561 | #expect(fixture.textWrites.isEmpty) | COMMENT |
| LOW | …tionKitTests/BoundedAXWindowIdentityScannerTests.swift | 21 | #expect(probed == [0, 1]) | COMMENT |
| LOW | …utomationKitTests/WindowRoutedPointerDriverTests.swift | 61 | targetProcessIdentifier: receipt.identity.ownerProcessIdentifier, | COMMENT |
| LOW | …utomationKitTests/WindowRoutedPointerDriverTests.swift | 261 | COMMENT | |
| LOW | …oAutomationKitTests/TargetedTypeInputPolicyTests.swift | 41 | #expect(fixture.actionCalls.count == (usesAccessibility ? payload.actionUnits : 0)) | COMMENT |
| LOW | …AutomationKitTests/DialogFileExecutionOwnerTests.swift | 21 | COMMENT | |
| LOW | …AutomationKitTests/DialogFileExecutionOwnerTests.swift | 101 | focus.records = [ | COMMENT |
| LOW | …/PeekabooAutomationKitTests/AsyncAXMutationTests.swift | 81 | COMMENT | |
| LOW | …onKitTests/DockContextMenuSelectionDispatchTests.swift | 441 | ApplicationProcessIdentity(processIdentifier: 456, processStartIdentity: generation) | COMMENT |
| LOW | …omationKitTests/ApplicationInventoryTimeoutTests.swift | 381 | #expect(healthy.isHiddenKnown == true) | COMMENT |
| LOW | …tomationKitTests/ScreenCaptureKitOwnerLeaseTests.swift | 381 | #expect(second == .alreadyOwnedByCurrentProcess(firstReceipt)) | COMMENT |
| LOW | …mationKitTests/SnapshotTargetReceiptPlannerTests.swift | 41 | COMMENT | |
| LOW | …mationKitTests/SnapshotTargetReceiptPlannerTests.swift | 101 | @Test | COMMENT |
| LOW | …abooAutomationKitTests/UIInputPolicyDefaultTests.swift | 41 | } | COMMENT |
| LOW | …ationKitTests/ClipboardPasteTransactionGateTests.swift | 521 | #expect(clock.now - started >= .milliseconds(140)) | COMMENT |
| LOW | …ationKitTests/DesktopMutationWatermarkStoreTests.swift | 421 | COMMENT | |
| LOW | …s/PeekabooAutomationKitTests/CaptureCadenceTests.swift | 241 | requestedCadenceIntervals: 10), | COMMENT |
| LOW | …ekabooAutomationKitTests/DialogTextMetadataTests.swift | 21 | let service = DialogService() | COMMENT |
| LOW | …omationKitTests/TypeServiceForegroundPolicyTests.swift | 61 | text: "ab", | COMMENT |
| LOW | …omationKitTests/TypeServiceForegroundPolicyTests.swift | 341 | try await fixture.service.type( | COMMENT |
| LOW | …omationKitTests/TypeServiceForegroundPolicyTests.swift | 441 | snapshotId: fixture.snapshotID, | COMMENT |
| LOW | …AutomationKitTests/AutomationKitTestSupportTests.swift | 121 | #expect(moved.subrole == original.subrole) | COMMENT |
| LOW | …KitTests/UIAutomationActionOutcomeProvidingTests.swift | 381 | for result in [pidType, processType] { | COMMENT |
| LOW | …sts/ForegroundModifierClickExecutorTests+Routing.swift | 661 | #expect(failure.outcome.state == .indeterminate) | COMMENT |
| LOW | …kabooAutomationKit/Extensions/NSArray+Extensions.swift | 1 | // | COMMENT |
| LOW | …s/PeekabooAutomationKit/Utilities/SpaceUtilities.swift | 1 | // Space (Virtual Desktop) Management Utilities | COMMENT |
| LOW | …s/PeekabooAutomationKit/Utilities/SpaceUtilities.swift | 21 | // | COMMENT |
| LOW | …s/PeekabooAutomationKit/Utilities/SpaceUtilities.swift | 41 | // try await service.switchToSpace(spaceNumber: 2) | COMMENT |
| LOW | …s/PeekabooAutomationKit/Utilities/FocusUtilities.swift | 1 | // Window Focus Management Utilities | COMMENT |
| LOW | …s/PeekabooAutomationKit/Utilities/FocusUtilities.swift | 21 | // 3. **Window Movement**: Bring windows to current Space | COMMENT |
| LOW | …rvices/GameBridge/GameBridgeDetectionIntegration.swift | 1 | import CoreGraphics | COMMENT |
| LOW | …t/Services/GameBridge/GameBridgeDetectionService.swift | 1 | import CoreGraphics | COMMENT |
| LOW | …tomationKit/Services/Capture/SmartCaptureService.swift | 1 | // | COMMENT |
| LOW | …omationKit/Services/Capture/ScreenCapturePlanner.swift | 101 | /// No displays were enumerated at all. Capture cannot proceed. | COMMENT |
| LOW | …rvices/Core/Protocols/ApplicationServiceProtocol.swift | 301 | /// - appIdentifier: Application name or bundle ID | COMMENT |
| LOW | …rvices/Core/Protocols/ApplicationServiceProtocol.swift | 661 | COMMENT | |
| LOW | …nKit/Services/Core/Protocols/MenuServiceProtocol.swift | 21 | /// - Returns: Menu structure information | COMMENT |
| LOW | …nKit/Services/Core/Protocols/FileServiceProtocol.swift | 1 | import Foundation | COMMENT |
| LOW | …vices/Core/Protocols/UIAutomationServiceProtocol.swift | 41 | public protocol UIAutomationServiceProtocol: Sendable { | COMMENT |
| LOW | …vices/Core/Protocols/UIAutomationServiceProtocol.swift | 61 | /// - target: Optional target element | COMMENT |
| LOW | …vices/Core/Protocols/UIAutomationServiceProtocol.swift | 81 | /// - holdDuration: How long to hold the keys in milliseconds | COMMENT |
| LOW | …vices/Core/Protocols/UIAutomationServiceProtocol.swift | 101 | /// - snapshotId: Snapshot ID for element resolution | COMMENT |
| LOW | …vices/Core/Protocols/UIAutomationServiceProtocol.swift | 121 | /// Get information about the currently focused UI element | COMMENT |
| LOW | …/Services/Core/Protocols/SnapshotManagerProtocol.swift | 101 | func createSnapshot(pendingAt observationStartedAt: Date) async throws -> String | COMMENT |
| LOW | …/Services/Core/Protocols/SnapshotManagerProtocol.swift | 121 | /// Retrieve element detection results from a snapshot | COMMENT |
| LOW | …/Services/Core/Protocols/SnapshotManagerProtocol.swift | 181 | COMMENT | |
| LOW | …/Services/Core/Protocols/SnapshotManagerProtocol.swift | 201 | /// - Returns: Array of matching elements | COMMENT |
| LOW | …ests/PeekabooFoundationTests/RawPressPolicyTests.swift | 21 | _ = try KeyboardChord(parsing: "super+c") | COMMENT |
| LOW | …FoundationTests/TypeActionReplacementPolicyTests.swift | 21 | func `only one leading clear followed by text has a deterministic replacement value`() { | COMMENT |
| LOW | …ndationTests/DesktopActionOutcomeProjectionTests.swift | 41 | #expect(object["route"] as? String == projection.route.rawValue) | COMMENT |
| LOW | …PeekabooTests/PeekabooServicesBrowserBridgeTests.swift | 41 | arguments: ToolArguments(raw: ["action": "connect", "channel": "canary"])) | COMMENT |
| LOW | …PeekabooTests/PeekabooServicesBrowserBridgeTests.swift | 401 | #expect(adapted.actionFailure == failure) | COMMENT |
| LOW | …ooTests/RemoteCaptureEnginePlanCacheRoutingTests.swift | 101 | #expect(first.capture.metadata.diagnostics?.windowPlanCacheStatus == .miss) | COMMENT |
| LOW | …ooTests/PeekabooBridgeClientTransportSafetyTests.swift | 21 | defer { try? FileManager.default.removeItem(at: root) } | COMMENT |
| LOW | …ests/PeekabooBridgeWindowEnumerationTimeoutTests.swift | 41 | let result = try await remote.listWindows(target: .application("Fixture")) | COMMENT |
| LOW | …ekabooTests/AgentObservationProviderContextTests.swift | 61 | } else { | COMMENT |
| 263 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | …sts/PeekabooTests/PeekabooAIServiceProviderTests.swift | 0 | { "aiproviders": { "providers": "openai/gpt-5.5" }, "customproviders": { "local-proxy": { "name": "local proxy", "type": | STRING |
| HIGH | …sts/PeekabooTests/PeekabooAgentServiceModelTests.swift | 0 | { "aiproviders": { "providers": "openai/gpt-5.5" }, "customproviders": { "local-proxy": { "name": "local proxy", "type": | STRING |
| HIGH | …Tests/CoreCLITests/AgentCommandModelParsingTests.swift | 0 | { "aiproviders": { "providers": "openai/gpt-5.5" }, "customproviders": { "local-proxy": { "name": "local proxy", "type": | STRING |
| HIGH | …sts/PeekabooTests/PeekabooAIServiceProviderTests.swift | 0 | { "aiproviders": { "providers": "openai/gpt-5.6,anthropic/claude-opus-5" } } | STRING |
| HIGH | …sts/PeekabooTests/PeekabooAgentServiceModelTests.swift | 0 | { "aiproviders": { "providers": "openai/gpt-5.6,anthropic/claude-opus-5" } } | STRING |
| HIGH | …kabooAgentRuntimeTests/AI/PeekabooAIServiceTests.swift | 0 | { "aiproviders": { "providers": "openai/gpt-5.6,anthropic/claude-opus-5" } } | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …mationKit/Sources/PeekabooAutomationKit/Core/README.md | 53 | print("Error: \(error.localizedDescription)") | CODE |
| LOW | scripts/notary-api-submit.py | 184 | except Exception: | CODE |
| LOW | scripts/notary-api-submit.py | 298 | except Exception: | CODE |
| LOW | scripts/notary-api-submit.py | 326 | except Exception: | CODE |
| LOW | scripts/notary-api-submit.py | 369 | except Exception: | CODE |
| MEDIUM | scripts/notary-api-submit.py | 363 | def main(): | CODE |
| LOW | .github/scripts/core-sigpipe-diagnostic.py | 165 | except Exception: | CODE |
| LOW | .github/scripts/core-sigpipe-diagnostic.py | 207 | except Exception: | CODE |
| LOW | Apps/Playground/scripts/peekaboo-perf.sh | 167 | except Exception: | CODE |
| LOW | Apps/Playground/scripts/peekaboo-perf.sh | 265 | except Exception: | CODE |
| LOW | Apps/Playground/scripts/peekaboo-perf.sh | 286 | except Exception: | CODE |
| LOW | Apps/Playground/scripts/peekaboo-perf.sh | 335 | except Exception: | CODE |
| MEDIUM | Apps/Playground/scripts/peekaboo-perf.sh | 332 | def git_value(args): | CODE |
| MEDIUM | …Sources/PeekabooCLI/Commands/System/CleanCommand.swift | 112 | print("Error: \(error.localizedDescription)", to: &stderrStream) | STRING |
| MEDIUM | …Sources/PeekabooCLI/Commands/System/CleanCommand.swift | 123 | print("Error: \(error.localizedDescription)", to: &localStandardErrorStream) | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/test-swift-workspace.py | 89 | def test_build_child_signal_retains_shell_exit_status(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 98 | def test_clean_setup_idempotence_and_remove_preserve_unrelated_settings(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 115 | def test_relocation_requires_explicit_setup(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 126 | def test_unowned_conflict_is_not_read_or_overwritten(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 136 | def test_owned_tampering_and_symlinks_fail_closed(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 151 | def test_symlinked_parent_and_hardlink_fail_closed(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 162 | def test_missing_wrong_uninitialized_or_aliased_submodule(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 171 | def test_release_source_gate_and_child_failure(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 182 | def test_effective_mapping_strict_arguments_and_post_build_integrity(self): | STRING |
| LOW⚡ | scripts/test-swift-workspace.py | 196 | def test_inherited_override_is_rejected_without_reading_it(self): | STRING |
| LOW⚡ | scripts/test-swift-workspace.py | 203 | def test_build_child_retains_callers_file_creation_permissions(self): | STRING |
| LOW⚡ | scripts/test-swift-workspace.py | 210 | def test_xcode_contexts_do_not_promote_commander_to_a_root_package(self): | STRING |
| LOW | scripts/test-swift-workspace.py | 298 | def test_gitfile_live_source_with_strict_swiftpm_and_xcode(self): | STRING |
| LOW | scripts/test-notary-api-submit.py | 25 | def test_aws_published_iam_vector(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 45 | def test_jwt_with_throwaway_key(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 103 | def test_deadline_and_no_credential_redirects(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 112 | def test_jwt_regenerated_for_each_api_request(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 123 | def test_request_retries_and_auth_failures(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 152 | def test_connection_retries_are_bounded_and_deadline_limited(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 191 | def test_slow_part_timeout_and_error_redaction(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 243 | def test_multipart_etag_binds_completed_object(self): | CODE |
| LOW | scripts/test-notary-api-submit.py | 279 | def test_fixture_override_boundary(self): | CODE |
| LOW | scripts/support/test-fixture-metadata.rb | 6 | def classify_fixture_metadata(names, size) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | …es/PeekabooBridge/PeekabooBridgeClient+Transport.swift | 1237 | bundle.receipt.payload.requestID.uuidString.lowercased() + ".json", | STRING |
| CRITICAL | …CLI/Tests/CoreCLITests/BridgeReceiptCommandTests.swift | 116 | .appendingPathComponent(bundle.receipt.payload.requestID.uuidString.lowercased()) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …t/Services/UI/UIAutomationService+ElementActions.swift | 389 | element.attributes["placeholder"], | CODE |
| LOW | …tionKit/Services/UI/TypeService+TargetResolution.swift | 50 | let placeholder = element.attributes["placeholder"]?.lowercased() | CODE |
| LOW | …kabooAutomationKit/Services/UI/ElementClassifier.swift | 148 | attributes["placeholder"] = placeholder | CODE |
| LOW | …/PeekabooAutomationKit/Services/UI/ScrollService.swift | 500 | element.attributes["placeholder"], | CODE |
| LOW | …ationKit/Services/UI/DetachedAXObservationWorker.swift | 608 | attributes["placeholder"] = placeholder | CODE |
| LOW | …Tests/PeekabooTests/ElementDetectionServiceTests.swift | 530 | #expect(attributes["placeholder"] == nil) | COMMENT |
| LOW | …abooAgentRuntime/MCP/Tools/DialogTool+Formatting.swift | 141 | "placeholder": field.placeholder ?? "", | CODE |
| LOW | .agents/skills/crabbox/SKILL.md | 465 | ../crabbox/bin/crabbox desktop paste --provider hetzner --id <cbx_id-or-slug> --text "user@example.com" | CODE |
| LOW | docs/logging-profiles/README.md | 39 | - **Simple strings**: `"user@example.com"` remains visible | CODE |
| LOW | docs/providers/ollama.md | 68 | printf '%s\n' 'dummy-key' | peekaboo config provider add ollama-openai \ | CODE |
| LOW | …eekabooCLI/Commands/Core/ConfigCommand+Providers.swift | 63 | printf '%s\\n' 'dummy-key' | peekaboo config provider add local-ollama \\ | CODE |
| LOW | …ces/PeekabooCLI/Commands/Interaction/TypeCommand.swift | 689 | peekaboo type "user@example.com" --foreground | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …Kit/Services/Observation/ObservationTextDetector.swift | 106 | return 0.0 // Definitely avoid | CODE |
| MEDIUM | …PeekabooAgentRuntimeTests/AgentSystemPromptTests.swift | 10 | #expect(prompt.utf8.count * 2 < comprehensive.utf8.count) | COMMENT |
| MEDIUM | scripts/test-restart-peekaboo.sh | 1664 | # Restore only this synthetic fixture directory so the harness can clean up even after a failed assertion. | COMMENT |
| MEDIUM | Apps/Playground/scripts/peekaboo-perf.sh | 5 | # Local benchmarking harness for source checkouts. This is not telemetry and is not intended | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/notary-api-submit.py | 165 | CODE | |
| LOW | scripts/notary-api-submit.py | 302 | CODE | |
| LOW | scripts/swift-runtime-exports.py | 234 | CODE | |
| LOW | scripts/swift-runtime-exports.py | 270 | CODE | |
| LOW | scripts/test-notary-api-submit.py | 123 | CODE | |
| LOW | scripts/test-notary-api-submit.py | 243 | CODE | |
| LOW | .github/scripts/core-sigpipe-diagnostic.py | 60 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | docs/research/agentic.md | 44 | ### PR #47 “enhancements” scaffolding | COMMENT |
| MEDIUM | …Tests/CoreCLITests/AgentCommandModelParsingTests.swift | 128 | #expect(command.parseModelString("xai/grok-4.20-multi-agent-0309") == nil) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | …n/Configuration/ConfigurationManager+Persistence.swift | 84 | # This file contains sensitive API keys and should not be shared | COMMENT |
| MEDIUM | …/PeekabooAutomation/Configuration/CredentialFile.swift | 123 | let header = "# Peekaboo credentials file\n# This file contains sensitive API keys and should not be shared\n\n" | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | homebrew/peekaboo.rb | 25 | export OPENAI_API_KEY="your-api-key" | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | scripts/swift-runtime-exports.py | 111 | except OSError: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | …CLI/Tests/CoreCLITests/AnnotationCoordinateTests.swift | 55 | // Step 1: Transform to window-relative (done in UIAutomationServiceEnhanced) | COMMENT |
| LOW⚡ | …CLI/Tests/CoreCLITests/AnnotationCoordinateTests.swift | 64 | // Step 2: Flip Y for drawing (done in SeeCommand annotation) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | …CLI/Tests/CoreCLITests/AnnotationCoordinateTests.swift | 55 | // Step 1: Transform to window-relative (done in UIAutomationServiceEnhanced) | COMMENT |
| LOW⚡ | …CLI/Tests/CoreCLITests/AnnotationCoordinateTests.swift | 64 | // Step 2: Flip Y for drawing (done in SeeCommand annotation) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | scripts/build-mac-debug.sh | 42 | # Check if workspace exists | COMMENT |
| LOW | Apps/Mac/run-tests.sh | 17 | # Check if we're in the right directory | COMMENT |