← back

universe

2026

the agent-native workspace, on your Mac

a desktop app where agents do real work on your machine. the conversation is on the left, and an artifact panel on the right shows what they build as it streams in: documents, data, code, decks, live browsers, even the iOS Simulator. it runs on five engines (Claude Code, Codex, Gemini, Grok and Mantis), drives a real Chrome, syncs sessions across your Macs, and gives every agent its own memory that builds up over time.

0:00 / 0:00

electron, five engines, 23 tool servers, ~/.universe as the record

typescript · electron · react · node · sqlite · postgres · fastapi · mcp · claude agent sdk · sse · streamable http · content addressed sync · zod

the problemEverything runs on your Mac

The agent works in the repo you already have checked out, drives the Chrome profile you're already signed into, and writes files you can open in Finder. None of that works from a server, so the model call happens on your machine and is billed to your own account. The server never sees prompts, completions or token counts. The client reports its own usage.

Everything else has to work within that. Sharing, resuming on a second machine, and several people in one conversation all depend on a record that lives on a laptop that's asleep half the time. ~/.universe is the source of truth. The SQLite file next to it is only a cache, and rebuilding it takes one walk of the directory.

three planes, and what each owns
  1. your Macelectron main and renderer · ~/.universe on disk · the model call itself
  2. the apigrants and membership · encrypted blobs · the SSE fan-out
  3. postgresspaces, channels · the room log · shared transcripts
  4. the webshare pages · published apps

spacesSpaces and shared rooms

A space carries folder access, an agent, a model and a memory into every session filed under it. The desktop decides what a space contains, the server decides who can open it, and one uuid names the local row, the remote row and the folder on disk. Spaces you never share never reach the server.

A room is a session that several people prompt from different Macs, and its id is the session id. Each Mac calls the model itself, so there's no shared clock. The server assigns the sequence number and the client creates the id, so two Macs writing to the same room merge instead of racing. Messages between people cost no model call, and the model only sees them if it asks.

resolution order
a room token first, then a unique path match. if neither works it refuses and lists the candidates.
not shared
the working tree. writing into another session's artifacts would race that session's sync, so it's refused.
two Macs, one room
mac auniverse-apimac bthe model callhappens herepush the group409 lifted for roomsassigns seqroom logdedupes on group idfan outdrops bodies over 7,000sseone listener per processlocal mirrora gap means refetchthe chat columnone ordered lista message groupstores a pointerpg_notifythis roomseq is last + 1everythingafter seq

the crewSeveral agents on one working tree

A crew shares one working directory, so agents can collaborate through artifacts/ without any protocol. What the filesystem can't provide is addressing, and that's what the six crew tools are for: a roster, a mailbox, and a read-only view of what another member is doing. Models address each other as @2, the number shown in the rail, because asking a model to copy a 36-character uuid goes wrong.

There are no locks, leases or per-worker worktrees. Each member gets the roster and a list of what changed in the tree since it last ran, capped at 25 paths. Concurrent writes are last-writer-wins, which is fine at eight members and wouldn't be at eighty. A crew message is filed as a row and a line in mail.jsonl, read without being consumed, and only marked done when the recipient's run finishes.

depth 2
main to worker to worker, and no further. deeper crews become impossible to follow.
6 rounds
how long a handoff continues on its own before the parent pauses and asks you
what a worker is handed, in order
  1. the rosterwho else is here · who it reports to · read before you edit
  2. its instructionsthe agent's standing instructions · 7,000 char cap
  3. the spaceMEMORY.md · the live journal
  4. the taskthe card this is work on
  5. the skillsthe ones attached · an index of the rest

the relayRunning a session on another Mac

The Agent SDK doesn't start claude directly. It starts whatever pathToClaudeCodeExecutable points to, so pointing that at a small bridge runs the same session on another machine, with the event parser, persistence and UI unchanged. The first version piped stdio back over the network and broke straight away. herds ends a session when whatever holds its stdio goes away, and closing a laptop does exactly that.

So the far Mac starts claude under nohup, appends stream-json to a file and writes the exit code next to it, and the bridge only tails that file. When the app comes back, it trusts the far machine's filesystem over its own notes, because the app may have been killed before it wrote anything down. Copying the session over takes 0.49s through the relay, against 9s directly. A session out there runs without the in-process tool servers, since those live in this app, and reattaching after the app relaunches isn't wired up yet.

