Community-maintained Agent Skills for complete Swift and Apple-platform app delivery.
73
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Medium
Suggest reviewing before use
Read this reference when the task needs concrete setup, API wiring, or implementation recipes. Keep scope, workflow, non-obvious invariants, mistakes, and review gates in the parent SKILL.md.
Request the category-specific entitlement from Apple's CarPlay entitlement form, accept the addendum, then provision the approved category key below.
| Entitlement | Category |
|---|---|
com.apple.developer.carplay-audio | Audio |
com.apple.developer.carplay-communication | Communication |
com.apple.developer.carplay-maps | Navigation |
com.apple.developer.carplay-charging | EV Charging |
com.apple.developer.carplay-parking | Parking |
com.apple.developer.carplay-quick-ordering | Quick Food Ordering |
Entitlements.plist with the entitlement key set to true.Entitlements.plist path.| Type | Role |
|---|---|
CPTemplateApplicationScene | UIScene subclass for the CarPlay display |
CPTemplateApplicationSceneDelegate | Scene connect/disconnect lifecycle |
CPInterfaceController | CarPlay-provided controller for setting the root template and pushing, presenting, or popping templates |
CPTemplate | Abstract base for all CarPlay templates |
CPSessionConfiguration | Vehicle display limits and content style |
Declare the CarPlay scene in Info.plist and implement
CPTemplateApplicationSceneDelegate to respond when CarPlay connects.
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>CPTemplateApplicationSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>CPTemplateApplicationScene</string>
<key>UISceneConfigurationName</key>
<string>CarPlaySceneConfiguration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).CarPlaySceneDelegate</string>
</dict>
</array>
</dict>
</dict>Non-navigation apps receive an interface controller only. No window.
import CarPlay
final class CarPlaySceneDelegate: UIResponder,
CPTemplateApplicationSceneDelegate {
var interfaceController: CPInterfaceController?
func templateApplicationScene(
_ templateApplicationScene: CPTemplateApplicationScene,
didConnect interfaceController: CPInterfaceController
) {
self.interfaceController = interfaceController
interfaceController.setRootTemplate(buildRootTemplate(),
animated: true, completion: nil)
}
func templateApplicationScene(
_ templateApplicationScene: CPTemplateApplicationScene,
didDisconnectInterfaceController interfaceController: CPInterfaceController
) {
self.interfaceController = nil
}
}Navigation apps receive both an interface controller and a CPWindow.
Set the window's root view controller to draw map content.
func templateApplicationScene(
_ templateApplicationScene: CPTemplateApplicationScene,
didConnect interfaceController: CPInterfaceController,
to window: CPWindow
) {
self.interfaceController = interfaceController
self.carWindow = window
window.rootViewController = MapViewController()
let mapTemplate = CPMapTemplate()
mapTemplate.mapDelegate = self
interfaceController.setRootTemplate(mapTemplate, animated: true,
completion: nil)
}CarPlay provides a fixed set of template types. The app supplies content; the system renders it on the vehicle display.
| Template | Purpose |
|---|---|
CPTabBarTemplate | Container with tabbed child templates |
CPListTemplate | Scrollable sectioned list |
CPGridTemplate | Grid of tappable icon buttons (max 8) |
CPInformationTemplate | Key-value info with up to 3 actions |
CPAlertTemplate | Modal alert with up to 2 actions |
CPActionSheetTemplate | Modal action sheet |
| Template | Category |
|---|---|
CPMapTemplate | Navigation -- map overlay with nav bar |
CPSearchTemplate | Navigation -- destination search |
CPNowPlayingTemplate | Audio -- shared Now Playing screen |
CPPointOfInterestTemplate | EV Charging / Parking / Food -- POI map |
CPContactTemplate | Communication -- contact card |
Use pushTemplate(_:animated:completion:) to add templates to the stack.
Use presentTemplate(_:animated:completion:) for modal display.
Use popTemplate(animated:completion:) to go back.
CPTabBarTemplate must be set as root -- it cannot be pushed or presented.
let browseTab = CPListTemplate(title: "Browse",
sections: [CPListSection(items: listItems)])
browseTab.tabImage = UIImage(systemName: "list.bullet")
let tabBar = CPTabBarTemplate(templates: [browseTab, settingsTab])
tabBar.delegate = self
interfaceController.setRootTemplate(tabBar, animated: true, completion: nil)let item = CPListItem(text: "Favorites", detailText: "12 items")
item.handler = { selectedItem, completion in
self.interfaceController?.pushTemplate(detailTemplate, animated: true,
completion: nil)
completion()
}
let section = CPListSection(items: [item], header: "Library",
sectionIndexTitle: nil)
let listTemplate = CPListTemplate(title: "My App", sections: [section])Navigation apps use com.apple.developer.carplay-maps. They are the only
category that receives a CPWindow for drawing map content. The root
template must be a CPMapTemplate.
let routeChoice = CPRouteChoice(
summaryVariants: ["Fastest Route", "Fast"],
additionalInformationVariants: ["Via Highway 101"],
selectionSummaryVariants: ["25 min"]
)
let trip = CPTrip(origin: origin, destination: destination,
routeChoices: [routeChoice])
mapTemplate.showTripPreviews([trip], textConfiguration: nil)extension CarPlaySceneDelegate: CPMapTemplateDelegate {
func mapTemplate(_ mapTemplate: CPMapTemplate,
startedTrip trip: CPTrip,
using routeChoice: CPRouteChoice) {
let session = mapTemplate.startNavigationSession(for: trip)
session.pauseTrip(for: .loading, description: "Calculating route...")
let maneuver = CPManeuver()
maneuver.instructionVariants = ["Turn right onto Main St"]
maneuver.symbolImage = UIImage(systemName: "arrow.turn.up.right")
session.upcomingManeuvers = [maneuver]
let estimates = CPTravelEstimates(
distanceRemaining: Measurement(value: 5.2, unit: .miles),
timeRemaining: 900)
session.updateEstimates(estimates, for: maneuver)
}
}let zoomIn = CPMapButton { _ in self.mapViewController.zoomIn() }
zoomIn.image = UIImage(systemName: "plus.magnifyingglass")
mapTemplate.mapButtons = [zoomIn, zoomOut]extension CarPlaySceneDelegate: CPSearchTemplateDelegate {
func searchTemplate(_ searchTemplate: CPSearchTemplate,
updatedSearchText searchText: String,
completionHandler: @escaping ([CPListItem]) -> Void) {
performSearch(query: searchText) { results in
completionHandler(results.map {
CPListItem(text: $0.name, detailText: $0.address)
})
}
}
func searchTemplate(_ searchTemplate: CPSearchTemplate,
selectedResult item: CPListItem,
completionHandler: @escaping () -> Void) {
// Navigate to selected destination
completionHandler()
}
}Audio apps use com.apple.developer.carplay-audio. They display browsable
content in lists and use CPNowPlayingTemplate for playback controls.
CPInformationTemplate is not available to audio-entitled apps.
CPNowPlayingTemplate is a shared singleton. It reads metadata from
MPNowPlayingInfoCenter. Do not instantiate a new one.
let nowPlaying = CPNowPlayingTemplate.shared
nowPlaying.isUpNextButtonEnabled = true
nowPlaying.isAlbumArtistButtonEnabled = true
nowPlaying.updateNowPlayingButtons([
CPNowPlayingShuffleButton { _ in self.toggleShuffle() },
CPNowPlayingRepeatButton { _ in self.toggleRepeat() }
])
nowPlaying.add(self) // Register as CPNowPlayingTemplateObserverAudio apps supporting INPlayMediaIntent can show an assistant cell.
Communication apps use INStartCallIntent with .startCall.
let config = CPAssistantCellConfiguration(
position: .top, visibility: .always, assistantAction: .playMedia)
let listTemplate = CPListTemplate(
title: "Playlists",
sections: [CPListSection(items: items)],
assistantCellConfiguration: config)Communication apps use com.apple.developer.carplay-communication.
They display message lists and contacts, and support INStartCallIntent
for Siri-initiated calls.
CPMessageListItem has no app-provided selection handler. When selected,
CarPlay invokes Siri compose, read, or reply behavior based on the item's
phone/email, unread state, or existing conversation configuration.
let leading = CPMessageListItemLeadingConfiguration(
leadingItem: .star, leadingImage: nil, unread: true)
let trailing = CPMessageListItemTrailingConfiguration(
trailingItem: .none, trailingImage: nil)
let message = CPMessageListItem(
conversationIdentifier: "conv-123",
text: "Jane",
leadingConfiguration: leading,
trailingConfiguration: trailing,
detailText: "Meeting at 3pm",
trailingText: "2:45 PM")
let messageList = CPListTemplate(title: "Messages",
sections: [CPListSection(items: [message])])EV charging, parking, and food ordering apps use CPPointOfInterestTemplate
and CPInformationTemplate to display locations and details.
CPPointOfInterestTemplate displays a maximum of 12 points of interest.
let poi = CPPointOfInterest(
location: MKMapItem(placemark: MKPlacemark(
coordinate: CLLocationCoordinate2D(latitude: 37.7749,
longitude: -122.4194))),
title: "SuperCharger Station", subtitle: "4 available",
summary: "150 kW DC fast charging",
detailTitle: "SuperCharger Station", detailSubtitle: "$0.28/kWh",
detailSummary: "Open 24 hours",
pinImage: UIImage(systemName: "bolt.fill"))
poi.primaryButton = CPTextButton(title: "Navigate",
textStyle: .confirm) { _ in }
let poiTemplate = CPPointOfInterestTemplate(
title: "Nearby Chargers", pointsOfInterest: [poi], selectedIndex: 0)
poiTemplate.pointOfInterestDelegate = selflet infoTemplate = CPInformationTemplate(
title: "Order Summary", layout: .leading,
items: [
CPInformationItem(title: "Item", detail: "Burrito Bowl"),
CPInformationItem(title: "Total", detail: "$12.50")],
actions: [
CPTextButton(title: "Place Order", textStyle: .confirm) { _ in
self.placeOrder() },
CPTextButton(title: "Cancel", textStyle: .cancel) { _ in
self.interfaceController?.popTemplate(animated: true,
completion: nil) }])Default window: 800x480 at @2x. Enable extra options for navigation apps:
defaults write com.apple.iphonesimulator CarPlayExtraOptions -bool YES| Configuration | Pixels | Scale |
|---|---|---|
| Minimum | 748 x 456 | @2x |
| Portrait | 768 x 1024 | @2x |
| Standard | 800 x 480 | @2x |
| High-resolution | 1920 x 720 | @3x |
Simulator cannot test locked-iPhone behavior, Siri, audio coexistence with car radio, or physical input hardware (knobs, touch pads). Test on a real CarPlay-capable vehicle or aftermarket head unit when possible. Design primary CarPlay flows so they do not require iPhone input while CarPlay is active.
.tessl-plugin
skills
accessorysetupkit
references
activitykit
adattributionkit
references
alarmkit
references
app-clips
app-intents
app-store-optimization
app-store-review
apple-on-device-ai
appmigrationkit
audioaccessorykit
references
authentication
references
avkit
background-processing
references
browserenginekit
callkit
references
carplay
cloudkit
contacts-framework
references
core-bluetooth
references
core-data
core-motion
references
core-nfc
references
coreml
references
cryptokit
cryptotokenkit
references
debugging-instruments
device-integrity
references
dockkit
energykit
references
eventkit
financekit
references
focus-engine
gamekit
healthkit
references
homekit
references
ios-accessibility
ios-app-workflow
references
ios-ettrace-performance
ios-localization
ios-memgraph-analysis
ios-networking
ios-simulator
references
metrickit
references
musickit
references
natural-language
references
paperkit
references
passkit
references
pdfkit
pencilkit
references
permissionkit
references
photokit
push-notifications
realitykit
references
relevancekit
references
scenekit
sensorkit
speech-recognition
references
spritekit
storekit
swift-api-design-guidelines
swift-architecture
references
swift-charts
swift-codable
references
swift-code-review
swift-concurrency
swift-formatstyle
references
swift-language
swift-security
references
swift-testing
swiftdata
swiftlint
swiftui-animation
swiftui-gestures
references
swiftui-layout-components
swiftui-liquid-glass
references
swiftui-patterns
swiftui-performance
swiftui-responsive-layout
swiftui-uikit-interop
swiftui-webkit
tabletopkit
tipkit
vision-framework
weatherkit
references