Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

What is a bundle, and how are frameworks different?

By: hoakley
25 April 2025 at 14:30

Apps, frameworks and other items come in bundles, structured hierarchies of folders and files that look like a single file in the Finder. This article explains what bundles are and shows how they are structured.

Bundles came to Mac OS X from its NeXTSTEP parent, not Classic Mac OS. The latter assembled its apps from many resources stored in the app’s resource fork. NeXTSTEP and Mac OS X instead built their apps from component files arranged in a series of directories. Those bundles gathered together all the files required for apps and similar items, into what was then presented to the user as a single item. Modern app bundles are descended from ‘new-style’ bundles introduced in Mac OS X, which had a minimum requirement of a top-level folder named Contents, and inside that a property list named Info.plist.

Bundles and packages

When a folder has a name with an extension for a standard bundle type, such as .app, .bundle, .plugin or .kext, the Finder will display and treat it as if it were a file, also offering to Show Package Contents in its contextual menu. For historical reasons, bundles with the extension .framework aren’t treated as bundles, but are displayed and navigated as if they were still folders.

Although bundles have similarities with packages, Apple draws a clear distinction between them, even if the Finder doesn’t. Directory-based documents and similar items that are used to contain multiple files for Rich Text Format Directory (RTFD) and other documents don’t conform to the rules for bundles, and should be referred to as packages to avoid confusion. Look inside an RTFD package, for example, and you’ll see the structure:

  • Contents, a directory containing a PkgInfo file
  • files containing graphics to be included within the documents
  • TXT.rtf, a Rich Text Format file containing the styled text.

which has some common features, but is structured differently and lacks both an Info.plist file and executable code.

Apps and frameworks

The fundamental requirements for an app or related bundle, including those for app extensions or appexes, are:

  • The whole bundle’s contents are within a single top-level folder named Contents.
  • Within Contents is an Info.plist property list containing information and settings for the bundle.
  • There’s executable code, normally in the form of a Mach-O binary inside the MacOS folder.
  • For historical and compatibility reasons, there’s a PkgInfo file containing a Classic Mac OS type and creator code for the bundle, e.g. APPL and ???? for an app.

However, frameworks have a different and more complex structure, lacking a Contents folder, providing at least one version of the framework, and burying the Info.plist file deeper in the hierarchy. This is shown in full later.

App bundles can contain frameworks and other app bundles, as can framework bundles. In the worst case you may need to dive deep into a series of folder hierarchies to reach your goal.

Info.plist

The information property list Info.plist contains key-value pairs in XML format, for attributes such as:

  • bundle name (CFBundleName),
  • name of bundle executable (CFBundleExecutable),
  • version (CFBundleShortVersionString),
  • document types handled by the app (CFBundleDocumentTypes),
  • app identifier (CFBundleIdentifier),
  • other metadata.

Because of the importance of its contents, code signatures protect the Info.plist from being changed in any way.

App bundle

In addition to the minimum requirements of an Info.plist, executable code, and PkgInfo file inside its Contents folder, apps almost invariably contain several additional folders, among them:

  • Resources is universal, and contains any of a rich range of images, localised versions of menu and other text contents, the app icon and any for custom document types, storyboards for GUI elements, Help books, and more.
  • PlugIns is now common, to contain appexes in particular.
  • Library, containing one or more sub-folders with QuickLook and Spotlight support for custom document types, any login items or property lists for LaunchServices, and other support and extensions for the main app.
  • Apps obtained through the App Store should contain a _MASReceipt folder with the store receipt inside it.
  • Signed apps will have a _CodeSignature folder containing the CodeResources file with signature data.
  • Notarized apps may have a notarization ticket in a CodeResources file, but that isn’t required for notarization to work.
  • Some apps may have an embedded.provisionprofile file containing their provisioning profile.
  • Other folders, such as Frameworks for nested framework bundles.

This layout is shown below, with the essentials in light red.

Framework bundle

In comparison, framework bundles are deeper, lack a top-level Contents folder, contain at least one version of the framework (although two or more are now exceptional), and come with symbolic links. This is shown below, again with the essentials in light red.

Three symlinks merit explanation:

  • Versions/Current links to A, the current (and only) version of the framework.
  • a symlink with the same name as the framework’s code is at the top level of the bundle, alongside the Versions folder. That links through the Current symlink, giving the path Current/A/.
  • a symlink named Resources is also at the top level of the bundle, alongside the Versions folder. That too links through the Current symlink, giving the path Current/A/Resources.

Thus paths to the Info.plist file include Resources ➜ Info.plist via the top-level Resources symlink, Versions/Current ➜ Resources via the Current symlink, and Versions/A/Resources without using any symlinks. This demonstrates how confusing this layout can appear in the Finder.

