I run dozens of bespoke little Mac apps: scratch notepads, screen resolution tuners, and even a mini-dashboard making use of that little bucktoothed notch atop MacBook screens. A simple but critical utility is an alternate app switcher—the default MacOS ⌘+⇥ (Cmd+Tab, or for Windows folks, Alt+Tab) switcher is glaringly basic, which makes it ripe for third-party improvement. The app I've used for the past decade has been Contexts; sadly, it has not seen any development activity since 2022, and, with the continued advancement of MacOS, is in danger of falling into complete incompatibility.
So you can guess what I spent a week building.
Before the current iteration of coding-focused LLMs, building a utility that integrates closely with the operating system felt like a daunting project. Web apps run within their browser sandbox; native apps are at their best when they hook into the operating system's multitude of subsystems. They tend to have richer notifications, snappier interfaces, and behave closer to the host OS in a dozen different, sometimes imperceptible ways.
The first thing that Switchboard—that's the name bestowed onto my Contexts replacement app—needed to do was monitor the global keyboard events queue, so it can capture and override the ⌘+⇥ combination. It also has to find and read the list of windows visible at the moment, delineated by Spaces[1]. Just getting this far requires understanding the interaction model for this part of the operating system, reading through lots of API and documentation, and building a bunch of prototypes to deduce how the underlying systems are reacting to Switchboard's system requests.
This is where current-gen coding tools shine. They have absorbed the tricks of the trade from previous generations, and folded the best-practice workflows into their default coding strategy[2]. Their harnesses are now advanced enough to work through these steps autonomously:
- Reading documentation and support forums to get the shape of the problem;
- Making system calls (with the user's permission) and capturing the responses to understand what it accepts and rejects;
- Constructing a plan with phases to derisk the project, while clarifying requirements from the user;
- Capturing screenshots and occasionally taking control (also with permission) to confirm its UI/UX renditions;
- Building ad hoc debugging tools, grepping logs and system dumps to chase down crashes and errors;
- Adding regression tests as it builds on top of its own work.
And this level of execution isn't just limited to MacOS either; I asked Claude to build a native reader app in HarmonyOS Next for a Huawei laptop, and it got to a fully functional app despite the scant Chinese documentation.
Coming back to Switchboard, Claude made tremendous progress, even without reference source code[3] and having to figure out many partially-defined behaviors. Its gaps, though, hint at the real bottleneck.
To be fair, Claude's design skill is actually quite good, to the point that many recent software projects are saturated with its "AI design aesthetic." But its agreeable defaults are also the tell. The interface would look perfectly reasonable in a static screenshot, but user interactions would render unreadable text and nonsensical layouts. The AI agent would happily construct elaborate workflows on top of outdated authentication schemes and APIs that make those screens unreachable. Its edges are jagged, in ways that break the regular rhythms of software development.
Perhaps another way to frame this is that LLMs lack developer taste—the dozens of little coding and design decisions that evince a persistent human touch, resulting in an uncanny valley of software products. Granted, this is not a fatal flaw. As with software development pre-AI, one tried-and-true solution is to demand denser checkpoints, poke around and flag incongruent decisions made by the machine, and patiently adjust its approach. Taste can be incrementally instilled… just one prompt at a time.
Switchboard suffered from this at every step. In the switcher panel, the typeface interacted poorly with MacOS's liquid glass treatments and made the text unintelligible. Its mouseover selection would be too slow, hampered by the aggressive loop that was cobbled together by a previous prompt. At one point, the AI reconstructed a tab bar meticulously to resemble the native component, only for it to be off by two pixels, so upon my feedback, apologize and unceremoniously scrap its prior work.
Yet, even with all the back-and-forth, the neat thing about AI-centric development is how the core interaction has graduated from code to prose. Coding has always felt unnatural because it required humans to think like machines: sharp specificity over misinterpreted ambiguity. The exact syntax, structure, and logic all matter tremendously in how the software gets interpreted, and some of the most insidious bugs turn out to be subtle typos or misplaced lines of code.
Claude and its AI coding brethren weave large amounts of code from user specifications. In particular, the advent of reasoning models has improved how they work through complex requirements. But the more assumptions LLMs have to make to fill in gaps in explicit user instructions, the worse taste they develop, which then gets amplified with further iterations. By design, the coding agent is implementing an average; it cannot internalize a set of decisions that comes from sharp opinions hardened by experience. Taste is the antithesis of decisioning by (training data) committee.
It's this singular vision that makes building Switchboard so tremendously fun. The app features my strong personal preferences, which means it'll be much less useful to anybody else—unless I add enough features to fully productize it. But this is the irony of vibecoding: it's increasingly easy for someone else to do the same and prompt their way to a functional app, and if they care enough they can spend more time fine-tuning its features, and adding to its bells and whistles to their liking. With a lower barrier to entry, the effort to support commercial or even open-source software diminishes.
So I'll just keep this bespoke app switcher to myself.
Spaces are MacOS's implementation of virtual desktops. ↩︎
The progress being made by successive generations of AI has greatly reduced the longevity of the emergent field of prompt engineering. ↩︎
On a recent episode of the Dithering podcast, they talked about tasking AI to port old, beloved Notational Velocity to Apple silicon, as support for Rosetta 2 is ending soon. ↩︎