Opus 4.7 landed on April 14. Fazm's floating bar showed it the same afternoon, without an App Store push
Every April 2026 Anthropic roundup talks about Opus 4.7, Mythos Preview, the Claude Code desktop redesign, and Routines. None of them describe what it actually takes for a consumer Mac app to show a brand new Claude model on release day. Fazm does it with one JSON-RPC response field, one WebSocket message type, and a three-row substring table in Swift. This page walks that path, line by line, from the ACP bridge to the floating bar picker.
Anthropic Claude update, April 2026 (headlines)
The question nobody is answering
"How does my AI app pick up Opus 4.7?"
Every roundup on the April Claude update tells you what Anthropic shipped. Fewer tell you what an app that depends on Claude has to do to catch up. For Fazm the answer is: nothing, as long as the ACP SDK is honest about what models it supports. The rest is a pipeline that was already there.
| Feature | Typical consumer Claude app | Fazm |
|---|---|---|
| How new Claude model IDs get into the UI | Ship a new build with an updated hardcoded list | Listen for models.availableModels in session/new response |
| Time from Anthropic GA to user-visible pick | Hours to days (release, review, rollout) | One session/new round trip on next launch |
| Source of truth for supported models | App bundle constant | Claude Code SDK, piped through ACP bridge |
| What happens when Anthropic renames a model | Stale option until next release | Substring match on 'haiku', 'sonnet', 'opus' keeps labels stable |
| Dedup so the UI does not re-render on every call | Often re-sets the picker on every session open | lastEmittedModelsJson guard at index.ts:1249 |
| Handles the SDK pseudo-model 'default' | Either shows it or hardcodes around it | Filters it at line 1274 before it ever crosses to Swift |
The anchor fact
One wire message, 0 lines of TypeScript, and a three-row Swift table
The entire "adopt a new Claude model" story for Fazm fits in a single function. It lives in acp-bridge/src/index.ts, starts at line 1271, and ends at line 1281. It emits exactly one message type, declared in acp-bridge/src/protocol.ts at line 276: type: "models_available". That is the wire.
From Anthropic's SDK to the floating bar chip
The five-hop pipeline
Five participants. Three JSON-RPC calls, one local IPC emit, one Swift property update. The same shape every launch, whether the SDK reports three models or thirteen.
session/new response becomes picker entry
The Swift side, verbatim
How Opus 4.7 gets its "Smart" label
There is no switch statement mapping specific Claude version IDs to labels. Fazm uses a substring match. That is the entire reason Opus 4.7 showed up as "Smart (Opus, latest)" on April 14 without a Swift change.
The family map, lines 159 to 163
Three rows. This is the only place Fazm knows what Haiku, Sonnet, and Opus mean as a brand. Extend the array with one new row and the app gains a new tier without touching anything else.
The size of the pipeline
Four numbers from the actual source tree
What the logs looked like on April 14
Opus 4.7 arrives, no code change fired
A compact log of the exact flow from bridge launch to the floating bar picker re-rendering with Opus 4.7 as "Smart (Opus, latest)". Output lines are from the real log statements in index.ts and ACPBridge.swift.
“The version number reached users before a release note did.”
Fazm engineering, log entry 2026-04-14 14:03:34 PDT
Why Fazm can do this and a browser-based AI agent often cannot
The product conditions that unlock same-day support
The ACP bridge pipeline is only half of the story. The other half is Fazm's stance on what the app is. It is a consumer Mac app that reads the real system through accessibility APIs, not a browser extension piping screenshots to a cloud model. Those choices flow downstream into how model discovery is wired.
What has to be true for an app to absorb model updates this cleanly
- Model list arrives from the SDK, not from an app bundle constant
- A single wire message type carries the update (models_available), not a schema migration
- Labels come from a small substring table, not a map keyed by exact version string
- A dedup guard prevents re-renders when the list has not actually changed
- The pseudo-model 'default' is filtered before it crosses to the UI layer
- Selected-model normalization covers renames (normalizeModelId at line 169)
- No App Store gatekeeper sits between new Anthropic models and users
- Desktop accessibility APIs mean screen reading does not care which model is selected
“We stopped shipping model list updates about a year ago. The SDK tells us. If a model is in session/new, it is in the picker. That is the whole deal.”
Frequently asked
Grounded in the files this page names. Every answer points at a line or a function you can open and verify.
Frequently asked questions
What exactly did Anthropic ship in the April 2026 Claude update?
Four dated events. April 7: Claude Mythos Preview, a new general-purpose model with a strong bias toward computer security tasks, plus the Project Glasswing announcement. April 14: Claude Opus 4.7 GA at the same $5 input and $25 output per million tokens as Opus 4.6, with measurable gains on long-running software engineering and higher-resolution vision. April 14 also: a full Claude Code desktop redesign (Mac and Windows) with /tui fullscreen rendering, mobile push notifications, cleaner transcripts, and Remote Control support, alongside the Routines research preview. Early April: the consumer Terms of Service update that forced users to re-accept on claude.ai before API calls resumed. Admin group roles and Claude Cowork gating also shipped mid-month.
How did Fazm add Claude Opus 4.7 support without shipping a new build?
Fazm does not carry a hardcoded model list in the Swift binary. Its ACP bridge (acp-bridge/src/index.ts) issues session/new to the Claude Code SDK, and the SDK response includes a models.availableModels array. The function emitModelsIfChanged at line 1271 filters out the pseudo 'default' entry, diffs against the last JSON it emitted, and sends a WebSocket message of type 'models_available' to Swift. ACPBridge.swift at line 1131 decodes that message, calls onModelsAvailable, and ShortcutSettings.updateModels(_:) at line 178 rebuilds the @Published availableModels array. When the underlying SDK started returning claude-opus-4-7 on April 14, Fazm's floating bar picker picked it up on the next session/new call. No App Store push, no Sparkle update.
What is the exact wire message Fazm uses for new Claude models?
A JSON object with type 'models_available' and a models array, defined in acp-bridge/src/protocol.ts at line 276 and emitted at index.ts:1279 via send({ type: 'models_available', models: filtered }). Each element is { modelId: string, name: string, description?: string }. It is the only place where new Anthropic model IDs enter the Fazm app after startup. It is idempotent: the bridge caches the last emitted JSON in lastEmittedModelsJson and skips the send if nothing changed.
How does Fazm map unknown Claude model IDs to UI labels?
A four-row substring table in ShortcutSettings.swift at lines 159 to 163: ('haiku', 'Scary', 'Haiku', 0), ('sonnet', 'Fast', 'Sonnet', 1), ('opus', 'Smart', 'Opus', 2). On each incoming ACP update, updateModels iterates the array and picks the first family whose substring appears in the model ID. claude-opus-4-7 contains 'opus', so it renders as 'Smart (Opus, latest)' with a short label of 'Smart'. Anything that does not match any family falls through to the raw API name the SDK returned. This is why the app can absorb a model release without a code change as long as the naming convention holds.
Does Fazm default to Opus 4.7 now that it is GA?
No. The DEFAULT_MODEL constant at acp-bridge/src/index.ts:1245 is 'claude-sonnet-4-6'. Sonnet is also the pre-warm default (line 1246), and the fallback list in ShortcutSettings.defaultModels lists Sonnet first among selectable tiers. Opus 4.7 is surfaced as an option in the picker as soon as the SDK reports it, but the floating bar does not auto-promote users to it. A separate one-time migration moves existing Opus 4.6 users to Sonnet on launch to avoid the new seven_day_opus weekly cap; that migration is described in the companion guide on April 2026 Claude news.
What happens in Fazm the first time a user opens the app after Opus 4.7 shipped?
ACP bridge runs preWarmSession with the pre-warm set of sessions (main, floating, observer). Each session/new call returns a response that now includes claude-opus-4-7 inside models.availableModels. emitModelsIfChanged sees the JSON differs from lastEmittedModelsJson and sends 'models_available' over the IPC channel. ACPBridge.swift decodes it, fires onModelsAvailable, and ShortcutSettings.updateModels runs the substring match. The floating bar's chip row re-renders with the latest Opus label. The user, if they tap the chip, sees claude-opus-4-7 in the menu. All of this happens once per launch, and the dedup guard prevents re-emission for the rest of the session.
How can I verify the pipeline in the Fazm source code myself?
Four file reads. First: /Users/matthewdi/fazm/acp-bridge/src/index.ts lines 1245 to 1281 — DEFAULT_MODEL, lastEmittedModelsJson, emitMcpServers, emitModelsIfChanged, and the protocol filter. Second: /Users/matthewdi/fazm/acp-bridge/src/protocol.ts line 276 — the 'models_available' type literal. Third: /Users/matthewdi/fazm/Desktop/Sources/Chat/ACPBridge.swift lines 1131 to 1213 — the message decoder, the log line 'received models_available with N models', and the onModelsAvailable dispatch. Fourth: /Users/matthewdi/fazm/Desktop/Sources/FloatingControlBar/ShortcutSettings.swift lines 159 to 212 — the family map and the updateModels function that turns the ACP list into picker entries. If any of those four do what this page says they do, every claim here is checkable at the commit level.
Why does the ACP bridge filter out the model ID literally called 'default'?
The Claude Code SDK reports a pseudo-entry with modelId 'default' that means 'whatever the session was last set to', which is not a selectable tier in the Fazm UI. emitModelsIfChanged at line 1274 drops any entry with modelId === 'default' before it hits Swift. Without that filter, the picker would grow a meaningless row that points to nothing. The filter is the only transformation the bridge performs on the raw list; it does not rename, reorder, or annotate the SDK output.
What does Fazm do when the SDK drops an older model, like if Haiku 4.5 were deprecated?
updateModels at ShortcutSettings.swift line 201 checks whether the currently selected model appears in the new list. If the current selection is no longer present, it tries to normalize it through normalizeModelId (which reduces any model ID containing 'haiku' to 'haiku', 'sonnet' to 'sonnet', 'opus' to 'opus') and retries the lookup. If normalization still fails to match, the selection is left alone and the app logs 'current selectedModel X not in new model list' so a support reader can see what happened. The next outbound call still uses the stale ID; the ACP SDK is the final authority on whether that request succeeds.
Does this dynamic pipeline have any downside?
One. Because the model list only refreshes when session/new actually returns it, the UI does not know about a newly GA'd Anthropic model until a Fazm session gets opened. On a cold machine that has not launched Fazm for a day, the first launch after Opus 4.7 release day is the moment the picker picks it up — not the moment Anthropic pressed GA. For a consumer app where launches are a daily event, that gap is short. The tradeoff is: Fazm never ships a release just to add a model, and it never has a hardcoded list that goes stale between updates.
Want a Mac AI assistant that already has Claude Opus 4.7
Fazm runs on real accessibility APIs, not screenshots. Works with any app on your Mac, not just the browser. Installs in about a minute.
Download Fazm for Mac →
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.