Somebody else's Mac works differently. The prompt goes into a queue, whichever machine holds the runner lease picks it up, and it runs there as an ordinary local session with all 171 tools. The transcript comes back every 700ms.

two verbs, one name
place and push briefly had the same name with different arguments, and every remote session quietly fell back to this Mac without logging it
exit 127
a bare .py ran under the system python, which doesn't have herds installed. the bridge now hardcodes the interpreter.
placing a session on the mac mini
this Macthe fleetthe far Macpick the machinepinned by youcopy the session dirrelay, 0.49sthe bridgestands in for the binaryherds control planewho is awake, and whereidentical pathso paths in the transcriptresolvenohup claudesurvives closing the lidstream-json, appendedsession idtheworkspaceas the executablewhichmachineone shellscripttailed from the file

the toolsHow tools reach each engine

Every tool server is built in-process, so a tool call is a function call that already holds the SQLite handle and the CDP connection to Chrome. There are 171 tools across 23 servers. Nineteen servers are always registered and four depend on the session: space tools only for a filed session, chain tools only while a session is driving itself, training only for runs started from the agent library, and the simulator and Blender only on macOS.

Codex and Mantis are separate binaries and can't be handed an in-process object, so the app listens on 127.0.0.1 on a random port and serves one path per session, agent and server. The path does all the routing. The token is 32 random bytes, compared in constant time and never written to disk. Each request gets a fresh server instance, because one instance can only hold one transport at a time.

bridged servers ask first
every bridged server is set to approve, because an approval policy of never makes them refuse instead of run
no tool search
nothing is deferred, so every engine gets all 171 schemas on every call. that's the next thing to fix.
a tool call, in-process vs over loopback
claude, in-processcodex, over loopback
a function calljson over http
the approval hook runs firstno approval hook
every path argument is policy-checkedonly the sandbox limits it
servers built once per runnerservers built per request

the hard partsThree bugs that took a while to find

The planner used to be a fork of the session, taken at the end of each round: same model, same memory, asked what to do next. It ran with no tools and no servers, resumed a transcript full of browser and crew calls, and concluded the only thing it could from inside, that every server had disconnected. Now the session decides while it's still running, and the Stop hook blocks exactly once, because a session that can't end can't be closed, synced or billed.

The other two went unnoticed for weeks. Message groups over 300 KB were replaced with a stub meant for a read-only viewer. Rooms have no viewer, so the Mac that wrote the group read its own stub back and saved it over the real one. Separately, opening a room rewrote a bookkeeping file that was inside the synced manifest, so the sync layer treated the new hash as a local edit and set aside every incoming version from then on.

smaller copies lose
a relayed copy with fewer items or less text never replaces the local one, whatever the far end claims. both are compared.
the repair
all 11 stubbed groups recovered from transcript.jsonl. 15 more ran on somebody else's Mac and couldn't be.
an empty manifest
pulling prunes, so publishing an empty manifest would delete a colleague's artifacts. it's never published now.
the forked planner, measured on one Mac's record
  • decisions made171 decisions
  • said tools were gone21 decisions
  • complete verdicts18 decisions
  • of those, same claim8 decisions
a 412 KB group, elided down to the 300 KB ceiling

One message group: an agent avatar, six tool calls with their results, and a thinking block.

  1. as written412 KB, over the ceiling
  2. the avatar147,857 bytes, dropped first. 267 KB
  3. tool resultstruncated to 4,000 chars each. 198 KB
  4. tool inputstruncated to 400 chars each. 191 KB
  5. still over?drop payloads entirely, keep every row
  6. still over?thinking blocks go
  7. last resortstub only the largest call

where it standsWhat works today

It ships as a signed and notarized DMG, currently 0.4.35, and updates itself. Spaces, rooms, crews, the relay, resuming on a second machine, five engines, 23 tool servers and search across every session all work end to end.

The decision I'd defend hardest is the record. Every problem above got easier once a session stopped being rows in a database file and became a directory with an append-only log in it.

done versus open
working end to endstill open
rooms stay ordered across Macseach Mac's agent has its own memory
sessions placed on another Macall 171 schemas sent on every call
crews of eight on one treeno lock on the shared tree
cross-room reads by referencean agent can't speak in a room
search across every sessionwriting across rooms is refused