Run a Jamf shop? Would you like to collect stats on who’s turned on Apple Intelligence so far? That is, if your company hasn’t already had you put the kibosh on it! Personally I think Apple Intelligence and it’s Private Cloud Compute are a secure and private way to use things like the Writing Tools to proofread, make list or tables, etc. without wondering if your corporate data is being used in further LLM training. If your company is so enlightened and you’d like to see which Macs have Apple Intelligence enabled, read on! Or perhaps, you’d just like to see how it’s done. It’s not as straightforward as you might think, Apple engineers are really into obfuscation these days!
Finding the Suspects
The first part of the fun is hunting down which file might indicate the status of Apple Intelligence. I closed all other apps except System Settings, toggled Apple Intelligence on and off and tried a few things: Looking at /Library/Preferences
in Finder sorted by date (in this case make sure to show hidden files), running FSMonitor to see things visualized, running fs_usage -w -f filesys | grep plist
while screen recording in Quicktime to see the exact moment I enabled/disable Apple Intelligence. After some toggling it is determined that ~/Library/Preferences/.GlobalPreferences.plist
is our target. A few days later I re-discovered Bob Gendler’s excellent post about using the command log stream --debug --predicate 'process == "cfprefsd" && eventMessage CONTAINS "wrote the key"'
to help narrow things down and this also confirmed this is the file (as well as many others) being written to when it’s enabled.
Obfuscation Investigations
Let’s look at ~/Library/Preferences/.GlobalPreferences.plist
and see if we can find the exact key name. This file is a bit special in that you can do the same thing 5 6 different ways with defaults! Run one of these commands as the console user not root:
defaults read ~/Library/Preferences/.GlobalPreferences.plist
defaults read ~/Library/Preferences/.GlobalPreferences
defaults read NSGlobalDomain
defaults read -globalDomain
defaults read -g
defaults read "Apple Global Domain"
- Bonus update: 👆Shows up in
defaults read
and nowhere else
- Bonus update: 👆Shows up in
Regardless of how we do it though, the output for the com.apple.gms.availability
keys is abridged and useless to us in this form.
What’s going on? What is this halting hexadecimal hodgepodge? Let’s use defaults export -g
– to print the contents to in XML1 format (BTW you won’t find export
documented in the man page, after a decade it still only exists in defaults -h
help).
Ah, OK, these keys are <data>
types which contain base64
encoded strings. The contents are possibly binary data. We’ve already established that defaults
is not going to be useful to us. In my previous post Respecting Focus and Meeting Status in Your Mac scripts (aka Don’t Be a Jerk) we are able to extract the data using plutil -extract
however because these key names contains periods (aka “full stop” U+2E) this clashes with plutil’s shoddy “keypath” parsing, which uses periods to delimit the path but doesn’t respect escaping periods with a backslashes (which is not hard to do as my JSON tool ljt can handles this). So all we are left with is /usr/libexec/PlistBuddy
let’s give that a try: /usr/libexec/PlistBuddy ~/Library/Preferences/.GlobalPreferences.plist -c "print :com.apple.gms.availability.key
(Spoiler alert the key is: com.apple.gms.availability.key
)
OK! There we go, it’s a binary plist inside the key of a plist! “Brilliant” Apple, really. 🙄 Alright then, let’s pipe this through plutil -convert xml1 - -o -
and get some ASCII XML yeah?
Pardon moi, but what the shit is this!? 💩 file
said it was an “Apple binary property list” – according to those first bytes. Let’s look at it run through xxd
to see if we can find more clues.
Aha! There is an extraneous newline (0x0a
) that PlistBuddy
is outputting (annoying but at least consistent!). Why can’t that just be ignored? Because apparently the last byte of a binary plist is the offset table, mess that up and it all falls apart. So what we need to do is trim this dangling newline. For this I consulted ChatGPT and perl -pe 'chomp if eof'
is the magic we need. BTW ChatGPT does well for me to ask very targeted and direct questions like this, I don’t ask it to write entire scripts but sometimes it will have insights into different methods I’d never considered.
OMG. SRSLY? Apple is writing data encoded binary plist data containing a single integer value in an array?! ATTN: Craig Federighi: Please tell your engineers to stop junking up an otherwise elegant system with these obfuscation games. Alright, let’s bring it home and get the value with this: /usr/libexec/PlistBuddy ~/Library/Preferences/.GlobalPreferences.plist -c "print :com.apple.gms.availability.key" | perl -pe 'chomp if eof' | plutil -convert xml1 - -o - | plutil -extract 0 raw - -o -
There we go: 0 (zero), which means Apple Intelligence is on. When it’s 2, it’s off. Yet another key like PrivateMACAddressModeSystemSetting which has the opposite meaning of what you might expect. BTW I’ve yet to see the value as 1, except for this June Tweet where someone writes a 1 to turn on Writing Tools on a beta. BTW this key only indicates the state, in my testing it does not affect the state, meaning if you change the value (and even do a killall cfprefsd
) all it will do is blank out the Apple Intelligence toggle for a moment and then it’ll sort itself out and display the true state.
And yes there is another way to get the state of Apple Intelligence however it makes the assumption that you only have one account in MobileMeAccounts.plist
to determine your AccountDSID
and then query yet another file but if you have more than one Apple Account, you know like for all your purchases in: iTunes/Music/App Store there may be multiple accounts (** cough** merge accounts Apple! **cough**) so it may return an erroneous results if you have more than one account.
The ChatGPT integration is actually a cinch to determine. I used the same method above to find the plist and then, because the engineers on this didn’t play games with encoded binary plist data within a plist, all you need to do is simply ask: defaults read com.apple.siri.generativeassistantsettings isEnabled
and amazingly 0
means off and 1
means on, imagine that!
Usable Extension Attributes
You’ve made it this far, here’s the goods: OS-Apple Intelligence Availability.sh and OS-Apple Intelligence ChatGPT Status.sh they are fully commented and when you run them here’s what they return. I’m trying out a new way to output both values and their interpretations, because let’s be honest, we are “reading tea leaves” here. 🍵 None of this is officially documented by Apple and always subject to change. If a new value pops up, it will still be reported in the output. You won’t have to scramble to fix the extension attribute right away, just adjust the criteria in your Smart Group to match the value in the parentheses if there’s a policy that depends on it.
Closing Thoughts
What an absolute pain it was to get a single numerical value from a single key! To that end after I had written these extension attributes I went to work over the Thanksgiving break and wrote a tool to make this effortless. I’ll be releasing this tool, which will work as both a standalone tool and a shell script function in the coming days!