Detect Menu Item Changes

I often use [if Menu Item > Exists, etc.] when building macros for applications that have various states/windows.

The issue is that it's time-consuming to detect changes in the menu items, and even if you find one, it might not be the best one.

Has anyone made a utility that can compare all the menu item names and states from one moment to another?

To illustrate, you run the script, then you do some stuff, then you press a button to end the script, and the output shows you everything that changed in the menu items?

Ideally it would show you which Menu Items were added/removed, changed names, or their state changed (checked/enabled/etc).

Cheers!

That's actually a very interesting idea. I like it. However I'm not adept with AppleScript so I'm not keen to write such a macro. But I hope someone does write this because I would use it.

I did once write a macro that checked for changes to the macOS defaults before and after some event, which is a similar kind of macro to the one you are requesting.

1 Like

I spent a half hour trying to build such a macro for you. And I realize there's a little problem. Many apps, including Apple's own apps, don't seem to populate the submenu items until the user actually clicks on the main menu names on the top of the screen. This is a design flaw (I believe) in macOS. If you don't mind, the macro that collects "before" and "after" may need to "click" on each of the main menu items for this to work. That will slow it down, (by adding several seconds before and after your app does its thing) but it should work, ---> I hope. <---

I will probably try again, trying to fix this problem, but I'm near the limits of my ability with AppleScript. EDIT: After 2 more hours, I think I have a working solution. Let me spruce up my solution and post it here in a short while.

1 Like

Okay, here's a macro that will give you the differences between the menus of an app before and after you make some change to that app's menu system. It was fun to write. There may be better ways to do this, so if anyone wants to try, please do so. This macro takes about 5 seconds to read all the menus, which is fast enough, but definitely not as fast as I wanted.

It places two files in your /tmp folder as a way to store the results to allow a comparison. The files in that folder get deleted by macOS automatically so I didn't bother to delete them in this macro.

I tested it a couple of times, but there's no guarantee it is bug-free.

You have to specify the name of the app near the top of the macro. I would like to get rid of this, but it seems like a pretty fair limitation.

Menus Comparison, Before and After Macro (v11.0.4)

Menus Comparison- Before and After.kmmacros (20 KB)

In case it's not obvious, you press Page Up to record the menu in the app's "Before" state, and then you press Page Down to record the menu in the app's "After" state. When you press Page Down it will also generate the results. Feel free to change how this works. You will have to change both the triggers and the Switch statement if you want to do that.

P.S. It uses a "dirty trick" to get the top level names of the menus for the app. That is, it uses OCR to read the top level names. If there's a better way to do that, someone should inform me. But it works in all the cases that I tested, so I was satisfied with it.

It's actually an intentional design decision, as I understand it—so that they don't use RAM and time to populate a menu that may never be shown.

I don't agree with the decision, as it makes our life as developers tougher (we have an app that puts menus under the mouse, and this is a big issue), but it was a decision they made (menus used to not work this way).

-rob.

1 Like

Okay. Still, they should let the user decide whether to "waste" resources. After all, they let the user turn off the energy saving options.

This'll return a linefeed-delimited list of the frontmost app's menu names, minus the Apple menu:

tell application "System Events"
	set theApp to item 1 of (every process whose frontmost is true)
	set theNames to (name of every menu bar item of menu bar 1 of theApp)
	set AppleScript's text item delimiters to linefeed
	return items 2 thru -1 of theNames as text
end tell

I did, briefly, look at using System Events to do the whole thing. But my Safari, for example, has 250 menu items (not counting listed windows) before even looking at sub-menus. Processing that lot, even if just to get {name,enabled,marked} will take "a while".

Sometimes "eyeballing" is both quicker and easier...

There's also the problem that many menu items are "of the moment" -- the Window menu's "Move to..." item will depend on which display the frontmost window is on, Edit->Copy may or may not be enabled depending on whether something is selected, etc, etc.

There presumably comes a point where generating menus when needed is far simpler (and cheaper) than constantly, unnecessarily, updating them on every state change.

1 Like

That's great. I'll use that in the future.

I have actually been fiddling with this exact thing in the past, and this topic made me finally finalize something I hope at the very least will meet my own needs for a 'menu state change comparison tool'.

I wish I was a better coder, but as I am not, both Swift scripts of this macro have been developed using an LLM (GPT-5, to be exact). While creating a snapshot of all the states, the first of the Swifts opens the different menus in quick succession. But for a tool like this, this is very acceptable for me, and it kind of works like a progress bar.

As some apps (KM included) have som menu options that it exceeds the environmental variable Size limit, I chose to write the snapshots to files in the /tmp folder, similarly to how @Airy's more native approach does.

The Macro first creates a snapshot of menus, before prompting you to run it again. You can run it again as many times as you want, optionally display the result of the last run, and the comparison at the end will check for and list changes between the last two runs.

Return All Menu State Changes of Front Application.kmmacros (53 KB)
(KM v11.0.4)

Macro Image

2 Likes

Thanks for giving this a shot and sharing it. I did get some errors while running it, but I ended up trying Alexander's solution (which worked) before digging into why.

I did notice that the variable AppName was Terminal and the KM Log had these for each menu (presumably ones that didn't exist in Terminal):

2025-08-14 16:43:44 Action 17021405 failed: Execute an AppleScript failed with script error: text-script:286:290: execution error: System Events got an error: Can’t get menu bar item "Notes" of menu bar 1 of process "Terminal". (-1728)

So I'm sure your script either works or it's close. I just didn't get it to the finish line. Thanks anyway :slight_smile:

Hey this works! Thank you so much!!! :beers:

Your GPT-5 must be smarter than mine :laughing: because I couldn't coerce it into making this. I kid of course; I'm sure you told it something that helped it architect things better? Maybe the thing you realized while reading this thread?

1 Like

My interaction with GPT-5 has not been anywhere close to those a-single-prompt-to-finished-results coding demonstration videos I've been seeing on GPT-5 — I'll tell you that much.

Loads of iterations, slowly chipping away towards a working result, is how I make do. Using a separate chat to review the code provided by the first has also proven useful. This model seems quite a bit better at not losing focus over many iterations though, something that might help me keep my sanity. Still far from delivering one prompt to working results for most of my use cases though.

Glad to hear that this solution seems to work for you too!

1 Like