What we're building next
What runs today, and what doesn't#
Horon has exactly one surface you can use without building anything: horon.ai. The landing page, /product, /pricing, /docs, /blog, the login screens and the account dashboard are served from a Cloudflare Worker. Auth answers on the same domain under /api/auth/*, and again at api.horon.ai. Two workers carry it: horon-web serves the site, horon-auth answers the auth paths.
Every other surface is in a different state, and the difference matters more than a sentence that says we're building. Desktop runs only if you compile it. The phone app is built up to its login screen. A plugin store doesn't exist, and neither does checkout.
So this post is a ledger rather than an announcement. For each surface: what you would see if you tried it today, and what happens after that.
The web app is the part that's live#
Sign-in is real. The forms post to /api/auth/* on the same origin, which is the horon-auth worker, and that worker keeps users and sessions in a D1 database. On production the provider endpoint reports Google and Apple as configured, which is why the login page draws those two buttons.
Behind the login, /dashboard has four screens: an overview, devices, settings and billing. The device list comes from the relay's device registry, so it fills in only when the deployment has a relay address. Billing is where the claim is easiest to check. It shows the plan, then says that no subscription record is stored, so nothing is charged.
There is also /login/device, a screen where a code shown by a device helper gets approved, which is how a computer joins an account.
Prices sit on /pricing as well, at $0, $12 and $20. The note under them reads: prices are advertised, not billed, and checkout is not built yet. That is the whole payment story.
The desktop app runs, and you can't download it#
The desktop client is a Tauri 2 app with five screens. /chat holds the session list, the transcript, the composer and the approval prompts. /host publishes this computer to the relay as a device and answers agent requests on its behalf. /relay is the other side, reading the device list and calling a remote agent. /agent and /llm are diagnostic screens for the harness socket and an OpenAI-compatible endpoint. The window borrows its components and tokens from the design system in a sibling repository, so it and the website share the same primitives.
None of it is a mockup. Text in /chat comes from frames the local horon-agent process sends over a Unix socket, and the app doesn't fake a send. A published device sends a heartbeat every 15 seconds, hands an incoming request to that socket, and returns the response.
What doesn't exist is the stretch between the code and your Applications folder. There is no bundle, no signing, no notarization, no updater and no release workflow in the repository. The bundle block in tauri.conf.json lists all targets and four icons, and that's the entire packaging configuration. Because the harness surface assumes a Unix socket, macOS is the only place it has been exercised.
The /download page is built anyway, gated on a confirmed email address and phone number. It has a state for 'no build is published yet', and that is the state today, because there is nothing to publish. If you want to run the desktop app now, you clone the repo and build it.
The phone app stops at the login screen#
The Flutter app has four tabs: home, messages, activity and settings. It picks a layout from the window width rather than the device type, and it ships in Korean and English. One codebase covers phones and tablets.
The login screen is real code, not a placeholder. It reads the auth server address and the provider list from build flags, treats an empty address as a configuration error instead of falling back to a hardcoded host, and returns from a browser passkey ceremony through the horon://auth/callback deep link.
Past that screen the app is still a shell. Messages, activity and the home cards draw sample data, there is no relay connection anywhere in the code, and notifications are local only, raised by a test button in settings. Logging in with a real account against a deployed server has not been verified. So the honest description is that the phone app is built to the login screen and doesn't reach the server yet.
There is no store, and nothing is charged#
A plugin is installed by name, from a directory, on the command line: horon-agent plugins install ./plugin-bundle. The other verbs are list, enable, disable, status and doctor. Six commands cover the whole lifecycle, and enable asks for a version when more than one compatible build is installed. No marketplace, no browse page, no one-click install. Install copies a validated bundle into the agent home and runs nothing.
Publishing is just as unfinished. The release groups in the plugins repo declare their versions and tags, and the check driver runs across four Cargo workspaces, but the destination in release-groups.json is not configured, so the publish step is skipped.
Billing matches. The team plan lists 'one seat per person, once billing exists' and 'a shared workspace, still in progress'. Both of those are the plan describing its own state, not a promise about when.
Each product still arrives as its own tool#
Mail is a bridge over Gmail, Outlook and any IMAP/SMTP mailbox, and it arrives with four surfaces plus a terminal UI: a CLI, an SDK, an MCP server and an HTTP server. Provider crates cover mock, Gmail, Outlook and a generic IMAP mailbox.
Messenger has the same shape across Slack, Discord, Telegram, WhatsApp, Instagram, LINE and iMessage, with KakaoTalk declared and every operation returning not-implemented. Router is a local proxy that puts several provider accounts behind one address and converts between API formats.
Three products, three installs, three ways to drive them, and one person holding the whole arrangement together. That's the setup the direction is meant to change. It is worth saying plainly that it hasn't changed yet.
One window over the tools, and plugins as the way in#
The direction isn't another tool. It's a window over the tools. One place where a session runs, where an approval appears, where the files a task touched are visible, and where the products you already use show up as capabilities rather than as separate apps with separate shortcuts. The desktop client's chat screen is that shape in miniature: sessions, transcript, approvals, and a work panel beside them. /host is there for the same reason, because the window shouldn't be trapped on the machine you happen to be sitting at.
The way a product reaches that window is a plugin. A plugin is a compiled library, a cdylib with a C entry point, that the agent loads into its own process. The contract is C ABI 1 and wire schema 1: the host calls one symbol, gets a table of functions, and sends tool calls through it, like mail__whoami with no arguments. Each product in the plugins repo carries one of these crates.
What a plugin is handed is small on purpose: a configuration blob, a directory it may write to, a directory it reads configuration from, and the features enabled for that instance. No file handle, no shell, no home directory. It isn't a sandbox either, and the contract says so. The library runs in the host's address space, and the size limits (64 MiB per frame, 32 frames queued per operation, 128 MiB of copy budget across all plugins) are budgets for a cooperative plugin, not a memory fence.
We aren't putting dates on any of this. What we can offer is a statement of state, and this post is that statement. When the desktop app has a signed build, the download page will hand it out. Once publishing is configured, a plugin will arrive without a path. Until then, every sentence above stays the way it is written.