Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ curl -fsSL https://raw.githubusercontent.com/AgentSystemLabs/agent-office/main/i
- **GitHub on the walls.** Issues and pull requests hang on cork boards. Hand an issue to a worker, queue tasks, give a worker its own git worktree and open its PR with one key. One task can span several projects: the worker gets a worktree of each, and a PR in each that links the others.
- **Together.** Voice, chat, screen sharing on the lounge TV and a shared whiteboard.

- **Other maps.** Turn the whole building into a castle: sit on a throne of iron blades while your workers line up before you when they're done, send new ones off through the Hand of the King, and watch their beards grow long and grey as they toil. Or make a map of your own in JSON ([docs/maps.md](docs/maps.md)).

There's a lot more (a rooftop bar, an office dog, an arcade): see [docs/features.md](docs/features.md).

## Requirements
Expand Down Expand Up @@ -351,6 +353,7 @@ Every change to the app that lands on `main` is published as a GitHub release by
- [Features](docs/features.md): everything in the office, room by room
- [Agents](docs/agents.md): Claude Code, Codex and OpenCode, models and effort, and the office's prompts
- [Configuration](docs/configuration.md): every command-line option, and where the office keeps its data
- [Maps](docs/maps.md): the castle, and making a map of your own
- [AWS reference](docs/aws.md): Tailscale, service tunnels, upgrades, and everything `deploy/aws.sh` does
- [Railway reference](docs/railway.md): what `deploy/railway.sh` sets up, and what the volume keeps
- [Fly.io reference](docs/fly.md): what `deploy/fly.sh` sets up, machine sizes, pausing and what the volume keeps
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Back to the [README](../README.md).

## Where the office keeps things

The office keeps its data in `~/agent-office` (`--home` or `AGENT_OFFICE_HOME` to move it) and clones projects next to it, as `~/agent-office/<owner>/<repo>`. To clone them somewhere else, like `~/Workspace`, an admin picks the **Workspace folder** in ⚙️ Settings → **🏢 Building** (or start with `--projects` or `AGENT_OFFICE_PROJECTS`). Floors you already have stay where they are, and a checkout of the same repository that's already in the new folder is used as it is. The list of floors is `~/agent-office/.agent-office/floors.json`, and each account's own Claude and GitHub sign-ins are in `~/agent-office/.agent-office/homes/<account>/` (revoking the account deletes them). Each floor keeps its workers, queue, pictures and worktrees in its own checkout's `.agent-office/`.
The office keeps its data in `~/agent-office` (`--home` or `AGENT_OFFICE_HOME` to move it) and clones projects next to it, as `~/agent-office/<owner>/<repo>`. To clone them somewhere else, like `~/Workspace`, an admin picks the **Workspace folder** in ⚙️ Settings → **🏢 Building** (or start with `--projects` or `AGENT_OFFICE_PROJECTS`). Floors you already have stay where they are, and a checkout of the same repository that's already in the new folder is used as it is. The building's map is in `~/agent-office/.agent-office/map.json`, and maps of your own go in `~/agent-office/.agent-office/maps/` (see [Maps](maps.md)). The list of floors is `~/agent-office/.agent-office/floors.json`, and each account's own Claude and GitHub sign-ins are in `~/agent-office/.agent-office/homes/<account>/` (revoking the account deletes them). Each floor keeps its workers, queue, pictures and worktrees in its own checkout's `.agent-office/`.

Already have a checkout? Pick its repository anyway: a checkout of it that's already where the workspace folder would clone it is used as it is. You can still start the office in a project, `agent-office ~/code/my-project`: that project becomes a floor, and the office keeps its data in `~/code/my-project/.agent-office` as it did before there were floors. An office that already ran in a project carries on in it when you start `agent-office` there again. An admin can take that project off the building in the elevator like any other floor.

