You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add experimental system-wide API key masking via Accessibility overlay
Add system-wide masking that detects API keys in any macOS application
using the Accessibility API and covers them with floating NSPanel overlays.
Core implementation:
- SystemMaskingService: AXObserver monitors focused UI elements across
all apps via kAXFocusedUIElementChangedNotification and
kAXValueChangedNotification. 10ms initial / 30ms debounce + 500ms
polling fallback. Immediate scan on app switch.
- AXBoundsForRange: precise multi-line text coordinate calculation,
supports keys spanning multiple visual lines
- SystemOverlayController: click-through NSPanel overlays with
ignoresMouseEvents, reuses panels via deterministic UUID per match
- MaskOverlayView: solid background overlay with masked text display
Integration:
- Settings toggle: "System-wide masking (experimental)" in Security tab,
default OFF. Only activates when both setting AND Demo Mode are ON.
- Peek mode: hold ⌃⌥Space to temporarily hide all overlays
- Overlay lifecycle: auto-clear on app switch, text change, Demo Mode OFF
Performance (measured):
- Pattern matching: 0.1-0.3ms per scan
- Total scan + overlay: 2-6ms
- NSHostingView reuse prevents view accumulation
- Text cache prevents redundant overlay updates
- Safe AX API usage: nil guards, isRunning check in callback
Known limitations (marked experimental):
- Only scans focused element (sidebar/non-focused areas not covered)
- Copy/paste still exposes original key (visual overlay only)
- Some apps may not fully support AX text attributes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CLAUDE.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -106,6 +106,9 @@ These are absolute rules — never violate them:
106
106
-**Terminal masking sync block buffering** (experimental): Shielded Terminal buffers PTY output by detecting DEC 2026 sync block markers (`\x1b[?2026h`/`\x1b[?2026l`). Complete sync blocks are masked atomically. Non-sync data uses 30ms timeout buffer. This matches claude-chill's approach.
107
107
-**Terminal masking ANSI-aware matching**: `maskTerminalOutput()` strips ANSI escape codes AND all whitespace (spaces, tabs, newlines) before regex matching. Ink word-wraps long keys with `\r\n` + indentation; stripping all whitespace allows regex to match keys across visual line breaks. Structural characters (ANSI + whitespace) within matched ranges are preserved in output via `extractStructural()`.
-**System-wide masking** (experimental): Uses `AXObserver` + `kAXFocusedUIElementChangedNotification` / `kAXValueChangedNotification` to monitor focused text elements across all apps. `AXBoundsForRange` provides precise multi-line text coordinates. NSPanel overlay with `ignoresMouseEvents = true` for click-through. Settings toggle (`systemWideMasking` in UserDefaults), only active when both setting AND Demo Mode are ON.
110
+
-**System-wide masking performance**: 10ms initial scan delay, 30ms debounce for changes, 500ms polling fallback. Actual processing 2-6ms. Immediate scan on app switch. Text cache (`lastScannedText`) prevents redundant overlay updates.
111
+
-**System-wide masking coordinate conversion**: AX API uses top-left origin, AppKit uses bottom-left. Convert via `primaryScreenHeight - axY - height`. Multi-screen: use primary screen height as reference.
0 commit comments