Skip to content

Zeron

A Rust desktop app that runs the coding agents you already use — Claude Code, Codex, Cursor, Devin, Grok, Hermes, Pi and Antigravity — on your own machine, with no account required, and syncs the sessions to your other devices only if you sign in.

Screenshot of Zeron
Editor screenshot, 30 Sep 2026Zeron ↗

What it is

A local-first control plane for coding agents, written in Rust. Every device runs a small engine that keeps its sessions on that device; a fresh installation starts in local-only mode with no account and no network connection, and signing in is a separate step that changes the profile the engine picks at its next start. The desktop app is a gpui window over that engine — a sidebar that is itself the data, an attention-sorted session list grouped into spaces, which are device-and-folder pairs — and the same binary runs headless, so a machine left on can keep agents working after the laptop closes. Eight agents sit behind one interface (Claude Code, Codex, Cursor, Devin, Grok, Hermes, Pi and Antigravity), each reached through its own subprocess or JSON-RPC protocol and normalised into a shared transcript. Sync is optional, rides Loro CRDT documents through Cloudflare Durable Objects, and makes terminals, file trees, diffs, previews and an iOS app reachable from every signed-in device.

Who built itThe repository’s two largest contributor accounts sit behind the same author name: wing-anara, with 727 commits, and wingleeio, with 342 — together 1,069 of the 1,690. José Gurruchaga wrote 402 more under jsgrrchg. Thirty-one accounts have contributed in all, and 1,670 of the 1,690 commits carry a linked GitHub account.

How it is put together

The parts · 6

A single Rust binary that can be a window or a daemon, wrapping an engine that owns everything device-side. The engine runs the agents, holds authentication, terminals, repositories and worktrees, hosts the CRDT documents, and answers a typed RPC — over a WebSocket to a separate process, or over an in-memory duplex when the interface runs it in-process, deliberately with no serialization shortcuts so that the boundary stays honest. Two consequences shape the code. The interface is a viewport onto state it does not own, which is why the sidebar list, the transcript and the diff pane are subscriptions to document updates rather than application state. And the storage boundary is captured once, at engine startup, as a workspace scope — local, synced or development — that later authentication changes cannot move, so a token refresh can never silently swap the database under a running session.

crates/
Sixteen crate directories, twice the eight the architecture document names: proto for wire types, doc for the schemas and the mirror layer, sync for the CRDT room client and its SQLite snapshot store, harness for the agent adapters, engine for sessions, repositories, terminals, accounts and diff sync, then rpc, theme and ui, plus client, mobile, markdown, mcp, preview, syntax, text and update.
crates/ui
The application: 635 files and 10.7 MB, dominated by a few enormous ones — a 701 KB shell, a 595 KB transcript, a 590 KB composer, a 327 KB picker, a 213 KB state store and a 197 KB history view. The whole surface is here: markdown and its link handling, terminals, the diff pane, file trees and previews, the theme compiler and settings, with a 65 KB file-icon table beside them.
crates/engine and crates/harness
The working core: sessions at 144 KB, the RPC surface at 184 KB, the document host at 289 KB, workspace files at 116 KB and diff sync at 76 KB — and above them 115 harness files carrying one adapter per agent, among them a 253 KB ACP module, a 170 KB OpenCode adapter and an 88 KB Codex adapter, with the probes and 28 test fixtures alongside.
edge/
TypeScript on Cloudflare: a Worker with one Durable Object per room — chat, registry, device, and a legacy session room at 65 KB that the architecture says no current client dials — plus R2 attachments, push notifications, WorkOS authentication routes, an install script and ten check scripts that run against the deployed edge.
apps/
The iOS client as a 1,012-file Swift project whose generated core binding alone is 412 KB, and the landing site as an 81 KB single page with a 13 KB field animation, 25 images of social posts and the sponsor logos. The binary crate itself is five files: the entry point, the daemon commands, authentication, updates and paths.
docs/
Thirty-three markdown files at the top level and eleven subdirectories under them: 22 research files, sixteen performance measurements and replays, thirteen transport result files from one dated run beside a metadata file, a screenshot corpus of 115 files and 18.5 MB, twelve sound auditions, three dated plans from 2026-08-20 and 2026-08-22, two architecture decision records, three regression write-ups and one agent worklog under docs/toolcraft/.

