Margaret Boden, Philosopher of Artificial Intelligence, Dies at 88
© Antonin Cermak/Fairfax Media, via Getty Images
© Antonin Cermak/Fairfax Media, via Getty Images
In addition to reading laid-out documents, the most popular purposes for PDFs are forms and annotation. As far as filling in PDF forms are concerned, I have just one word to say: Fillably, Joel Norvell’s outstanding app available from the App Store, which transforms Preview into the ideal platform for tax and other forms. Rather than struggling with the tangle of tools in a general PDF editor, Fillably provides the perfect suite for creating PDF forms.
Annotating PDFs is more complicated, though.
Annotations aren’t an afterthought, but a central part of PDF. All PDF documents consist of a list of hundreds or thousands of objects of different types, including annotations of the Annot type, and those are listed in one of the file’s standard dictionaries, its Annotations Dictionary, Annots.
There are at least 27 sub-types of Annot, including Caret, Highlight and Stamp, which are reflected in the annotation tools provided by apps from Acrobat to Preview. Seemingly complex annotations like popup notes are straightforward to code in PDF, requiring just two linked objects, one for the popup and its text, the other to specify its placement on the page. Others are more involved, as they can extend to include file attachments, sound, movie and other multimedia.
Despite their original simplicity, there are multiple problems that can arise with annotations.
With more recent versions of PDF, the ways in which they can be coded has increased. Mark up a PDF using the latest versions of Adobe Acrobat Reader or its ‘Pro’ CC colleague and they’ll cast it in PDF-1.6 and you’re unlikely to see a single Annot in their source. Most apps built on the Quartz PDF engine should write their files in PDF-1.3 so they can be accessed more widely, and should use regular Annot sub-types throughout. However, Preview likes to use opaque AAPL:AKAnnotationObjects that you won’t encounter anywhere else.
What Quartz does is to ‘flatten’ each PDF into a common 1.3 format for rendering, and that can be saved to disk. At present, that seems to work faithfully, but might give the impression that macOS can’t render more recent versions of PDF, which isn’t true. You can demonstrate that by opening an Acrobat PDF-1.6 document using an app that relies on the Quartz engine, such as PDF Expert, Preview or my Podofyllin, and comparing that with the original in Acrobat.
Podofyllin has a convenient feature for doing just that, in its source window. The uppermost of its three views displays Quartz ‘flattened’ code in PDF-1.3, the middle shows the original, here in PDF-1.6, and the lowermost is a summary of the latter.
The biggest dangers with annotations arise because of PDF’s ancient origins and a file format that doesn’t make sufficiently clear distinction between data and metadata. All annotations are metadata added to the underlying document, but in PDF, objects for each are mixed freely within the source. When they’re clearly distinguished with the Annot type, they should be easy to remove as a group, and PDF Expert offers that as a convenient command. That’s ideal when a document has been developed with the aid of reviewers’ annotations, to prepare the finished version for release.
Unfortunately this can cause its own problems, as PDF source is notorious for retaining old content that’s no longer visible in the rendered document, but can be read by anyone with a little knowledge about PDF. Like incomplete redactions, such hidden annotations have caused many embarrassments in the past, and will continue to catch folk out.
Finally, Preview has had more than its fair share of bugs in handling PDF annotations. During my research for this article, Preview 11.0 (1069.7.1) in macOS 15.6 was generally well behaved, but did mangle comments added to a test document by PDF Expert and Adobe Acrobat. Preview has two behaviours that can appear disconcerting: that of its Highlights and Notes tool, and its use of versioning.
All Preview’s tools are single-shot apart from Highlights and Notes, the drawing pencil icon to the left of its popup menu. Click this once to apply highlighting to selected blocks of text, and to remove existing highlighted sections. Unfortunately when this tool is turned on, its own highlighting is so weak that it’s hard to see.
Preview has a habit of saving PDF documents automatically when closing them, without any warning. If it has just mutilated an annotation, for example, you might assume the original file has just been overwritten and lost. However, Preview saves PDFs using the macOS document versioning system, so you can always recover the previous version.
This might at first seem an impossible task: use Preview to restore that old version and it will repeat its mutilation, defeating the purpose. Yet the original PDF editor won’t have access to previous versions, as it doesn’t use the versioning system. The solution is to use Revisionist, or Versatility, which can save the original as a separate document.
Spotlight has been able to find text extracted from images using Live Text, and the names of objects recognised using Visual Look Up, for some years now. This article considers how you can and cannot search for those. Although this might seem obvious, it’s more confusing than it appears and could mislead you into thinking that Spotlight indexing or search isn’t working.
As detailed in yesterday’s account of Live Text, text recognition in images uses a lexicon to match words rather than proceeding in single characters. Terms assigned to recognised objects are also words. Thus, when searching for either type you should use words as much as possible to increase the chances of success.
Type a word like cattle into Spotlight’s search window and you can expect to see a full selection of documents and images containing the term or cattle objects. Those include images containing the word, and images containing objects identified as cattle, but don’t include images in PDF files, as they’re not analysed by mediaanalysisd
, so don’t undergo character or object recognition in the same way that regular images like JPEGs do.
Open a new window in the Finder and turn it into a Spotlight search using the Finder’s File menu Find command. In its search box at the top right, type in a word like cattle and in the popup menu select the lower option, Content contains. Press Return and the search box will now display ANY cattle. Then set the Kind to Image in the toolbar above search results, to narrow results down to image files. You should then see a full listing of image files that either contain the word cattle, or contain objects identified by image analysis as being cattle. Note how many of those appear.
Reconfigure the search so the search box is empty, and there are two rows of search settings: the first can remain the same as Kind is Image, but set the second to Contents contains cattle. Those images containing objects identified as cattle will now vanish, leaving images containing the word cattle still listed.
To understand the difference between these, you can save those two Find windows and read the underlying terms used for each search. The search that returned text obtained by both Live Text and Visual Look Up used(((** = "cattle*"cdw)) && (_kMDItemGroupId = 13))
while the one excluding Visual Look Up used(((kMDItemTextContent = "cattle*"cdw)) && (_kMDItemGroupId = 13))
instead. We can transfer those to the mdfind
command tool to explore further.
mdfind
To use those as search predicates with mdfind
we’ll translate them into more general form,mdfind "(** == 'cattle*'cdw) && (kMDItemContentTypeTree == 'public.image'cd)"
should return both Live Text and Visual Look Up, whilemdfind "(kMDItemTextContent == "cattle*"cdw) && (kMDItemContentTypeTree == 'public.image'cd)"
only returns Live Text results.
The term (** == 'cattle*'cdw)
has a special meaning because of its wild card **
, and will return any match found in the metadata and contents of files. kMDItemTextContent
is similar, but confined to text content, which doesn’t include the names of objects recognised in an image, and Apple doesn’t reveal whether there’s an equivalent that does.
Although apps can call mdfind
to perform searches, they normally use NSMetadataQuery with an NSPredicate instead. That isn’t allowed to use a predicate like** ==[cdw] "cattle"
so can’t search for objects identified using Visual Look Up. When it uses the substitute ofkMDItemTextContent ==[cdw] "cattle"
it also fails to find text obtained using Live Text. So the only way to search for recovered text in a compiled app is to call mdfind
.
Searching for text obtained using Live Text, or object labels obtained using Visual Look Up, depends entirely on those being added to the Spotlight indexes on the volume. Observations of the log demonstrate just how quickly normal indexing by mdworker
processes takes place. Here’s an example for a screenshot:06.148292 com.apple.screencapture Write screenshot to temporary location
06.151242 [0x6000009bc4b0] activating connection: mach=true listener=false peer=false name=com.apple.metadata.mds
06.162302 com.apple.screencapture Moving screenshot to final location
06.169565 user/501/com.apple.mdworker.shared.1E000000-0600-0000-0000-000000000000 internal event: WILL_SPAWN, code = 0
06.198868 com.apple.DiskArbitration.diskarbitrationd mdworker_shared [7266]:118071 -> diskarbitrationd [380]
06.226997 kernel Sandbox apply: mdworker_shared[7266]
In less than 0.1 second an mdworker
process has been launched and granted the sandbox it uses to generate metadata and content for Spotlight’s indexes. Unfortunately, that doesn’t include any Live Text or Visual Look Up content, which are generated separately by mediaanalysisd
later. It’s hard to estimate how much later, although you shouldn’t expect to find such recovered text for several hours or days, depending on the opportunities for mediaanalysisd
to perform background image analysis for this purpose.
mdfind
can give full access to both types only when using a wildcard term such as (** == 'cattle*'cdw)
.mdfind
instead.Apple has just released an update to XProtect for all supported versions of macOS, bringing it to version 5310. As usual, Apple doesn’t release information about what security issues this update might add or change.
This version adds a single new detection rule for MACOS.SOMA.AUENA, further extending its coverage of Soma/Amos.
You can check whether this update has been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight and SystHist for El Capitan to Tahoe available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight or at the command line.
If you want to install this as a named update in SilentKnight, its label is XProtectPlistConfigData_10_15-5310
This update has already been released for Sequoia via iCloud. If you want to check it manually, use the Terminal commandsudo xprotect check
then enter your admin password. If that returns version 5310 but your Mac still reports an older version is installed, you may be able to force the update usingsudo xprotect update
© Chicago History Museum/Getty Images
Live Text and Visual Look Up are recent features in macOS, first appearing in Monterey nearly four years ago. As that immediately followed Apple’s short debacle over its now-abandoned intention to scan images for CSAM, most concerns have been over whether these features send details of images to Apple.
Although recent Intel Macs also support both these features, they don’t have the special hardware to accelerate them, so are far slower. For this walkthrough, I’ll only present information from Apple silicon Macs, in particular for the M4 Pro chip in a Mac mini.
When an image is opened from disk, the VisionKit system starts up early, often within 0.1 second of it starting to open. Its initial goal is to segment the image according to its content, and identify whether there’s any part of it that could provide text. If there is, then Live Text is run first so you can select and use that as quickly as possible.
In the log, first mention of this comes from com.apple.VisionKit announcingSetting DDTypes: All, [private]
Cancelling all requests: [private]
Signpost Begin: "VKImageAnalyzerProcessRequestEvent"
It then adds a request to Mad Interface, that’s the mediaanalysisd
service, with a total method return time, and that’s processed with another signpost (a regular log entry rather than a Signpost):Signpost Begin: "VisionKit MAD Parse Request"
com.apple.mediaanalysis receives that request[MADServicePublic] Received on-demand image processing request (CVPixelBuffer) with MADRequestID
then runs thatRunning task VCPMADServiceImageProcessingTask
This is run at a high Quality of Service of 25, termed userInitiated, for tasks the user needs to complete to be able to use an app, and is scheduled to run in the foreground. Next Espresso creates a plan for a neural network to perform segmentation analysis, and the Apple Neural Engine, ANE, is prepared to load and run that model. There’s then a long series of log entries posted for the ANE detailing its preparations. As this proceeds, segmentation may be adjusted and the model run repeatedly. This can involve CoreML, TextRecognition, Espresso and the ANE, which can appear in long series of log entries.
With segmentation analysis looking promising for the successful recognition of text in the image, LanguageModeling prepares its model by loading linguistic data, marked by com.apple.LanguageModeling reportingCreating CompositeLanguageModel ([private]) for locale(s) ([private]): [private]
NgramModel: Loaded language model: [private]
and the appearance of com.apple.Lexicon. An n-gram is an ordered sequence of symbols, that could range from letters to whole words, and the lexicon depends on the language locales. In my case, two locales are used, en
(generic English) and en_US
(US English).
At this point, mediaanalysisd
declares the VCPMADVIDocumentRecognitionTask is complete, and runs a VCPMADVIVisualSearchGatingTask, involving com.apple.triald, TRIClient, PegasusKit and Espresso again. Another neural network is loaded into the ANE, and is run until the VCPMADVIVisualSearchGatingTask is complete and text returned.
The next task is for the translationd
service to perform any translations required. If that’s not needed, VisionKit reportsTranslation Check completed with result: NO, [private]
These may be repeated with other image segments until all probable text has been discovered and recognised. At that stage, recognised text is fully accessible to the user.
Further image analysis is then undertaken on segments of interest, to support Visual Look Up. Successful completion of that phase is signalled in Preview by the addition of two small stars at the upper left of its ⓘ Info tool. That indicates objects of interest can be identified by clicking on that tool, and isn’t offered when only Live Text has been successful. VisionKit terms those small buttons Visual Search Hints, and remains paused until the user clicks on one.
Clicking on a Visual Search Hint then engages the LookupViewService, and changes the state from Configured to Searching. VisionKit records anotherSignpost Begin: "VisionKit MAD VisualSearch Request"
and submits a request to MAD for image processing to be performed. If necessary, the kernel then brings all P cores online in preparation, and the ANE is put to work with a new model.
PegasusKit then makes the first off-device connection for assistance in visual search:Querying https: // api-glb-aeus2a.smoot.apple.com/apple.parsec.visualsearch.v2.VisualSearch/VisualSearch with request (requestId: [UUID]) : (headers: ["grpc-message-type": "apple.parsec.visualsearch.v2.VisualSearchRequest", "Content-Type": "application/grpc+proto", "grpc-encoding": "gzip", "grpc-accept-encoding": "gzip", "X-Apple-RequestId": "[UUID]", "grpc-timeout": "10S", "User-Agent": "PegasusKit/1 (Mac16,11; macOS 15.6 24G84) visualintelligence/1"]) [private]
When the visual search task completes, information is displayed about the object of interest in a floating window. Visual Look Up is then complete, and in the absence of any further demands, the ANE may be shut down to conserve energy, and any inactive CPU cluster likewise:ANE0: power_off_hardware: Powering off... done
PE_cpu_power_disable>turning off power to cluster 2
mediaanalysisd
, MAD.I hope that you enjoyed Saturday’s Mac Riddles, episode 320. Here are my solutions to them.
What ET wants (to phone home) is a call (a phone call) coming to the Mac (macOS Tahoe is bringing the Phone app).
A glass (a magnifying glass) to enlarge (what it does) among the liquid (Tahoe’s Liquid Glass interface feature).
Daybook (a journal) you might already have started elsewhere (it was released in iOS 17.2, and is coming to macOS in Tahoe).
They are all new apps coming to macOS 26 Tahoe.
I look forward to your putting alternative cases.
Six years ago, in July 2019, Macs came closer to disaster than at any time before or since. Millions of Mac users around the world had, at some time or other, installed Zoom conferencing software, and in doing so had unknowingly put their Macs at risk. For their convenience, the old Zoom installers of that time also installed a hidden web server that was left running. That was capable of reinstalling the Zoom client, and had been discovered to contain an easily exploitable vulnerability that exposed all those Macs to remote attacks.
The only solution was for Apple to harness its old Malware Removal Tool, MRT, to remove that web server from all Macs before they came under attack. Although MRT had been widely criticised for what others considered to be weakness, on this occasion it proved its value. MRT version 1.45 was released by Apple on 10 July 2019, and averted that potential catastrophe.
Three years later, in the summer of 2022, Apple replaced MRT with its successor, XProtect Remediator or XPR, which has been vastly improved, and still contains the remnants of MRT in its MRTv3 scanning module. As Apple documents almost nothing about XPR, it has been up to others to dive deep inside it, among them Koh M Nakagawa, @tsunek0h, of FFRI Security. While others have merely scratched the surface, he has just presented a superb and deep account of XPR at Black Hat USA. You can download the slides for his presentation from here.
If you check XPR scans using SilentKnight or XProCheck, you’ll be aware that for many months some of them are terminated prematurely with a status_code of 30 and the message PlugInCanceled. This most commonly affects Adload scans, and still occurs in beta-releases of macOS 26 Tahoe. According to Koh’s research, the Adload scanning module alone contains over 1,000 Yara detection rules, accounting for the long time it takes whenever XPR runs a set of scans.
Before XPR started terminating its scans as it does now, a full set could take an hour or more, so XPR has started using a timer. If the scan exceeds the time allowed, then it will be abruptly terminated, resulting in this status_code and message. There’s nothing the user can do to avoid it, and we’re surprised that XPR continues to exhibit this behaviour.
The other significant limitation in XPR affects those using MacBook Pro, MacBook Air and MacBook models. Because XPR scans take a substantial amount of energy, even when run almost entirely on the E cores of Apple silicon Macs, daily full scans will only be run when those laptops are using mains power, and won’t be run at all on battery.
As XPR scans are also normally run when a Mac is awake but only under a light load, it’s possible for a laptop to go several days without running an XPR scan. The only solution is to leave it connected to mains power, awake and doing little else for an hour or so, when it should seize the opportunity to catch up with that and other important background tasks with similar requirements.
Unfortunately, XPR won’t warn you that it hasn’t run any scans for several days, but SilentKnight and XProCheck will.
According to scientific tradition, we first observe then experiment. If you proceed to the latter before you understand how a system behaves, then you’re likely to labour under misapprehensions and your trials can become tribulations. Only when a system is thoroughly opaque and mysterious can we risk attempting both together.
That’s the case for Spotlight, which despite its name does everything but shine any light on its mechanisms. It presents itself in several guises, as a combination of web and local search (), as local search using terms limited in their logical operators (Finder’s Find), as full-blown predicate-based local search (
mdfind
), as in-app file search (Core Spotlight), and the coder’s NSMetadataQuery and predicates. It relies on indexes scattered across hundreds of binary files, and runs multiple processes, while writing next to nothing in the log.
Last week’s code-doodling has been devoted to turning the Spotlight features in Mints into a separate app, SpotTest, so I can extend them to allow testing of different volumes, and search for text that has been derived from images. Those are proving thorny because of Spotlight’s unpredictable behaviour across different Macs running Sequoia.
Every week I search for screenshots to illustrate another article on Mac history. When using my old iMac Pro where most of them are stored, Spotlight will find many images containing search terms from the text shown within them, even from ancient QuickDraw PICT images, demonstrating that text is being recovered using Live Text’s optical character recognition. When I try to repeat this using test images on an Apple silicon Mac, Spotlight seems unable to recognise any such recovered text.
Image analysis on Macs has a stormy history. In a well-intentioned gaffe four years ago, Apple shocked us when it declared it was intending to check our images for CSAM content. Although it eventually dropped that idea, there have been rumours ever since about our Macs secretly looking through our images and reporting back to Apple. It didn’t help that at the same time Apple announced Live Text as one of the new features of macOS Monterey, and brought further image analysis in Visual Look Up.
Although I looked at this in detail, it’s hard to prove a negative, and every so often I’m confronted by someone who remains convinced that Apple is monitoring the images on their Mac. I was thus dragged back to reconsider it in macOS Sonoma. What I didn’t consider at that time was how text derived from Live Text and image analysis found its way into Spotlight’s indexes, which forms part of my quest in SpotTest.
This doesn’t of course apply to images in PDF documents. When I looked at those, I concluded: “If you have PDF documents that have been assembled from scans or other images without undergoing any form of text recognition, then macOS currently can’t index any text that you may still be able to extract using Live Text. If you want to make the text content of a PDF document searchable, then you must ensure that it contains its own text content.” I reiterated that in a later overview.
My old images aren’t PDFs but QuickDraw PICTs, TIFFs, PNGs and JPEGs, many from more than 20 years ago. When the circumstances are right, macOS quietly runs Live Text over them and stores any text it recovers in Spotlight’s indexes. It also analyses each image for recognisable objects, and adds those too. These happen more slowly than regular content indexing by mdworker
, some considerable time after the image has been created, and have nothing whatsoever to do with our viewing those images in QuickLook or the Finder, or even using Live Text or Visual Look Up ourselves.
There are deeper problems to come. Among them is discovering the results of image recognition as can be revealed in the command line using a search such asmdfind "(** == 'cattle*'cdw) && (kMDItemContentTypeTree == 'public.image'cd)"
to discover all images that have been recognised as containing cattle. There’s no equivalent of the first part of that when calling NSMetadataQuery from Swift code, and a predicate ofkMDItemTextContent CONTAINS[cd] \"cattle\"
will only discover text recovered by Live Text, not the names of objects recognised within an image.
What started as a quick doodle is now bogged down in the quirks of Spotlight, which defies the scientific method. Perhaps it’s time for a little sorcery.
Here are this weekend’s Mac riddles to entertain you through family time, shopping and recreation.
1: What ET wants is a call coming to the Mac.
2: A glass to enlarge among the liquid.
3: Daybook you might already have started elsewhere.
To help you cross-check your solutions, or confuse you further, there’s a common factor between them.
I’ll post my solutions first thing on Monday morning.
Please don’t post your solutions as comments here: it spoils it for others.
To make its graphical interface work, the Mac needed a high-performance graphics system, for which the late Bill Atkinson (1951-2025) and Andy Hertzfeld designed and implemented QuickDraw. When it came to driving printers, though, Steve Jobs licensed the new page description language PostScript from Adobe, where it had just been developed by John Warnock (1940-2023), Charles Geschke (1939-2021) and others. PostScript is a stack-based interpreted language that could take many seconds or even minutes to image a page for printing, so wasn’t practical for doing much else at that time.
In the early 1990s, as desktop publishing became dominant among Mac users and we were all sending one another faxes, several companies recognised the need for a universal document format that could display laid-out text and graphics. Among them was Adobe, where Warnock formulated the aims of what he then referred to as Interchange PostScript or IPS, and so led the development of Portable Document Format. It’s telling that the final sentence of his proposal reads: “In any event corporations should be interested in site-licensing arrangements.”
When the first version of PDF was released in 1993, with its Carousel reader app, it faced competition from other similar ideas, and Adobe found itself competing against products including Farallon’s Replica, and Tumbleweed’s Envoy that gained the support of WordPerfect, then a popular cross-platform word processor. PDF didn’t become dominant until Adobe distributed its reader app free, rather than charging $50 for it as it had initially.
For many years, the only way to create really good PDFs was using Adobe’s Acrobat Distiller app, costing $695 for a single-user licence. That ingested PostScript files, created on the Mac by printing to a file, and transformed them into PDFs that could in turn only be read using Adobe’s software. Although PostScript was by then a prerequisite for all publishing work on Macs, it wasn’t until 1996, when PDF reached version 1.2 in Acrobat 3.0, that it captured the prepress market, which it consolidated in 1998 with the PDF/X-1 standard.
This is Acrobat Distiller 4.0 running on Mac OS 9.1 in early 2001, showing a few of its bewildering array of options for turning PostScript files into PDF.
At the same time, John Warnock’s aspirations for success in enterprise markets were being realised, and PDF steadily became the standard for fixed-format electronic documents, with the support of the US Internal Revenue Service and Adobe’s free cross-platform Acrobat Reader.
When Steve Jobs established NeXT in 1985 he must have become the only person to have licensed PostScript from Adobe twice, as NeXTSTEP adopted Display PostScript as the centrepiece of its graphics, developed collaboratively between NeXT and Adobe. At the time many thought this to be a mistake, as PostScript isn’t as efficient a graphics language as QuickDraw, despite Adobe’s efforts to accelerate it.
When NeXT and Mac merged to form the beginnings of Mac OS X in 1997, Display PostScript was replaced with PDF as the central graphics standard for both display and printing, in what was dubbed Quartz 2D. This was first demonstrated at WWDC in 1999 and lives on today in macOS. At the time, Apple’s in-house PDF engine in Quartz was one of few, alongside Adobe’s.
Prior to Mac OS X, Adobe Acrobat, both in its free viewer form and a paid-for Pro version, had been the de facto standard for reading, printing and working with PDF documents on the Mac. The Preview app had originated in NeXTSTEP in 1989 as its image and PDF viewer, and was brought across to early versions of Mac OS X, where it has remained ever since.
This PDF shows Apple’s original iPod promotional literature from late 2001.
Adobe continued providing its free Acrobat Reader for Mac OS X, here seen in 10.0 Cheetah.
The full paid-for version of Adobe Acrobat provided an extensive suite of editing tools, here in Mac OS X 10.1 Puma in early 2002.
By Mac OS X 10.3 Panther in 2003, Apple was claiming that Preview was “the fastest PDF viewer on the planet”, capable of navigating and searching text within PDF documents “at lightning speed”. This worked with the Mac’s new built-in support for faxing, which rendered received faxes in PDF to make them easier and clearer to access.
This is an early Keynote Quick Reference guide from 2003, viewed in Preview.
At that time, Preview was also able to convert Encapsulated PostScript (EPS) files and raw PostScript to PDF, so they could be saved in the more accessible format, and printed easily.
This page from the 9/11 Commission Report of 22 July 2004 is being viewed in Preview.
Acrobat Distiller remained an important component in Adobe’s paid-for product, even though Mac OS X was capable of generating its own PDFs. It’s seen here in Mac OS X 10.4 Tiger in 2005.
This is Acrobat Pro in 10.4 Tiger in early 2006, showing its long list of supported export formats.
Since those heady days, Preview has been relatively neglected. Revision of both the Quartz PDF engine and its API brought a spate of bugs that only abated with macOS Sierra. Preview has adopted an uncommon model for PDF annotations that often doesn’t work well with other PDF products, but it has remained very popular for completing electronic forms. Then, in macOS Ventura, Apple removed all support for converting EPS and PostScript to PDF, most probably as a result of security concerns, and their progressive disuse.
Although rumours of the death of Preview continue to prove unfounded, it’s unlikely to feature again as one of the strengths of macOS.
John Warnock (1991) The Camelot Project, on the Internet Archive’s Wayback machine.
Laurens Leurs’ The history of PDF.
With the next scheduled update to macOS Sequoia likely to be released in September or October, macOS 15.6 officially marks the end of its year-long cycle of full support. This article looks at its updates and how it has changed.
It took Sequoia a total of 11 updates to reach version 15.6 at the end of July, including five unscheduled patch updates, which is close to average. Prominent through those updates has been the number of security vulnerabilities addressed, peaking at 81 in 15.6.
In terms of cumulative size of updates, Sequoia was close to average at a total of 27.5 GB for Apple silicon Macs and 19.3 GB for Intel models. Although not as bad as Big Sur which took over 50 GB for Apple silicon Macs, it wasn’t as good as Sonoma at just over 21 GB. Update size was relatively small up to 15.3, but added over 9 GB in the three updates it took to reach 15.4. Apple doesn’t appear to have made progress in reducing the size of updates for Apple silicon Macs, and that may not be achieved until macOS 27 next year, when Intel support is finally dropped.
The total number of bundled apps has increased slightly, from 60 in Sonoma to 62 in 15.0, and 64 in 15.6. That’s set to rise again in Tahoe, with the addition of Journal and Phone.
The total number of bundles in /System/Library has risen further to reach 9,304, almost double the number in 10.14.5 six years ago, and up from 8,392 a year ago in 14.6. Unusually, this has risen by nearly 300 through Sequoia’s cycle. Previously it has been more common for only small rises to occur during a cycle, and in macOS 13 the total fell slightly.
Over that period, the main growth has been in the number of Private Frameworks, which have risen from about 1,760 in 10.14 to over 4,400 in 15.6. Public Frameworks have risen less, from less than 520 to 806. Despite Apple’s campaign for third-parties to move away from kernel extensions, those in macOS also continue to grow, rising from a minimum of 515 in 10.15.0 to 939 in 15.6. Sequoia has added 39 of those in going from 15.0 to 15.6.
This is a more detailed breakdown by category of bundles in /System/Library, comparing 10.15.6 with 15.6:
Five years ago in 10.15.6, public Frameworks were almost a quarter of all Frameworks. In 15.6, they are less than 18%. macOS continues to become an increasingly private operating system supporting Apple’s apps, not those of third party developers.
If RunningBoard’s copious log entries record the life cycle of apps, can we use them to our advantage? To test this out, I’ve analysed a section of log using waypoints and information provided in RunningBoard’s entries.
Waypoints, or landmarks if you prefer, are essential for navigating the log. In an ideal world we would always know when any significant event occurred, timed to the millisecond. In practice we may only be able to estimate to the nearest few seconds or minutes. Without some means of discovering exactly when to obtain log extracts, you can waste many hours trying to pin down when something happened, and in many cases will be forced to abandon the hunt.
My aim was to separate RunningBoard log entries into those handling its assertions, which should represent life-cycle events, and job descriptions giving details of apps launched. To try this yourself, open LogUI and set the Start date and time to the start of the period of interest. Set the Period to at least 100 seconds, and Max entries to 2,000 or more. Then set the Predicate popup menu to read subsystem, and type in com.apple.runningboard
so that LogUI only gets entries from that subsystem. Click on the Get Log tool in the toolbar, and check you get at least 1,000 entries.
Click on the Save JSON tool to save the whole of this excerpt. To view all the RunningBoard assertions acquired over that excerpt, type acquiring assertion
in the search box at the top right, and press Enter.
The window name then changes to append the text from the search box.
To save this limited selection of entries, first click on the Reduce tool to discard all the others, then click on the Save JSON tool again and save the entries using a different filename. Repeat that using each of three search terms:
acquiring assertion
to see RunningBoard’s outline of life cycle events,constructed job
to see job descriptions for newly launched apps,extension overlay
to see similar information for appexes and similar extensions.In my case, I analysed a period of 4 minutes of user activity on a Mac mini M4 Pro running macOS 15.6, during which there were 6,580 RunningBoard entries, suggesting that the whole log would have had well over 50,000 entries in that time, far too many to attempt any more detailed analysis. My search terms found 305 assertions acquired, 3 job descriptions constructed, and 20 extension overlays submitted.
The three captured represented the three apps I had launched over those four minutes, Cormorant, DelightEd and Consolation 3. Each of them has a platform ID of 1, as notarized macOS apps. I also noticed that one was run in app translocation, although this was long after its first run. Recent versions of macOS, Sequoia in particular, appear prone to this, when an app that should have cleared quarantine gets stuck in perpetual app translocation.
While I had expected to find those three app launches, I didn’t expect to see any appexes being run over this period. Those encountered consisted of three widgets, none of which had ever been opened, and five QuickLook thumbnail extensions. Most of these were run multiple times, with ScappleThumbnail appearing on six occasions. All were platform 1, except for the widgets, all three of which are bundled in macOS, for the FindMy widget and NewsToday2. They were platform 6, and subject to RunningBoard’s resource controls.
RunningBoard’s log entries here give potentially valuable insights that might otherwise be missed.
It’s straightforward to construct a narrative of the key events that took place over that period of 4 minutes using a selection of assertions acquired. Rather than reproduce the whole of each of those waypoints, here they are laid out in more readable form.
11:40:50.424950 Acquiring assertion targeting app application.co.eclecticlight.Cormorant.10809046.10809052(501)
description "LS launch co.eclecticlight.Cormorant" ID:424-620-716
target: application.co.eclecticlight.Cormorant.10809046.10809052(501)
attributes: domain:"com.apple.launchservicesd" name:"LaunchRoleUserInteractive" sourceEnvironment:"(null)"
This marks the start of the launch process for Cormorant, handled in the normal way through LaunchServices and RunningBoard.
11:41:18.304367 Acquiring assertion targeting app application.co.eclecticlight.DelightEd.10206240.10206246(501)
description "LS launch co.eclecticlight.DelightEd" ID:424-620-756
target: application.co.eclecticlight.DelightEd.10206240.10206246(501)
attributes: domain:"com.apple.launchservicesd" name:"LaunchRoleUserInteractive" sourceEnvironment:"(null)"
This is the same for DelightEd.
11:41:20.050166 Acquiring assertion targeting [xpcservice com.apple.appkit.xpc.openAndSavePanelService([app application.co.eclecticlight.DelightEd.10206240.10206246(501) :1553])(501) 1576:1576]
description "viewBridge:1576" ID:424-391-769
target: 1576
attributes: domain:"com.apple.launchservicesd" name:"RoleViewBridge" sourceEnvironment:"(null)"
DelightEd is here being used to open a document using the openAndSavePanelService, a separate process.
11:41:44.171636 Acquiring assertion targeting app application.co.eclecticlight.Consolation3.430650.430692(501)
description "LS launch co.eclecticlight.Consolation3" ID:424-620-788
target: application.co.eclecticlight.Consolation3.430650.430692(501)
attributes: domain:"com.apple.launchservicesd" name:"LaunchRoleUserInteractive" sourceEnvironment:"(null)"
This is the launch of Consolation 3, a user error on this occasion!
Two long runs of assertions were discovered, both involving syncing the address book for Contacts.
11:41:57.462118 Acquiring assertion targeting [osservice com.apple.AddressBook.SourceSync(501):1610]
description "App is holding power assertion" ID:424-362-811
target: 1610
attributes: domain:"com.apple.appnap" name:"PowerAssertion" sourceEnvironment:"(null)", RBSAcquisitionCompletionAttribute policy:AfterApplication
The first of these was to sync the Address Book with its source in iCloud, and lasted 12.181 seconds.
11:42:11.840349 Acquiring assertion targeting [osservice com.apple.AddressBook.abd(501):1625]
description "Contacts shared filesystem lock" ID:424-1625-857
target: 1625
attributes: domain:"com.apple.common" name:"FinishTaskUninterruptable" sourceEnvironment:"(null)", RBSAcquisitionCompletionAttribute policy:AfterApplication
Shortly after that completed, synced data was updated by a service abd
(Address Book Daemon?) that I had been unaware of. This only lasted 2.238 seconds.
RunningBoard’s assertions seldom appear for single-shot shell commands, and most commonly handle executable bundles rather than bare Mach-O binaries. They also don’t appear to provide clear information recording when apps are quit normally.
By now your Mac should have the latest macOS update installed, and be running the current firmware. This article takes stock of where EFI, T2 and Apple silicon firmware are now, and where they’re heading with the forthcoming release of macOS 26 Tahoe in a month or two.
For many years, the only way your Mac will have its firmware updated is when macOS or one of its updates is installed on it. There is one significant exception to that, in Apple silicon Macs, whose firmware will be completely replaced when it’s put into DFU mode and restored from an IPSW file.
Each macOS update or full installer comes with the firmware current at the time Apple built it. So if your Mac is still running macOS 12.7.6 Monterey and has never installed any later version, it will have the firmware that came with that, such as iBoot 10151.140.19, or T2 version 2022.140.5.0.0 with iBridge 21.16.6074.0.0,0.
Note that firmware is updated whether macOS is installed or updated on the internal storage, or on an external disk. So if your Mac’s internal SSD is still running 12.7.6, but it has been used to update Ventura to 13.7.7 on an external SSD, then it will have the firmware brought in that version of Ventura, rather than that for Monterey. That doesn’t of course apply to macOS installed in any virtual machines, as they can’t update the host firmware.
All these models appear to have reached the end of their EFI firmware updates, with the versions shown.
iMac:
MacBook:
MacBook Pro:
All those date from 23 June 2024, apart from that for the iMac19,1, whose latest firmware is from March 2025. Although the latter could still be updated in a security update to Sonoma or Sequoia, that now looks increasingly unlikely.
The current EFI version is 2075.140.4.0.0 and iBridge is 22.16.16083.0.0,0, and those are likely to continue to be updated over the coming year. However, T2 models still running macOS Ventura are likely to stay there, unless Apple releases one final extra update. To ensure that your T2 Mac continues to get firmware updates, it now needs to be running Sonoma or later.
The current iBoot version is 11881.140.96, and that is sure to see a substantial update with the release of macOS 26.0, and in the simultaneous security updates for Sequoia and Sonoma. However, any Apple silicon Mac still running Ventura or earlier will be running an older version of iBoot that it can’t update, unless it installs or updates a more recent macOS in another boot volume group, such as on an external disk.
Display firmware remains at version 17.0 (build 21A329) as it was when updated with macOS Sonoma nearly two years ago in September 2023. Although there’s no sign of any update with the beta-test versions of Tahoe, maybe it’s likely that this will be updated with macOS 26.0 and its associated security updates.
The currently installed firmware version is displayed in System Information, by selecting the Hardware item at the top left. It’s also checked against the current version in SilentKnight. However, in recent Mac models with T2 or Apple silicon chips it’s most unlikely to differ from that brought with the latest version of macOS that Mac has installed or updated. Macs without T2 chips were less reliable, and some older models often failed to update when expected. Thankfully that’s now a problem of the past. If there’s one thing you should be able to trust it’s firmware updating.
Apple has just released updates to XProtect for all supported versions of macOS, bringing it to version 5309, and to XProtect Remediator for all macOS from Catalina onwards, to version 153. As usual, Apple doesn’t release information about what security issues these updates might add or change.
Yara definitions in this version of XProtect add a single new detection rule for MACOS.SOMA.JUENB, part of the Soma/Amos family.
XProtect Remediator doesn’t change the list of scanner modules.
There are extensive changes to the Bastion rules, which add a new definition for common system binaries, extend Rule 1 coverage to include support folders for more browsers, tweak Rules 3 and 14-17, and add new Rules 18-24.
You can check whether these updates have been installed by opening System Information via About This Mac, and selecting the Installations item under Software.
A full listing of security data file versions is given by SilentKnight and SystHist for El Capitan to Tahoe available from their product page. If your Mac hasn’t yet installed this update, you can force it using SilentKnight or at the command line.
If you want to install these as named updates in SilentKnight, their labels are XProtectPayloads_10_15-153
and XProtectPlistConfigData_10_15-5309
.
The XProtect update has already been released for Sequoia and Tahoe via iCloud. If you want to check it manually, use the Terminal commandsudo xprotect check
then enter your admin password. If that returns version 5304 but your Mac still reports an older version is installed, you may be able to force the update usingsudo xprotect update
macOS comes with no support for the file systems most likely to be used by Linux. This article suggests how you might be able to access them, for example when a NAS system is connected directly to an Apple silicon Mac, or when you need to access external storage that has been used with a Linux system.
I believe Paragon Software’s extFS is the only generally available commercial solution, and is described here. If you only need access for a short period, it’s free to use for up to ten days, but must be licensed for $39.95, €39.95, or £38.81 if you want to unlock it to use for any longer. Paragon also offers support for accessing APFS from Linux and Windows.
If you need more than simple access to the contents of the file system, you can also combine extFS with an Ubuntu VM running in UTM to access backups made using Duplicity, for example. This is detailed here by Benjamin, to whom I’m very grateful for information about extFS and for inspiring this note.
Benjamin Fleischer’s free fork of Google’s MacFUSE software should be able to implement a fully functional alien file system running in user space. Its latest release 5.0.5 is compatible with current betas of macOS Tahoe as well as older versions back to macOS 12. However, some report that it isn’t able to deliver reliable support for Ext4 and similar. In theory, this should now be simpler, as recent versions of macOS can support macFUSE without requiring a kernel extension, and there’s an alternative backend in recent versions of macFUSE to support that. Project front page.
Jeff Geerling’s walkthrough using macFUSE with ext4fuse.
This is based on the libkrun
microVM hypervisor, available separately from here. It has the advantage that it doesn’t rely on either kernel or system extensions, and is available from here. I’ve been unable to discover how reliable this is on Apple silicon, if it works at all.
If you know of other ways of doing this with an Apple silicon Mac, please provide details in a comment.
I hope that you enjoyed Saturday’s Mac Riddles, episode 319. Here are my solutions to them.
Successor to 3 (Adobe developed it to replace the ailing PageMaker) inside (in) a scheme (a design) was part of a popular atelier (for many years it was one of the leading apps in Adobe’s Creative Studio).
High speed (express) subatomic particle (a quark) took the lead in the 1990s (by the mid-1990s it had taken around 90% of the desktop publishing market on Macs).
Creator (maker) of a squire’s assistant (a page) was the first (released in July 1985 for the Mac), but died before Mac OS X (by 2000, it was moribund as Adobe was replacing it with InDesign, released in 1999, and it was never ported to Mac OS X).
They have all been leading desktop publishing apps for Macs.
I look forward to your putting alternative cases.
With additional information about Spotlight’s volume indexes, this article looks in more detail at how those indexes are updated when new files are created, and how local search is reflected in log entries. To do this I use the Spotlight test feature in my free utility Mints, which is designed to assess its performance.
Mints can create a test folder and populate it with 9 test files, copied from inside the app bundle using File Manager’s copyItem
function. Provided the app and that newly created folder in ~/MintsSpotlightTest4syzFiles are in the same volume, this will almost certainly occur by creating APFS clone files. The files are:
The search target they each contain is a string starting with the characters syzygy999
so most likely to be unique to the test files and Mints’ bundle.
This example test was performed on a Mac mini M4 Pro running macOS 15.6 from its internal SSD, with the Home folder located in the boot Data volume in that storage.
Folder creation and file copying should take place soon after clicking on the Create Test button, in this example test in just over 0.3 seconds. The first mdworker
process responding to this is spawned about 0.9 seconds after file copying starts, and further mdworker
processes are added to it, making a total of 11. These are uncorked by launchd
in about 0.03-0.05 seconds and are active for a period of about 0.2 seconds before they appear to have finished creating new posting lists to be added to the local indexes.
Shortly after those are complete, spotlightknowledge
is active briefly, then 0.2 seconds after file copying mediaanalysisd
receives a text processing request and initialises CGPDFService. Just over 0.1 second later CoreSceneUnderstanding is invoked from mediaanalysisd
. For the following 5 seconds, a series of MADTextEmbedding (mediaanalysisd
text embedding) tasks are performed. Finally, content obtained by mdworker
and MADTextEmbedding is compressed by mds_stores
, finishing about 6.7 seconds after the new files were created.
These steps are summarised in the diagram above, where those in blue update metadata indexes, and those in yellow and green update content indexes. It’s most likely that each file to be added to the indexes has its own individual mdworker
process that works with a separate mdimporter, although in this case at least 11 mdworker
processes were spawned for 9 files to be indexed.
Text extraction from files by mediaanalysisd
involves a series of steps, and will be covered in more detail separately. In this test, local Spotlight indexes should have been updated within 7-8 seconds of file creation, so waiting at least 10 seconds after clicking the Create Test button should be sufficient to enable the test files to be found by search.
When the Check Search button in Mints is clicked, an NSMetadataQuery is performed using a search predicate over the search scope of NSMetadataQueryUserHomeScope
, the Home folder. This uses the search predicate (kMDItemTextContent CONTAINS[cd] "syzygy999") OR (kMDItemKeywords CONTAINS[cd] "syzygy999") OR (kMDItemAcquisitionMake CONTAINS[cd] "syzygy999")
to find all items containing any of:
kMDItemTextContent CONTAINS[cd] "syzygy999"
looks for the target string in a text representation of the content of the document, as in most of the test files used.kMDItemKeywords CONTAINS[cd] "syzygy999"
looks for keywords in an extended attribute of type com.apple.metadata:kMDItemKeywords as attached to the SpotTestMD.txt file.kMDItemAcquisitionMake CONTAINS[cd] "syzygy999"
looks for the Make field of an EXIF IDF0 as embedded in the SpotTestEXIF.jpg file.Each of those is both case- and diacritic-insensitive, although the test cases all use lower case without any diacritics.
Remarkably little is recorded in the log for these test searches. com.apple.metadata starts the query within 0.001 second of clicking the Check Search button, and is interrupted by TCC approving the search to proceed. About 0.03 seconds after the start of the query, a series of entries from mds_stores
reports query node counts of 4, and results are fetched and sent as replies between 0.09 and 19.5 seconds after the start of the query. However, Mints typically reports a considerably shorter search time of around 4 seconds.
The test currently included in Mints appears useful, in that it assesses the whole of Spotlight local search from file creation to completion of a test search. However, in its current form it doesn’t test LiveText or other in-image text extraction, and only applies to the volume containing the Home folder. Log extracts obtained in its Log Window are basic and don’t capture much of the detail used for this article. There seems scope for a dedicated Spotlight test app that addresses these and more.
mediaanalysisd
(‘MAD’) is significantly slower than extraction of metadata and other text content.One thing we humans are good at is searching. It’s a task we engage in from a few moments after birth until the time we slip away in death, we search everything around us. Locating and identifying that bird of prey wheeling high, finding the house keys, and that book we mislaid some time last week, meeting the perfect partner, discovering the right job, choosing the best education, looking through a Where’s Wally? or Where’s Waldo? book, and so on. Searching has transformed some into explorers like Christopher Columbus, and was the purpose of the chivalric quest. It’s what researchers in every field do, and thanks to Douglas Adams can be answered by the number 42.
Last week my searching took two new turns.
The first was more of a meta-search, in trying to discover more about the internals of Spotlight. Following the example of Maynard Handley, who has used them so successfully in understanding how M-series CPUs work, I looked through patents that have been awarded to Apple for the work of its search engineers. Yesterday’s slightly fuller history of Spotlight search is one result, and there are more to come in the future as I digest those patents concerned with performing search.
There’s a tinge of irony here, as many of my searches have been conducted using Google Patents, alongside Google Scholar one of the remaining search engines that doesn’t yet use AI and attempt to provide its own answers.
The other marks a new phase in my quest to get more information from the Unified log. Looking back to my first comment here, I realise how wildly over-optimistic I was when I wrote that it “should make my life a lot easier”, and that “a new version of Console will provide improved features to help us wade through logs.” Nine years later, I look wistfully at what remains of Console and realise how wrong I was on both counts.
When RunningBoard arrived in macOS Catalina, I soon noticed how “its log entries are profuse, detailed, and largely uncensored for privacy.” Since then it has proved garrulous to the point where its apparently ceaseless log chatter is a distraction, and can overwhelm attempts to read other log entries. I suspect it has contributed significantly to those advanced Mac users who now refuse to even try to make sense of the log.
One answer might be to tweak log preferences to shut out this noise, but given the purpose of RunningBoard in monitoring the life cycle of apps, why not try to use the information it provides? To do that, it’s first necessary to understand RunningBoard’s idiosyncratic language of assertions, and its protocols under which they’re acquired. The only way to do that without documentation is by observation: catalogue over 30 of those assertions for an interesting example like Apple’s Developer app, and see what they reveal.
By far the most informative entries from RunningBoard are those announcing that it’s acquiring an assertion, such asAcquiring assertion targeting [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] from originator [osservice<com.apple.uikitsystemapp(501)>:748] with description <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:424-748-2228 target:2946 attributes:[
<RBSDomainAttribute| domain:"com.apple.frontboard" name:"AfterLife-Subordinate" sourceEnvironment:"(null)">
]>
In a log often censored to the point of being unintelligible, this contains frank and explicit detail. The app is identified clearly, with the user ID of 501 and process ID of 2946. The originator is similarly identified as com.apple.uikitsystemapp with its PID of 748, which is confirmed in the middle digits in the Assertion ID. This is explicitly related to FrontBoard and an attribute named AfterLife-Subordinate. There’s not a single <private> to blight this entry, although further knowledge is needed to decode it fully.
Normally to get such information from a running process would require its source code to be instrumented with calls to write log entries, many of which would be lost to <private>, yet RunningBoard seems happy, for the moment, to provide that information freely. You can see what I mean by applying the predicatesubsystem == "com.apple.runningboard" AND message CONTAINS "Acquiring assertion t"
in LogUI, to obtain a running commentary on active apps and processes. Once you’ve identified a relevant assertion, you can focus attention on other log entries immediately prior to that. I will be following this up in the coming week, with fuller instructions and some demonstrations.
Although neither patents nor assertions have the significance of the number 42, in their own ways they show how the art and science of search aren’t dead yet, nor have they succumbed to AI.
Here are this weekend’s Mac riddles to entertain you through family time, shopping and recreation.
1: Successor to 3 inside a scheme was part of a popular atelier.
2: High speed subatomic particle took the lead in the 1990s.
3: Creator of a squire’s assistant was the first, but died before Mac OS X.
To help you cross-check your solutions, or confuse you further, there’s a common factor between them.
I’ll post my solutions first thing on Monday morning.
Please don’t post your solutions as comments here: it spoils it for others.
Since writing A brief history of local search, I have come across numerous patents awarded to Apple and its engineers for the innovations that have led to Spotlight. This more detailed account of the origins and history of Spotlight uses those primary sources to reconstruct as much as I can at present.
1990
ON Technology, Inc. released On Location, the first local search utility for Macs, a Desk Accessory anticipating many of the features to come in Spotlight 15 years later. This indexed text found in the data fork of files, using format-specific importer modules to access those written by Microsoft Word, WordPerfect, MacWrite and other apps of the day. Those files and their indexed contents were then fully searchable. This required System Software 6.0 or later, and a Mac with a hard disk and at least 1 MB of RAM. It was developed by Roy Groth, Rob Tsuk, Nancy Benovich, Paul Moody and Bill Woods.
1991
Version 2 of On Location was released. ON Technology was later acquired by Network Corporation, then by Symantec in 2003.
AppleSearch was released, and bundled in Workgroup Servers. This was based on a client-server system running over AppleShare networks. September’s release of System Software 7.5 introduced a local app Find File, written by Bill Monk.
Sherlock was released in Mac OS 8.5. This adopted a similar architecture to AppleSearch, using a local service that maintained indexes of file metadata and content, and a client app that passed queries to it. This included remote search of the web through plug-ins working with web search engines, as they became available.
Early patent applications were filed by Apple’s leading engineers who were working on Sherlock, including US Patent 6,466,901 B1 filed 30 November 1998 by Wayne Loofbourrow and David Cásseres, for a Multi-language document search and retrieval system.
Sherlock 2 was released in Mac OS 9.0. This apparently inspired developers at Karelia Software to produce Watson, ‘envisioned as Sherlock’s “companion” application, focusing on Web “services” rather than being a “search” tool like Sherlock.’
On 5 January, Yan Arrouye and Keith Mortensen filed what became Apple’s US Patent 6,847,959 B1 for a Universal Interface for Retrieval of Information in a Computer System. This describes the use of multiple plug-in modules for different kinds of search, in the way that was already being used in Sherlock. Drawings show that it was intended to be opened using an item on the right of the menu bar, there titled [GO-TO] rather than using the magnifying glass icon of Sherlock or Spotlight. This opened a search dialog resembling a prototype for Spotlight, and appears to have included ‘live’ search conducted as letters were typed in.
Karelia Software released Watson.
Mac OS X Jaguar brought Sherlock 3, which many considered had an uncanny resemblance to Watson. That resulted in acrimonious debate.
In preparation for the first Intel Macs, Mac OS X 10.4 Tiger, released in April 2005, introduced Spotlight as a replacement for Sherlock, which never ran on Intel Macs.
Initially, the Spotlight menu command dropped down a search panel as shown here, rather than opening a window as it does now.
On 4 August, John M Hörnkvist and others filed what became US Patent 7,783,589 B2 for Inverted Index Processing, for Apple. This was one of a series of related patents concerning Spotlight indexing. Just a week later, on 11 August, Matthew G Sachs and Jonathan A Sagotsky filed what became US Patent 7,698,328 B2 for User-Directed search refinement.
A Finder search window, precursor to the modern Find window, is shown in the lower left of this screenshot taken from Tiger in 2006.
Spotlight was improved in Mac OS 10.5 Leopard, in October. This extended its query language, and brought support for networked Macs that were using file sharing.
This shows a rather grander Finder search window from Mac OS X 10.5 Leopard in 2009.
Search attributes available for use in the search window are shown here in OS X 10.9 Mavericks, in 2014.
In OS X 10.10 Yosemite, released in October, web and local search were merged into ‘global’ Spotlight, the search window that opens using the Spotlight icon at the right end of the menu bar, accompanied by Spotlight Suggestions.
John M Hörnkvist and Gaurav Kapoor filed what was to become US Patent 10,885,039 B2 for Machine learning based search improvement, which appears to have been the foundation for Spotlight Suggestions, in turn becoming Siri Suggestions in macOS Sierra. Those were accompanied by remote data collection designed to preserve the relative anonymity of the user.
This shows a search in Global Spotlight in macOS 10.12 Sierra, in 2017.
Apple acquired Laserlike, Inc, whose technology (and further patents) has most probably been used to enhance Siri Suggestions. Laserlike had already filed for patents on query pattern matching in 2018.
I’m sure there’s a great deal more detail to add to this outline, and welcome any additional information, please.
4 August 2025: I’m very grateful to Joel for providing me with info and links for On Location, which I have incorporated above.
We’re now into August, Apple has released the last substantial updates to macOS before the arrival of Tahoe, so where does macOS stand now?
macOS Sequoia has just had its last scheduled update to 15.6 before it’s expected to enter the first of its two years of security-only updates. The main benefits of this update are an important fix to restoring Macs in DFU mode using either the Finder or Apple Configurator, and its long list of security updates, 81 vulnerabilities in total. If you’re already running Sequoia, it’s an important update.
Sequoia is fully supported on the following Macs:
macOS Sonoma is now entering its second and final year of security-only updates, and in the latest to 14.7.7 has around 50 vulnerabilities fixed. Although that’s a lot less than in 15.6, those are still important if you’re staying with Sonoma for the time being.
Sonoma is fully supported on the following Macs:
macOS Ventura has probably had the last of its security updates, although in the past Apple has sometimes released one more update in the autumn/fall. Its latest update to 13.7.7 has around 41 vulnerabilities fixed, making it essential if your Mac can’t be upgraded to Sonoma or later. If your Mac is supported by Sonoma, now is the time to plan upgrading it so that it can continue receiving security updates from September.
macOS Tahoe has now entered the public phase of its beta-testing, with the fourth version provided to developers. While much of the debate surrounds its Liquid Glass and new look, it does bring new features such as a Phone app to Macs. So far it appears internally stable and doesn’t look likely to be delayed for major bugs to be wrangled.
Tahoe is fully supported on the following Macs:
Although the first couple of versions of Tahoe presented themselves to older apps and scripts as macOS 16, since beta 3 it has been thoroughly macOS 26 regardless of how it’s asked. As this hasn’t been mentioned in Apple’s release notes, it’s unclear what it will do in the final release. If you have apps or scripts that could break when they discover the version of macOS running is 26, now is the time to send Apple feedback to make your case for it to report as version 16.
Open Core Legacy Patcher, OCLP, is being updated in the hope that it will be able to run macOS Tahoe on at least some unsupported models, although that probably won’t be available until the end of this year. You can follow progress here, where you’ll see some of the challenges its developers are facing. Another site worth watching is Mr. Macintosh on YouTube.
Next stop, probably in September, should be:
if Apple remains consistent with previous numbering. Farewell to Ventura, old friend!
This week’s dive into RunningBoard tackles one of the central questions: this subsystem repeatedly uses the term assertion, but what are these assertions, and how does RunningBoard handle them?
In computing, assertions may have their origin in hardware verification languages like Verilog, where they’re used to state required conditions in declarative form. They appear to have entered macOS through the background service assertiond
, which made a name for itself as a killer of processes and apps. Power assertions have been noted in the log and elsewhere for at least the last decade, and are mentioned in IOPMLib, part of IOKit. Since macOS Catalina, assertions have been at the centre of RunningBoard, which remains essentially undocumented.
To get a better idea of how assertions are used, I launched Apple’s Developer app on a Mac mini M4 Pro running macOS 15.5, and followed log entries for a period of over 14 seconds from the start of the launch process. Although RunningBoard’s job description records this app’s platform as 6, typical of a Catalyst app, in other log entries it’s claimed not to be a Catalyst app.
At an arbitrary start time of 01.126 seconds, LaunchServices decided to launch this app initially through CoreServicesUIAgent, which 0.04 seconds later requested RunningBoard to execute the launch request. This eventually led to a connection being initialised to FrontBoard Scene Manager, where the app was registered as a new scene, and activated.
FrontBoard set the process visibility to Foreground:01.593239 com.apple.FrontBoard [app<application.developer.apple.wwdc-Release.9312198.9312203~>:2946] Setting process visibility to: Foreground
RunningBoard then announced it was acquiring a new assertion, giving its descriptor and the PID of the target process01.593248 com.apple.runningboard Acquiring assertion: <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:(null) target:2946>
01.593288 com.apple.runningboard PERF: Received request from [osservice<com.apple.uikitsystemapp(501)>:748] (euid 501, auid 501) (persona (null)): acquireAssertionWithDescriptor:error:
01.593289 runningboardd acquireAssertionWithDescriptor
A fuller description followed, including the RunningBoard ID, and the attributes of the assertion01.593324 com.apple.runningboard Acquiring assertion targeting [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] from originator [osservice<com.apple.uikitsystemapp(501)>:748] with description <RBSAssertionDescriptor| "com.apple.frontboard.after-life.subordinate" ID:424-748-2228 target:2946 attributes:[
<RBSDomainAttribute| domain:"com.apple.frontboard" name:"AfterLife-Subordinate" sourceEnvironment:"(null)">
]>
This assertion was made active, and RunningBoard stated how many assertions were currently targeting that process01.593343 com.apple.runningboard Assertion 424-748-2228 (target:[app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946]) will be created as active
01.593389 com.apple.runningboard app<application.developer.apple.wwdc-Release.9312198.9312203(501)> is now targeted by 11 assertions
That triggered a state update for the process01.593400 runningboardd state update
In this case, RunningBoard couldn’t do anything, so left the process’s assertions as they were01.593461 com.apple.runningboard _checkForSuspendableAssertionCycle for app<application.developer.apple.wwdc-Release.9312198.9312203(501)> bailing out since it's not holding a suspendable assertion
01.593466 com.apple.runningboard Removing 0 assertions
This did, though, alter the inheritance of existing assertions01.593556 com.apple.runningboard Process: [app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946] has changes in inheritances: {(
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2215 0>,
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2215 0>,
<RBSInheritance| environment:(none) name:com.apple.launchservices.userfacing origID:424-391-2214 0>,
<RBSInheritance| environment:(none) name:com.apple.frontboard.visibility origID:424-420-2216 0>
)}
This completed the acquisition of this assertion, and the process’s new state was calculated01.593564 com.apple.runningboard Finished acquiring assertion 424-748-2228 (target:[app<application.developer.apple.wwdc-Release.9312198.9312203(501)>:2946])
01.593741 com.apple.runningboard Calculated state for app<application.developer.apple.wwdc-Release.9312198.9312203(501)>: running-active (role: UserInteractiveFocal) (endowments: <private>)
This was all accomplished in around 0.0005 seconds. FrontBoard then continued processing the app’s scene01.593743 com.apple.FrontBoard Ingesting properties from UIApplicationSceneSettings...
RunningBoard assertion numbers are of the form 424-748-2228, where the second group 748 is the PID of the source of the assertion, and the third group 2228 is a sequential number.
storekitagent
was running as PID 2947, accompanying the Developer app.uikitsystemapp
was drawing, presumably for the Developer app.All these assertions were completed in 14 seconds.
As shown in the series of assertions recorded in the log for the Developer app, RunningBoard provides a detailed account of milestones through the launch and early running of this app, covering much other than its security and TCC activity.
This starts with a job description containing a great deal of useful information about the app, when it’s neither visible nor focal. At that stage it’s given a minimal Jetsam priority, putting it in the front line to be forcibly quit if memory was short, and it’s denied access to the GPU. As launch proceeds, its Jetsam priority is raised to 100 and it’s allowed GPU access. Its role is then changed to UserInteractiveFocal, its window management is handled by FrontBoard and it becomes visible, and able to undergo AppNap. Two supporting services are engaged, storekitagent
to handle its data, and uikitsystemapp
to draw its interface.
Once the novelty of RunningBoard had worn off, I had come to consider its incessant chatter in the log as a distraction. However, a log extract obtained with the subsystem set to com.apple.runningboard
provides a detailed account of events during an app’s life cycle, without the nuisance of privacy censorship, or the app having to make its own log entries.
com.apple.runningboard
subsystem, and initially filter entries on Acquiring assertion
in the Messages field.File data integrity is one of those topics that never goes away. Maybe that’s because we’ve all suffered in the past, and can’t face a repeat of that awful feeling when an important document can’t be opened because it’s damaged, or crucial data have gone missing. Before considering what we could do prevent that from happening, we must be clear about how it could occur.
We have an important file, and immediately after it was last changed and saved, a SHA256 digest was made of it and saved to that file as an extended attribute, in the way that you can using Dintch, Fintch or cintch
. A few days or weeks later we open the file and discover its contents have changed.
What could account for that?
One obvious reason is that the file was intentionally changed and saved without updating its digest. Provided there are good backups, we should be able to step back through them to identify when that change occurred, and decide whether it’s plausible that it was performed intentionally. Although the file’s Modified datestamp should coincide with the change seen in its backups, there’s no way of confirming that change was intentional, or even which app was used to write the changed file (with some exceptions, such as PDF).
Exactly the same observations would also be consistent with the file being unintentionally changed, perhaps as a result of a bug in another app or process that resulted in it writing to the wrong file or storage location. The changed digest can only detect the change in file content, and can’t indicate what was responsible. This is a problem common to file systems that automatically update their own records of file digests, as they are unable to tell whether the change is intentional, simply that there has been a change. This also applies to changes resulting from malicious activity.
The one circumstance in which change in contents, hence in digest, wouldn’t necessarily follow a change in the file’s Modified datestamp is when an error occurs in the storage medium. However, this is also the least likely to be encountered in modern storage media without that error being reported.
Errors occurring during transfer to and from storage are detected by CRC or similar checks made as part of the transfer protocol. This is one of the reasons why a transfer bandwidth of 40 Gb/s cannot realise a data transfer rate of 5 GB/s, because part of that bandwidth is used by the error-checking overhead. Once written to a hard disk or SSD, error-correcting codes are used to verify integrity of the data, and are used to detect bad storage blocks.
Out of interest, I’ve been conducting a long-term experiment with 97 image files totalling 60.8 MB stored in my iCloud Drive since 11 April 2020, over five years ago. At least once a year I download them all and check them using Dintch, and so far I haven’t had a single error.
There are dangers inherent in putting trust in file datestamps as markers of change.
In APFS, each file has four different datestamps stored in its attributes:
create_time
, time of creation of that file,mod_time
, time that file was last modified,change_time
, time that the file’s attributes including extended attributes were last modified,access_time
, time that file was last read.For example, a file with the following datestamps
create_time
2025-04-18 19:58:48.707+0100mod_time
2025-04-18 20:00:56.134+0100change_time
2025-07-19 06:59:10.542+0100access_time
2025-07-19 06:52:17.504+0100was created on 18 April this year, last modified a couple of minutes later, last had its attributes changed on 19 July, but was last read 7 minutes before that modification to its attributes.
These can be read using Precize, or in Terminal, but there’s a catch with access_time
. APFS has an optional feature, set by volume, determining whether access_time
is changed strictly. If that option is set, then every time a file is accessed, whether it’s modified or not, its access_time
is updated. However, this defaults to only updating access_time
if its current value is earlier than mod_time
. I’m not aware of any current method to determine whether the strict access_time
is enabled for any APFS volume, and it isn’t shown in Disk Utility.
mod_time
can be changed when there has been no change in the file’s data, for example using the Terminal command touch
. Any of the times can be altered directly, although that should be very unusual even in malware.
Although attaching a digest to a file as an extended attribute will update its change_time
, there are many other reasons for that being changed, including macOS adding or changing quarantine xattrs, the file’s ‘last used date’, and others.
Unlike automatic integrity-checking built into a file system, this will detect all unexpected changes, regardless of whether they are made through the file system, are intentional or unintentional, are malicious, or result from errors in storage media or transmission. Because only intentionally changed files are retagged, this also minimises the size of backups.
Here are this weekend’s Mac riddles to entertain you through family time, shopping and recreation.
1: Total banker’s order quickly verifies integrity.
2: 1 broke by 2005, 2 is still cryptographic, 3 is even better, but not in Iran.
3: Missing from …MNOPQTUVW… but present in CD.
To help you cross-check your solutions, or confuse you further, there’s a common factor between them.
I’ll post my solutions first thing on Monday morning.
Please don’t post your solutions as comments here: it spoils it for others.
Plenty of great apps have been created using the Mac’s scripting languages, but commercial developers have largely relied on compiled languages used and supported by Apple for app and system development. Over the years those have included Object Pascal, C/C++, Objective-C and most recently Swift. This article provides a brief overview of how those changed.
Following Apple’s use of UCSD Pascal on Apple II computers, when the Lisa was being developed its primary language was Lisa Pascal. Apple was also working on the novel object-oriented language Smalltalk which originated in Xerox’s PARC in 1969, but its syntax was unfamiliar and performance was poor. Lisa Pascal was therefore developed into Clascal, dividing code into distinct interface and implementation sections, with classes, subclasses, methods and inheritance.
During the first couple of years, software for the Mac was thus developed using Clascal on Lisa systems.
In 1984-85, Larry Tesler and supporting engineers in Apple (including Barry Haynes, Ken Doyle and Larry Rosenstein) worked with Niklaus Wirth, the inventor of Pascal, to develop Clascal into Object Pascal, the primary language for Mac development. With this, they also developed the first version of the MacApp class library that provided a framework to support common application features including the Mac’s GUI.
These were released together in September 1986, in Macintosh Programmer’s Workshop (MPW), which was adopted as the standard development environment for the Mac, both in-house and for third-parties. At that time, the only compiled language supported by MPW was Object Pascal, and it wasn’t until the following summer that the first beta of its C/C++ compiler was released with MPW 2.0. That was developed by Greenhills, but Object Pascal remained the more widely used, particularly in combination with MacApp, also written in Object Pascal. Major developers including Adobe created early versions of their products using Object Pascal and MacApp, perhaps the most famous example being Adobe Photoshop.
At the same time, Think Technologies released the first popular third-party compiler, LightSpeed C, in 1986. This soon became THINK C, gained C++ support, was joined by THINK Pascal, and was bought by Symantec. Borland ported its Turbo Pascal to the Mac, where it adopted the extensions of Object Pascal, and eventually became the cross-platform Delphi in 1995.
With the release of System 7 in 1991, Apple abruptly switched from Object Pascal to C++, and MacApp 3.0 also changed language. Smaller developers who had extensive source in Object Pascal were far from happy, and in some cases successful products vanished from the market. Others were rescued when Metrowerks released a new integrated development environment for C/C++ as CodeWarrior at the end of 1993 or early 1994. This drew most who had been using THINK C, and MPW also went into decline. The decisive factor was CodeWarrior’s early support for Apple’s new PowerPC Macs. CodeWarrior’s C/C++ saw many Mac developers through that hardware transition until the release of Mac OS X in 2000-01.
With Mac OS X came its own primary development language Objective-C, and Apple’s new integrated development environment Project Builder, also derived from NeXTSTEP but written from scratch for the Mac. That was replaced by the first version of Xcode with Mac OS X 10.3 Panther in 2003.
This screenshot shows Xcode in 2015.
Objective-C had been one of the two object-oriented contenders to succeed C. The other, C++, had already become more widely adopted, and had been favoured by Apple for the previous decade. Although both claim C as their ancestor, there’s little in common between them, and in many respects Objective-C more closely resembles Smalltalk, rejected by Apple when developing the Lisa. Developers whose source code had started in Object Pascal and was then ported to C++, had another major task to convert that to Objective-C.
Originally designed and developed by Brad Cox and Tom Love during the early 1980s, Objective-C’s biggest success had been its selection as the primary development language for NeXTSTEP later that decade. When Apple adopted that as the foundation for Mac OS X, it was inevitable that the language should come with it.
In keeping with its track record, no sooner had Apple entered the 2010s than its engineers, under the lead of Chris Lattner, were working on the successor to Objective-C. Significant early collaborators included Doug Gregor, John McCall, Ted Kremenek and Joe Groff. A first beta-release was provided at WWDC in 2014, and since then Swift has been progressively replacing Objective-C as Apple’s primary development language.
Swift is described as being a multi-paradigm language, and over the course of the last 15 years it has assimilated and adopted almost every available programming paradigm, from classes and objects to protocols and declaratives. Although it’s still possible to write plain code that is understandable by someone with a grounding in C or Pascal, those who prefer to adopt almost any other paradigm can render their code nearly unintelligible to others. Differences between the current version 6.1.2 and version 1.0 from 2014 are huge.
From those early days, Swift has had an interactive mode, based on the ‘read-eval-print loop’ (REPL) popularised by Lisp. This versatility has been developed in Swift Playgrounds, both within Xcode and as a standalone app targeted at those of all ages learning to code for the first time.
As an introduction to Swift in education, this has been impressive, but it hasn’t proved a gateway for those who didn’t really want to learn how to use Xcode in the first place.
With the release of Swift 5.0 in February-March 2019, the language reached a major milestone of stability in its application binary interface (ABI). Prior to that, executable code built from Swift source had to be delivered with its own copy of Swift’s runtime libraries, amounting to over 11 MB for regular apps. Starting from the release of macOS 10.14.4, and Xcode 10.2, apps written in Swift 5.0 didn’t need those frameworks (except for compatibility when running on older macOS), as their ‘glue’ to macOS has since been delivered in the system. Later that year, module stability was added, to allow sharing of binary frameworks compatible with future versions of Swift.
This screenshot shows the Interface Builder feature in Xcode in 2024.
Although those have been primary development languages, Apple and third-parties have supported many others. Here’s a small personal sample.
In 1984, what was to become Macintosh Common Lisp (MCL) began development. It was released in 1987, initially as Coral Common Lisp (CCL), then Macintosh Allegro Common Lisp, and MCL. It moved on to Digitool in 1994 for PowerPC support, and was made open source in 2007. Unusually for what’s normally considered a specialist language, MCL was well integrated with Mac OS and its GUI.
After MCL drifted off into oblivion, LispWorks’ cross-platform implementation of ANSI Common Lisp took over, and remains thoroughly mature and productive, with extensive browsing facilities, debugging, and more.
An extraordinarily concise and powerful language, APL is also one of the oldest, having been defined in 1962 and first implemented a couple of years later. It uses Greek and special symbols in its own custom font, concatenating them into cryptic lines that make perl look verbose. Its last Mac implementation, MicroAPL’s APLX 5.1, was still able to run in El Capitan, but has sadly been abandoned. However, Dyalog APL remains actively developed, and even supports Apple silicon Macs. Other notable losses include Absoft, whose Fortran compilers were widely used on Macs from 1985, and shut down in 2022.
Microsoft’s Visual Studio Code, supporting more than thirty programming languages including JavaScript, C#, C++, and Java, was a latecomer to the Mac, and has most recently become VS Code.
David Cásseres (1983) Clascal Reference Manual for the LISA, First Draft
Clascal, Wikipedia
Larry Tesler (1985) Object Pascal, Report
Object Pacal, Wikipedia
MPW, Wikipedia
CodeWarrior, Wikipedia
Swift, Wikipedia
For the last nine years, Apple silicon chips in iPhones and iPads, and most recently Macs since 2020, have had Efficiency cores, designed to eke out their use of power to extend battery time and stay cool. Although you have no control over what runs on the Efficiency cores in a device, there are options for Macs. This article explains how you can reduce energy use in an Apple silicon Mac, and why that’s a good idea.
M series chips can have between 2 and 8 E cores, each with slightly less than half the processing power of their Performance core equivalent. If you’re unsure how many CPU cores of each type your Mac has, and how they’re used, open the CPU History window in Activity Monitor and watch.
Particularly in the first few minutes after starting a Mac up, the E cores will be busy catching up with their housework, routine tasks such as updating Spotlight’s indexes, checking for various updates, and making an initial backup. Once those are out of the way, you’ll see other bursts of activity, such as XProtect Remediator scans, and a steady trickle of background tasks. Because most user processes are run on the P cores, even hectic E core activity has no effect on what you’re doing.
When threads run on the E cores, they run more slowly, take longer to complete, and for all that take substantially less energy and power. That’s because those cores are designed to be more energy-efficient and are run at lower frequencies, or clock speeds. For almost any given task, running its threads on E cores will thus use less total energy, and
Although the code run by apps can’t be directly allocated to P or E cores, macOS can get a strong hint by a setting known as the Quality of Service (QoS). By default, the whole of a user app will normally be run at high QoS, and macOS will try to do that on P cores, so long as they’re available.
Some apps are starting to give the user control over this in a ‘speed control’. Among those is the compression utility Keka.
In Keka’s settings, you can give its tasks a maximum number of threads, and even run them at custom Quality of Service (QoS) if you want them to be run in the background on E cores, and not interrupt your work on P cores. Although you’re unlikely to do this when compressing or decompressing a few small files, when its tasks are likely to take several minutes, and you can afford to wait a little longer, run them on the E cores.
Two of my apps, Dintch and Cormorant, have even simpler controls.
Dintch has a three-position slider, offering
The first two of those took 6.2 seconds to check a 16.8 GB file, and the third took almost 25 seconds. The difference between the first two is in their priority, if there are several threads competing for the same CPU cores. If you’re waiting for files to be checked in Dintch, set the speed control at the racing car, but if you can leave the Mac to get on with checking in the background and want the efficiency of E cores, set the control to the tortoise instead.
Cormorant, a much simpler compression utility aimed at AirDrop transfers, has a fourth slider position with a pointing hand that allows you to set a custom number of threads and QoS level, as I also use that to test and compare P and E cores.
You can observe the effects of these controls in Activity Monitor’s CPU History window.
Here’s the window after Dintch has checked that 16.8 GB file with the setting for the racing car. All the P cores show four bursts of activity as they run the code to compute the SHA256 digest.
When set to the tortoise, there’s almost no activity on the P cores, but the four E cores are busy computing for nearly 25 seconds.
One word of caution about over-interpreting what you see in the CPU History window. Both P and E cores can run at a wide range of frequencies, but Activity Monitor takes no account of that. Taken at face value, you might think these E cores were working far harder than the P cores, but in fact they were only running at low frequency, little more than idle. In contrast, those small bursts of P core activity were at higher frequency, so were using far greater energy and power, albeit more briefly.
I’m sure that other apps are offering the user control over whether their longer tasks are run on the E cores, and will be pleased to learn of them. There are also two ways that you can control them yourself, using St. Clair Software’s excellent utility App Tamer, or the command tool taskpolicy
.
App Tamer works best with apps, and makes it simple to demote their threads so they’re run on E cores in the background. If you want to demote the threads of a running process from Terminal, use a command liketaskpolicy -b -p 567
to confine all threads of the process with PID 567 to the E cluster. You can then reverse that using the -B option for threads with higher QoS, but can’t alter those set to a low QoS by the process. The ground rule here is that high QoS threads can be demoted to the E cores, but low QoS threads can’t be promoted to run on the P cores.
Running a virtual machine on an Apple silicon Mac always uses P cores first, even though they will also be used to run background threads inside the VM. So the worst thing you can do in terms of energy efficiency and core use is to run code inside a VM.
taskpolicy
command tool.