Choosing a driving route in CarPlay

If you pay any attention at all to the Apple-centric web, you saw an explosion of links yesterday to this article by Nikita Prokopov, which rightly eviscerates the proliferation of menu icons in macOS 26. I may write up my thoughts on menu icons in a future post (short version: they don’t belong), but today I have something else on my mind. Like Prokopov’s post, it addresses the question, “Why the fuck has Apple forgotten the UI principles it knew forty years ago?”

If you’re using CarPlay and ask for directions, you’ll see a screen that looks like this:

CarPlay with alternate routes in Maps

That the default route’s Go button is gray while the alternates are green is a stupidity addressed by Sage Olson and Joe Rosensteel1, so I won’t bother.

What I will address is that whichever route you choose, you have to tap its Go button. Even though the full description of each route looks like a button, the only part that’s tappable is the part that looks like a button inside another button.

Is this just as stupid as having a dull color as the default and a bright color as the alternate? Yes. And Apple has known that descriptions should be click/tap targets since the very beginning of the Mac. Here, courtesy of Infinite Mac, is MacWrite 1.0 running on a simulation of an original Macintosh.

MacWrite Find window in Infinite Mac

I’ve brought up the Find window. It’s currently set to do a Whole Word search, but I can switch to a Partial Word search by clicking on the Partial Word radio button or anywhere on that button’s label. Even with a label that doesn’t look like a button, Apple knew it would be helpful to select the radio button if I clicked on its label. After all, what else could I possibly mean if I clicked on the word Partial?

Apple understood this in 1984. But now, in 2026, if I’m driving and ask Siri for directions to Starved Rock State Park, CarPlay doesn’t understand what I mean if I tap in the middle of either of those large gray buttons-that-aren’t-buttons.

Why, you may ask, would I even consider tapping outside the Go button? Because Apple has trained me for forty years to expect that I can tap on its label.


  1. Even Joe couldn’t find the Mastodon post where he complains about it, but we both remember that he did. 


Proofreading with the Claude API

As an alternative to the Writing Tools proofreading macro I showed in yesterday’s post, I built another one, called Proofread With Claude, which gets the edited text through a call to Anthropic’s Claude API. I make the call in Python using Simon Willison’s llm module and the llm-anthropic extension.

Although I knew about the llm module a while ago, I hadn’t considered using it for proofreading until Giovanni Lanzani explained how he does it. His macro uses the llm command-line tool, and he has the LLM highlight the changes by making them bold, but it’s the inspiration for my macro below. I didn’t realize how easy Simon Willison had made using the various LLM APIs until I saw how Giovanni used it.

Here’s the macro:

KM Proofread With Claude

It copies the text of the frontmost BBEdit document and passes it as standard input to this Python script:

python:
 1:  #!/usr/bin/env python
 2:  
 3:  import llm
 4:  import sys
 5:  import subprocess
 6:  
 7:  # Standard input is the Markdown source of the post to be proofread.
 8:  # cmd = 'tell application "BBEdit" to get text of front text document'
 9:  post = sys.stdin.read()
10:  
11:  # The prompt for proofreading the document.
12:  prompt = f'''Find typographical errors and grammatical mistakes in the
13:  following Markdown text. Ignore all embedded URLs, quoted text, and
14:  programming code. Only report actual errors, not style suggestions.
15:  Return the edited text in plain Markdown format without any
16:  introductory text. After that, add a blank line, a line with 10
17:  asterisks, another blank line, and then the reasons for the changes
18:  you made. The Markdown text you're analyzing starts after a line with
19:  20 asterisks.
20:  
21:  ********************
22:  {post}
23:  '''
24:  
25:  # Do the proofreading and get the response.
26:  model = llm.get_model('claude-sonnet-4.5')
27:  response = model.prompt(prompt)
28:  
29:  # Split the response into the edited post and the explanation.
30:  # Put them on the clipboard.
31:  edit, explanation = response.text().split('\n**********\n')
32:  subprocess.run('pbcopy', text=True, input=explanation)
33:  subprocess.run('pbcopy', text=True, input=edit)

The script creates a prompt consisting of the instructions given in Lines 12–21 and the text from BBEdit. It then passes that off to the Claude Sonnet 4.5 model (Lines 26–27).

The response comes back as the edited text with all the changes Claude thinks I should make, a line of ten asterisks, and more text explaining the reasons for the changes. Lines 31–33 split the response at the line of asterisks and copy each part to the clipboard—first the explanation, then the edited text.

