Prelude

You know those exponential growth charts. The ones that open every pitch deck, every keynote, every breathless blog post about AI changing the world. Revenue up. Users up. Adoption through the roof. Hockey stick. To the moon.

Here is my exponential growth chart.

Month Issues Filed
Feb 2025 232
Mar 2025 415
Apr 2025 220
May 2025 529
Jun 2025 1,220
Jul 2025 2,039
Aug 2025 1,948
Sep 2025 1,363
Oct 2025 2,116
Nov 2025 1,788
Dec 2025 3,087
Jan 2026 6,014
Feb 2026 7,081
Mar 2026 ~9,100 (projected)

That is the Claude Code GitHub issue queue. 31,995 issues filed to date. 6,093 currently open. One hundred new issues filed before breakfast this morning. 30x year-over-year growth.

This is not a failure metric. This is what it looks like when the most capable AI coding tool ever built ships faster than its ecosystem can stabilise. This is the chart that tells you what AI development actually looks like in 2026. Not from the stage. From the trenches.

I build systemprompt.io, a platform for AI governance and plugin management. Our dashboard ingests data from Claude via HTTP hooks. Simple webhooks. The kind of integration that has worked reliably since the early days of the web. POST a JSON payload to a URL. Receive a 200. Done.

It does not work. Or rather, it works on some surfaces, on some operating systems, some of the time. The rest of the time, it fails silently, fails loudly, or fails in ways that require building entirely new debugging tools to even understand the failure.

This is a story about five specific, deeply technical problems that emerge when you try to build one product that works across every Claude surface. Each one is documented, reproducible, and backed by real issues in that exponential queue.

The Problem

Claude now ships on five distinct surfaces. Claude Code is the command-line tool. Claude Desktop is the Electron application. Claude Cowork runs tasks inside a sandboxed VM. Claude Chat lives in the browser at claude.ai. And all of these behave differently depending on whether you are running Linux, macOS, Windows, or WSL.

If you are building a platform that integrates with Claude, not just using it, but building infrastructure that other people's Claude instances connect to, you need it to work everywhere. Every surface. Every OS. Every configuration.

The promise of HTTP is that a POST request works the same everywhere. The reality of the 2026 AI ecosystem is that the same HTTP request succeeds from the command line, fails from the desktop app, crashes the VM, and gets blocked by the CDN. Same URL. Same payload. Same machine. Different outcomes depending on which layer of abstraction your request originates from.

Here are the five walls we hit.

The Journey

Two Marketplaces, Two Schemas

Claude Code and Claude Desktop both support plugins. Both have marketplaces. Both use a marketplace.json manifest to describe available plugins. They are not the same schema.

This is not a subtle incompatibility. A plugin that validates and installs correctly in Claude Code CLI fails in Claude Desktop, and vice versa. The CLI tool accepts type: "http" in MCP server configurations. The Desktop app does not recognise it. The Desktop app has an extension management system that the CLI knows nothing about.

It gets worse. The official Anthropic marketplace itself ships plugins that fail validation in Claude Code. The marketplace.json in claude-plugins-official defines category and source fields on every plugin entry. When Claude Code fetches these plugins, those marketplace-level metadata fields leak into the cached per-plugin plugin.json. The schema validator then rejects them as unrecognised keys. Plugins from Anthropic's own official marketplace, Figma, Sentry, Vercel, PostHog, Notion, all fail with Unrecognized keys: "category", "source".

The Cowork surface has its own distinct problems. The LocalPlugins interface continuously throws schema validation errors, making it impossible to use custom plugins even when they pass claude plugin validate on the command line. A plugin that Claude Code CLI says is valid, that installs correctly, that works perfectly from the terminal, crashes Cowork with a silent redirect back to the main page and no error in the UI.

Then there is the auto-update trap. Claude Desktop silently migrated from a manual mcpServers configuration to an extension-based management system. Every user who set up MCP servers using the previously documented method, hand-editing claude_desktop_config.json, which was the only documented method, had their configuration silently broken by an update. Both the old and new server launch simultaneously, conflict, and the routing layer exposes zero tools. No warning. No error in the UI. No migration path.

Our workaround at systemprompt.io was to stop maintaining static manifests entirely. We built a server-side export system that dynamically generates marketplace.json on request, tailoring the output to handle the schema differences at the server level. When a user's Claude Code CLI requests our marketplace, it gets one shape. When Cowork requests it, it gets another. One set of plugins, two schemas, generated on the fly because the consuming surfaces cannot agree on what a valid plugin looks like.

