The juggling problem
Anyone using coding agents seriously ends up with separate terminals for Claude, Codex, Gemini and friends, plus a local Ollama nobody remembers to use because switching costs a context. Each tool keeps its own history, its own approvals, its own idea of the project.
Cortex is a Tauri 2 desktop app — Rust backend, React frontend — that puts all of them behind one window. You type a task once; it goes to a model that can actually do it. It runs entirely on your own machine: agent CLIs authenticate with the subscriptions you already have, API keys live in the OS keychain, and nothing is sent anywhere you did not configure.
Routing by capability first, cost second
Three classes of provider are treated as one pool. Maker CLIs run as subprocesses under their own logins, so usage bills against existing plans rather than metered tokens. OpenAI-compatible APIs connect with a base URL and a key. Local runtimes — Ollama, llama.cpp, vLLM and the rest — connect over localhost and cost nothing.
The router checks what a model can do before it checks the price, so a chat-only model is never handed shell access. Among capable models, cheaper wins, and a free local model wins ties. Explicit selection always overrides.
More than one agent at a time
- Teams pairs a manager model with specialist workers on a single task.
- Lanes runs the same task across several providers in isolated git worktrees, so their edits cannot collide and the diffs can be compared before any of them touches the real branch.
- Arena runs two models head-to-head on one prompt and keeps an ELO leaderboard of the results — opinion about which model is better, replaced with a record.
An answer to “what did the agent do?”
Every run is recorded to a local SQLite store. Run Replay plays any past run back as a timeline: the prompt, why that model was chosen, each tool call and approval, file edits, errors, and per-run cost. A reliability dashboard aggregates the history into per-provider success rates, latency percentiles and spend.
The other half of trust is containment. Commands run in an untrusted-by-default sandbox with a safe-command allowlist; plan mode blocks write and exec tools entirely; checkpoints snapshot the workspace independently of git, and an undo shows the exact diff before rolling anything back.
Shipping a desktop app is its own project
Releases build in CI on a self-hosted runner: a tag push produces the Linux .deb and AppImage and publishes them, and an in-app updater picks new builds up from the release feed.
The AppImage taught the best lesson. Tauri bundles the build host's WebKitGTK, and on a newer distribution that bundled WebKit could not initialise EGL — the web process died and the app launched to a black window, with no error a user would ever see. No runtime setting could fix it, because the bad library was inside the bundle. The fix is at build time: post-process the AppImage to prefer the host's WebKit and fall back to the bundled copy only where the host has none.
That failure is also why the pipeline gained a headless end-to-end probe: the built app is launched under a virtual display and must prove it actually painted before a release goes out. A build that would ship a black screen now fails instead of shipping.