Skip to content

fix: stop SCShareableContent polling loop that spammed screen recording prompt#20

Merged
execsumo merged 1 commit into
masterfrom
claude/screen-recording-permission-loop-5IC7f
May 26, 2026
Merged

fix: stop SCShareableContent polling loop that spammed screen recording prompt#20
execsumo merged 1 commit into
masterfrom
claude/screen-recording-permission-loop-5IC7f

Conversation

@execsumo

Copy link
Copy Markdown
Owner

PermissionCenter.refreshAsync() was calling SCShareableContent.excludingDesktopWindows()
every 3 seconds in the background polling task. On macOS, calling that API when screen
recording hasn't been granted yet triggers the TCC permission dialog. On a fresh install
or a non-dev machine this created an infinite loop: a new permission dialog every 3 seconds.

Fix:

  • refreshAsync() now polls with CGPreflightScreenCaptureAccess() only. This reads the
    live TCC database state without triggering any dialog. The macOS 15+ per-process cache
    is invalidated by TCC database changes, so a grant made in System Settings appears
    within one polling cycle (≤3 s) without needing SCShareableContent.

  • Rename checkScreenCapturePermission() → checkScreenCapturePermissionLive() and add a
    prominent WARNING in the doc comment: this function triggers the TCC dialog and must
    only be called from a direct user action, never from a polling loop.

  • In openScreenCaptureSettings(), keep the one-shot post-grant check (it's user-initiated
    so it's safe) but: (a) try the fast sync path first, (b) increase the delay from 1 s
    to 3 s so the SCShareableContent call fires after the user has returned from System
    Settings, not mid-interaction.

https://claude.ai/code/session_01XVfXe31wxQrYWMnQaTpAcy

…ng prompt

PermissionCenter.refreshAsync() was calling SCShareableContent.excludingDesktopWindows()
every 3 seconds in the background polling task. On macOS, calling that API when screen
recording hasn't been granted yet triggers the TCC permission dialog. On a fresh install
or a non-dev machine this created an infinite loop: a new permission dialog every 3 seconds.

Fix:
- refreshAsync() now polls with CGPreflightScreenCaptureAccess() only. This reads the
  live TCC database state without triggering any dialog. The macOS 15+ per-process cache
  is invalidated by TCC database changes, so a grant made in System Settings appears
  within one polling cycle (≤3 s) without needing SCShareableContent.

- Rename checkScreenCapturePermission() → checkScreenCapturePermissionLive() and add a
  prominent WARNING in the doc comment: this function triggers the TCC dialog and must
  only be called from a direct user action, never from a polling loop.

- In openScreenCaptureSettings(), keep the one-shot post-grant check (it's user-initiated
  so it's safe) but: (a) try the fast sync path first, (b) increase the delay from 1 s
  to 3 s so the SCShareableContent call fires after the user has returned from System
  Settings, not mid-interaction.

https://claude.ai/code/session_01XVfXe31wxQrYWMnQaTpAcy
@execsumo
execsumo merged commit 610d21a into master May 26, 2026
4 checks passed
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.

2 participants