Source profileQuality 91/100

aka-kika/akakika-skills/skills/swift-macos/macos-permissions-privacy/SKILL.md

macos-permissions-privacy

Use when a macOS app needs a TCC permission or touches private data — the map of which API, Info.plist key, and entitlement each permission needs, pre-prompt explanation patterns, denied-state recovery with System Settings deep links, and honest privacy copy.

Source repository stars
8
Declared platforms
0
Static risk flags
1
Last source update
2026-08-19
Source checked
2026-08-25

Decision brief

What it does: where it fits

Request only what the app needs now, explain why before the system asks, and give every denied state a recovery path. On macOS the permission landscape (TCC) is a patchwork — each permission has its own API, its own Info.plist key, and its own failure mode; the map below is most…

Best for

  • permission / permission prompt / TCC
  • Accessibility access, Screen Recording, Full Disk Access, Input Monitoring
  • Automation / Apple Events / "wants to control"

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/aka-kika/akakika-skills --skill "skills/swift-macos/macos-permissions-privacy"
Safe inspection promptEditorial

Inspect the Agent Skill "macos-permissions-privacy" from https://github.com/aka-kika/akakika-skills/blob/b7081fb221ba5dc51c3b074c2dda67f143c20112/skills/swift-macos/macos-permissions-privacy/SKILL.md at commit b7081fb221ba5dc51c3b074c2dda67f143c20112. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    The four-step flow (every permission)

    1. Check silently. Never re-prompt on launch; read status first.

    1. Check silently. Never re-prompt on launch; read status first.2. Pre-explain at the moment of need. The system dialog must never be the first the user hears of it:3. Request narrowly. A folder picker instead of Full Disk Access. One target app for Automation instead of "everything". whenInUse instead of always.
  2. 02

    When to use

    Use this skill when the user says:

    permission / permission prompt / TCCAccessibility access, Screen Recording, Full Disk Access, Input MonitoringAutomation / Apple Events / "wants to control"
  3. 03

    Core rule

    Review the “Core rule” section in the pinned source before continuing.

    Review and apply the “Core rule” source section.
  4. 04

    The permission map

    The column you'll consult most. "Prompt?" = can the app trigger a system dialog, or must the user flip a switch in System Settings themselves?

    The column you'll consult most. "Prompt?" = can the app trigger a system dialog, or must the user flip a switch in System Settings themselves?Sandboxed apps additionally need the matching entitlement (com.apple.security.files.user-selected.read-write, .device.camera, .personal-information., …) — without it the API fails without even prompting. A missing Info.…
  5. 05

    System Settings deep links

    A denied state without a button to the right pane is a dead end; with it, it's a two-click fix.

    A denied state without a button to the right pane is a dead end; with it, it's a two-click fix.

Permission review

Static risk signals and limitations

Reads files

low · line 165

The documentation asks the agent to read local files, directories, or repositories.

What we access concrete: "the folder you choose", not "your files"

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score91/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars8SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
aka-kika/akakika-skills
Skill path
skills/swift-macos/macos-permissions-privacy/SKILL.md
Commit
b7081fb221ba5dc51c3b074c2dda67f143c20112
License
MIT
Collected
2026-08-25
Default branch
main
View the original SKILL.md

macOS Permissions & Privacy

Request only what the app needs now, explain why before the system asks, and give every denied state a recovery path. On macOS the permission landscape (TCC) is a patchwork — each permission has its own API, its own Info.plist key, and its own failure mode; the map below is most of the work.

When to use

Use this skill when the user says:

  • permission / permission prompt / TCC
  • Accessibility access, Screen Recording, Full Disk Access, Input Monitoring
  • Automation / Apple Events / "wants to control"
  • access files, contacts, calendar, camera, microphone
  • app can't see the folder / operation not permitted
  • privacy settings / privacy copy
  • sandbox entitlements for user data

Do not use this skill for notification permission specifically (see macos-notifications) or for iOS-only flows like App Tracking Transparency.

Core rule

Explain before the system prompts. Request at the moment of need.
Request the narrowest thing that works. Every denied state has a
visible recovery path.

