The April 2026 developer-tools update nobody wrote up. The reference ACP agent drops nine kinds of SDK events.
Every roundup this month lists OpenAI Codex 2.0, WordPress 7.0 delay, Apple watchOS 64-bit, Chrome DevTools notes, Xbox mode on Windows 11. All real. None of them point out the quiet convergence happening underneath: Claude Code, Zed, and Fazm all rebase on Agent Client Protocol (ACP), and the reference adapter silently swallows the events you most want to see.
What every April 2026 developer-tools recap already covers
The per-vendor recaps are right, and incomplete.
Search "developer tools updates April 2026" and the front page is a stack of per-vendor recaps. OpenAI shipped Codex 2.0 with computer use, memory, and SSH devboxes. Apple set a hard line that any watchOS app uploaded to App Store Connect from April 2026 must be built with the watchOS 26 SDK and include 64-bit support. WordPress extended the 7.0 release cycle to get Real-Time Collaboration right. Microsoft shipped Xbox mode to every Windows 11 PC. Chrome DevTools kept its weekly cadence.
All true. All app-layer. None of them describe the shift happening one layer down, at the wire protocol an AI coding agent uses to talk to a client. That shift is why next month's recaps are going to read surprisingly similar to this month's: the tools are converging.
The protocol is called Agent Client Protocol. The relevant reference adapter is @agentclientprotocol/claude-agent-acp. It does one job really well and one job poorly. The job it does poorly is the reason Fazm ships a patched entry point.
The nine event categories the reference adapter drops
These are not hypothetical. Every branch below has a real line range insideacp-bridge/src/patched-acp-entry.mjsand a concrete sessionUpdate shape that the Fazm Swift side parses. This is the uncopyable part of the page.
rate_limit_event
Claude Agent SDK rate-limit payload with status, resetsAt, rateLimitType, utilization, overageStatus. Forwarded at lines 132 to 152.
system/compact_boundary
Fired when the SDK compacts context mid-session. Carries trigger (auto/manual) and pre_tokens. Forwarded at lines 65 to 73.
system/status
Session status transitions the reference agent eats. Forwarded at lines 74 to 78 with the raw status string.
system/task_started
New sub-task kickoff events, with task_id and description. Forwarded at lines 79 to 87.
system/task_notification
In-flight sub-task progress markers with status and summary. Forwarded at lines 88 to 97.
system/api_retry
Attempt number, max_retries, HTTP status, error category, retry_delay_ms. Forwarded at lines 98 to 125.
tool_progress
Long-running tool elapsed time, keyed by tool_use_id and tool_name. Forwarded at lines 156 to 166.
tool_use_summary
Post-tool summaries the reference agent drops. Forwarded at lines 167 to 176 with preceding_tool_use_ids.
compaction stream chunks
content_block_start + content_block_delta with a compaction shape. Forwarded at lines 182 to 201 as compaction_start and compaction_delta.
The data path, end to end.
Claude Agent SDK emits nine event categories the reference ACP agent eats. Fazm's patched entry intercepts them and re-emits them. The Swift floating bar renders them. Same wire protocol in both directions.
Claude Agent SDK → Patched Entry → Fazm Swift UI
The anchor code, verbatim.
This is the live shape of the patch. The real file also handlessystem/* subtypes, tool summaries, and stream-event compaction chunks. You can open it at acp-bridge/src/patched-acp-entry.mjs on any Fazm checkout.
What the patched entry actually prints at runtime.
Tail the Fazm dev log (/tmp/fazm-dev.log) during a long session. The[patched-acp] prefix is every event the reference adapter would have eaten.
One turn, mapped event by event.
A real session that hits a retry, a compaction, and a rate-limit inside a single turn. Without the wrapper, arrows two, four, six, and eight never reach the UI.
ACP session with the patched entry active
Vanilla adapter vs. Fazm patched entry
Same dependency, two emissions
Reference @agentclientprotocol/claude-agent-acp 0.29.2: the Claude Agent SDK emits rate_limit_event, system/compact_boundary, system/api_retry, tool_progress, tool_use_summary, and compaction stream events, but the ACP adapter does not propagate them. The desktop UI sees chat deltas and tool calls, then silence during retries, compactions, and rate-limit pauses.
- rate_limit_event silently swallowed
- compact_boundary silently swallowed
- api_retry silently swallowed
- tool_progress silently swallowed
- no per-turn cost on the prompt() return
How the April 2026 convergence plays out for a developer
Claude Code, Zed, and Fazm all rebase on ACP
The April 2026 AI-coding story is not a new model. It is that three different agent runtimes now accept the same JSON-RPC dialect over stdio. An integration built against ACP once targets all three.
The reference ACP adapter drops SDK events
@agentclientprotocol/claude-agent-acp 0.29.2 speaks ACP cleanly for chat deltas and tool calls but does not forward rate_limit_event, compact_boundary, api_retry, tool_progress, tool_use_summary, or compaction stream chunks. Nine categories, all real SDK events.
Fazm ships a 267-line wrapper instead of a fork
acp-bridge/src/patched-acp-entry.mjs monkey-patches ClaudeAcpAgent.prototype.createSession, wraps session.query.next(), inspects item.value.type and subtype, and re-emits every dropped event as a sessionUpdate. Zero changes to the upstream package source.
Swift UI gets live rate-limit, retry, compact signals
ACPBridge.swift parses the new sessionUpdate types, updates FloatingControlBarState, and renders the five-hour vs seven-day rate limit, the compaction banner, the HTTP 529 retry counter, and per-turn USD cost in the floating bar.
Accessibility APIs drive the app, the UI stays honest
Fazm uses real macOS accessibility APIs (not screenshots) to click buttons, type into fields, and read trees from any Mac app. That only works if the operator trusts the session. The wrapper is what keeps the session legible.
Feature matrix
Both rows use the same @agentclientprotocol/claude-agent-acp package at version 0.29.2. The only difference is the entry file.
| Feature | Reference @agentclientprotocol/claude-agent-acp | Fazm patched entry |
|---|---|---|
| Forwards rate_limit_event to the UI | Silently swallowed | Forwarded as sessionUpdate (8 fields) |
| Forwards system/compact_boundary | Silently swallowed | Forwarded with trigger + pre_tokens |
| Forwards system/api_retry | Silently swallowed | HTTP status + attempt/max + delay |
| Forwards tool_progress for long-running tools | Silently swallowed | Elapsed time per tool_use_id |
| Attaches real cost + usage to prompt() return | Usage absent | costUsd, inputTokens, outputTokens, cache read/write |
| Forks @agentclientprotocol/claude-agent-acp | N/A | No fork; wraps via prototype monkey-patch |
Why this matters for accessibility-API automation
Fazm drives Mac apps through accessibility APIs, not screenshots
The macOS automation tool Fazm exposes to an ACP agent walks the accessibility tree of any Mac app and clicks, types, and reads from real AXUIElements. It does not sample pixels. It does not rely on a vision model to identify a button. Any Mac app with a valid accessibility hierarchy is reachable, even ones with no public API.
Accessibility-native only works if the UI is honest
The operator of a desktop AI agent has to trust what the UI tells them. When the SDK is compacting 180k of context, the UI has to say compacting. When the session is on api_retry attempt three with an HTTP 529, the UI has to say that. The patched entry is the unglamorous plumbing that turns silent drops into visible state.
Try the patched-entry build yourself
Fazm is free to download and open source. The patched ACP entry ships with every build.
Download Fazm →Frequently asked questions
What are the biggest developer tools updates in April 2026 that everyone is covering?
The public SERP is dominated by per-vendor recaps: OpenAI's Codex 2.0 expansion into computer use and SSH devboxes, the WordPress 7.0 release cycle being extended to land Real-Time Collaboration, Apple requiring watchOS apps uploaded after April 2026 to be built with the watchOS 26 SDK and include 64-bit support, Microsoft's Xbox mode going generally available on Windows 11 PCs from April, the WordPress @wordpress/build esbuild replacement for webpack, and weekly Chrome DevTools release notes. Those are all real. They are also all at the app or vendor layer.
What is the wire-level developer tools story of April 2026 that nobody is covering?
AI coding agents are quietly converging on a single transport, Agent Client Protocol (ACP). Claude Code publishes an ACP adapter via @agentclientprotocol/claude-agent-acp. Zed speaks ACP natively. Fazm's desktop app ships an ACP bridge so any ACP-speaking agent can drive it. The effect is that the thing you build an integration against is the protocol, not the vendor. That story is not in any of the April 2026 recaps, but it is the reason those recaps will start looking repetitive next month.
Why does Fazm ship a patched ACP entry point instead of the reference @agentclientprotocol/claude-agent-acp agent?
Because the reference agent drops events. Read acp-bridge/src/patched-acp-entry.mjs in the Fazm source. It imports ClaudeAcpAgent from @agentclientprotocol/claude-agent-acp/dist/acp-agent.js, monkey-patches ClaudeAcpAgent.prototype.createSession, and wraps session.query.next() so it can forward nine SDK event categories the upstream agent silently swallows: rate_limit_event, system/compact_boundary, system/status, system/task_started, system/task_notification, system/api_retry, tool_progress, tool_use_summary, and compaction stream chunks (content_block_start and content_block_delta with a compaction shape). Without that wrapper, the UI sits idle while the SDK is actually rate-limiting, compacting context, or retrying an HTTP 529. The file is 267 lines. The dependency version in acp-bridge/package.json is @agentclientprotocol/claude-agent-acp ^0.29.2.
Which specific dropped event matters most for a developer who is watching their session?
rate_limit_event. The Claude Agent SDK has fired it since late March 2026 with an eight-field rate_limit_info payload (status, resetsAt, rateLimitType, utilization, overageStatus, overageDisabledReason, isUsingOverage, surpassedThreshold). The reference ACP agent does not propagate it. In the Fazm patch, lines 132 to 152 forward it as a sessionUpdate of type rate_limit so the Swift UI in ACPBridge.swift can render a five-hour vs seven-day window indicator and an overage status chip. If you are using the reference agent, the UX difference on a rate-limit hit is no-signal vs. progressive-warning.
How does this connect to the accessibility-API automation angle Fazm keeps talking about?
Directly. Fazm drives Mac apps through real macOS accessibility APIs (AXUIElement, axorc-style trees), not screenshots. For that to be useful, the desktop chat layer has to faithfully show what the underlying agent is doing. If the agent is compacting 180k of context, the UI has to say compacting, not just spin. If the agent is on api_retry attempt 3 of 5 with a 529 status, the UI has to say that, not hide it. The patched entry is what makes accessibility-native automation legible. Accessibility APIs are how we touch the app; faithful event forwarding is how the human knows why we are not.
Can I read the Fazm patched entry point myself to confirm this is real?
Yes. Fazm is open source at github.com/mediar-ai/fazm. The file is acp-bridge/src/patched-acp-entry.mjs. The key landmarks are: line 16 imports ClaudeAcpAgent from @agentclientprotocol/claude-agent-acp/dist/acp-agent.js, line 21 overrides createSession, line 39 overrides session.query.next, lines 62 to 129 forward the five system/* subtypes, lines 132 to 152 forward rate_limit_event, lines 156 to 176 forward tool_progress and tool_use_summary, lines 182 to 201 forward compaction stream chunks, and line 212 onward patches prompt() to attach costUsd and usage to the return value so the Swift side can render real per-turn cost in the floating bar.
Is Fazm's approach to ACP going to stay on a patched entry or will it merge upstream?
The patch is additive, not destructive. Every call ultimately delegates to the real ClaudeAcpAgent; the wrapper only re-emits dropped events as additional sessionUpdate messages. That means it coexists with any upstream fix without conflicting. As @agentclientprotocol/claude-agent-acp adds native emission for these events (work is ongoing upstream), Fazm's wrapper can drop the corresponding branches without changing the public ACP surface the Swift app consumes. So the patch is a safety net, not a fork.
What does the ACP v0.25.0 upgrade mentioned in the Fazm 2.1.2 changelog actually change?
Fazm 2.1.2 (released April 7, 2026, per CHANGELOG.json) says: 'Upgraded ACP protocol to v0.25.0 with improved error handling for credit exhaustion and rate limits.' In practice that means the ACP sessionUpdate payload now carries structured errorType values like billing_error and rate_limit (see acp-bridge/src/index.ts lines 1901, 1963, 2032 and the rate_limit case at 2443), so the onboarding flow in Fazm stops silently failing when built-in credits run out, as it did before 2.1.2. The same version fixed onboarding silently failing when credits run out.
If I am a developer building on ACP today, what is the single most useful thing to learn from Fazm's patched entry?
That the reference agent's silence is not the SDK's silence. If you ever thought Claude Agent SDK sessions go dark during rate limits or context compaction, they do not. The SDK emits real events; the default ACP adapter just does not forward all of them. Copy the pattern from patched-acp-entry.mjs: monkey-patch createSession, wrap query.next(), inspect item.value.type and item.value.subtype, re-emit as sessionUpdate. That pattern is reusable on top of any ACP-compatible agent.
Does any of this matter if I am not writing my own ACP agent?
It matters because it explains why Fazm's floating bar feels responsive under load where other desktop agents feel dead. When you send a long query, you see compaction markers. When the SDK retries a 529, you see the retry counter. When you run out of overage credits, you see the exact reset time. That legibility exists because a 267-line wrapper file inside acp-bridge forwards what the reference agent throws away. If your desktop AI agent does not show you those signals, ask it why.
Last updated 2026-04-19. Verified against acp-bridge/src/patched-acp-entry.mjs (267 lines) and /Users/matthewdi/fazm/CHANGELOG.json v2.1.2.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.