How I Built a Native Mac App Without Being a Developer — Using Claude Code
The Problem
Claude Code is, without exaggeration, the most capable coding AI that exists today. It reads entire codebases, writes production-grade code, manages files, runs bash commands, handles git, debugs complex issues — and does all of this with a contextual understanding that still catches me off guard.
But you use it in a terminal. A raw, scrolling wall of text where your conversation, your file changes, your commands, and your thinking all share one cramped lane. It is like driving a Ferrari through a parking garage. The power is there. The experience is not.
I kept losing track of what Claude had changed. I would ask it to modify three files and then spend five minutes scrolling to figure out which ones. I would lose the thread of a conversation because a long command output pushed everything off screen. The activity feed — the record of what the AI actually did — was tangled into the chat itself. There was no separation of concerns.
Every developer I talked to had the same complaints. They loved Claude Code. They tolerated the terminal. And that gap between love and toleration felt like an opportunity.
The Decision
I decided to build a proper Mac app. Not a web app running in a browser tab. Not an Electron wrapper around a web view. A real native macOS application — one that launches instantly, renders at Retina resolution, respects system dark mode, and sits in your Dock like it belongs there.
The technology choice was Tauri v2 with a Rust backend and a React frontend. This was not an obvious pick for someone who had never written Rust. But the reasoning was straightforward: Claude Code manages your files and runs bash commands on your machine. The application wrapping it needs to be fast and trustworthy. Rust gives you both. Tauri produces native windows with the system's built-in WebView, which means no bundled Chromium, no 200MB downloads, and none of the sluggishness that Electron apps are known for.
A CodeMantis install is under 50MB. It launches in under 3 seconds. Memory usage sits around 40-120MB during active use. These numbers matter when you are running an AI that already consumes significant resources on its own.
The Irony
Here is the part that still makes me smile: the app that wraps Claude Code was built by Claude Code.
I am not a developer. I am a product person — I have spent years designing interfaces, writing specs, thinking about user experience. I can read code, understand architecture, and reason about systems. But I had never shipped a compiled binary. I had never written Rust. I had never dealt with code signing, DMG packaging, or Tauri's IPC bridge.
Claude Code did all of it. Thousands of lines of Rust for the backend — process management, file system watchers, streaming communication between the AI and the UI. Thousands more lines of TypeScript and React for the frontend — the three-panel layout, the activity feed parser, the Monaco editor integration, the theme system. It wrote the GitHub Actions workflow that builds, signs, and notarizes the DMG. It configured the auto-updater. It even debugged the code signing issues that are notoriously painful on macOS.
A non-developer shipped a native desktop application with a Rust backend. That sentence would have been absurd two years ago.
The Journey
Claude Code excels at certain things and struggles with others, and understanding this boundary was the most important skill I developed.
It is extraordinary at boilerplate and scaffolding. Give it a clear description of a Tauri command and it produces correct Rust with proper error handling, serde serialization, and async patterns. React components come out clean and idiomatic. CSS that would take me hours of iteration appears in seconds.
It handles Tauri's IPC bridge well — the invoke commands, the event listeners, the typed payloads between Rust and TypeScript. It generates proper error types, implements Display and Error traits in Rust, and maps them to TypeScript-friendly responses. It understands the async runtime model and produces code that does not block the main thread.
Where it struggled was complex state synchronization. The original architecture included a Task Board — a kanban-style project management system that would sync task states between the UI, the local file system, and Claude Code's context. The state machine had maybe a dozen transitions and three sources of truth. Claude Code could implement any individual piece correctly, but getting them all to stay consistent was a different problem. It would fix a race condition in the file watcher and introduce one in the UI update cycle. It would solve the UI issue and break the context synchronization.
After three full rebuilds of the Task Board, I killed it. Not because Claude Code failed — because the design was wrong. The complexity was a signal, not a challenge. And from that failure came something better.
Why Mac
This question comes up constantly, so here is the honest answer: macOS users care about software quality in a way that creates a higher bar and a better outcome.
Mac users notice when an app does not have a native title bar. They notice laggy scrolling. They notice when text rendering looks wrong, when window management feels off, when the app does not respond to system-level keyboard shortcuts. They expect the app to support dark mode, to respect their accent color, to integrate with Spotlight and the menu bar.
Tauri v2 delivers on this. The windows are native. Text renders through the system's font stack. The title bar is real — not a CSS imitation. The app appears in Mission Control and responds to trackpad gestures. It feels like a Mac app because, at the window level, it is one.
The developer demographic also matters. A disproportionate number of professional developers use Macs. The people most likely to use Claude Code — and to benefit from a better interface for it — are sitting in front of MacBooks. Starting where your users are is not a limitation. It is focus.
The SpecWriter Origin Story
The most useful feature in CodeMantis was born from the most frustrating part of working with Claude Code.
When you ask Claude Code to build something non-trivial, you need to give it a specification. Not a vague prompt — a real spec. What the feature does, how it interacts with existing code, what the edge cases are, what the acceptance criteria look like. Without this, Claude Code does what any intelligent agent does with ambiguous instructions: it makes assumptions. And some of those assumptions are wrong.
So I started writing spec documents by hand. Markdown files with sections for requirements, technical approach, file changes, and verification steps. I would paste them into Claude Code and say "implement this." The results were dramatically better than ad-hoc prompting. The first 70% of every feature would land perfectly.
But the last 30% kept getting dropped. Edge cases I described but Claude Code deprioritized. Error states I specified but that did not make it into the implementation. Verification steps I listed but never ran because they were buried on page three of a document I had already moved past mentally.
The insight was obvious in retrospect: the spec and the verification checklist should be generated together, by an AI that understands what is likely to be missed. SpecWriter is that tool. You describe what you want to build in natural language. SpecWriter analyzes your codebase, produces a structured specification, and generates a verification checklist tied to each requirement. The checklist is not generic — it is specific to the changes being made and the patterns in your code.
It then hands the spec to Claude Code to implement, and afterward you can run the verification checklist against what was actually built. The "last 30%" problem did not disappear entirely, but it shrank to maybe 5-10%. That is the difference between a feature that works and a feature that ships.
What's Next
CodeMantis 1.0 shipped in March 2026 and the roadmap is driven by how people actually use it.
The preview browser is getting refinements — better viewport presets, responsive design tooling, and the ability to pin multiple preview URLs across sessions. The template system is expanding with community contributions. SpecWriter is being improved to handle multi-file refactoring specs more gracefully.
Linux support is on the table. Tauri v2 supports Linux natively and the Rust backend is platform-agnostic. The question is not whether it is technically possible but whether I can deliver the same quality of experience. Linux desktop environments are fragmented — GTK vs Qt, X11 vs Wayland, different file managers and notification systems. If CodeMantis ships on Linux, it needs to feel like it belongs there too. That is a higher bar than just compiling and hoping.
The broader bet is simple: Claude Code is going to keep getting better. Every model improvement, every context window expansion, every new capability makes the AI more powerful. CodeMantis ensures that power is accessible through an interface that respects both the tool and the person using it.
If you had told me a year ago that I would ship a native Mac app with a Rust backend, I would have laughed. But here we are. The AI wrote the code. I wrote the specs. And the app works.
Sometimes the best tools are built by the people who need them most.
Sincerely, Harald
Share this article