The permission map

The column you'll consult most. "Prompt?" = can the app trigger a system dialog, or must the user flip a switch in System Settings themselves?

NeedAPI to check/requestInfo.plist usage stringPrompt?
Files the user picksNSOpenPanel / drag-in + security-scoped bookmarksPicker is consent
Desktop / Documents / Downloads (programmatic)just access it; system prompts onceYes, automatic
Network volumes / removablesameYes, automatic
Full Disk Accessnone — attempt access, detect failureNo — Settings only
Accessibility (control UI, event taps)AXIsProcessTrustedWithOptionsPrompt opens Settings
Screen RecordingCGPreflightScreenCaptureAccess() / CGRequestScreenCaptureAccess()Once; then Settings
Input MonitoringIOHIDCheckAccess(.listenEvent) / IOHIDRequestAccessYes
Automation (Apple Events)AEDeterminePermissionToAutomateTargetNSAppleEventsUsageDescriptionYes, per target app
Camera / MicrophoneAVCaptureDevice.requestAccess(for:)NSCameraUsageDescription / NSMicrophoneUsageDescriptionYes
ContactsCNContactStore.requestAccessNSContactsUsageDescriptionYes
Calendar / RemindersEKEventStore.requestFullAccessToEvents()NSCalendarsFullAccessUsageDescriptionYes
LocationCLLocationManager.requestWhenInUseAuthorizationNSLocationUsageDescriptionYes

Sandboxed apps additionally need the matching entitlement (com.apple.security.files.user-selected.read-write, .device.camera, .personal-information.*, …) — without it the API fails without even prompting. A missing Info.plist usage string doesn't ask either: it crashes the app at request time.

The four-step flow (every permission)

1. Check silently. Never re-prompt on launch; read status first.

2. Pre-explain at the moment of need. The system dialog must never be the first the user hears of it:

The user clicks "Watch this folder"
  → sheet: "To notice new files, the app needs access to the
     folder you choose. Nothing leaves your Mac."   [Choose Folder…]
  → NSOpenPanel (which itself grants the access)

3. Request narrowly. A folder picker instead of Full Disk Access. One target app for Automation instead of "everything". whenInUse instead of always.

4. Handle denial with recovery. Show the off state where the feature lives and in Settings, with a deep link.

System Settings deep links

func openPrivacyPane(_ pane: String) {
    let url = URL(string:
        "x-apple.systempreferences:com.apple.preference.security?\(pane)")!
    NSWorkspace.shared.open(url)
}

// The panes you'll actually need:
// Privacy_Accessibility      Privacy_ScreenCapture      Privacy_AllFiles
// Privacy_Automation         Privacy_Microphone         Privacy_Camera
// Privacy_ListenEvent (input monitoring)                Privacy_LocationServices

A denied state without a button to the right pane is a dead end; with it, it's a two-click fix.

Worked patterns

Files: the picker is the permission

In the sandbox, whatever the user picks (or drags in) is granted. Persist access with a security-scoped bookmark, or the grant dies with the process:

// After NSOpenPanel:
let bookmark = try url.bookmarkData(options: .withSecurityScope,
                                    includingResourceValuesForKeys: nil,
                                    relativeTo: nil)
// store `bookmark` (Data) in your app support dir

// On next launch:
var stale = false
let url = try URL(resolvingBookmarkData: bookmark,
                  options: .withSecurityScope,
                  relativeTo: nil,
                  bookmarkDataIsStale: &stale)
guard url.startAccessingSecurityScopedResource() else { /* re-pick */ return }
defer { url.stopAccessingSecurityScopedResource() }
// … read/write …

If stale is true, re-create the bookmark from the resolved URL. If resolving fails (folder moved/deleted), ask the user to pick again — don't silently do nothing.

Accessibility

// Check without prompting:
let trusted = AXIsProcessTrusted()

// Check AND show the system's "grant in Settings" dialog once:
let options = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true]
let trusted = AXIsProcessTrustedWithOptions(options as CFDictionary)

The grant does not take effect until your process is relaunched in some flows — after the user enables it, re-check on didBecomeActiveNotification and offer "Relaunch" if features still fail.