Expand Down
3 changes: 2 additions & 1 deletion docs/controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Back to the [README](../README.md).
| W A S D / arrows | Walk (hold Shift to run); on the ladder, W and S climb; in a car, W is the gas, S brakes and reverses, A and D steer |
| Space | Jump (you can land on desks, couches and the cars in the garage); in a car, brake |
| Mouse drag / wheel | Orbit / zoom the camera |
| E | Interact: hire a worker, open its terminal, read a board, take an issue's note off the board, prompt a board agent, call a meeting in the meeting room, draw on the whiteboard, read the docs at the bookshelf, watch the TV, sit down (or get up), ride the elevator, climb the ladder (or get off it), slide down a fire pole, grab a coffee, take a smoke break, tee off at the golf tee, pet the dog, pick up the basketball (then hold E and let go to shoot), order a drink at the rooftop bar, blow the DJ's air horn, step up to the dart board or the axe lane on the roof (then hold Space and let go to throw), get into one of the cars in the garage (behind the wheel, or beside whoever's driving) or out of it |
| E | Interact: hire a worker, open its terminal, read a board, take an issue's note off the board, prompt a board agent, call a meeting in the meeting room, draw on the whiteboard, read the docs at the bookshelf, watch the TV, sit down (or get up), ride the elevator, climb the ladder (or get off it), slide down a fire pole, grab a coffee, take a smoke break, tee off at the golf tee, pet the dog, pick up the basketball (then hold E and let go to shoot), order a drink at the rooftop bar, blow the DJ's air horn, step up to the dart board or the axe lane on the roof (then hold Space and let go to throw), get into one of the cars in the garage (behind the wheel, or beside whoever's driving) or out of it. In the [castle](maps.md#the-castle): sit on the throne, where E is for whoever's first in line (or the Hand of the King, with nobody waiting), and speak to the Hand to send out a new worker |
| K | On the castle's throne: speak to the Hand of the King, to send out a new worker |
| P | Prompt: give a task to a new worker, or to the one at this desk |
| C | Changes: the files the worker at this desk changed and their diff; commit, discard or open a PR |
| B | Open a shared shell at an empty desk |
Expand Down
1 change: 1 addition & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Everything in the office, room by room. Back to the [README](../README.md).
- **Drive the supercars.** Walk up to one of the Lambos or Ferraris in the garage (or the one parked out front) and press **E** to get behind the wheel. **W** is the gas, **S** brakes and then reverses, **A** and **D** steer, **Space** brakes and **H** honks. Take it out of the garage, round the lots and along the street either way. Columns, lamp posts, trees and the other cars stop you, and anyone standing in your way gets knocked aside. Everyone on your floor sees the car go by with you in it (the roof comes off, so they can see who's driving), and hears its engine and horn. Press **E** at a car someone else is driving to ride along beside them. **E** gets you out, and the car stays parked wherever you leave it until the office restarts, when every car goes back to its spot. Like the people you see, the cars are your floor's own: the garage under another floor has its cars where people on that floor left them.
- **A tower that grows with your projects.** Every floor is a storey of the same building, so from outside it's as tall as you have projects: add enough of them and it's a skyscraper, a balcony off every floor, windows lit here and there at night and a cornice round the top. Up on a higher floor the street is that many storeys further down. Only the bottom floor has the EXIT door and the stairs down; the floors above it have wall there, so take the elevator down to the garage to leave.
- **Day and night, and weather.** Outside the windows it's the office's own time of day: the sun comes up and goes down with the clock of the machine running it, and at night the street lamps, the balcony's string lights and the windows across the street come on while the office lights warm up. The weather comes and goes by itself (sun, clouds, rain, thunderstorms, fog, and snow in winter), with raindrops on the glass, wet streets and snow settling outside. Start the office with `--city Berlin` and the sky follows that city's sunrise, sunset and live forecast instead. Everyone sees the same sky, and **⚙️** shows what it's doing.
- **Maps: the office, a castle, or your own.** Under **⚙️** → *Map*, anyone can turn the whole building into another place, for everyone on every floor, and back. The **🏰 Castle** is a great hall with a throne of iron blades at the end: you sit on it, the workers at the long tables down either side get up and line up before you when they're done or need you, and the Hand of the King at your left sends a new one running off to a free seat when you speak to him. Workers there dress as peasants and wear out as they toil, growing long grey beards, getting grubby and stooping, fully after 30 minutes of work. The boards hang on the hall's walls with a scribe at each, and the workers, queue, meetings and PRs all work as in the office. A map is plain JSON, so you can move things about or make your own without touching the code: see [Maps](maps.md).
- **Halloween and Christmas.** Under **⚙️** → *Holiday theme*, anyone can dress the whole building up, for everyone on every floor. For Halloween the workers turn into shambling zombies with stitched grins and bandages, your first-person hands become an undead warlock's, bony and clawed with green witch-fire curling round them, everyone wears a crooked warlock's hat, and the dog gets bat wings and a witch's hat. The sky goes creepy, purple overhead and blood orange at the horizon, with a big harvest moon, bats crossing it and circling the building, and the odd far-off flash. Jack-o'-lanterns glow everywhere: on every desk, the window sills, the counter, the balcony rail and down the street, with gravestones on the lawn and cobwebs in the corners. For Christmas the workers are elves, your hands are in mittens, everyone wears a Santa hat, the dog is Rudolph, the potted plants turn into little decorated trees with presents under them, and it snows outside, onto a big lit tree and a few snowmen out front. *By the calendar* (the default) puts up Halloween through October and Christmas through December, by the office's clock.
- **Smoke breaks.** Glass doors on the south wall slide open onto a balcony with string lights, a bench and a bistro table. Press **E** at the ashtray to light up. Everyone sees you puffing away until you stub it out or step back inside.
- **Golf off the balcony.** Next to the ashtray there's a tee: a square of turf, a ball on a tee and a bag of clubs. Across the street, where the neighbours leave a gap, a fairway runs up to a green with a flag on it, 43 m out and a storey down (further down from the floors above). Press **E** at the tee to step up with a club. The camera drops down behind the ball. The mouse or **A**/**D** aims, **W**/**S** set the loft (too flat and it hits the railing), and holding **Space** takes the club back while the power meter runs up and down: let go to hit. The camera follows the ball out and down, and a label says where it stopped and how far from the pin. Everyone on your floor sees you swing and your ball fly, landing in the same spot. Hole one and the green goes up in confetti. Your closest shot and your holes in one are kept in your browser. **E** puts the club back.
Expand Down
1 change: 1 addition & 0 deletions docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ browser ──HTTPS/WSS──▶ agent-office (Node)
- **Shared terminals.** Each worker's PTY lives in `agent-office-ptys` (`src/server/ptyhost.ts`), a detached process the server starts for each floor and talks to over a Unix socket in that project's `.agent-office/`. On SIGTERM the server leaves the PTYs running there, and the next server takes them back with a snapshot of each screen. Hooks that fire in between retry until it's up. If no server comes back within 30 minutes, the PTYs are ended. The server mirrors each PTY in a headless xterm. People who open the terminal get a serialized snapshot, then the live stream. Laptops get compact per-row diffs a few times a second. The PTY takes the size of whoever is typing.
- **Scrollback and search.** Every 15 seconds, for each worker that printed something new, and again as the office shuts down, its last 3,000 lines are serialized, colors included, to `.agent-office/scrollback/<worker>.ansi`. A worker that starts again (after a restart, or when you resume it) gets its old lines replayed into its terminal first, then a dim *office restarted* line. The chat is appended to `.agent-office/chat.jsonl` and trimmed to the last 1,000 messages. `GET /api/search?q=` matches case-insensitively, treating runs of whitespace as one space, over the chat and each worker's terminal buffer. It returns the newest lines first, each distinct line once. The browser finds the hit again in its own copy of the terminal and scrolls to it.
- **Cost.** Hooks carry no usage, but each one names the session's transcript (`~/.claude/projects/<dir>/<session>.jsonl`). The office reads what gets appended to it, and to the subagent transcripts next to it: every assistant message records the API's token usage and the model, which the office prices from its own table (cache writes and reads included). When a session ends, Claude Code appends its own tally (`cost-state`), and the worker's numbers snap to that, which also covers calls that never reach the transcript. Per-worker totals are saved with the worker, and `.agent-office/usage.json` keeps the office's all-time and per-day spend, so nothing is lost on a restart or when a worker is sent home. On an office deployed with `deploy/aws.sh`, put `AGENT_OFFICE_BUDGET=20` (and `AGENT_OFFICE_BUDGET_PAUSE=1`) in `/etc/agent-office/env` and restart the service.
- **Maps.** A map other than the office is data (`MapConfig`, [`src/shared/maps/`](../src/shared/maps)): the server and every browser work out the same plan from it, with every seat the office has, by the same ids, placed at its tables, so workers, the queue and meetings never notice which map they're on. The server keeps the building's pick (`src/server/maps.ts`, saved in `.agent-office/map.json`) and reads maps of your own from `.agent-office/maps/` when someone joins or opens Settings, sending each one's whole config (what it `extends` filled in) or why it won't load. A browser builds the world for it by its style (`src/client/world/castle.ts`) and swaps it in for the office the way it does the rooftop. Whether a worker is waiting on you is the office's own (done and not yet seen to, or needs input), so the castle's line is worked out in each browser, in the order N goes; how worn out a worker looks comes from `workedMs` and `workingSince`, which the office keeps for every worker.
- **Holiday themes.** The server keeps the building's pick (`src/server/theme.ts`, saved in `.agent-office/theme.json`) and, for *By the calendar*, works out the holiday from the office's clock, checking again every ten minutes. Each browser then dresses its own scene: the costumes are in `src/client/world/costumes.ts`, the decorations in `src/client/world/holiday.ts`, and Halloween's sky and Christmas's snow in `src/client/world/sky.ts`.
- **Sky.** The server decides the weather and tells everyone (`src/server/sky.ts`), and each browser works out where the sun is from that and its own clock. Without `--city`, the office sits in the middle of the host's time zone at 40° north (34° south if its clocks go forward in January), and the weather changes every 20 to 50 minutes, with the season's odds. With `--city` (a name, or `lat,lon`), it asks open-meteo.com for the place once and for its current weather every 15 minutes; no key is needed, and nothing but the city's name and coordinates is sent. The office has no roof, so the sun and the sky light the rooms too. At night a few lines added to every lit material put lamplight back in the office and the garage, and pools of light around the lamps outside (`src/client/world/sky.ts`). A server on AWS keeps UTC, so on an office deployed with `deploy/aws.sh`, put `AGENT_OFFICE_CITY="Portland, Oregon"` in `/etc/agent-office/env` and restart the service.
- **Services.** Every 4 seconds the office lists the TCP ports its user's processes listen on (`ss`, or `lsof` on macOS). It credits each port to the worker whose terminal started it. It goes by the process tree first. For a server that detached from it, it uses the `AGENT_OFFICE_WORKER_ID` the process inherited (Linux), then whether it runs inside that worker's worktree. Ports that answer HTTP are shown. A request for `localhost:<port>` that reaches the office's own port (that's what a service tunnel does) is relayed to that server, WebSockets included, so hot reload works. On a Tailscale office (`AGENT_OFFICE_TAILSCALE_HOST`, set by `deploy/provision.sh --tailscale`), a request for `<office>.ts.net:<port>` is relayed the same way, with `localhost:<port>` as its Host so dev servers that check it let it in. Whenever the list changes, the office has Tailscale Serve point exactly those ports at itself, through the `agent-office-serve` helper (`src/server/tailnet.ts`).
Expand Down
Loading
Loading