Frameworks commonly include other nested frameworks, appexes in their PlugIns folder, and a diverse range of other resources including localisations in the Resources folder.

Conclusions

  • Bundles are formal structures of folders and files used for apps and their relatives, and for frameworks. Packages used for RTFD and other documents have different structural requirements.
  • App bundles have a top-level Contents folder, inside which is an Info.plist property file, and executable code inside a MacOS folder.
  • Framework bundles don't have a Contents folder, but contain versions of the framework, normally only one named A. They use important symlinks to provide standard access paths to their contents, and their Info.plist file is inside their Resources folder.
  • Info.plist files and other contents are protected by code signatures and can't be modified without breaking the signature. However, they contain valuable information about the app or framework.
  • Building bundles by hand is prone to error, causing bugs. When possible, leave it to Xcode.

Reference

Apple's instructions for developers.

An overview of app extensions and plugins in macOS Sequoia

By: hoakley
23 April 2025 at 14:30

With well over 400 app extensions and plugins managed by PlugInKit in Sequoia 15.4.1, this article tries to give an overview of their management and control, as well as the diversity of their functions. This follows:

Appex types

Although Apple refers to the type identifier for appexes as NSExtensionPointIdentifier in its developer documentation, where it lists some of them, in macOS this is also synonymous with NSExtensionPointName. In pluginkit dumps, it’s referred to as the SDK, and LaunchServices dumps use both terms, NSExtensionPointName in NSExtensionsAttributes, and NSExtensionPointIdentifier in NSExtension. This is even more confused in the log, where PlugInKit’s entries use the term NSExtensionPointName, but use NSExtensionIdentifier to refer instead to the appex-specific identifier, such as com.apple.iCal.CalendarWidgetExtension.

For the sake of clarity and consistency here, I’ll refer to the appex type identifier as NSExtensionPointName.

Appex locations

Many appexes supplied in macOS are stored as bundles inside dedicated collections such as /System/Library/ExtensionKit/Extensions or in frameworks. Where they are supplied in an app or similar bundle, they’re normally in a PlugIns folder, although according to this article QuickLook generators should be installed in Library/QuickLook, and Spotlight importers in Library/Spotlight.

Types and management

The rest of this article lists appex types, omitting the universal prefix com.apple., according to their management and discovery by PlugInKit during startup. I provide for each, as far as I’m able to tell, the type-specific manager, any controls provided in System Settings or elsewhere, and illustrative examples and other relevant information.

Type-specific managers are those services or subsystems that PlugInKit hands over to during discovery. For example, when it discovers appexes that extend QuickLook by providing either thumbnails or previews, PlugInKit hands those over to com.apple.quicklook.ThumbnailsAgent to manage.

Many appex types aren’t exposed in System Settings, are managed by PlugInKit, but don’t appear to undergo startup discovery. I have relegated those to the appendix at the end. Most of those are single-appex types, and others are only used by macOS.

Appex types that are managed in System Settings and by PlugInKit, and undergo startup discovery:

  • FinderSync, managed by the Finder, and controlled in File Providers settings, e.g. Keka Finder Integration
  • quicklook.preview, managed by com.apple.quicklook.ThumbnailsAgent, and controlled in Quick Look settings; these are modern substitutes for qlgenerators
  • quicklook.thumbnail, managed by com.apple.quicklook.ThumbnailsAgent, and controlled in Quick Look settings; these are modern substitutes for qlgenerators
  • ui-services, managed by the Finder, and controlled in Actions settings, includes Markup, ShareSheetUI (not exposed in settings)

Appex types that aren’t managed in System Settings, but are managed by PlugInKit, and undergo startup discovery:

  • AppSSO.idp-extension, managed by AppSSOAgent, includes Kerberos and Sign In With Apple; these are single-sign-on extensions
  • appstored-services.testflight, managed by appstoreagent; these handle App Store TestFlight
  • AudioUnit, managed by AudioComponentRegistrar and axassetsd, for WardaSynthesizer
  • AudioUnit-Speech, managed by AudioComponentRegistrar and axassetsd, include KonaSynthesizer and AUSPs
  • AudioUnit-UI, managed by AudioComponentRegistrar
  • cache_delete_extension, managed by deleted; these support app-specific cache management
  • contacts.donation, managed by contactsdonationagent; these exchange info with Contacts
  • ctk-tokens, managed by ctkd, include CryptoTokenKit and PlatformSSOToken; these handle tokens for CryptoTokenKit
  • diagnosticextensions-service, managed by ControlCenter and diagnosticextensionsd, includes many service-specific Diagnostic Extensions
  • email.extension, managed by maild, e.g. SpamSieve; these are Mail plugins
  • fileprovider-nonui, managed by the Finder, includes iCloud Drive and PhotosFileProvider
  • services, managed by the Finder; none listed
  • spotlight.import, managed by mdbulkimport, includes PDFImporter
  • spotlight.index, managed by corespotlightd, includes system extensions but not mdimporters
  • textinputmethod-services, managed by imklaunchagent, includes many Input Methods
  • usernotifications.content-extension, managed by NotificationCenter, includes ContentExtensions
  • widgetkit-extension, managed by chronod, includes system and third-party widgets.

