[All work](/work?type=work)

# The City

I saw [AI Office](https://sael.net/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.

[Download ](https://github.com/Slaymish/theCity/releases)[Source code ](https://github.com/Slaymish/theCity)[Read on Alphero](https://www.alphero.com/intelligence/articles/turning-claude-code-sessions-into-a-visual-dashboard)

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.](https://cdn.sanity.io/images/qnuj1c4o/production/25cb42d26ff47825a8266cbb51651f9a37a2376c-1600x1000.png?w=1280\&q=80\&auto=format)

## 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.](https://cdn.sanity.io/images/qnuj1c4o/production/337b402160a379cbbae429a66115ef8e1e30a861-1600x1000.png?w=1200\&q=80\&auto=format)

Robots at the Research, Build and Review desks show what their subagent is doing right now, taken straight from the stream.

[All work](/work?type=work)
