Generates app extension infrastructure for Share Extensions, Action Extensions, Keyboard Extensions, and Safari Web Extensions with data sharing via App Groups. Use when user wants to add a share extension, action extension, keyboard extension, Safari web extension, or any app extension type.
Generate production app extension infrastructure -- Share Extensions for receiving content from other apps, Action Extensions for manipulating content in-place, Keyboard Extensions for custom input, and Safari Web Extensions for browser integration. Includes App Group data sharing between the host app and extensions.
Use this skill when the user:
Search for existing extension targets:
Glob: **/*Extension*/*.swift, **/*Extension*/Info.plist
Grep: "NSExtensionPointIdentifier" or "NSExtensionPrincipalClass"
If existing extensions found:
Check for existing App Groups setup:
Glob: **/*.entitlements
Grep: "com.apple.security.application-groups"
If App Groups exist, reuse the existing group identifier.
Ask user via AskUserQuestion:
What type of extension?
What content types does it handle?
Does the extension need to share data with the main app?
Read templates.md for production Swift code.
Based on extension type selected:
Share Extension:
ShareViewController.swift -- Main share extension view controller with content handlingInfo.plist -- Extension configuration with activation rulesAction Extension:
3. ActionViewController.swift -- Action extension with content manipulation
4. Info.plist -- Extension configuration
Keyboard Extension:
5. KeyboardViewController.swift -- Custom keyboard with UIInputViewController
6. Info.plist -- Keyboard extension configuration
Safari Web Extension:
7. SafariWebExtensionHandler.swift -- Native message handler
8. manifest.json -- Web extension manifest
9. content.js -- Content script template
If data sharing selected:
10. SharedDataManager.swift -- App Group data sharing helper
Extensions are separate targets:
ShareExtension/ActionExtension/KeyboardExtension/SafariWebExtension/Shared/ or within main app targetAfter generation, provide:
Share Extension:
ShareExtension/
├── ShareViewController.swift # Main share extension view controller
└── Info.plist # Extension activation rules & config
Action Extension:
ActionExtension/
├── ActionViewController.swift # Content manipulation controller
└── Info.plist # Extension activation rules & config
Keyboard Extension:
KeyboardExtension/
├── KeyboardViewController.swift # UIInputViewController subclass
└── Info.plist # Keyboard extension config
Safari Web Extension:
SafariWebExtension/
├── SafariWebExtensionHandler.swift # Native message handler
└── Resources/
├── manifest.json # Web extension manifest
├── content.js # Content script
└── popup.html # Popup UI (optional)
Shared (if data sharing enabled):
Shared/
└── SharedDataManager.swift # App Group data sharing
1. Add Extension Target in Xcode:
com.yourapp.ShareExtension2. Configure App Groups (if data sharing):
group.com.yourapp.shared3. Share code between targets:
Accept shared URLs:
if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) {
provider.loadItem(forTypeIdentifier: UTType.url.identifier) { item, error in
guard let url = item as? URL else { return }
// Process URL
}
}
Accept shared images:
if provider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
provider.loadItem(forTypeIdentifier: UTType.image.identifier) { item, error in
if let imageURL = item as? URL {
let imageData = try? Data(contentsOf: imageURL)
// Process image data
}
}
}
Share data to main app via App Groups:
let shared = SharedDataManager.shared
shared.saveSharedContent(url.absoluteString, forKey: "lastSharedURL")
Share Extension:
Action Extension:
Keyboard Extension:
Safari Web Extension:
completeRequest() or cancelRequest() when doneThe system can terminate extensions at any time for resource reclamation. Save state frequently and handle interruption gracefully.
The extension host waits for extensionContext?.completeRequest(returningItems:). If you never call it, the share sheet hangs and the user is stuck. Always call it in both success and error paths.
By default keyboard extensions have no network access. The user must explicitly grant "Allow Full Access" in Settings. Without it, URLSession calls fail silently. Design your keyboard to work without network and enhance when access is granted.
The App Group identifier must be identical in both the main app and extension entitlements. A typo means UserDefaults(suiteName:) returns a different (empty) container.
Content scripts cannot directly access the page's JavaScript variables. Use window.postMessage or the browser messaging API to communicate between content scripts and the page.
Extension bundle identifiers must be prefixed with the main app bundle identifier:
com.yourcompany.myappcom.yourcompany.myapp.ShareExtensiongenerators/deep-linking -- Handle URLs received via extensionsgenerators/push-notifications -- Notification extensions (Service/Content)