SnapAction is a local-first macOS utility that turns screen or image OCR into a confirmed action: create a Reminder, create a Calendar event, or copy clean text/table output.
SnapAction is maintained by RSI Tech and licensed under Apache License 2.0. Copyright 2026 Rafal Sikora. Contributions are accepted under Apache-2.0 with a DCO sign-off; see Contributing, Security, and Privacy.
- macOS 26+
- Xcode 26+
- Swift 6.2+
- Apple Intelligence enabled for AI-first extraction
The app remains useful without Apple Intelligence: it falls back to safe text/table extraction and does not silently create Reminder or Calendar candidates.
- The capture shortcut takes the first display; there is no display picker yet.
- Local source builds use an ad-hoc-signed community identity. The initial
v0.1.0direct-download prerelease is Developer ID signed but not notarized, sandboxed, or App Store packaged; standard Gatekeeper launch remains blocked until a notarized asset replaces it. - Foundation Models availability depends on the local macOS and Apple Intelligence configuration.
- System-wide shortcut monitoring can be limited by macOS privacy settings; focused menu commands remain available.
- The formal Codex Security scan was skipped for the initial release by explicit owner direction. This is disclosed as accepted residual risk, not as completed security evidence.
swift test
swift build
script/build_and_run.shFor a non-interactive verification pass:
script/build_and_run.sh --verifyCommand-Shift-1: capture the first display through ScreenCaptureKit, OCR it with Vision, then suggest actions.Command-Shift-2: run the built-in demo capture without needing Screen Recording permission.Command-Shift-I: import an image and run Vision OCR.- Suggested actions are capped to three candidates and must be reviewed before execution.
- Reminders and Calendar writes use EventKit and request permission on first write.
- Text/table extraction copies to the macOS pasteboard.
- The last copied text/table payload is cached locally for up to seven days so it can be restored after closing, reopening, or restarting the app. It can be cleared independently in Settings.
- Local history stores only minimal action summaries: timestamp, action title and kind, and a bounded outcome. It does not persist OCR text, structured candidates, EventKit identifiers, or screenshot pixels. History expires according to the 1–90 day setting and can be cleared in Settings.
Screen capture requires macOS Screen Recording permission. If capture fails, use SnapAction Settings to request permission or open Privacy Settings, then restart the app if macOS requires it.
Calendar and Reminders permissions are requested only when a confirmed EventKit write is attempted. Denial is treated as a recoverable result and is not recorded as a successful action.
The global hotkey monitor uses macOS event monitoring. The menu commands always work while SnapAction is focused; system-wide key monitoring may require Accessibility permission depending on local privacy settings.
When a text/table action is confirmed, SnapAction saves the copied payload to:
~/Library/Application Support/SnapAction/clipboard.json
Use Restore Clipboard in the review surface to put the last saved payload back onto the macOS clipboard. The cache stores text only, never screenshot pixels.
The clipboard cache expires after seven days and can be cleared from Settings without clearing action history. Its containing directory and file are restricted to the current user where supported.
script/build_and_run.sh stages an unofficial SnapAction Community bundle with the neutral identifier org.example.snapaction.community unless a developer supplies validated overrides. See community build configuration. Official identity, signing credentials, Team IDs, and App Store credentials are not part of this repository.
Download the latest Apple-silicon ZIP and SHA-256 sidecar from GitHub Releases. The official archive uses the ai.rsitech.snapaction identity and is signed with RSI Tech's installed Developer ID Application identity. The initial v0.1.0 prerelease is not notarized and is rejected by Gatekeeper as Unnotarized Developer ID; check the release page for the exact status of later replacement assets, then verify the checksum:
shasum -a 256 -c SnapAction-0.1.0-macos-arm64.zip.sha256Build the same version locally with:
bash script/package_release.shswift test
swift build -c release
bash script/test_build_configuration.sh
bash script/test_bundle_metadata.sh
bash script/test_release_package.sh
python3 -m unittest discover -s Tests/ToolingTests -v
python3 script/check_repository_policy.py
python3 script/check_publication_gates.pyThe generated source manifest is at docs/open-source/OPEN_SOURCE_MANIFEST.json; the CycloneDX source SBOM is at artifacts/sbom/snapaction.cdx.json.
- If screen capture is denied, open SnapAction Settings, follow the Screen Recording guidance, and restart the app if macOS requests it.
- If Calendar or Reminders writes are denied, review the corresponding macOS Privacy & Security permission; the app will not record the action as successful.
- If the default bundle identity was overridden incorrectly, run
script/build_and_run.sh --print-config; invalid values fail before build or process changes. - If stale clipboard data should be removed, use Clear clipboard cache in Settings. History has a separate clear control.
- Contributing — Apache-2.0 and DCO contribution mechanics.
- Security — private reporting routes and supported-version scope.
- Support — safe support boundaries.
- Releasing — owner-controlled release gates.
- Changelog — factual unreleased changes.
Version 0.1.0 is the first public RSI Tech open-source release. See NOTICE for attribution and Apache-2.0 for use and redistribution terms.
SnapActionCore: OCR document model, action candidates, validation, extraction contracts, execution protocol, metadata-only history, and workflow orchestration.SnapActionApp: SwiftUI macOS app, menu bar extra, settings, Vision OCR, Foundation Models extraction, ScreenCaptureKit snapshot capture, EventKit writes, and pasteboard copy.
Rust is intentionally not part of v1. The future Rust boundary mirrors ActionExtractionRequest in and [ActionCandidate] plus validation diagnostics out.