4 min readRUST · AI · POSTMORTEM

Lessons from shelving a computer-use daemon

Nerve was a working cross-platform computer-use runtime: a Rust daemon, two SDKs, a real Anthropic Computer Use loop. I stopped active development on the consumer-product framing. Here is what it got right, what computer-use is genuinely hard at, and why I shelved it anyway.

I want to be precise about what “abandoned” means here, because the dishonest postmortem is the useless one. Nerve was never vaporware. The Rust daemon, the WebSocket protocol, the CLI, the dashboard, the Python and TypeScript SDKs, and the Anthropic Computer Use adapter all work, on Windows, with a 26-test suite passing and cassette-replayed benchmarks across eight tasks. What I stopped was the framing of it as a consumer product. The code that works is still there as a reference. That distinction is the whole lesson.

Timeline
2026 Daemon, protocol, SDKs working on Windows UIA tree walk, SendInput Unicode, audit log, safety policies, emergency stop
2026 Real Anthropic Computer Use loop ships computer_20250124, full tool_result loop, verified end to end
2026 Active development on the product framing stops Daemon, protocol, SDKs maintained as a hackable reference

What it got right: the daemon, not the library

The one architectural decision I would keep without hesitation is making this a daemon instead of an in-process library. Computer-use has costs that a library pays per agent and a daemon pays once. OS permissions (Screen Recording, Accessibility) get granted a single time to the daemon instead of re-granted by every agent. Observation is a persistent capture streamed to clients rather than each step re-grabbing OS handles. Most importantly, safety and audit live at one enforcement point: dry-run, an allowlist, an emergency stop, and one canonical JSONL log that replays identically everywhere.

What computer-use is genuinely hard at

The honest difficulty is not “click the button.” It is everything around the click. The action compiler is a ladder: resolve a semantic target, fall through to the accessibility tree, then to bounds, then to OCR, and finally to a typed ElementNotFound rather than a wrong click. Every rung exists because the one above it fails on real software. Accessibility trees lie or are absent, bounds drift, OCR misreads. Getting an action to fail loudly and correctly is harder than getting the happy path to work.

The deeper trap is cross-platform. The README is blunt about it and so am I: Windows is the verified golden path. The macOS backend (ScreenCaptureKit, AX, CGEvent) and the Linux backend (X11, Wayland, AT-SPI, uinput) compile, but I only ship and test on Windows. “Cross-platform” was a stated goal, and the gap between “compiles” and “validated end to end on hardware I own” is exactly where a solo project’s reach exceeds its grip. Claiming three platforms when you can only test one is the lie I refused to ship.

Why I shelved it anyway

The market answered the question before I could. ByteDance UI-TARS Desktop, Cua, Anthropic’s own desktop work, OpenAI’s, and the OS-level hooks in Apple Intelligence and Microsoft’s Agent 365 all ship working products in this space. Two of those have OS-level integration a third-party userspace daemon simply cannot match. Competing with that as a consumer product is a losing position, and I’d rather say so than burn months pretending otherwise.

The Anthropic adapter clarified this. It was always a reference, not the product: it exists to prove the wire protocol survives contact with a real model loop. The live demo is one screenshot, a paragraph describing your actual desktop, and an exit, for about half a cent. That proves the platform capture, the prompt-cached request, and the tool_result loop all work. It was never meant to be “Nerve calls the model for you.” The intended path was always “your narrower tool connects to Nerve over WebSocket.”

What I’d keep

The protocol and the daemon split. If I built in this space again I would start from exactly this: one privileged process that owns OS permissions, capture, and safety, speaking a documented wire protocol, with audit and emergency stop as first-class features rather than afterthoughts. The thing that didn’t survive was the ambition to be a product. The thing that did is the layer underneath one: a worked reference for the daemon split, the action ladder, the prompt-cached adapter, and the safety model. Shipping something real and then being honest that its slot is taken beats keeping a dead product on life support. The code stays up because reference value outlives product ambition.