From cocoapods
Implements iOS 17+ privacy manifests for CocoaPods libraries: creates PrivacyInfo.xcprivacy files, declares required API reasons, and integrates via Podspec resource bundles for App Store compliance.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cocoapods:privacy-manifestsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement iOS 17+ privacy manifests for App Store compliance and user transparency.
Implement iOS 17+ privacy manifests for App Store compliance and user transparency.
Privacy manifests (PrivacyInfo.xcprivacy) are XML property list files that declare:
Starting with iOS 17 and Xcode 15, Apple requires privacy manifests for:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array/>
</dict>
</plist>
Pod::Spec.new do |spec|
spec.name = 'MyLibrary'
spec.version = '1.0.0'
spec.source_files = 'Source/**/*.swift'
# Include privacy manifest in resource bundle
spec.resource_bundles = {
'MyLibrary' => [
'Resources/**/*.xcprivacy',
'Resources/**/*.{png,jpg,xcassets}'
]
}
end
spec.resources = 'Resources/PrivacyInfo.xcprivacy'
# Or with glob pattern
spec.resources = 'Resources/**/*.xcprivacy'
MyLibrary/
├── MyLibrary.podspec
├── Source/
│ └── MyLibrary/
└── Resources/
├── PrivacyInfo.xcprivacy # Privacy manifest
└── Assets.xcassets
Apple requires declarations for these privacy-sensitive APIs:
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
</array>
Reason Codes:
C617.1: Display timestamps to user0A2A.1: Access timestamps of files in app container3B52.1: Access timestamps for app functionalityDDA9.1: Timestamp access for debugging<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
Reason Codes:
CA92.1: Access user defaults in same app group1C8F.1: Access user defaults for app functionalityC56D.1: SDK-specific configuration preferencesAC6B.1: Third-party SDK functionality<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
Reason Codes:
35F9.1: Measure time elapsed for app functionality8FFB.1: Calculate absolute timestamp3D61.1: Measure time for performance testing<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>85F4.1</string>
</array>
</dict>
Reason Codes:
85F4.1: Display disk space to userE174.1: Check disk space before file operations7D9E.1: Health/fitness app disk spaceB728.1: User-initiated file management<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeEmailAddress</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
NSPrivacyCollectedDataTypeEmailAddressNSPrivacyCollectedDataTypeNameNSPrivacyCollectedDataTypePhoneNumberNSPrivacyCollectedDataTypeDeviceIDNSPrivacyCollectedDataTypeUserIDNSPrivacyCollectedDataTypePreciseLocationNSPrivacyCollectedDataTypeCoarseLocationNSPrivacyCollectedDataTypeSearchHistoryNSPrivacyCollectedDataTypeBrowsingHistoryNSPrivacyCollectedDataTypePurposeThirdPartyAdvertisingNSPrivacyCollectedDataTypePurposeAppFunctionalityNSPrivacyCollectedDataTypePurposeAnalyticsNSPrivacyCollectedDataTypePurposeProductPersonalizationNSPrivacyCollectedDataTypePurposeOther<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyTracking</key>
<true/>
<key>NSPrivacyTrackingDomains</key>
<array>
<string>analytics.example.com</string>
<string>tracking.example.com</string>
</array>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- No tracking -->
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<!-- Data collection -->
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeUserID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<!-- Required Reasons APIs -->
<key>NSPrivacyAccessedAPITypes</key>
<array>
<!-- User Defaults for caching -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<!-- File timestamps for cache validation -->
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>3B52.1</string>
</array>
</dict>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Tracking enabled -->
<key>NSPrivacyTracking</key>
<true/>
<key>NSPrivacyTrackingDomains</key>
<array>
<string>analytics.myservice.com</string>
</array>
<!-- Data collection -->
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<true/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
</array>
<!-- Required Reasons APIs -->
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array>
</dict>
</plist>
Pod::Spec.new do |spec|
spec.name = 'MyAnalyticsSDK'
spec.version = '1.0.0'
spec.ios.deployment_target = '13.0'
spec.source_files = 'Source/**/*.swift'
# Include privacy manifest
spec.resource_bundles = {
'MyAnalyticsSDK' => [
'Resources/PrivacyInfo.xcprivacy'
]
}
# Platform-specific privacy manifests
spec.ios.resource_bundles = {
'MyAnalyticsSDK_iOS' => ['Resources/iOS/PrivacyInfo.xcprivacy']
}
spec.osx.resource_bundles = {
'MyAnalyticsSDK_macOS' => ['Resources/macOS/PrivacyInfo.xcprivacy']
}
end
# Lint with privacy manifest
pod lib lint
# Validate privacy manifest is included
pod lib lint --verbose | grep -i privacy
# Generate .xcarchive
xcodebuild archive -workspace MyApp.xcworkspace -scheme MyApp
# Validate before submission
xcodebuild -exportArchive -archivePath MyApp.xcarchive -exportPath MyApp.ipa -exportOptionsPlist ExportOptions.plist
<!-- Only declare what you actually use -->
<key>NSPrivacyCollectedDataTypes</key>
<array>
<!-- Only include if you actually collect this data -->
</array>
<!-- Use correct reason codes -->
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string> <!-- Must match actual usage -->
</array>
# Update privacy manifest when adding new APIs
spec.version = '1.1.0' # Bump version
# Update PrivacyInfo.xcprivacy with new declarations
❌ Omit privacy manifest for iOS 17+ apps
# Missing privacy manifest - App Store rejection risk
spec.resource_bundles = {
'MyLibrary' => ['Resources/**/*.png']
# No PrivacyInfo.xcprivacy
}
❌ Use incorrect reason codes
<string>WRONG.1</string> <!-- Invalid code -->
❌ Declare tracking without domains
<key>NSPrivacyTracking</key>
<true/>
<key>NSPrivacyTrackingDomains</key>
<array/> <!-- Empty - inconsistent -->
✅ Include privacy manifest for all iOS SDKs
spec.resource_bundles = {
'MyLibrary' => ['Resources/PrivacyInfo.xcprivacy']
}
✅ Use accurate reason codes
<string>CA92.1</string> <!-- Valid, matches usage -->
✅ Be truthful about tracking
<key>NSPrivacyTracking</key>
<true/>
<key>NSPrivacyTrackingDomains</key>
<array>
<string>analytics.example.com</string>
</array>
npx claudepluginhub thebushidocollective/han --plugin cocoapodsGuides App Store submission preparation and rejection prevention. Covers privacy manifests, StoreKit/IAP rules, ATT, HIG compliance, and metadata requirements.
Guides creation and modification of CocoaPods podspec files, covering required attributes, source file patterns, dependencies, and platform specs for iOS, macOS, tvOS, watchOS, visionOS.
Implements data minimization, granular permissions, consent management, and user privacy controls for mobile apps to meet App Store, Play Store, GDPR, and CCPA requirements.