{"id":"5afce087-1b99-4647-8ae3-f95cb30039f3","shortId":"jLMtDQ","kind":"skill","title":"permissionkit","tagline":"Create child communication safety experiences using PermissionKit to request parental permission for children. Use when building apps that involve child-to-contact communication, need to check communication limits, request parent/guardian approval, or handle permission responses ","description":"# PermissionKit\n\n> **Note:** PermissionKit is new in iOS 26. Method signatures should be verified against the latest Xcode 26 beta SDK.\n\nRequest permission from a parent or guardian to modify a child's communication\nrules. PermissionKit creates communication safety experiences that let children\nask for exceptions to communication limits set by their parents. Targets\nSwift 6.3 / iOS 26+.\n\n## Contents\n\n- [Setup](#setup)\n- [Core Concepts](#core-concepts)\n- [Checking Communication Limits](#checking-communication-limits)\n- [Creating Permission Questions](#creating-permission-questions)\n- [Requesting Permission with AskCenter](#requesting-permission-with-askcenter)\n- [SwiftUI Integration with PermissionButton](#swiftui-integration-with-permissionbutton)\n- [Handling Responses](#handling-responses)\n- [Significant App Update Topic](#significant-app-update-topic)\n- [Common Mistakes](#common-mistakes)\n- [Review Checklist](#review-checklist)\n- [References](#references)\n\n## Setup\n\nImport `PermissionKit`. No special entitlements are required.\n\n```swift\nimport PermissionKit\n```\n\n**Platform availability:** iOS 26+, iPadOS 26+, macOS 26+.\n\n## Core Concepts\n\nPermissionKit manages a flow where:\n\n1. A child encounters a communication limit in your app\n2. Your app creates a `PermissionQuestion` describing the request\n3. The system presents the question to the child for them to send to their parent\n4. The parent reviews and approves or denies the request\n5. Your app receives a `PermissionResponse` with the parent's decision\n\n### Key Types\n\n| Type | Role |\n|---|---|\n| `AskCenter` | Singleton that manages permission requests and responses |\n| `PermissionQuestion` | Describes the permission being requested |\n| `PermissionResponse` | The parent's decision (approval or denial) |\n| `PermissionChoice` | The specific answer (approve/decline) |\n| `PermissionButton` | SwiftUI button that triggers the permission flow |\n| `CommunicationTopic` | Topic for communication-related permission requests |\n| `CommunicationHandle` | A phone number, email, or custom identifier |\n| `CommunicationLimits` | Checks whether communication limits apply |\n| `SignificantAppUpdateTopic` | Topic for significant app update permission requests |\n\n## Checking Communication Limits\n\nBefore presenting a permission request, check if communication limits are\nenabled and whether the handle is known.\n\n```swift\nimport PermissionKit\n\nfunc checkCommunicationStatus(for handle: CommunicationHandle) async -> Bool {\n    let limits = CommunicationLimits.current\n    let isKnown = await limits.isKnownHandle(handle)\n    return isKnown\n}\n\n// Check multiple handles at once\nfunc filterKnownHandles(_ handles: Set<CommunicationHandle>) async -> Set<CommunicationHandle> {\n    let limits = CommunicationLimits.current\n    return await limits.knownHandles(in: handles)\n}\n```\n\n### Creating Communication Handles\n\n```swift\nlet phoneHandle = CommunicationHandle(\n    value: \"+1234567890\",\n    kind: .phoneNumber\n)\n\nlet emailHandle = CommunicationHandle(\n    value: \"friend@example.com\",\n    kind: .emailAddress\n)\n\nlet customHandle = CommunicationHandle(\n    value: \"user123\",\n    kind: .custom\n)\n```\n\n## Creating Permission Questions\n\nBuild a `PermissionQuestion` with the contact information and communication\naction type.\n\n```swift\n// Question for a single contact\nlet handle = CommunicationHandle(value: \"+1234567890\", kind: .phoneNumber)\nlet question = PermissionQuestion<CommunicationTopic>(handle: handle)\n\n// Question for multiple contacts\nlet handles = [\n    CommunicationHandle(value: \"+1234567890\", kind: .phoneNumber),\n    CommunicationHandle(value: \"friend@example.com\", kind: .emailAddress)\n]\nlet multiQuestion = PermissionQuestion<CommunicationTopic>(handles: handles)\n```\n\n### Using CommunicationTopic with Person Information\n\nProvide display names and avatars for a richer permission prompt.\n\n```swift\nlet personInfo = CommunicationTopic.PersonInformation(\n    handle: CommunicationHandle(value: \"+1234567890\", kind: .phoneNumber),\n    nameComponents: {\n        var name = PersonNameComponents()\n        name.givenName = \"Alex\"\n        name.familyName = \"Smith\"\n        return name\n    }(),\n    avatarImage: nil\n)\n\nlet topic = CommunicationTopic(\n    personInformation: [personInfo],\n    actions: [.message, .audioCall]\n)\n\nlet question = PermissionQuestion<CommunicationTopic>(communicationTopic: topic)\n```\n\n### Communication Actions\n\n| Action | Description |\n|---|---|\n| `.message` | Text messaging |\n| `.audioCall` | Voice call |\n| `.videoCall` | Video call |\n| `.call` | Generic call |\n| `.chat` | Chat communication |\n| `.follow` | Follow a user |\n| `.beFollowed` | Allow being followed |\n| `.friend` | Friend request |\n| `.connect` | Connection request |\n| `.communicate` | Generic communication |\n\n## Requesting Permission with AskCenter\n\nUse `AskCenter.shared` to present the permission request to the child.\n\n```swift\nimport PermissionKit\n\nfunc requestPermission(\n    for question: PermissionQuestion<CommunicationTopic>,\n    in viewController: UIViewController\n) async {\n    do {\n        try await AskCenter.shared.ask(question, in: viewController)\n        // Question was presented to the child\n    } catch let error as AskError {\n        switch error {\n        case .communicationLimitsNotEnabled:\n            // Communication limits not active -- no permission needed\n            break\n        case .contactSyncNotSetup:\n            // Contact sync not configured\n            break\n        case .invalidQuestion:\n            // Question is malformed\n            break\n        case .notAvailable:\n            // PermissionKit not available on this device\n            break\n        case .systemError(let underlying):\n            print(\"System error: \\(underlying)\")\n        case .unknown:\n            break\n        @unknown default:\n            break\n        }\n    }\n}\n```\n\n## SwiftUI Integration with PermissionButton\n\n`PermissionButton` is a SwiftUI view that triggers the permission flow\nwhen tapped.\n\n```swift\nimport SwiftUI\nimport PermissionKit\n\nstruct ContactPermissionView: View {\n    let handle = CommunicationHandle(value: \"+1234567890\", kind: .phoneNumber)\n\n    var body: some View {\n        let question = PermissionQuestion<CommunicationTopic>(handle: handle)\n\n        PermissionButton(question: question) {\n            Label(\"Ask to Message\", systemImage: \"message\")\n        }\n    }\n}\n```\n\n### PermissionButton with Custom Topic\n\n```swift\nstruct CustomPermissionView: View {\n    var body: some View {\n        let personInfo = CommunicationTopic.PersonInformation(\n            handle: CommunicationHandle(value: \"user456\", kind: .custom),\n            nameComponents: nil,\n            avatarImage: nil\n        )\n        let topic = CommunicationTopic(\n            personInformation: [personInfo],\n            actions: [.follow]\n        )\n        let question = PermissionQuestion<CommunicationTopic>(\n            communicationTopic: topic\n        )\n\n        PermissionButton(question: question) {\n            Text(\"Ask to Follow\")\n        }\n    }\n}\n```\n\n## Handling Responses\n\nListen for permission responses asynchronously.\n\n```swift\nfunc observeResponses() async {\n    let responses = AskCenter.shared.responses(for: CommunicationTopic.self)\n\n    for await response in responses {\n        let choice = response.choice\n        let question = response.question\n\n        switch choice.answer {\n        case .approval:\n            // Parent approved -- enable communication\n            print(\"Approved for topic: \\(question.topic)\")\n        case .denial:\n            // Parent denied -- keep restriction\n            print(\"Denied\")\n        @unknown default:\n            break\n        }\n    }\n}\n```\n\n### PermissionChoice Properties\n\n```swift\nlet choice: PermissionChoice = response.choice\nprint(\"Answer: \\(choice.answer)\")  // .approval or .denial\nprint(\"Choice ID: \\(choice.id)\")\nprint(\"Title: \\(choice.title)\")\n\n// Convenience statics\nlet approved = PermissionChoice.approve\nlet declined = PermissionChoice.decline\n```\n\n## Significant App Update Topic\n\nRequest permission for significant app updates that require parental approval.\n\n```swift\nlet updateTopic = SignificantAppUpdateTopic(\n    description: \"This update adds multiplayer chat features\"\n)\n\nlet question = PermissionQuestion<SignificantAppUpdateTopic>(\n    significantAppUpdateTopic: updateTopic\n)\n\n// Present the question\ntry await AskCenter.shared.ask(question, in: viewController)\n\n// Listen for responses\nfor await response in AskCenter.shared.responses(for: SignificantAppUpdateTopic.self) {\n    switch response.choice.answer {\n    case .approval:\n        // Proceed with update\n        break\n    case .denial:\n        // Skip update\n        break\n    @unknown default:\n        break\n    }\n}\n```\n\n## Common Mistakes\n\n### DON'T: Skip checking if communication limits are enabled\n\nIf communication limits are not enabled, calling `ask` throws\n`.communicationLimitsNotEnabled`. Check first or handle the error.\n\n```swift\n// WRONG: Assuming limits are always active\ntry await AskCenter.shared.ask(question, in: viewController)\n\n// CORRECT: Handle the case where limits are not enabled\ndo {\n    try await AskCenter.shared.ask(question, in: viewController)\n} catch AskError.communicationLimitsNotEnabled {\n    // Communication limits not active -- allow communication directly\n    allowCommunication()\n} catch {\n    handleError(error)\n}\n```\n\n### DON'T: Ignore AskError cases\n\nEach error case requires different handling.\n\n```swift\n// WRONG: Catch-all with no user feedback\ndo {\n    try await AskCenter.shared.ask(question, in: viewController)\n} catch {\n    print(error)\n}\n\n// CORRECT: Handle each case\ndo {\n    try await AskCenter.shared.ask(question, in: viewController)\n} catch let error as AskError {\n    switch error {\n    case .communicationLimitsNotEnabled:\n        allowCommunication()\n    case .contactSyncNotSetup:\n        showContactSyncPrompt()\n    case .invalidQuestion:\n        showInvalidQuestionAlert()\n    case .notAvailable:\n        showUnavailableMessage()\n    case .systemError(let underlying):\n        showSystemError(underlying)\n    case .unknown:\n        showGenericError()\n    @unknown default:\n        break\n    }\n}\n```\n\n### DON'T: Create questions with empty handles\n\nA question with no handles or person information is invalid.\n\n```swift\n// WRONG: Empty handles array\nlet question = PermissionQuestion<CommunicationTopic>(handles: [])  // Invalid\n\n// CORRECT: Provide at least one handle\nlet handle = CommunicationHandle(value: \"+1234567890\", kind: .phoneNumber)\nlet question = PermissionQuestion<CommunicationTopic>(handle: handle)\n```\n\n### DON'T: Forget to observe responses\n\nPresenting a question without listening for the response means you never\nknow if the parent approved.\n\n```swift\n// WRONG: Fire and forget\ntry await AskCenter.shared.ask(question, in: viewController)\n\n// CORRECT: Observe responses\nTask {\n    for await response in AskCenter.shared.responses(for: CommunicationTopic.self) {\n        handleResponse(response)\n    }\n}\ntry await AskCenter.shared.ask(question, in: viewController)\n```\n\n### DON'T: Use deprecated CommunicationLimitsButton\n\nUse `PermissionButton` instead of the deprecated `CommunicationLimitsButton`.\n\n```swift\n// WRONG: Deprecated\nCommunicationLimitsButton(question: question) {\n    Text(\"Ask Permission\")\n}\n\n// CORRECT: Use PermissionButton\nPermissionButton(question: question) {\n    Text(\"Ask Permission\")\n}\n```\n\n## Review Checklist\n\n- [ ] `AskError.communicationLimitsNotEnabled` handled to allow fallback\n- [ ] `AskError` cases handled individually with appropriate user feedback\n- [ ] `CommunicationHandle` created with correct `Kind` (phone, email, custom)\n- [ ] `PermissionQuestion` includes at least one handle or person information\n- [ ] `AskCenter.shared.responses(for:)` observed to receive parent decisions\n- [ ] `PermissionButton` used instead of deprecated `CommunicationLimitsButton`\n- [ ] Person information includes name components for a clear permission prompt\n- [ ] Communication actions match the app's actual communication capabilities\n- [ ] Response handling updates UI on the main actor\n- [ ] Error states provide clear guidance to the user\n\n## References\n\n- Extended patterns (response handling, multi-topic, UIKit): [references/permissionkit-patterns.md](references/permissionkit-patterns.md)\n- [PermissionKit framework](https://sosumi.ai/documentation/permissionkit)\n- [AskCenter](https://sosumi.ai/documentation/permissionkit/askcenter)\n- [PermissionQuestion](https://sosumi.ai/documentation/permissionkit/permissionquestion)\n- [PermissionButton](https://sosumi.ai/documentation/permissionkit/permissionbutton)\n- [PermissionResponse](https://sosumi.ai/documentation/permissionkit/permissionresponse)\n- [CommunicationTopic](https://sosumi.ai/documentation/permissionkit/communicationtopic)\n- [CommunicationHandle](https://sosumi.ai/documentation/permissionkit/communicationhandle)\n- [CommunicationLimits](https://sosumi.ai/documentation/permissionkit/communicationlimits)\n- [SignificantAppUpdateTopic](https://sosumi.ai/documentation/permissionkit/significantappupdatetopic)\n- [AskError](https://sosumi.ai/documentation/permissionkit/askerror)\n- [Creating a communication experience](https://sosumi.ai/documentation/permissionkit/creating-a-communication-experience)","tags":["permissionkit","swift","ios","skills","dpearson2699","accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills"],"capabilities":["skill","source-dpearson2699","skill-permissionkit","topic-accessibility","topic-agent-skills","topic-ai-coding","topic-apple","topic-claude-code","topic-codex-skills","topic-cursor-skills","topic-ios","topic-ios-development","topic-liquid-glass","topic-localization","topic-mapkit"],"categories":["swift-ios-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dpearson2699/swift-ios-skills/permissionkit","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dpearson2699/swift-ios-skills","source_repo":"https://github.com/dpearson2699/swift-ios-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 599 github stars · SKILL.md body (13,316 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:53:43.417Z","embedding":null,"createdAt":"2026-04-18T20:34:37.039Z","updatedAt":"2026-05-18T18:53:43.417Z","lastSeenAt":"2026-05-18T18:53:43.417Z","tsv":"'+1234567890':379,420,436,471,655,1042 '/documentation/permissionkit)':1227 '/documentation/permissionkit/askcenter)':1231 '/documentation/permissionkit/askerror)':1263 '/documentation/permissionkit/communicationhandle)':1251 '/documentation/permissionkit/communicationlimits)':1255 '/documentation/permissionkit/communicationtopic)':1247 '/documentation/permissionkit/creating-a-communication-experience)':1270 '/documentation/permissionkit/permissionbutton)':1239 '/documentation/permissionkit/permissionquestion)':1235 '/documentation/permissionkit/permissionresponse)':1243 '/documentation/permissionkit/significantappupdatetopic)':1259 '1':187 '2':197 '26':45,55,94,175,177,179 '3':206 '4':222 '5':232 '6.3':92 'action':408,491,500,501,706,1188 'activ':586,897,925 'actor':1203 'actual':1193 'add':820 'alex':479 'allow':523,926,1137 'allowcommun':929,983 'alway':896 'answer':272,779 'app':18,141,146,196,199,234,308,800,807,1191 'appli':303 'appropri':1144 'approv':33,227,266,750,752,756,781,794,812,851,1071 'approve/decline':273 'array':1026 'ask':80,671,717,882,1121,1130 'askcent':120,125,247,538,1228 'askcenter.shared':540 'askcenter.shared.ask':564,834,900,916,956,970,1079,1098 'askcenter.shared.responses':733,845,1091,1164 'askerror':578,936,978,1139,1260 'askerror.communicationlimitsnotenabled':921,1134 'assum':893 'async':340,361,560,730 'asynchron':726 'audiocal':493,506 'avail':173,608 'avatar':458 'avatarimag':484,699 'await':347,367,563,737,833,842,899,915,955,969,1078,1088,1097 'befollow':522 'beta':56 'bodi':659,685 'bool':341 'break':590,597,603,612,623,626,770,855,860,863,1004 'build':17,399 'button':276 'call':508,511,512,514,881 'capabl':1195 'case':581,591,598,604,613,621,749,760,850,856,907,937,940,966,981,984,987,990,993,999,1140 'catch':574,920,930,947,960,974 'catch-al':946 'chat':515,516,822 'check':28,103,107,299,312,320,352,869,885 'checkcommunicationstatus':336 'checking-communication-limit':106 'checklist':155,158,1133 'child':3,22,68,189,214,548,573 'child-to-contact':21 'children':14,79 'choic':742,775,785 'choice.answer':748,780 'choice.id':787 'choice.title':790 'clear':1184,1207 'common':149,152,864 'common-mistak':151 'communic':4,25,29,70,74,84,104,108,192,286,301,313,322,372,407,499,517,532,534,583,754,871,876,922,927,1187,1194,1266 'communication-rel':285 'communicationhandl':290,339,377,384,391,418,434,439,469,653,692,1040,1147,1248 'communicationlimit':298,1252 'communicationlimits.current':344,365 'communicationlimitsbutton':1106,1113,1117,1176 'communicationlimitsnoten':582,884,982 'communicationtop':282,450,488,497,703,711,1244 'communicationtopic.personinformation':467,690 'communicationtopic.self':735,1093 'compon':1181 'concept':99,102,181 'configur':596 'connect':529,530 'contact':24,404,415,431,593 'contactpermissionview':649 'contactsyncnotsetup':592,985 'content':95 'conveni':791 'core':98,101,180 'core-concept':100 'correct':904,963,1032,1083,1123,1150 'creat':2,73,110,114,200,371,396,1007,1148,1264 'creating-permission-quest':113 'custom':296,395,678,696,1154 'customhandl':390 'custompermissionview':682 'decis':242,265,1170 'declin':797 'default':625,769,862,1003 'deni':229,763,767 'denial':268,761,783,857 'deprec':1105,1112,1116,1175 'describ':203,256 'descript':502,817 'devic':611 'differ':942 'direct':928 'display':455 'email':294,1153 'emailaddress':388,443 'emailhandl':383 'empti':1010,1024 'enabl':325,753,874,880,912 'encount':190 'entitl':166 'error':576,580,619,890,932,939,962,976,980,1204 'except':82 'experi':6,76,1267 'extend':1213 'fallback':1138 'featur':823 'feedback':952,1146 'filterknownhandl':358 'fire':1074 'first':886 'flow':185,281,640 'follow':518,519,525,707,719 'forget':1052,1076 'framework':1224 'friend':526,527 'friend@example.com':386,441 'func':335,357,552,728 'generic':513,533 'guardian':64 'guidanc':1208 'handl':35,135,138,329,338,349,354,359,370,373,417,426,427,433,447,448,468,652,665,666,691,720,888,905,943,964,1011,1016,1025,1030,1037,1039,1048,1049,1135,1141,1160,1197,1216 'handleerror':931 'handlerespons':1094 'handling-respons':137 'id':786 'identifi':297 'ignor':935 'import':162,170,333,550,644,646 'includ':1156,1179 'individu':1142 'inform':405,453,1019,1163,1178 'instead':1109,1173 'integr':127,132,628 'invalid':1021,1031 'invalidquest':599,988 'involv':20 'io':44,93,174 'ipado':176 'isknown':346,351 'keep':764 'key':243 'kind':380,387,394,421,437,442,472,656,695,1043,1151 'know':1067 'known':331 'label':670 'latest':53 'least':1035,1158 'let':78,342,345,363,375,382,389,416,423,432,444,465,486,494,575,615,651,662,688,701,708,731,741,744,774,793,796,814,824,975,995,1027,1038,1045 'limit':30,85,105,109,193,302,314,323,343,364,584,872,877,894,909,923 'limits.isknownhandle':348 'limits.knownhandles':368 'listen':722,838,1060 'maco':178 'main':1202 'malform':602 'manag':183,250 'match':1189 'mean':1064 'messag':492,503,505,673,675 'method':46 'mistak':150,153,865 'modifi':66 'multi':1218 'multi-top':1217 'multipl':353,430 'multiplay':821 'multiquest':445 'name':456,476,483,1180 'name.familyname':480 'name.givenname':478 'namecompon':474,697 'need':26,589 'never':1066 'new':42 'nil':485,698,700 'notavail':605,991 'note':39 'number':293 'observ':1054,1084,1166 'observerespons':729 'one':1036,1159 'parent':11,62,89,221,224,240,263,751,762,811,1070,1169 'parent/guardian':32 'pattern':1214 'permiss':12,36,59,111,115,118,123,251,258,280,288,310,318,397,462,536,544,588,639,724,804,1122,1131,1185 'permissionbutton':129,134,274,630,631,667,676,713,1108,1125,1126,1171,1236 'permissionchoic':269,771,776 'permissionchoice.approve':795 'permissionchoice.decline':798 'permissionkit':1,8,38,40,72,163,171,182,334,551,606,647,1223 'permissionquest':202,255,401,425,446,496,556,664,710,826,1029,1047,1155,1232 'permissionrespons':237,261,1240 'person':452,1018,1162,1177 'personinfo':466,490,689,705 'personinform':489,704 'personnamecompon':477 'phone':292,1152 'phonehandl':376 'phonenumb':381,422,438,473,657,1044 'platform':172 'present':209,316,542,570,829,1056 'print':617,755,766,778,784,788,961 'proceed':852 'prompt':463,1186 'properti':772 'provid':454,1033,1206 'question':112,116,211,398,411,424,428,495,555,565,568,600,663,668,669,709,714,715,745,825,831,835,901,917,957,971,1008,1013,1028,1046,1058,1080,1099,1118,1119,1127,1128 'question.topic':759 'receiv':235,1168 'refer':159,160,1212 'references/permissionkit-patterns.md':1221,1222 'relat':287 'request':10,31,58,117,122,205,231,252,260,289,311,319,528,531,535,545,803 'requesting-permission-with-askcent':121 'requestpermiss':553 'requir':168,810,941 'respons':37,136,139,254,721,725,732,738,740,840,843,1055,1063,1085,1089,1095,1196,1215 'response.choice':743,777 'response.choice.answer':849 'response.question':746 'restrict':765 'return':350,366,482 'review':154,157,225,1132 'review-checklist':156 'richer':461 'role':246 'rule':71 'safeti':5,75 'sdk':57 'send':218 'set':86,360,362 'setup':96,97,161 'showcontactsyncprompt':986 'showgenericerror':1001 'showinvalidquestionalert':989 'showsystemerror':997 'showunavailablemessag':992 'signatur':47 'signific':140,145,307,799,806 'significant-app-update-top':144 'significantappupdatetop':304,816,827,1256 'significantappupdatetopic.self':847 'singl':414 'singleton':248 'skill' 'skill-permissionkit' 'skip':858,868 'smith':481 'sosumi.ai':1226,1230,1234,1238,1242,1246,1250,1254,1258,1262,1269 'sosumi.ai/documentation/permissionkit)':1225 'sosumi.ai/documentation/permissionkit/askcenter)':1229 'sosumi.ai/documentation/permissionkit/askerror)':1261 'sosumi.ai/documentation/permissionkit/communicationhandle)':1249 'sosumi.ai/documentation/permissionkit/communicationlimits)':1253 'sosumi.ai/documentation/permissionkit/communicationtopic)':1245 'sosumi.ai/documentation/permissionkit/creating-a-communication-experience)':1268 'sosumi.ai/documentation/permissionkit/permissionbutton)':1237 'sosumi.ai/documentation/permissionkit/permissionquestion)':1233 'sosumi.ai/documentation/permissionkit/permissionresponse)':1241 'sosumi.ai/documentation/permissionkit/significantappupdatetopic)':1257 'source-dpearson2699' 'special':165 'specif':271 'state':1205 'static':792 'struct':648,681 'swift':91,169,332,374,410,464,549,643,680,727,773,813,891,944,1022,1072,1114 'swiftui':126,131,275,627,634,645 'swiftui-integration-with-permissionbutton':130 'switch':579,747,848,979 'sync':594 'system':208,618 'systemerror':614,994 'systemimag':674 'tap':642 'target':90 'task':1086 'text':504,716,1120,1129 'throw':883 'titl':789 'topic':143,148,283,305,487,498,679,702,712,758,802,1219 'topic-accessibility' 'topic-agent-skills' 'topic-ai-coding' 'topic-apple' 'topic-claude-code' 'topic-codex-skills' 'topic-cursor-skills' 'topic-ios' 'topic-ios-development' 'topic-liquid-glass' 'topic-localization' 'topic-mapkit' 'tri':562,832,898,914,954,968,1077,1096 'trigger':278,637 'type':244,245,409 'ui':1199 'uikit':1220 'uiviewcontrol':559 'under':616,620,996,998 'unknown':622,624,768,861,1000,1002 'updat':142,147,309,801,808,819,854,859,1198 'updatetop':815,828 'use':7,15,449,539,1104,1107,1124,1172 'user':521,951,1145,1211 'user123':393 'user456':694 'valu':378,385,392,419,435,440,470,654,693,1041 'var':475,658,684 'verifi':50 'video':510 'videocal':509 'view':635,650,661,683,687 'viewcontrol':558,567,837,903,919,959,973,1082,1101 'voic':507 'whether':300,327 'without':1059 'wrong':892,945,1023,1073,1115 'xcode':54","prices":[{"id":"794cc306-ac93-4c89-a308-0ff12c09366c","listingId":"5afce087-1b99-4647-8ae3-f95cb30039f3","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dpearson2699","category":"swift-ios-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T20:34:37.039Z"}],"sources":[{"listingId":"5afce087-1b99-4647-8ae3-f95cb30039f3","source":"github","sourceId":"dpearson2699/swift-ios-skills/permissionkit","sourceUrl":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/permissionkit","isPrimary":false,"firstSeenAt":"2026-04-18T22:01:11.139Z","lastSeenAt":"2026-05-18T18:53:43.417Z"},{"listingId":"5afce087-1b99-4647-8ae3-f95cb30039f3","source":"skills_sh","sourceId":"dpearson2699/swift-ios-skills/permissionkit","sourceUrl":"https://skills.sh/dpearson2699/swift-ios-skills/permissionkit","isPrimary":true,"firstSeenAt":"2026-04-18T20:34:37.039Z","lastSeenAt":"2026-05-07T22:40:34.028Z"}],"details":{"listingId":"5afce087-1b99-4647-8ae3-f95cb30039f3","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dpearson2699","slug":"permissionkit","github":{"repo":"dpearson2699/swift-ios-skills","stars":599,"topics":["accessibility","agent-skills","ai-coding","apple","claude-code","codex-skills","cursor-skills","ios","ios-development","liquid-glass","localization","mapkit","networking","storekit","swift","swift-concurrency","swiftdata","swiftui","widgetkit","xcode"],"license":"other","html_url":"https://github.com/dpearson2699/swift-ios-skills","pushed_at":"2026-04-26T21:04:17Z","description":"Agent Skills for iOS 26+, Swift 6.3, SwiftUI, and modern Apple frameworks","skill_md_sha":"cc2e55a8d60f31b0efd6a46803dfa2da31fdd190","skill_md_path":"skills/permissionkit/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dpearson2699/swift-ios-skills/tree/main/skills/permissionkit"},"layout":"multi","source":"github","category":"swift-ios-skills","frontmatter":{"name":"permissionkit","description":"Create child communication safety experiences using PermissionKit to request parental permission for children. Use when building apps that involve child-to-contact communication, need to check communication limits, request parent/guardian approval, or handle permission responses for minors."},"skills_sh_url":"https://skills.sh/dpearson2699/swift-ios-skills/permissionkit"},"updatedAt":"2026-05-18T18:53:43.417Z"}}