This is not how mature ecosystems work. In mature ecosystems, you publish a manifest once and every consumer reads it the same way. In this ecosystem, you need server-side content negotiation for your plugin metadata.

The TLS Nightmare: unknown_certificate_verification_error

Claude Code is built on Bun. Bun bundles its own TLS implementation via BoringSSL. This bundled TLS stack does not use your operating system's certificate store. It does not respect NODE_EXTRA_CA_CERTS. It does not respect SSL_CERT_FILE. It does not respect NODE_TLS_REJECT_UNAUTHORIZED=0. It respects nothing.

I filed this issue after our HTTP hooks started failing with unknown_certificate_verification_error on every single event. Our server uses a perfectly standard Let's Encrypt ECDSA certificate, the E7 intermediate, signed by ISRG Root X1. Every browser trusts it. Every operating system trusts it. curl trusts it. node trusts it. openssl s_client trusts it. Claude Code does not trust it.

If you are seeing failed to connect to api.anthropic.com: unknown_certificate_verification_error or unable to connect to Anthropic services: failed to connect to api.anthropic.com: unknown_certificate_verification_error, the root cause is the same: BoringSSL's sealed certificate store, not a network problem and not a firewall. Standard workarounds (setting NODE_TLS_REJECT_UNAUTHORIZED=0, adding your CA to the system store, running update-ca-certificates) will not help because the bundled runtime never reads the system store.

The system CA bundle on the machine contains 146 root certificates, including ISRG Root X1. None of that matters. The binary's TLS stack is a sealed box. I tested every standard environment variable. I tested combinations of environment variables. Nothing penetrated the bundled BoringSSL.

The rabbit hole goes deeper. Another investigator ran strace on the Claude Code process and discovered that the HTTP hook client sets the TLS SNI to include the port number. The Server Name Indication field, the part of the TLS handshake that tells the server which certificate to present, gets set to example.com:443 instead of example.com. This is a bug in Bun's HTTP client. The malformed SNI breaks the TLS handshake because no server expects a port in the hostname field. The error that bubbles up to the user is ECONNREFUSED, which is misleading, the TCP connection succeeds, the TLS handshake fails, and Bun maps that failure to a connection refused error.

For comparison, Anthropic's own API connection in the same process uses SNI api.anthropic.com without the port. It works. The hook client, in the same binary, in the same process, sets the SNI differently. One works. One does not.

The root cause traces back to Bun's custom DNS lookup function. Claude Code uses a function called B2L for SSRF protection that validates resolved IPs against private ranges. Passing this custom lookup to Bun's HTTP client triggers bugs in BoringSSL's networking layer. The upstream fix was merged in Bun on March 8, 2026. As of this writing, Claude Code still bundles Bun v1.3.11 without the fix.

The mTLS story is equally grim. Client certificates that worked in v2.1.22 broke in v2.1.23. Corporate environments using Zscaler proxies cannot use WebFetch at all because the bundled Bun runtime ignores the proxy's CA certificates. The Claude Desktop app does not forward NODE_EXTRA_CA_CERTS to the CLI subprocess it spawns, creating a different failure mode on every surface.

HTTPS is a solved problem. It has been a solved problem for over a decade. Bundling your own TLS implementation that ignores the operating system's trust chain unsolved it.

Cloudflare Versus Claude

When your TLS implementation rejects Let's Encrypt certificates, you need a workaround. The standard workaround is to proxy your traffic through Cloudflare, which terminates TLS with its own certificates that the bundled BoringSSL does trust.

This creates a new problem. Cloudflare's entire business model is distinguishing real traffic from bot traffic. Claude Code making HTTP requests to your server is, by any reasonable definition, bot traffic. Cloudflare blocks it.

The OAuth login flow fails entirely from cloud VPS environments. The token exchange request gets a Cloudflare JavaScript challenge. The CLI cannot execute JavaScript challenges. Authentication fails. The workaround suggested in the issue, exempt the token exchange endpoint from bot challenges, requires you to control the Cloudflare configuration for claude.ai, which only Anthropic can do.

On Windows, Claude Desktop enters an infinite redirect loop when it encounters a Cloudflare Turnstile challenge. The Electron webview cannot solve the challenge. The app fires Cloudflare challenge detected, redirecting... errors thirty times per second. The EventEmitter memory leak warning triggers. The application becomes completely unusable. Claude.ai works fine in a regular browser on the same machine.

