Skip to content
Closed
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ curl -fsSL https://raw.githubusercontent.com/AgentSystemLabs/agent-office/main/i
- **From your phone, too.** `/lite` is the office in 2D: every worker and what it's waiting on, its terminal with the keys a phone keyboard lacks, and the boards. The 3D office offers it on a phone or a slow computer.
- **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 (if one gets deleted behind the office's back, the worker waits at its desk until you rebuild it). One task can span several projects: the worker gets a worktree of each, and a PR in each that links the others.
- **Agents that manage agents.** Every worker can list, hire, message and send home the others, through an `agent-office` MCP server (Claude Code, Codex, OpenCode) or the `office-workers` command. Ask one to "send everyone whose PR merged home" and it does, deleting their worktrees and branches unless they hold unpushed work. A worker that opens its pull request itself (`gh pr create`) shows it at its desk, and one the office missed can be told which is its own (`office-workers pr`).
- **Together.** Voice, chat, screen sharing on the lounge TV and a shared whiteboard.
- **Together.** Voice, chat, screen sharing on the lounge TV with a 30 FPS capture request, 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. Send one home and the Kingsguard runs up from the dungeon, marches it down the stairs and throws it in a cell, where it starves, dies and rots down to a skeleton. Or into a space station in orbit, the Earth turning outside its windows: you run it from the captain's chair on the bridge, and a worker sent home is marched to the airlock and blown out into space, to drift off past the observation windows with everyone who went before it. Or make a map of your own, with its own way of seeing workers off in JSON ([docs/maps.md](docs/maps.md)).

Expand Down
2 changes: 1 addition & 1 deletion docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ Everything in the office, room by room. Back to the [README](../README.md).
- **The rooftop bar.** The elevator goes up to the roof, over every floor. A DJ plays drum and bass on a stage under a rig of moving lights and lasers, with an LED wall behind and a dance floor lighting up in front, all flashing in time with the music. The Sky Bar is under a pergola hung with string lights, there's a lounge round a fire pit, and sun loungers look out over the street. The city goes on all around, and its windows, street lamps and traffic light up at night. Press **E** at the bar (or sitting on a stool at it) for a drink: a beer, wine, a cocktail or a shot goes to your head for a minute or so, and the view sways, doubles and smears while you stagger a little. The more you have, the worse it gets, until the bartender pours you a water. Everyone up there sees the glass in your hand and hears the same bar of music. Press **E** at the DJ booth to blow the air horn for all of them.
- **Darts and axe throwing.** In the rooftop bar's north-west corner, past the DJ, there's a wooden axe-throwing booth with a target on its back wall, and a dart board in a cabinet on the outside of it. Walk up to either and press **E** to step up to the line: the camera looks over your shoulder at the target. Move the mouse (or use the arrow keys) to aim; your hand wanders a little, and more after a few drinks from the bar. Hold **Space** (or the mouse button) to draw back while a meter runs up and down, and let go in its green: a dart flies true, too soft and it drops, too hard and it sails high. An axe let go in the green turns over just right and sticks; off it, it comes in handle first, bounces off and clanks onto the mat. A visit is three darts (180 is the most) and an axe round five throws, scored 1 to 4 in the rings, 6 for the bullseye and 8 for either blue killshot dot. Everyone up there sees you throw, the darts and axes stuck in the target, and your round chalked up on the board beside it. Your best round at each is kept in your browser. **E** steps back from the line.
- **Jukebox.** A jukebox glows in the corner of the lounge. Walk up and press **E** to put on one of its four lo-fi tunes, skip to the next, turn it off, or paste a link to internet radio or an audio file. Everyone on the floor hears the same song from the same bar, coming from the jukebox: loud on the couch, faint at the desks. The tunes are synthesized in the browser like the office sounds, and it keeps playing when you switch tabs. The jukebox has its own volume under **⚙️**, just for you.
- **Screen sharing.** Your screen appears on the lounge TV for everyone, and there's a full-screen viewer.
- **Screen sharing.** Your screen appears on the lounge TV for everyone, and there's a full-screen viewer. The browser is asked to capture at 30 frames per second; the actual rate depends on the shared content and the browser.
- **An account for everyone.** Open **🔑 Accounts** from the **☰** menu and make an invite link. Whoever opens it picks a password and gets an account in their own name. That name is the one on their character, in chat and on every terminal they type into (**⌨️** in the terminal header shows who typed last), and nobody else can take it. Admins see everyone's accounts there, can make someone an admin, and can revoke an account, which signs that person out at once. The shared office password keeps working alongside the accounts until an admin switches it off. Sessions are signed cookies, and login attempts are rate limited.
- **Your own Claude and GitHub.** With an account, the workers you hire run on your own Claude plan, and the office acts on GitHub as you: comments, merges, labels, claimed issues, commits, pushes and pull requests show up under your name, with your git name and GitHub noreply email. The first time you come in, **🔐 Your sign-ins** opens (it's in the **☰** menu too). **Sign in with Claude** gives you Claude's sign-in page and takes back the code it shows; **Sign in with GitHub** shows a one-time code for github.com/login/device. Or paste a token from `claude setup-token` (or an API key), or a GitHub token. A 🐚 shell you open at a desk runs as you, so `claude auth login` and `gh auth login` typed there sign you in too. Hiring a Claude worker, queueing a task, calling a meeting or asking a board agent needs your own Claude sign-in first; without one, the window opens and says why. A worker keeps running as whoever hired it: a queued task as whoever queued it, a meeting's workers as whoever called it. Admins can pick the office machine's own sign-ins instead. Everyone's sign-ins are kept apart, so any number of people can be signed in to different accounts at once. Revoking an account signs it out and deletes its sign-ins. On the office password, with no account, everything runs on the machine's own `claude` and `gh` as before.
2 changes: 1 addition & 1 deletion src/client/voice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export class Voice {
if (this.screen) return null;
if (!window.isSecureContext || !navigator.mediaDevices?.getDisplayMedia) return 'Screen sharing needs HTTPS (or localhost).';
try {
this.screen = await navigator.mediaDevices.getDisplayMedia({ video: { frameRate: 15 }, audio: false });
this.screen = await navigator.mediaDevices.getDisplayMedia({ video: { frameRate: 30 }, audio: false });
} catch (err) {
return (err as Error).name === 'NotAllowedError' ? null : `Could not share: ${(err as Error).message}`;
}
Expand Down