All work

The City

I saw AI Office showing Claude Code agents as robots at desks, and wanted something that fitted the way I work. In The City, each project folder is a building and each team has a floor of robots, so I can see which ones need me.

Solo designer and developer, from the stream parser to the 3D scenes and the release pipeline. The demo replay came from an outside contributor.

A cutaway office building labelled theCity on a street grid among trees, with robots working at colour-coded desks on each of its three floors.

Driving claude -p as a process

Each floor starts claude -p --input-format stream-json --output-format stream-json --verbose --permission-prompt-tool stdio and keeps stdin open. Prompts, follow-ups and answers go in as JSON lines, and every event comes out as one. Departments go in with --agents, the budget with --max-budget-usd, and a follow-up adds --resume with the session id from the init event.

Surfacing questions in the UI

With --permission-prompt-tool stdio, every tool call that needs permission arrives as a control_request with subtype can_use_tool, and the CLI waits for a control_response on stdin. AskUserQuestion only exists in this mode, since plain -p leaves it out. A question is just a can_use_tool request for that tool, so the app draws its options as a card at the robot’s desk and replies allow with the choices added to the input under answers. Always allow echoes the request’s permission_suggestions back as updatedPermissions, and the CLI saves the rule itself. A subagent’s request carries an agent_id, which puts the card at the right desk.

Turning the stream into an office

A Swift package called OfficeCore parses the stream and reduces it into the state of the office, with no UI imports. task_started and task_progress give each subagent’s type, last tool and token count, and assistant messages carry a parent_tool_use_id back to their subagent. A type the floor didn’t hire sits at the Contractor desk. Recorded streams in the repo drive the tests and a replay mode, so the scene can be checked without spending tokens.

Reading a project’s kit for free

Hiring needs a project’s agents, skills and MCP servers before any job runs. The app starts the CLI with the model office-inventory-no-such-model, which still sends an init event listing all of them and then stops with model_not_found before costing anything.

Reception and City Hall

Each building has a receptionist. Apple’s on-device model fills in a @Generable struct with an existing floor’s name or a name for a new one, prewarmed while you type and abandoned after 12 seconds. Without Apple Intelligence the same question goes to Haiku as a bare claude -p with --json-schema, no tools, an empty MCP config and no settings sources.

City Hall is the same idea one level up: it picks the building, then that building’s reception picks the floor. An optional mayor answers questions about the city on-device and makes rounds that flag changed workspaces and waiting floors, without starting jobs or spending tokens.

Where it stands

Version 0.15.0 is on GitHub under MIT, with signed Sparkle updates and an iPhone companion. It needs macOS 26 and Claude Code 2.1.163 or later, and the build is not notarised yet, so the first launch goes through Open Anyway.

Office floor

Each desk is a department

A close view of an office floor: robots at the Research, Build and Review desks under status bubbles reading Reading, Running a command and Searching.
Robots at the Research, Build and Review desks show what their subagent is doing right now, taken straight from the stream.
All work