Let me step in here and point out that Keyboard Maestro keeps a clipboard history, whether you use it interactively or not. After the script above runs, there are three new items in the history:

The edited text is the most recent and is the one used by BBEdit when the File>New>(with Clipboard) menu item is selected.

The rest of the macro follows much of the same logic as yesterday’s: it creates a new BBEdit text document with the edited text and compares it with the original text in a two-pane window. In addition, this macro displays the explanation in a floating window, which I refer to as I work my way through the proposed changes.

Keyboard Maestro floating window with explanation of changes

You’ll notice that I use the same keyboard shortcut, ⇧⌃⌥⌘P, for both the Writing Tools and Claude proofreading macros. When I press those keys, a conflict palette appears, and I choose the proofreader I want.

Keyboard Maestro Conflict Palette

This is easier than remembering a different shortcut for each macro.

Claude’s API access isn’t free, nor is OpenAI’s, which I could switch to through a simple change of the model in Line 26 of the Python script.1 But they’re pay-as-you-go systems, charging for the input and output tokens you use, and neither costs more than a few cents per proofreading session. I don’t see this breaking the bank. I should mention, though, that API access is on top of any monthly subscription you might have. I don’t have a monthly subscription and don’t use LLMs for anything else. For me, pay-as-you-go will be cheaper than a monthly subscription.

There’s no particular reason I chose to make this macro with Claude’s API rather than OpenAI’s. I’ll probably make another one that uses OpenAI soon, just to see how the three variants compare. I don’t think I’ll add Gemini to the mix; if the rumors are correct, I’ll be getting that for free through Writing Tools soon enough.


  1. I could switch to Gemini, too, which has a free tier, but I don’t know how good that free tier is. 


Proofreading with Writing Tools

Yes, it’s been less than a week since I wrote about LLM proofreading and showed you the “final” version of the Keyboard Maestro macro I’d been using. And that wasn’t a lie because it is the final version of that macro. It’s just that I’m now using two new macros with a different approach. Today’s post will be about the first of these new macros, which combines the Proofreading command in Apple’s Writing Tools with BBEdit’s document comparison system.

The new macros came about because of some conversations I had after my previous proofreading posts. Marc Zeedar (via email), Giovanni Lanzani (via Mastodon), and Jason Snell (via Slack, but he also talked about it on Upgrade) all told me how they were using LLMs for proofreading, and all of their ideas were good in different ways. I’ve stolen different parts of their systems to come up with my new macros. Today’s macro is based mainly on Marc Zeedar’s work.

Marc is the publisher of xDev Magazine, which is focused on cross-platform development with the Xojo app system. As you might expect, his main proofreading system, which uses the OpenAI API, is built in Xojo, but he also has a couple of simple Keyboard Maestro macros that use Writing Tools. Marc’s main contribution to my new method of proofreading was to convince me that I shouldn’t fear having the LLM create a new version of the document I’m working on, one with all the changes it wants.

I needed convincing because I had the wrong model in my head for applying changes. I thought that if I had two versions of a document, my original and the one with the LLM’s changes, I’d have to either accept or reject each change in turn. While that’s fine for many changes, I had learned that LLMs often point out a mistake but don’t give me the fix I want. It’s a situation in which neither accept nor reject is the right answer. But if you use the comparison tools in BBEdit, you get a third option: you can edit text directly in the two-pane comparison window.

Here’s an example. (I know it’s small, but you probably don’t need to see the details to follow along. And you can zoom in if necessary.)

Two-pane comparison window in BBEdit

The document on the right is the original Markdown source for a post I wrote in February of last year. The document on the left has what the Writing Tools Proofread command thinks I should have written. The complaint is that I wrote “Jan 16 and Jan 2,” while Writing Tools thinks I should have written “Jan. 16 and Jan. 2,” with periods to make it clear that I was abbreviating “January.” Let’s say I agree that the text should be changed, but I don’t want what Writing Tools suggested; I want to use the full month name. I can just click in the right pane and add “uary” after each “Jan.” The regular text window with that file will be updated accordingly because the right pane isn’t just a view, it’s a live document. This makes the proofreading go very smoothly.

If you want to do this sort of thing by hand in BBEdit, choose Proofread from the Writing Tools submenu of the Edit menu.

Writing Tools submenu in BBEdit