Significant appex types that are managed by PlugInKit, but don’t undergo startup discovery:

  • appintents-extension, multiple instances
  • intents-service, many IntentsExtensions
  • photo-editing, Photos editing, controlled in Photos Editing settings
  • Safari.extension, Safari extensions, managed in Safari settings
  • share-services, many Share extensions, managed in Sharing settings
  • widget-extension, only a couple, e.g. iStat Menus.

Appex types that apparently aren’t managed by PlugInKit, but are controlled in System Settings:

  • Dock Tiles
  • Finder, these are services offered in the Finder’s Services menu
  • Spotlight, these are mdimporters.

also Safari.content-blocker, which is managed in Safari settings rather than System Settings.

Appex types that aren’t apparently managed by PlugInKit or controlled in System Settings:

  • authentication-services-account-authentication-modification-ui
  • authentication-services-credential-provider-ui
  • broadcast-services-setupui
  • broadcast-services-upload
  • callkit.call-directory
  • classkit.context-provider
  • dt.Xcode.extension.source-editor
  • fileprovider-actionsui
  • identitylookup.classification-ui
  • identitylookup.message-filter
  • intents-ui-service
  • keyboard-service
  • networkextension.app-proxy
  • photo-project
  • tv-top-shelf

Appendix:

Appex types that aren’t exposed in System Settings, are managed by PlugInKit, but don’t undergo startup discovery

System, multiple appexes:
followup-extension – multiple FollowUpExtensions
lighthouse.SAOrchestratedExtension – multiple Ingestors
message-payload-provider – multiple
mlhost.worker – many ML-related
mlruntime.extension-point-high
mlruntime.extension-point-ondemand
mlruntime.extension-point-restricted
screensaver – several ScreenSavers
Settings.extension.ui – System Settings
storagemanagement – many apps
usernotifications.service – several NotificationServiceExtensions
wallpaper – several Wallpapers

System, single-app extensions:
amsengagementd-extension – Books, News
amsutility-extension – News
app.non-ui-extension – Swift Playground
app.non-ui-extension.multiple-instances – Swift Playground
app.ui-extension.multiple-instances – Swift Playground
applemediaservices.extensions.compose-review – ComposeReviewExtension
askpermission-extension – App Store related
askto.extension – AskToMessagesHost
calendar.EventKitUIRemoteUIService – EventKitUIRemoteUIExtension
calendar.virtualconference – FaceTimeExtension
contact-view – System Service
contacts.avatar-picker-ui – AvatarPickers
deviceactivity.monitor-extension – ScreenTimeDeviceActivityMonitorExtension
deviceactivityui.report-service – DeviceActivityReportService
extension-view-service-sample-rk – RPVideoEditorExtension_macOS, ReplayKit
extensionkit.app-extension-management – AppExtensionManagement
extensionkit.app-extension-settings – ExtensionKit components
facetime.notification – FaceTimeNotificationExtension
feedback.drafting-extension – Feedback
freeform.USD-renderer-remote-UI – USDRendererExtension
fskit.fsmodule – exfat and msdos file systems (File System Extensions)
GenerativePlaygroundUI.remoteUI – Image Playground
groupactivities – FaceTime RemotePeoplePicker
Home.ui-extension.userList – HomeUIUserList
ImagePlayground.NonUIExtension – GPNonUIExtension
ManagedSettings.service – ManagedClientMSExtension
mapkit.private.RemoteUI – MKRemoteUI for MapKit
mobileslideshow.photo-picker – PhotoPicker and PhotosPicker
networkextension.packet-tunnel – network extensions
PaperKit.extension.ui – PaperKitExtension
PassKit.in-app-payment-ui – Wallet
pdfkit-private – PDFExtensionView in PDFKit
people-picker – System Service
people.legacy.extension – PeopleLegacyMessageService
Photos.MacMusicPickerExtension – PhotosMacMusicPickerExtension
preference.security.privacy – Apple Advertising
preference.sharing.service – Media Sharing
private.translation-api-support – TranslationAPISupportExtension
private.translation-ui – Translate
private.voiceshortcuts-ui – three extensions
replaykit.broadcast-picker – RPBroadcastActivityExtension_macOS in ReplayKit
screentime.web-service – ScreenTimeWebExtension.

❌
❌