Screen recording

if !CGPreflightScreenCaptureAccess() {        // silent check
    let granted = CGRequestScreenCaptureAccess() // prompts once, ever
    if !granted { /* show recovery UI → Privacy_ScreenCapture */ }
}

CGRequestScreenCaptureAccess only produces a dialog the first time; afterwards it just returns false. Treat "false" as "send them to Settings", and expect macOS 15+ to periodically re-confirm this permission with the user on your behalf.

Full Disk Access — avoid, then detect

There is no API to request FDA. First redesign: can a folder picker cover it? If genuinely not (backup tools, indexers), detect by probing a protected path and guide:

// TCC-protected on every Mac; unreadable without FDA
let probe = FileManager.default
    .homeDirectoryForCurrentUser
    .appendingPathComponent("Library/Mail")
let hasFDA = (try? FileManager.default
    .contentsOfDirectory(atPath: probe.path)) != nil

Pair the guide screen with Privacy_AllFiles and exact instructions ("drag the app into the list, then relaunch").

Automation (controlling another app)

var target = NSAppleEventDescriptor(bundleIdentifier: "com.apple.finder")
let status = AEDeterminePermissionToAutomateTarget(
    target.aeDesc, typeWildCard, typeWildCard, true)   // true = may prompt
// noErr = allowed · errAEEventNotPermitted = denied
// procNotFound = target not running (launch it first, then ask)

Requires NSAppleEventsUsageDescription in Info.plist and (sandboxed) a scripting-targets entitlement. The prompt names the target app — one prompt per target.

Privacy copy pattern

Wherever a permission is explained — pre-prompt sheet, Settings, onboarding:

Why we need this      one sentence, the feature not the API
What we access        concrete: "the folder you choose", not "your files"
What stays local      say it plainly if everything does
How to change it      "System Settings > Privacy & Security > X, anytime"

If the app is local-first, say so in the permission moment — "processed on your Mac, never uploaded" is the sentence that converts a hesitant deny into a grant, and it must be true.

Settings: the permission dashboard

Apps that need 2+ permissions should show their state honestly in one place:

Permissions
  Folder access      ~/Notes granted        Change…
  Accessibility      Not granted            Open System Settings…
  Screen recording   Granted

Re-read all statuses when the app becomes active — every one of these can be revoked behind your back, and stale "Granted" labels destroy trust.

Checklist

[ ] Every permission has a pre-prompt explanation in product language
[ ] Requests fire at the moment of need, never stacked at first launch
[ ] Narrowest scope chosen (picker over FDA, one target over many)
[ ] Info.plist usage strings present for every prompting API (missing = crash)
[ ] Sandbox entitlements match the APIs used
[ ] Denied state visible where the feature lives, with the right deep link
[ ] Statuses re-checked on app activation, never cached across launches
[ ] Security-scoped bookmarks persisted and stale-handled for file access
[ ] Privacy copy states what stays local — and it's true

Manual test

  1. Fresh profile (or tccutil reset <service> <bundle-id>) → feature first-use shows your explanation, then the system prompt.
  2. Deny → feature shows its off state + deep link lands on the right pane.
  3. Grant in Settings → return to app → status updates without relaunch (or app offers relaunch where required).
  4. Revoke while the app is running → app degrades with the recovery UI, no crash.
  5. Move a bookmarked folder → app asks to re-pick, doesn't silently break.

Frequently asked questions

What to verify before installation and use

What does the macos-permissions-privacy source document cover?

Request only what the app needs now, explain why before the system asks, and give every denied state a recovery path. On macOS the permission landscape (TCC) is a patchwork — each permission has its own API, its own Info.plist key, and its own failure mode; the map below is most…

How do I install macos-permissions-privacy?

The source record exposes this install command: npx skills add https://github.com/aka-kika/akakika-skills --skill "skills/swift-macos/macos-permissions-privacy". Inspect the command and pinned source before running it.

Which permission-related actions were detected?

Static rules flagged read-files in the source; the page lists the matching lines and excerpts.

Alternatives

Compare before choosing