
Rooms and FoxDesk: one conversation, any machine, any agent
A coding session lives in one agent, on one machine. Close the app, change machine, or let the agent run all night, and you lose the thread. Rooms fix that: a room is a conversation that outlives the session, the app and the screen that started it. FoxDesk is the desktop window on those rooms, next to the phone.
What you get. Start on the laptop, finish on the phone, let the agent work all night: the conversation is always there, whole, on every screen. One small controller and SQLite do it.
1. A rooms controller in front of the agents
Our controller, CloudFoxRoom, sits in front of several OpenFox instances, one per machine. It is a small program with no dependency beyond the language's standard library, and it:
- records rooms, prompts and events in SQLite (WAL mode, so reads never block writes);
- makes every creation idempotent by a
request_id: the same request twice returns the same receipt; - keeps one client per instance with isolated errors: a machine asleep never hides the others;
- keeps a queue per room that you can edit, cancel, reorder, pause or interrupt;
- streams events by SSE, with replay from the last event received after a disconnection.
Replay is the feature you notice. The phone loses its signal in a lift; when it comes back, it asks "everything after event 412" and the conversation is whole again.
2. An open-source core, never patched
For multi-agent sessions we use the core of an open-source project, cloudroom (Apache 2.0), which already runs Claude Code natively. Our rule: never patch the core. Every agent it does not know (Kimi, local models through the gateway) is plugged in by an adapter outside the core, which speaks the same protocol as a native harness. Upstream updates then install without a merge.
3. FoxDesk: the desktop client
FoxDesk is a web client served by every workstation, not by one server. If one machine falls, the others still drive the fleet. A small local server in front of it injects the token on the server side: the browser never holds a secret.
Two rules make it trustworthy:
- What is not wired is greyed, with the reason. A button that does nothing yet is shown disabled, with "not wired: the core sends no state for this". Never fake data, never a button that silently does nothing.
- The mascot is a gauge. FoxBot's mood is computed from real probes (health, load, a task waiting for you), never a decorative animation.
Traps
Never show an identifier or a raw timestamp to a human. A room is shown by its title, its project and "2 min ago".
Do not reinvent the core's gestures. If the core can move a session between machines, call it; do not simulate it in the interface.
Sources
Found this useful? Tell us what to measure next.