Choices, and what they beat

  • Keep the edge in TypeScript and everything device-side in Rust over writing the Durable Objects in Rust as well

    The architecture document names the decision and points at docs/research/durable-objects-language.md as its evidence, so the choice is inspectable rather than a matter of taste.

  • Pin one Zed revision of gpui but write markdown, components and theme in-house over reusing Zed’s markdown, ui, theme and editor crates

    Stated as a licence decision: the gpui crates are pinned to a single revision, while the four Zed crates under GPL are deliberately not used, which is why the repository carries its own markdown parser, its own component set and a compiler for VS Code theme families.

  • Leave token-usage display out of the rewrite over the parity target, which covered everything else

    The exclusion is named with its reason — the profile meter is a poor fit for a CRDT document — while the rate-limit meters on agent accounts are kept, because they are probed from the CLIs and never synced.

  • No filename denylist for remote workspace access over blocking known-sensitive names when one device browses another

    Written out as a refusal with the reasoning attached: ignored-file visibility is not an authorization boundary, hiding entries in the interface is not a security control, and a denylist would be incomplete while implying a guarantee the project cannot provide. What replaces it is enforcement inside the owning engine on every remote request.

  • Capture the storage boundary once, at engine startup over re-resolving the open store whenever authentication changes

    Authentication state and workspace scope are separate state machines on purpose, so a sign-in, token refresh or revocation cannot silently swap databases or attach online transports to a runtime that started local-only. The cost is written into the README instead of hidden: the daemon has to be stopped before logging in or out, and the change lands on the next start.

  • Publish a parity document with named gaps over declaring the rewrite complete

    The milestone table marks two stages as shipped with gaps — the composer attachment UI and a Cursor harness for Rust among them — and records the macOS bundling configuration under dist/macos/ as written but not executed, because it needs a Mac.

Read fromARCHITECTURE.md (24,176 characters), README.md (4,330 characters), the complete 2,498-file tree with sizes, the directory summary by size, the release and tag lists, and the thirty issue and pull request bodies.

Build log

