Skip to content

Add native Accessibility selection capture - #13

Merged
CamaroW merged 5 commits into
mainfrom
codex/native-accessibility-selection
Jul 21, 2026
Merged

CamaroW merged 5 commits into
mainfrom
codex/native-accessibility-selection

Conversation

@CamaroW

@CamaroW CamaroW commented Jul 21, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add native, user-triggered selected-text capture through macOS Accessibility
  • add configurable ⌥⇧⌘S and preserve existing shortcut settings during migration
  • open Quick Capture near the selected text when Accessibility supplies bounds
  • keep the current backend/schema contract: native selections save as existing clipboard captures without surrounding context
  • add an off-by-default Clipboard Compatibility Mode for controls such as WeChat that can copy a selection but do not expose selected text through Accessibility
  • keep Accessibility status and a Manage Access… System Settings entry visible after permission is granted; macOS, not Recall, owns revocation

Clipboard fallback safety

  • bind every ticket to the exact frontmost external PID and revalidate it around both Copy attempts
  • bind the exact focused AX control when the app exposes one with complete safety evidence
  • use an application-scoped ticket when a custom-drawn app such as WeChat exposes no focused application/control relationship or selected-text value
  • reject known secure/protected controls, Secure Event Input, and any later app/control switch
  • wait for the physical shortcut modifiers to be released
  • archive bounded ordered pasteboard items/types in memory, send Copy twice, and accept only consecutive byte-identical payloads and identical text
  • restore only after that double confirmation and while the observed change count is unchanged
  • run the serial AX/pasteboard transaction outside MainActor
  • fail closed for missing permission, Recall itself, known secure/protected content, event denial, focus changes, timeouts, payload/count races, cancellation, and oversized text

macOS exposes neither clipboard-writer identity nor an atomic compare-and-restore operation. Custom-drawn apps may also omit per-control safety attributes. A very narrow writer race, delayed source-app Copy, crash, lazy representation, or restore failure can still change the clipboard. Clipboard history tools and Universal Clipboard may record the two temporary copies. The mode is therefore opt-in and these limits are disclosed in Settings and Quick Capture.

Verification

  • ./scripts/test-macos.sh — 149/149 passed
  • signed Xcode Debug build succeeds with the stable Recall development identity
  • real WeChat AX inspection confirmed the root cause: the current app exposes only its window, with no usable focused control
  • Settings UI verified locally, including the custom-drawn-app disclosure
  • staged/final diff checks pass

Manual acceptance before merge

  • Primary Accessibility path accepted with the physical ⌥⇧⌘S shortcut
  • Enable Clipboard Compatibility Mode and capture selected text in WeChat
  • Repeat while the prior clipboard holds plain text, rich text, an image, and Finder files; verify each prior value is restored
  • Confirm password/secure fields, no selection, app/control switching, rapid repeats, and competing clipboard writes fail safely without a draft
  • Confirm the corrected WeChat flow and Settings permission UI have no observed issue

B-016 closed on 2026-07-21 after the user reported no issue in final testing and explicitly authorized merge. The unchecked extended clipboard/race cases remain release-regression coverage rather than claims of completed manual evidence.

@CamaroW
CamaroW marked this pull request as ready for review July 21, 2026 14:18
@CamaroW
CamaroW merged commit e6206e0 into main Jul 21, 2026
5 checks passed
@CamaroW
CamaroW deleted the codex/native-accessibility-selection branch July 21, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant