makgunay/claude-swift-skills

macos-permissions

macOS permission handling for Accessibility (AXIsProcessTrusted), Screen Recording, Full Disk Access, input monitoring, camera, microphone, location, and contacts. Covers TCC (Transparency Consent and Control) database, graceful degradation when permissions are denied, permission prompting patterns, opening System Settings to the correct pane, detecting permission changes, and the privacy manifest (PrivacyInfo.xcprivacy) requirement. Use when implementing features that require system permission…

First seen Feb 14, 2026

Installation

$ npx skills add makgunay/claude-swift-skills --skill macos-permissions

Summary

  • macOS permission handling for Accessibility (AXIsProcessTrusted), Screen Recording, Full Disk Access, input monitoring, camera, microphone, location, and contacts.
  • Covers TCC (Transparency Consent and Control) database, graceful degradation when permissions are denied, permission prompting patterns, opening System Settings to the correct pane, detecting permission changes, and the privacy manifest (PrivacyInfo.xcprivacy) requirement.
  • Use when implementing features that require system permissions, building permission onboarding flows, or handling denied permissions gracefully.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from makgunay/claude-swift-skills · top by installs.

npx skills add makgunay/claude-swift-skills

Browse all from makgunay/claude-swift-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License LICENSE
Default branch main
Open issues 0
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,898 B
  • docs SUMMARY.md 607 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 24 installs

SKILL.md

macOS Permissions

Critical Constraints

  • ❌ DO NOT assume permissions are granted → ✅ Always check before using protected APIs
  • ❌ DO NOT repeatedly prompt after denial → ✅ Guide user to System Settings instead
  • ❌ DO NOT block the entire app on missing permission → ✅ Gracefully degrade, offer reduced functionality
  • ❌ DO NOT forget PrivacyInfo.xcprivacy → ✅ Required for App Store submission

Permission Types

Permission Check API Required For
Accessibility AXIsProcessTrusted() Global hotkeys, text insertion, CGEvent
Screen Recording CGPreflightScreenCaptureAccess() Screen capture, window list
Full Disk Access Try access + handle error Reading other app data
Camera AVCaptureDevice.authorizationStatus(for: .video) Camera access
Microphone AVCaptureDevice.authorizationStatus(for: .audio) Audio capture
Location CLLocationManager().authorizationStatus Location services
Contacts CNContactStore.authorizationStatus(for: .contacts) Contact access

Accessibility Permission

import ApplicationServices

// Check without prompting
func isAccessibilityGranted() -> Bool {
    AXIsProcessTrusted()
}

// Check and prompt user (shows system dialog)
func requestAccessibilityPermission() -> Bool {
    let options = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as String: true]
    return AXIsProcessTrustedWithOptions(options as CFDictionary)
}

// Open System Settings → Privacy → Accessibility
func openAccessibilitySettings() {
    NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")!)
}

Screen Recording Permission

import CoreGraphics

// Check (macOS 15+)
func isScreenRecordingGranted() -> Bool {
    CGPreflightScreenCaptureAccess()
}

// Request (macOS 15+)
func requestScreenRecording() -> Bool {
    CGRequestScreenCaptureAccess()
}

// Open Settings
func openScreenRecordingSettings() {
    NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture")!)
}

Camera / Microphone

import AVFoundation

func checkCameraPermission() async -> Bool {
    switch AVCaptureDevice.authorizationStatus(for: .video) {
    case .authorized: return true
    case .notDetermined: return await AVCaptureDevice.requestAccess(for: .video)
    case .denied, .restricted: return false
    @unknown default: return false
    }
}

Graceful Degradation Pattern

struct FeatureAvailability {
    var canInsertText: Bool { AXIsProcessTrusted() }
    var canUseGlobalHotkey: Bool { AXIsProcessTrusted() }
    var canCaptureScreen: Bool { CGPreflightScreenCaptureAccess() }

    var degradedFeatures: [String] {
        var features: [String] = []
        if !canInsertText { features.append("Text insertion into other apps") }
        if !canUseGlobalHotkey { features.append("Global keyboard shortcuts") }
        return features
    }
}

struct PermissionBanner: View {
    let availability: FeatureAvailability

    var body: some View {
        if !availability.degradedFeatures.isEmpty {
            VStack(alignment: .leading, spacing: 8) {
                Label("Some features require permissions", systemImage: "lock.shield")
                    .font(.headline)
                ForEach(availability.degradedFeatures, id: \.self) { feature in
                    Text("• \(feature)")
                        .font(.caption)
                }
                Button("Open System Settings") { openAccessibilitySettings() }
                    .buttonStyle(.borderedProminent)
            }
            .padding()
            .glassEffect(.regular.tint(.orange), in: .rect(cornerRadius: 12))
        }
    }
}

Permission Onboarding Flow

struct OnboardingPermissionView: View {
    @State private var accessibilityGranted = AXIsProcessTrusted()
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack(spacing: 20) {
            Image(systemName: accessibilityGranted ? "checkmark.circle.fill" : "lock.circle")
                .font(.system(size: 48))
                .foregroundStyle(accessibilityGranted ? .green : .orange)

            Text(accessibilityGranted ? "Permission Granted!" : "Accessibility Permission Required")
                .font(.title2)

            if !accessibilityGranted {
                Text("This app needs Accessibility access to insert text into other apps and register global shortcuts.")
                    .multilineTextAlignment(.center)

                Button("Open System Settings") {
                    requestAccessibilityPermission()
                }
                .buttonStyle(.borderedProminent)
            }
        }
        .onReceive(timer) { _ in
            accessibilityGranted = AXIsProcessTrusted()
        }
    }
}

Privacy Manifest (PrivacyInfo.xcprivacy)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
<plist version="1.0">
<dict>
    <key>NSPrivacyTracking</key>
    <false/>
    <key>NSPrivacyTrackingDomains</key>
    <array/>
    <key>NSPrivacyCollectedDataTypes</key>
    <array/>
    <key>NSPrivacyAccessedAPITypes</key>
    <array>
        <dict>
            <key>NSPrivacyAccessedAPIType</key>
            <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
            <key>NSPrivacyAccessedAPITypeReasons</key>
            <array><string>CA92.1</string></array>
        </dict>
    </array>
</dict>
</plist>

Common Mistakes & Fixes

Mistake Fix
Prompting repeatedly after denial Check status first, guide to Settings if denied
App crashes without permission Always check before calling protected API
User can't find permission setting Open specific System Settings pane via URL
Missing privacy manifest Add PrivacyInfo.xcprivacy to app bundle

References