6 stages
  1. 01

    Seventy-two days, 1,690 commits and a release train

    The repository was created on 2026-07-20; its oldest commit is dated 2026-07-19 and is titled Foundation: architecture, research, Rust workspace scaffold, TS edge port, and the newest, on 2026-09-30, is Bump version to v0.2.99. In between: 151 commits in the eleven days left of July, 894 in August, and 645 in September. The report’s release list caps at twenty entries and runs from v0.2.79 on 2026-09-19 to v0.2.99 on 2026-09-30 — twenty releases in twelve days, roughly two a day — with v0.2.87 present as a tag and absent from the release list. The project has 2,506 stars, 239 forks, two watchers, 191 open issues and pull requests, 2,498 files and 117 MB under MIT. Thirty-one accounts have contributed: the largest are wing-anara with 727 commits and wingleeio with 342, and José Gurruchaga (jsgrrchg) added 402. Of 764 co-author trailers, 663 name a Claude model — 517 Claude Fable 5, 64 Claude Opus 5.5, 34 Claude Opus 5 (1M context); eight say Cursor and ten name Devin or Devin AI. The README thanks one company for sponsoring the work and links a GitHub sponsors page.

  2. 02

    A ground-up rewrite that kept the schema and deleted the server

    ARCHITECTURE.md opens by calling the project a ground-up native rewrite of an earlier zeron — a multi-device controller for Claude Code and Codex — in Rust with a gpui interface, and states the premise bluntly: Fresh app; no backwards compatibility required. What that bought and what it cost is written down as lists. Kept verbatim: the session-document schema shape and its constants, the command-ledger rules, the Durable Object design, the render-parts privacy policy, and the animation timings. Changed: Postgres entity sync and an old Hono server replaced by a workspace registry plus a TypeScript edge; Electron and React replaced by gpui with techniques ported from two named projects; Node harness SDKs replaced by subprocess protocols; the mobile app of the previous generation declared out of scope. One excluded feature is named with its reason — token-usage display, dropped because it is a poor fit for CRDTs — while the smaller rate-limit meters survive because they are probed from the CLIs rather than synced. Two engineering choices are recorded the same way, each with an evidence file: the edge stays TypeScript, and the interface pins a single Zed revision of gpui while refusing Zed’s GPL crates, which is why markdown, components and theme are written in-house.

  3. 03

    Eight closed agents, taken apart with probes and fake binaries

    crates/harness is where other companies’ closed agent CLIs get mapped. It holds one adapter per agent — claude at 46 KB, codex at 88 KB, cursor at 41 KB plus a 30 KB shim.mjs, opencode at 170 KB, pi at 39 KB, and a 253 KB ACP module carrying Antigravity, Devin and Grok — and beside them a set of probe programs kept in the repository as evidence: cursor_stability_probe.rs at 25 KB, a steering probe, model probes for Devin and OpenCode, a Grok subagent probe and an Antigravity ACP probe. Under docs/research/ three incidents have their own folders holding a README, a results.json and, in one case, a 12 KB validation.log. The tests ship 28 fixture files, among them fake-claude.sh, a 27 KB fake-codex.sh, fake-cursor-sdk.mjs, fake-pi-rpc.py, fake-devin-auth.sh and two fake Antigravity ACP scripts. The pinned Cursor SDK is the one third-party piece kept current by a workflow: scripts/update-cursor-sdk.py opens a pull request that checks token refresh, stream authentication invalidation and session recovery, and states in its own body that it is never automatically merged.

  4. 04

    The review queue: pull requests stacked on pull requests

    The thirty most recent issues and pull requests were all open on 2026-09-29 and 2026-09-30, numbered 653 to 682. Eleven come from one contributor, katulevskiy, who has landed five commits, and his bodies describe work parked in large branches and cut up for review: one feature is stacked on #609, the Android app, and tells reviewers to base onto upstream/zeron/android-app-implementation; a device-to-device transfer pull request says it was extracted from that same Android branch so it can be reviewed on its own, and that the Android pull request will be restacked on top of it once this one lands; a third says it depends on another pull request, includes its commit, asks reviewers to look only at the last commit and promises a rebase. Review still happens in the ordinary way: on an appearance pull request the maintainer writes any screenshots? curious what it actually looks like, and the contributor posts one about seventy minutes later. On a bug report about model changes not applying on an iPhone, a contributor points at the fix that was already open, and the reporter answers, Oh, I see. You’re right. Thanks! — three hours after filing. Several bodies end with a generated footer for a hosted review service, in pull requests from contributors and from the actions bot alike.

  5. 05

    What the pull requests admit

    The bodies are unusually specific about what was and was not verified. A fix for model changes in open iOS sessions records that git show --check passed and then states plainly: iOS UI tests were not run, because this environment is Linux and has no Xcode. A transcript link change reports 1,315 tests passing in zeron-ui, 48 in the markdown crate, and for the harness crate 303/304 unit tests passed. A live-update pull request shows an animation, labels it Schematic (generated by docs/media/live-update/generate.py), not a screen recording, and then supplies a second recording that is real output from scripts/live-update-demo.sh, which starts an actual headless engine and a scripted agent parked on a question before replacing the engine in place. Measurement outlives the argument elsewhere in the tree: docs/performance/ holds sixteen files of profiles and replays, one of them 243 KB, and docs/transport-results/2026-09-15/ holds one dated transport run in thirteen result files — fixed-* and main-* pairs for catch-up and three stream runs, and fixed-side results for HTTP, an outage, upload, repeated upload and a very slow link — beside a metadata file describing the run.

  6. 06

    The boundaries the author wrote down

    The architecture document ends with a milestone table that marks two stages as shipped with named gaps rather than done: terminals, the diff pane, worktrees and settings are in, while the composer attachment UI and a Cursor harness for Rust are listed as missing, and the macOS bundling configuration under dist/macos/ is recorded as not executed, because it needs a Mac. Four open questions are tracked as non-blocking, including the fallback if Rust-to-TypeScript CRDT interop fails: a hand-rolled client of about three hundred lines. The security section is the sharpest writing in the repository. Devices signed into one account are trusted peers with full workspace access; turning on ignored-file visibility exposes .env remotely; and the author states that ignored-file visibility is not an authorization boundary, that hiding entries in the interface is not a security control, and that there is deliberately no filename denylist, because such a list would be incomplete and would imply a guarantee the project cannot make. Three items are listed as deliberately deferred, among them any supported self-hosted backend contract.

Adjacent records

All records →