It’s quite a ways down. A new window will pop up next to the frontmost document, and Writing Tools will spend some time working out the edits that should be made. When it’s done, the buttons at the bottom of the popup window will become active, and you can click Copy to put the edited text on the clipboard.

Writing Tools window with BBEdit

Now you create a new document in BBEdit, paste the clipboard contents into it, and choose Compare Two Front Windows from the Find Differences submenu in the Search menu.

Find Differences submenu in BBEdit

That will bring up the two-pane comparison window we saw earlier, and you can step through the differences, applying the suggested changes, rejecting the suggested changes, or making your own changes as you see fit.

I, of course, refuse to do all that messing around with copying, pasting, and selecting menu items when I can write a Keyboard Maestro macro to do it for me. Here’s Proofread With Writing Tools (you may need to right-click the link to get it to download).

KM Proofread With Writing Tools

The only tricky thing about this macro is the Pause Until Conditions Are Met action. There’s no way to predict how long it will take for Writing Tools to generate the edited text. I initially thought I could pause until the Copy button became active, but that didn’t work. Then I realized that I could use my mouse click on the Copy button to get the macro going again.

You may be thinking, “Doesn’t Writing Tools suck? It is, after all, part of Apple Intelligence.” In my limited experience, it’s worked surprisingly well. I’ve had only two problems crop up:

  1. If the document is long and complex, Writing Tools may simply fail. It thinks for a long time and then puts up an error message saying it can’t do it. I don’t know what the underlying problem is, but it won’t finish unless you split the document into smaller chunks.
  2. It doesn’t understand Markdown footnote markers. Whenever I have something in the body of the document that looks like [^note], it either replaces it with some other text (without the brackets and caret) or just deletes it. Obviously, I reject these changes, but it’s weird that it makes them. It’s never deleted the footnote text or the marker in front of it, just the marker in the body of the text.

My other new proofreading macro, which I hope to show you in the next few days, uses the Anthropic API instead of Writing Tools, but it still uses BBEdit’s comparison system. Thanks to Marc Zeedar for showing me its advantages.

Update 2 Jan 2026 7:59 AM
I added the last two actions to the macro this morning. The first of these (typing ⌘`) brings the text window with the edited text to the foreground, and the second closes it. Now when the macro finishes, the two-pane comparison window is in the foreground as before, but I no longer have to close the temporary text window.


Overlapping rectangle puzzle

A couple of weeks ago, Scientific American published this puzzle.

Overlapping rectangle puzzle

There are nine overlapping rectangles, A through I. They overlap one another in a specific pattern using a notation I hadn’t seen before:

A\(D, F)    F\(A, B, I)
B\(F, G)    G\(B, C, I)
C\(G, H)    H\(C, D, E)
D\(A, H)    I\(E, F, G)
E\(H, I)

This means that rectangle A overlaps with two rectangles: D and F; rectangle F overlaps with three rectangles: A, B, and I; and so on. The goal is to correctly label the rectangles in the image.

My sense of the “right” way to handle this puzzle is to think of it as a network and use some powerful result from graph theory to solve it in an instant. But since the only thing I know about graph theory is that it exists, I went about it differently.

First, I labeled each rectangle with a code that indicates the number of rectangles it intersects and the number of rectangles its overlapping rectangles intersect.

Overlapping rectangles labeled with intersection counts

For example, the rectangle at the top is labeled 3–222. That means it intersects three rectangles, and each of those intersecting rectangles intersects with two rectangles. I put the numbers after the dash in increasing order, just as the puzzle puts the rectangle letters in alphabetical order in its notation.

Then I added my notation after the puzzle’s notation:

A\(D, F)     2–23 
B\(F, G)     2–33
C\(G, H)     2–33
D\(A, H)     2–23
E\(H, I)     2–33
F\(A, B, I)  3–223
G\(B, C, I)  3–223
H\(C, D, E)  3–222
I\(E, F, G)  3–233

The H and I rectangles are unique in my notation, so they could be identified immediately. I then went counterclockwise from H and saw that the leftmost rectangle had to be D (the only 2–23 intersecting H), the one at the bottom had to be A (the only 2–23 intersecting D), and then similarly up from the bottom through F, B, G, and C. E came from its connection to H and I.

Labeled rectangles

When I looked at the SciAm solution, I was disappointed. It was faster than mine, but not because they used some clever math. They basically identified H and I using my method (albeit without my notation), figured out B and E from that, and then “the rest is simple.” It is simple, but it didn’t teach me anything new. Oh well, maybe next year.