Even Cloudflare's own product conflicts with Claude Code. Running Cloudflare Warp, Cloudflare's VPN product, alongside Claude Code produces Unable to connect to API due to poor internet connection errors. Disabling Warp fixes it immediately.

The MCP authentication flow is caught in the middle. HTTP MCP servers that require OAuth silently fail. The initialize handshake succeeds without authentication. The server advertises its tool capabilities. Then tools/list returns Unauthorized. Claude Code swallows this error entirely. No notification. No prompt to authenticate. No indication that the server exists or needs attention. The user has to independently discover the /mcp command and manually trigger the OAuth flow.

So here is the chain: your server needs HTTPS. Claude Code's bundled TLS rejects your Let's Encrypt certificate. You proxy through Cloudflare. Cloudflare blocks Claude Code as a bot. You configure Cloudflare to allow it. Now the MCP OAuth flow breaks because the authentication redirect goes through Cloudflare, which challenges the automated client. Every solution creates the next problem.

The VM That Will Not Restart

Claude Cowork runs code inside a Hyper-V virtual machine. The idea is sound, sandbox untrusted code execution in an isolated environment. The implementation on Windows is catastrophic.

VMs start successfully but crash within five minutes. The Hyper-V event log confirms the VM initialises, connects to the virtual network, runs for approximately five minutes, then turns off. All subsequent attempts to restart the service fail. Deleting the VM directories, restarting Hyper-V services, full system reboots, nothing recovers it.

The filesystem mounting layer is the primary failure point. The sandbox-helper fails to unmount host shares using both virtiofs and Plan9 protocols with invalid argument. This corrupts the JSON output stream, debug output from the sandbox helper contaminates stdout, which Claude Code parses as JSON, which fails. After the first failure, the VM service will not start at all. The error reads VM service not running. The service failed to start. Cycle repeats indefinitely.

The virtiofs mount failures produce RPC error -1: Plan9 mount failed: bad address. These are intermittent, triggered by environmental conditions rather than specific user actions. The VM download itself fails with EXDEV: cross-device link not permitted when trying to rename VM image files, a basic filesystem operation that should never fail on a local disk.

Users report workspaces becoming permanently bricked after normal usage. A Chrome automation task runs, the workspace corrupts, and no recovery path exists. Clearing the cache does nothing. Deleting the VM bundle and reinstalling does nothing. The fresh install fails with the same VM service not running error. The only option is to reinstall Claude Desktop entirely.

Perhaps the most telling issue is that Claude Desktop spawns a 1.8 GB Hyper-V VM on every launch, even for chat-only use. One user found 2,689 stale session files from previous Cowork sessions that were never cleaned up, following Docker-style naming conventions like nifty-dreamy-volta and tender-vigilant-goodall. These are the claude vm bundles accumulating silently on disk. On a 16 GB laptop, the VM consumes 11% of total memory before the user has typed a single message, and the stale bundles can fill tens of gigabytes over time.

Some machines report Virtualization is not enabled despite Hyper-V being fully enabled and confirmed functional. The sandbox ignores sandbox.enabled: false in the configuration, meaning you cannot opt out even when you know it will fail.

Another failure mode: the cowork session vm process not available. The session may not be fully initialized. error, which appears even when Hyper-V is functional. This happens when the VM initialises the network layer but the Cowork session handshake times out before the VM process registers its socket. Waiting and retrying does not help. The session remains in a partially-initialised state that blocks all subsequent Cowork launches until the VM bundle directory is cleared manually. On Windows, these bundles live at %LOCALAPPDATA%\AnthropicClaude\cowork and accumulating stale session state across failed launches is a confirmed trigger.

The pattern across all these issues is the same: the VM breaks, there is no recovery path short of a full reinstall, and the error messages are unactionable. VM service not running tells you nothing. Plan9 mount failed: bad address tells you nothing. session vm process not available tells you nothing. The diagnostic information that would help, Hyper-V event logs, virtiofs mount state, sandbox-helper output, is buried in system logs that most users do not know how to access.

The practical workaround that has the best success rate across all VM failure modes: clear the cowork bundle directory, disable and re-enable Hyper-V through Windows Features, then reinstall Claude Desktop fresh. Not elegant. Not documented. But it is the only path that consistently unblocks a bricked Cowork installation without a full OS reinstall.

