Commit graph

94 commits

Author SHA1 Message Date
Peter Steinberger
eb6bd60f20
Add PID-based application targeting (#14)
Co-authored-by: Claude <noreply@anthropic.com>
2025-06-09 00:30:10 +01:00
Peter Steinberger
2b5c03697c Release v1.0.1
Re-release due to npm registry issue with v1.0.0.
No code changes from v1.0.0.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:58:48 +01:00
Peter Steinberger
8d8d9cb5f9 Release v1.0.0 🎉
First stable release of Peekaboo MCP with:
- macOS 14.0+ support (lowered from 15.0)
- Swift 6 with strict concurrency
- Complete async/await implementation
- Robust error handling
- Universal binary for Intel and Apple Silicon

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:56:04 +01:00
Peter Steinberger
5d4a656fa7 Prepare v1.0.0-beta.26 release
- Removed v1.0.0 from npm to continue beta testing
- Updated version to 1.0.0-beta.26
- Added changelog entry for macOS requirement change

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:50:30 +01:00
Peter Steinberger
606290ec79 Lower macOS requirement from 15.0 to 14.0
Based on API usage analysis, Peekaboo only requires macOS 14.0 (Sonoma), not macOS 15.0 (Sequoia). The APIs we use:
- SCScreenshotManager.captureImage: macOS 14.0+
- configuration.shouldBeOpaque: macOS 14.0+
- Typed throws syntax: Works with macOS 14.0

This change makes Peekaboo available to more users who haven't upgraded to Sequoia yet.

Also fixed warning about undefined modelName in AI providers by using nullish coalescing.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:48:00 +01:00
Peter Steinberger
1095f488ea Fix macOS version requirement documentation
- Update to macOS 15.0+ (Sequoia) to match Package.swift
- Fix incorrect version in CHANGELOG.md
- Update README badges and requirements section

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:39:18 +01:00
Peter Steinberger
0bec93e364 Apply SwiftFormat changes for v1.0.0 release
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:35:27 +01:00
Peter Steinberger
1a2a817822 Prepare v1.0.0 stable release
- Update version to 1.0.0
- Add comprehensive changelog for stable release
- Mark project as production-ready

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:34:56 +01:00
Peter Steinberger
80e5ea338a Fixes a local only test 2025-06-08 20:26:05 +01:00
Peter Steinberger
1084050f18 Improve error handling 2025-06-08 20:24:46 +01:00
Peter Steinberger
17e73f12f2 Revert to AsyncParsableCommand with parse-as-library
- Remove problematic AsyncAdapter that was causing continuation leaks
- Use AsyncParsableCommand directly with @main attribute
- Add -parse-as-library flag to Package.swift to enable @main
- This fixes the Swift continuation leak issue

Note: Integration tests still timeout in CI environment, likely due to
screen capture permissions or environment differences. The CLI works
correctly when run directly.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 12:09:43 +01:00
Peter Steinberger
3f4a7c864b Fix list tool server_status handling and improve robustness
- Remove empty string from item_type enum to prevent undefined values
- Add defensive programming to buildSwiftCliArgs to filter out undefined/null values
- Improve item type determination logic with explicit string checks
- Add debug logging for Swift CLI arguments
- Fix double --json-output flag issue

This fixes the "Unknown operation: undefined" error when calling list with server_status.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:50:00 +01:00
Peter Steinberger
3e8f787dbb v1.0.0-beta.24 2025-06-08 11:38:08 +01:00
Peter Steinberger
559349f198 Fix Swift 6 async execution with synchronous adapter
- Add AsyncAdapter.swift to bridge async/sync execution
- Change AsyncParsableCommand back to ParsableCommand
- Implement AsyncRunnable protocol for async execution
- Use DispatchSemaphore pattern for synchronous blocking
- Make ErrorBox thread-safe with @unchecked Sendable

This fixes the CLI execution issue where commands were showing help
instead of executing, by properly bridging the async/sync worlds
as required by ArgumentParser.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:34:53 +01:00
Peter Steinberger
8b46d11015 Update ApplicationFinderTests to use modern Swift Testing patterns
- Replace #expect(throws:) with more expressive error validation pattern
- Use #expect { } throws: { } for better error type checking
- Improve error handling in nonExistentAppThrowsError test

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:28:37 +01:00
Peter Steinberger
84df333f2b v1.0.0-beta.23 2025-06-08 11:24:44 +01:00
Peter Steinberger
92d3bdb1f7 Fix WindowManagerTests to use return instead of XCTSkip
- Replace XCTSkip with simple return for non-running apps
- This avoids dependency on XCTest framework in Swift Testing

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:24:01 +01:00
Peter Steinberger
612f69f459 Improve test assertions for better clarity
- Remove redundant bundle ID checks in ApplicationFinderTests
- Replace do-catch with #expect(throws:) for cleaner error testing
- Simplify permission test assertions to avoid false failures
- Remove unnecessary boolean comparisons in permission checks

These changes make the tests more maintainable and less prone to
environment-specific failures.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:23:43 +01:00
Peter Steinberger
c04b8e7af0 Migrate to Swift 6 with strict concurrency
- Update to swift-tools-version 6.0 and enable StrictConcurrency
- Make all data models and types Sendable for concurrency safety
- Migrate commands from ParsableCommand to AsyncParsableCommand
- Remove AsyncUtils.swift and synchronous bridging patterns
- Update WindowBounds property names to snake_case for consistency
- Ensure all error types conform to Sendable protocol
- Add comprehensive Swift 6 migration documentation

This migration enables full Swift 6 concurrency checking and data race
safety while maintaining backward compatibility with the existing API.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:23:10 +01:00
Peter Steinberger
50984f8dc2 Fix async concurrency issues without semaphores
- Replace problematic DispatchSemaphore usage with NSCondition-based async bridge
- Revert to ParsableCommand for compatibility while maintaining async operations
- Use CGWindowListCopyWindowInfo for sync permission checking instead of async ScreenCaptureKit
- Remove all RunLoop workarounds in favor of proper Task.runBlocking pattern
- Eliminate all deadlock sources while preserving async capture functionality
2025-06-08 10:10:04 +01:00
Peter Steinberger
d2fb50b289 Fix deadlock in PermissionsChecker by replacing semaphore with RunLoop
- Replace DispatchSemaphore usage in checkScreenRecordingPermission with RunLoop pattern
- This was the root cause of CLI hangs affecting all commands that check permissions
- Use same async-to-sync bridging pattern as ImageCommand for consistency
2025-06-08 09:53:11 +01:00
Peter Steinberger
fafa8fdc2a Convert test to use proper async/await instead of semaphore
- Replace DispatchSemaphore usage in ScreenshotValidationTests with async/await
- Make test functions async and use Task.sleep instead of RunLoop/Thread.sleep
- Use proper Swift Testing async patterns for better compatibility
2025-06-08 09:47:58 +01:00
Peter Steinberger
40acc9669b Fix deadlock in ImageCommand by replacing semaphore with RunLoop
- Remove DispatchSemaphore usage that violated Swift concurrency rules
- Implement RunLoop-based async-to-sync bridging in runAsyncCapture()
- Convert all capture methods to async/await patterns
- Replace Thread.sleep with Task.sleep in async contexts
- Keep ParsableCommand for compatibility, avoid AsyncParsableCommand issues
- Add comprehensive tests and documentation
- Improve error handling and browser helper filtering

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 09:41:50 +01:00
Peter Steinberger
5bdb2092ca feat: Add browser helper filtering for improved Chrome/Safari matching
Addresses the issue where searching for 'Chrome' or 'Safari' would incorrectly
match helper processes (like 'Google Chrome Helper (Renderer)') instead of the
main browser application, leading to confusing 'no capturable windows' errors.

Key improvements:
- Added filterBrowserHelpers() method that filters out helper processes for browser searches
- Supports common browsers: chrome, safari, firefox, edge, brave, arc, opera
- Filters out processes containing: helper, renderer, utility, plugin, service, crashpad, gpu, background
- Provides browser-specific error messages when main browser isn't running
- Only applies filtering to browser identifiers, preserves normal matching for other apps
- Comprehensive test coverage for browser filtering scenarios

Example: Searching for 'chrome' now finds 'Google Chrome' instead of
'Google Chrome Helper (Renderer)' which has no capturable windows.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:47:09 +01:00
Peter Steinberger
d5b40c1550 feat: Implement proper frontmost window capture
Adds support for capturing the frontmost window of the frontmost application
instead of falling back to screen capture mode.

Changes:
- Added 'frontmost' case to CaptureMode enum in Swift CLI
- Implemented captureFrontmostWindow() method using NSWorkspace.shared.frontmostApplication
- Updated TypeScript to use --mode frontmost instead of defaulting to screen mode
- Added comprehensive test coverage for frontmost functionality
- Updated existing tests to reflect new behavior

The frontmost mode now:
1. Detects the currently active application
2. Captures only its frontmost window (index 0)
3. Returns a single image file with proper metadata

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:42:43 +01:00
Peter Steinberger
17dea6ad79 fix: Prevent security vulnerability from malformed app targets
Addresses critical edge case where malformed app targets with multiple leading colons
(e.g., "::::::::::::::::Finder") created empty app names that would match ALL system
processes. This could potentially expose sensitive information or cause unintended
system-wide captures.

Key improvements:
- Enhanced app target parsing to validate non-empty app names
- Added fallback logic to extract valid app names from malformed inputs
- Default to screen mode when all parts are empty (security-first approach)
- Comprehensive test coverage for edge cases
- Improved backward compatibility with hidden path parameters

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:16:39 +01:00
Peter Steinberger
dd680eb638 feat: Improve window title matching and error messages for URLs with ports
When users search for windows with URLs containing ports (e.g., 'http://example.com:8080'),
the system now provides much better debugging information when the window isn't found.

Key improvements:
- Enhanced window not found errors now list all available window titles
- Added specific guidance for URL-based searches (try without protocol)
- New CaptureError.windowTitleNotFound with detailed debugging info
- Comprehensive test coverage for colon parsing in app targets
- Better error messages help users understand why matching failed

Example improved error:
"Window with title containing 'http://example.com:8080' not found in Google Chrome.
Available windows: 'example.com:8080 - Google Chrome', 'New Tab - Google Chrome'.
Note: For URLs, try without the protocol (e.g., 'example.com:8080' instead of 'http://example.com:8080')."

This addresses the common issue where browsers display simplified URLs in window titles
without the protocol, making it easier for users to find the correct matching pattern.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:09:47 +01:00
Peter Steinberger
822ea1cce7 fix: Correct error handling for path traversal and file system errors
Previously, path traversal attempts like `../../../../../../../etc/passwd` were incorrectly
reported as screen recording permission errors instead of file system errors.

Changes:
- Modified ScreenCapture error handling to distinguish between CaptureError types and ScreenCaptureKit errors
- CaptureError.fileWriteError now bypasses screen recording permission detection
- Added path validation in OutputPathResolver to detect and log path traversal attempts
- Added logging for system-sensitive path access attempts
- Comprehensive test coverage for various path traversal patterns and error scenarios

This ensures users get accurate error messages that guide them to the actual problem
(invalid paths, missing directories, file permissions) rather than misleading
screen recording permission prompts.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:05:03 +01:00
Peter Steinberger
4afd15279c feat: Capture all windows from multiple exact app matches instead of erroring
When multiple applications have exact matches (e.g., "claude" and "Claude"), the system now:
- Captures all windows from all matching applications instead of throwing an ambiguous match error
- Maintains sequential window indices across all matched applications
- Preserves original application names in saved file metadata
- Only returns errors for truly ambiguous fuzzy matches

This provides more useful behavior for common scenarios where users have multiple apps with
similar names (different case, etc.) and want to capture windows from all of them.

Updates:
- Added `captureWindowsFromMultipleApps` method to handle multi-app capture logic
- Modified error handling in both single window and multi-window capture modes
- Updated documentation (spec.md, CHANGELOG.md) to reflect new behavior
- Comprehensive test suite covering various multiple match scenarios

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:00:44 +01:00
Peter Steinberger
089d96ce22 fix: Handle edge cases for invalid screen index and JSON null paths
- Invalid screen index (e.g., screen:99) now properly falls back to capturing all screens with unique filenames
- String "null" in path parameter is now correctly treated as undefined instead of literal path
- Added fallback-aware filename generation to prevent file overwrites when screen index is out of bounds
- Comprehensive test coverage for both edge cases

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:53:21 +01:00
Peter Steinberger
9837e7bea8 style: Apply SwiftFormat formatting
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:29:37 +01:00
Peter Steinberger
c3e03a730b chore: Bump version to 1.0.0-beta.20
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:27:43 +01:00
Peter Steinberger
ed1860d546 feat: Improve error propagation and debugging for system-level failures
- Enhanced CaptureError types to include underlying system errors
- Added comprehensive error logging in debug_logs for troubleshooting
- Fixed duplicate error output from ApplicationFinder
- Improved error details for app not found to show available applications
- Updated test expectations to match new error message formats

This ensures that errors from deep within ScreenCaptureKit and file operations
are properly surfaced to users with full context in the debug logs.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:08:35 +01:00
Peter Steinberger
c6148849f8 feat: Hide window count for single-window apps (PR #6)
- Only show window count when it's not 1 in list apps output
- Extract formatApplicationList method for better testability
- Fix Swift test compatibility with new CaptureError signatures
- Add comprehensive test coverage for window count display logic

This improves readability by reducing visual clutter for the common
case of apps with single windows.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:07:53 +01:00
Peter Steinberger
f3c3cbb073 fix: Improve permission error detection and add debug logging
- Added debug logging to PermissionsChecker when screen recording check fails
- Updated CHANGELOG with details about the permission error fixes
- This complements the previous commit that fixed overly broad error detection

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:57:34 +01:00
Peter Steinberger
e6b8931d91 refactor: Improve screen recording permission error detection
- Extract permission error detection into a dedicated method
- Add specific error code checks for ScreenCaptureKit and CoreGraphics
- Improve directory existence check in saveImage method
- More reliable detection of screen recording permission denials

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:50:38 +01:00
Peter Steinberger
cef648fa8f style: Apply SwiftFormat formatting
🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:19:17 +01:00
Peter Steinberger
30277bbf6c fix: Prevent format 'data' for screen captures to avoid stack overflow
- Screen captures now reject format: 'data' with clear error message
- Large screen images cause JavaScript stack overflow when base64 encoded
- Application window captures can still use format: 'data'
- Update tests and documentation to reflect this limitation
2025-06-08 06:04:09 +01:00
codegen-sh[bot]
338b994ac9
Fix all test warnings (#4)
Co-authored-by: codegen-sh[bot] <131295404+codegen-sh[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2025-06-08 05:37:15 +01:00
Peter Steinberger
e24c2b6de7 fix: Resolve SwiftLint violations in fuzzy matching code 2025-06-08 05:24:34 +01:00
Peter Steinberger
94e966fa98 feat: Add fuzzy matching for application names
- Implement Levenshtein distance algorithm for fuzzy app name matching
- Handle common typos like "Chromee" → "Google Chrome"
- Add window-specific labels in analysis results
- Improve error messages with app name suggestions
- Fix TypeScript JSON parsing for error responses
- Update tests for new error message formats

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 05:22:58 +01:00
Peter Steinberger
2b72a69a70 Fix Swift lint violations for release
- Remove trailing comma in test array
- Fix long line in error message

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 04:38:27 +01:00
Peter Steinberger
e85f0c81b8 Apply SwiftFormat changes for release preparation
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 04:37:52 +01:00
Peter Steinberger
282d00f5d9 Add auto capture focus mode and fix list tool validation
- Added new "auto" capture focus mode that intelligently brings windows to foreground only when needed
- Changed default capture_focus from "background" to "auto" for better screenshot success rates
- Fixed list tool server_status validation to allow empty include_window_details arrays
- Added comprehensive tests for new auto mode functionality
- Enhanced error messages for better user experience

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 04:31:28 +01:00
Peter Steinberger
e9e2cdb6cb Improve error handling when no windows are available 2025-06-08 04:05:52 +01:00
Peter Steinberger
8145455fc4 add tests for path handling 2025-06-08 03:48:49 +01:00
Peter Steinberger
0c4706393e Improve output path handling 2025-06-08 03:48:33 +01:00
Peter Steinberger
e2eef703a6 Improve error handling 2025-06-08 03:48:19 +01:00
Peter Steinberger
10672e57c0 Prepare v1.0.0-beta.15: Improved list tool usability and robustness
### Improved
- The list tool is now more lenient and user-friendly
- item_type parameter is now optional (defaults to 'running_applications')
- Intelligent auto-detection when app parameter is provided
- Enhanced error handling and validation

### Fixed
- Fixed crash when list tool called with empty item_type
- Improved image tool path handling for temporary files
- Better error messages and validation throughout

### Tests
- Added comprehensive test coverage for new list tool features
- Enhanced integration tests for improved scenarios
- Total test count increased from 223 to 228 tests

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 02:36:13 +01:00
Peter Steinberger
dc0b29b0b1 fix: resolve Swift test compilation issue with allSatisfy closure 2025-06-08 02:03:45 +01:00