The Fragmentation Matrix

Every Claude surface behaves differently on every platform. This is not an exaggeration. Here is a partial matrix of what works and what does not, as of March 12, 2026:

Feature CLI (Linux) CLI (WSL) CLI (Windows) Desktop (Windows) Cowork (Windows) Desktop (Mac)
HTTP hooks to HTTPS endpoints Broken (TLS) Broken (TLS) Broken (TLS) Broken (MSIX) N/A Broken (TLS)
HTTP hooks to localhost Works Works Works Broken (MSIX) N/A Works
MCP server (stdio) Works Works Works Works Partial Works
MCP server (HTTP) Works Works Works Broken Broken Broken
Plugin marketplace install Works Works Works Schema conflict Schema conflict Works
Plugin marketplace update Works Works Works Fails silently Fails silently Works
VM sandbox N/A N/A N/A N/A Crashes N/A
OAuth behind Cloudflare Fails on VPS Works Works Infinite loop Unknown Works
Let's Encrypt certificates Rejected Rejected Rejected Rejected Rejected Rejected
System CA store Ignored Ignored Ignored Ignored Ignored Ignored

This morning, we spent two hours debugging why HTTP hooks work from WSL but fail with ECONNREFUSED on Windows Claude Desktop. Same machine. Same network. Same endpoint. Same plugin. 56 hooks registered across 5 plugins. All firing correctly. Every single POST failing on Windows.

The hooks are registered. They match. They fire. The server is healthy, curl and node from the same machine return HTTP 401 (expected without credentials). The server never sees a request from Claude Desktop.

We traced it through multiple layers. The Claude Desktop app is installed from the Microsoft Store as an MSIX package. MSIX apps run inside an AppContainer sandbox. The package declares internetClient capability but not internetClientServer. Claude Code CLI is spawned as a child process of the MSIX-packaged Desktop app. The child inherits the AppContainer sandbox restrictions.

The critical discovery: the MSIX AppContainer network sandbox blocks the in-process HTTP client that fires hooks, but spawned child processes like bash and node are not affected. We proved this by running the exact same HTTPS request from a node process spawned by Claude Code, it succeeded with HTTP 401. The in-process hook client, in the same Claude Code instance, got ECONNREFUSED.

WSL works because it runs in its own network namespace with a virtual adapter, entirely outside the MSIX AppContainer sandbox. The CLI launched directly from a terminal works because it is not a child of the MSIX app. Only the specific combination of Claude Desktop (Store edition) spawning Claude Code as a subprocess triggers the failure.

This is the kind of bug that no documentation warns you about. It requires understanding Windows MSIX packaging, AppContainer network isolation, Hyper-V virtual networking, Bun's bundled TLS, and Claude Code's hook dispatch architecture. It requires debugging skills across five different technology stacks simultaneously. And it affects everyone who installs Claude Desktop from the Microsoft Store and tries to use HTTP hooks, which is the primary use case for platform integration.

The Recursive Loop

Here is the part that should make you laugh, or possibly weep.

We build systemprompt.io. Our platform distributes plugins through the Claude Code marketplace. One of our plugins is called "Debugging claude on windows". It contains four skills: debug-claude-hooks, debug-cowork-vm, debug-mcp-connections, and claude-windows-file-locations.

We built a marketplace plugin, distributed through the marketplace system that has schema validation bugs, using Claude Code which has TLS bugs, to debug Claude Code's hooks which have ECONNREFUSED bugs, running on Claude Desktop which has MSIX sandbox bugs, connecting to a server proxied through Cloudflare which has bot-detection bugs.

The tool that is broken is the tool we use to build the tools that diagnose why the tool is broken. The platform we are trying to integrate with is the platform we use to write the integration code. The marketplace we publish to is the marketplace that cannot consistently install what we publish.

This is not a metaphor. This is a screenshot from this morning's debugging session: bash commands grepping for ECONNREFUSED in the background while the Claude Desktop plugin menu shows our "Debugging claude on windows" skills in the foreground. The AI is helping us debug the AI. The recursive loop is the development workflow.

And somehow, despite all of this, it works. Not reliably. Not on every surface. Not without workarounds. But the fact that we can use Claude Code to build a debugging plugin, distribute it through a marketplace, and have that plugin actually help diagnose the platform's own bugs, that is remarkable. It is infuriating and remarkable in equal measure.

The Lesson

The issue queue is not a failure metric. It is a maturity indicator, and what it indicates is that the AI development ecosystem in 2026 is roughly where web development was in 2004. The tools are powerful. The pace of innovation is staggering. And the number of sharp edges that will cut you is growing faster than anyone can file them down.

232 issues in February 2025. 7,081 in February 2026. That 30x growth is not because the product got worse. It is because the surface area exploded. And it is not just the issue queue. The service itself has been unstable. In the first twelve days of March 2026 alone: a major worldwide outage on March 2 that took down all consumer-facing surfaces with over 2,000 reports on Downdetector, Anthropic cited "unprecedented demand". Then Haiku 4.5 elevated error rates on March 7. Then another outage on March 11 with 1,400+ reports. In late February, the usage report API returned errors and missing analytics data for two days. A daylight saving time transition caused an infinite loop in Cowork and Claude Code scheduled tasks. API connection timeouts from upstream network peering degradation. This is not one bad week. This is the baseline. Claude went from a CLI tool to a CLI tool plus a desktop app plus a sandboxed VM environment plus a web interface plus a plugin marketplace plus an MCP protocol plus HTTP hooks. Each new surface multiplied the integration matrix. Each multiplication created new failure modes that only manifest in specific combinations of platform, surface, and configuration.

The deeper pattern is that AI tools are shipping on top of technology stacks that are themselves immature. Bun is not Node.js. It is a newer, faster runtime with its own TLS implementation, its own DNS resolution, its own HTTP client behaviours. When Claude Code bundles Bun, it inherits Bun's sharp edges. When Bun bundles BoringSSL, it inherits BoringSSL's opinions about certificate chains. When the MSIX package wraps the Electron app that spawns the Bun-based CLI that makes the HTTP request that hits the Cloudflare proxy that challenges the bot that built the house that Jack built, each layer adds its own failure mode, and no single team understands all the layers.

This is the fundamental challenge of building on the AI ecosystem today. It is not that the tools are bad. Claude Code is genuinely extraordinary. The model behind it produces code that would have seemed impossible two years ago. The problem is that the infrastructure around the model, the packaging, the networking, the sandboxing, the marketplace, the plugin system, the authentication flow, is being built at the same pace as the model improves, which means it is being built too fast to be stable.

For those of us building platforms on this ecosystem, the practical implications are clear:

Test on every surface, every time. The fragmentation matrix is not theoretical. A feature that works on CLI Linux will break on Desktop Windows in ways you cannot predict from reading the documentation.

Build server-side workarounds. Do not rely on the client behaving consistently. Generate your marketplace manifests dynamically. Handle schema differences at the server level. Assume the client will send you something unexpected and be right about half the time.

File detailed bugs. The 6,093 open issues are not going to fix themselves. But every detailed bug report with reproduction steps, strace output, and root cause analysis moves the ecosystem forward. The community investigators on these issues, the people running strace on TLS handshakes, the people dissecting MSIX manifests, the people building test matrices across Bun and Node.js, are doing the work that makes the ecosystem eventually stable.

Budget for debugging. If your project plan assumes that HTTP webhooks will just work, that TLS will just work, that plugins will install the same everywhere, add a multiplier. We spent two hours this morning on one ECONNREFUSED. That is a normal morning.

Conclusion

The growth chart at the top of this post is going to keep growing. March 2026 is on pace for over 9,000 new issues. That number will likely double again before the year is out. This is not a crisis. This is what building in public looks like when the entire industry is moving at escape velocity.

The AI tools we have today are genuinely useful. I write this using the same tool I spent the morning debugging. The irony is not lost on me. Neither is the productivity gain. Even with every bug documented in this post, even with the TLS nightmares and the MSIX sandbox traps and the marketplace schema conflicts, building with Claude Code is faster and more capable than building without it.

But the gap between what these tools can do and how reliably they do it, that gap is where the real engineering happens. Not in the prompt. Not in the model. In the plumbing. In the TLS handshakes and the AppContainer policies and the virtiofs mount points. In the boring, unglamorous infrastructure that has to work perfectly for the extraordinary AI on top of it to deliver on its promise.

That is the growth chart nobody shows you. Not the model capabilities going up. The integration complexity going up right alongside it. And until the ecosystem matures enough to close that gap, we will keep building debugging tools to debug the tools we use to build debugging tools.

That is the job. Somebody has to do the plumbing.