agent-office-studio 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/LICENSE +21 -0
  3. package/README.md +85 -2
  4. package/bin/agentoffice.js +38 -0
  5. package/dist/apple-touch-icon.png +0 -0
  6. package/dist/assets/_commonjsHelpers-CqkleIqs.js +1 -0
  7. package/dist/assets/addon-fit-BwprjgOP.js +1 -0
  8. package/dist/assets/index-CozPk6R9.js +4457 -0
  9. package/dist/assets/index-i7sU9SN-.css +32 -0
  10. package/dist/assets/inter-cyrillic-ext-wght-normal-B2xhLi22.woff2 +0 -0
  11. package/dist/assets/inter-cyrillic-wght-normal-CMZtQduZ.woff2 +0 -0
  12. package/dist/assets/inter-greek-ext-wght-normal-CGAr0uHJ.woff2 +0 -0
  13. package/dist/assets/inter-greek-wght-normal-CaVNZxsx.woff2 +0 -0
  14. package/dist/assets/inter-latin-ext-wght-normal-CFHvXkgd.woff2 +0 -0
  15. package/dist/assets/inter-latin-wght-normal-C2S99t-D.woff2 +0 -0
  16. package/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  17. package/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  18. package/dist/assets/jetbrains-mono-cyrillic-400-normal-CIEtRijs.woff +0 -0
  19. package/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  20. package/dist/assets/jetbrains-mono-greek-400-normal-CNojz0t3.woff +0 -0
  21. package/dist/assets/jetbrains-mono-latin-400-normal-B11XCQ5g.woff +0 -0
  22. package/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  23. package/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  24. package/dist/assets/jetbrains-mono-latin-ext-400-normal-DHMOLxAi.woff +0 -0
  25. package/dist/assets/jetbrains-mono-vietnamese-400-normal-BeU3T8wf.woff +0 -0
  26. package/dist/assets/xterm-C7kOH91j.js +9 -0
  27. package/dist/icon-192.png +0 -0
  28. package/dist/icon-512.png +0 -0
  29. package/dist/icon.svg +9 -0
  30. package/dist/index.html +240 -0
  31. package/dist/manifest.webmanifest +16 -0
  32. package/dist/sw.js +39 -0
  33. package/docs/README.md +26 -0
  34. package/docs/claude-access.md +31 -0
  35. package/docs/configuration.md +53 -0
  36. package/docs/development.md +76 -0
  37. package/docs/getting-started.md +54 -0
  38. package/docs/guides/troubleshooting.md +99 -0
  39. package/docs/guides/updating.md +36 -0
  40. package/docs/guides/working-with-the-team.md +56 -0
  41. package/docs/guides/your-first-job.md +65 -0
  42. package/docs/how-it-works.md +80 -0
  43. package/docs/images/office.jpg +0 -0
  44. package/docs/jobs.md +54 -0
  45. package/docs/leaderboard.md +65 -0
  46. package/docs/packaging.md +49 -0
  47. package/docs/phone.md +28 -0
  48. package/docs/security.md +48 -0
  49. package/docs/terminal.md +46 -0
  50. package/docs/using-the-office.md +109 -0
  51. package/docs/voice.md +44 -0
  52. package/package.json +64 -4
  53. package/server/auth.js +89 -0
  54. package/server/banter.js +53 -0
  55. package/server/changes.js +72 -0
  56. package/server/chief.js +130 -0
  57. package/server/index.js +1952 -0
  58. package/server/leaderboard.js +190 -0
  59. package/server/office-mcp.js +101 -0
  60. package/server/procstat.js +85 -0
  61. package/server/standup.js +78 -0
  62. package/server/supervise.js +51 -0
  63. package/server/terminal.js +255 -0
  64. package/server/tools.js +52 -0
  65. package/server/usage.js +40 -0
  66. package/server/voice.js +172 -0
  67. package/shared/speakable.js +50 -0
@@ -0,0 +1,99 @@
1
+ # Troubleshooting
2
+
3
+ Find the message you're seeing, or the symptom.
4
+
5
+ ## The office won't start
6
+
7
+ **`Error: listen EADDRINUSE: address already in use 127.0.0.1:4317`**
8
+ Something is already on that port — usually another office. Find it with
9
+ `lsof -i :4317`, or start this one elsewhere: `PORT=4400 npm start`.
10
+
11
+ **The page says "No build yet."**
12
+ The server is running but `dist/` is empty. Run `npm run build`, or use
13
+ `npm start`, which builds first.
14
+
15
+ **The page loads but the office is blank.**
16
+ Open the browser console. The office needs WebGL; if it's disabled (some
17
+ remote desktops and VMs), the 3D view can't draw.
18
+
19
+ ## Jobs don't run
20
+
21
+ **A job fails with "Could not start claude: spawn claude ENOENT".**
22
+ Claude Code isn't on the `PATH` the office was started with. Check
23
+ `which claude` in the same terminal. If it lives somewhere unusual, point the
24
+ office at it: `CLAUDE_BIN=/path/to/claude npm start`.
25
+
26
+ **Jobs fail straight away with an authentication error.**
27
+ On the **Claude Code login**: run `claude` in a terminal and sign in, then
28
+ retry. On an **API key**: open the key button beside Appearance and check
29
+ which key is in use; paste a new one if it was revoked.
30
+
31
+ **"That project folder is gone."**
32
+ The project was moved or renamed after the job was created. Projects are the
33
+ folders directly inside `OFFICE_ROOT`; see
34
+ [Getting started](../getting-started.md#where-your-projects-are).
35
+
36
+ **A project doesn't show up.**
37
+ It must be a folder directly inside `OFFICE_ROOT` — not nested deeper. The
38
+ server prints `OFFICE_ROOT` when it starts: *"projects in …"*.
39
+
40
+ **A job keeps getting blocked.**
41
+ Its clearance doesn't allow what it's trying to do — *Edit files* refuses
42
+ shell commands. Grant more from the job's drawer, or give the next job
43
+ *Full autonomy* if it needs to run tests or builds.
44
+
45
+ **No "What changed" card.**
46
+ The project isn't a git repository. Run `git init` in it.
47
+
48
+ ## The plan meters
49
+
50
+ **"Sign in to Claude Code to see usage."**
51
+ No Claude Code login was found on this machine. Run `claude` and sign in.
52
+
53
+ **"Claude Code login expired."**
54
+ Run `claude` once; it refreshes the login.
55
+
56
+ **"Usage unavailable (429)."**
57
+ The usage endpoint is rate-limiting. The office backs off and tries again on
58
+ its own; jobs aren't affected.
59
+
60
+ **The meters are gone.**
61
+ Claude access is set to *API key*. There's no plan to measure; usage is in
62
+ your Anthropic Console.
63
+
64
+ ## Voice
65
+
66
+ **The microphone does nothing, or "No speech model installed."**
67
+ Install the listening side: `brew install ffmpeg whisper-cpp`, then
68
+ `npm run voice:model`. See [Talking out loud](../voice.md).
69
+
70
+ **"Piper is not installed" or "Piper has no voices downloaded."**
71
+ Run `npm run voice:piper` (needs Python 3). Until then, replies use the
72
+ browser's built-in voices.
73
+
74
+ **The browser won't allow the microphone.**
75
+ Browsers only allow it on `localhost` or HTTPS. Open the office at
76
+ `http://localhost:4317`, not an IP address.
77
+
78
+ ## The terminal won't open
79
+
80
+ **There's no terminal button, or it says the terminal is off.**
81
+ It's off by default. Start the office with `OFFICE_TERMINAL=1 npm start`.
82
+
83
+ **"node-pty is not installed."**
84
+ It's a native module and needs build tools. On macOS:
85
+ `xcode-select --install`, then `npm install`. On Linux: install
86
+ `build-essential` and `python3`, then `npm install`.
87
+
88
+ ## On a phone
89
+
90
+ **"Local only." (HTTP 403)**
91
+ The office only accepts its own hostnames. Add the one you're using:
92
+ `OFFICE_ALLOWED_HOSTS=my-mac.tail1234.ts.net npm start`. See
93
+ [On your phone](../phone.md).
94
+
95
+ ## Still stuck?
96
+
97
+ Search the [issues](https://github.com/onuohasilver/agent-office/issues), or
98
+ open one with the server output and the browser console. Please remove keys,
99
+ tokens and private paths first.
@@ -0,0 +1,36 @@
1
+ # Updating
2
+
3
+ Your office's state — jobs, chat, channels, XP, team profiles, Claude access —
4
+ lives in `data/`, which updates never touch.
5
+
6
+ ## From a git clone
7
+
8
+ ```bash
9
+ cd agent-office
10
+ git pull
11
+ npm install
12
+ npm run build
13
+ ```
14
+
15
+ Then stop the office (Ctrl-C in its terminal) and start it again with
16
+ `npm start`. Running jobs are stopped cleanly and resume when it comes back.
17
+
18
+ Read [CHANGELOG.md](../../CHANGELOG.md) for what changed, and anything you
19
+ need to do.
20
+
21
+ ## Pinning a version
22
+
23
+ To stay on a release rather than the latest code:
24
+
25
+ ```bash
26
+ git fetch --tags
27
+ git checkout v0.1.0
28
+ npm install && npm run build
29
+ ```
30
+
31
+ ## If something breaks
32
+
33
+ - `npm install` failing on `node-pty` is harmless: it's optional, and only
34
+ the terminal needs it. See [Troubleshooting](troubleshooting.md#the-terminal-wont-open).
35
+ - To keep a way back, copy `data/` before updating. Going back is then: stop
36
+ the office, check out the previous tag, restore `data/`, build and start.
@@ -0,0 +1,56 @@
1
+ # Working with the team
2
+
3
+ Habits that get better work out of the office for less.
4
+
5
+ ## Write briefs like you would for a colleague
6
+
7
+ The agent starts knowing nothing but the project folder and what you wrote.
8
+
9
+ - **Say what done looks like.** *"Make the tests pass"* is clearer than
10
+ *"look at the tests"*.
11
+ - **Point at the place.** A file, a route, an error message. Paste the error
12
+ or drop a screenshot on the composer — the chief can read screenshots.
13
+ - **Say what not to touch** if it matters: *"don't change the public API"*.
14
+ - **One job, one outcome.** Three unrelated fixes are three jobs; they can run
15
+ at the same time with three agents.
16
+
17
+ ## Pick the clearance for the job, not the agent
18
+
19
+ | Job | Clearance |
20
+ |---|---|
21
+ | "How does X work?", "plan the migration" | **Plan only** — nothing changes |
22
+ | Most code changes | **Edit files** — no commands |
23
+ | Needs tests, builds, git, installs | **Full autonomy** |
24
+
25
+ You don't have to guess right. An *Edit files* job that needs a command stops
26
+ and asks, and you can grant it then. A *Plan only* job ends with a plan you
27
+ can approve and have built.
28
+
29
+ ## Let the chief pick the model
30
+
31
+ **Chief picks** sends small mechanical work to Haiku, ordinary work to Sonnet
32
+ and hard work to Opus, and steps up a rung on its own when a job fails.
33
+ Choose a model yourself only when you know better — and then it won't change.
34
+
35
+ ## Use channels for strands of work
36
+
37
+ Everything said in a channel stays in it, and the chief only reads that
38
+ channel's history when working out what you mean. A `#billing` channel for a
39
+ week of billing work keeps the context tight and the chief's answers sharp.
40
+
41
+ ## Follow up in the thread
42
+
43
+ Replying in a job's thread resumes the same agent's session, so they keep
44
+ everything they already read. A new message in the main chat may go to
45
+ someone else, who starts from scratch.
46
+
47
+ ## Keep an eye on cost
48
+
49
+ - The bar at the top shows what's working, queued, shipped and spent.
50
+ - On the Claude Code login, the **Session** and **Week** meters show how much
51
+ of your plan is used. They turn amber at 70% and red at 90%.
52
+ - Each job's drawer shows its model and how much context its last turn
53
+ carried. A long-running session gets expensive; a fresh job with a good
54
+ brief is often cheaper than one more follow-up.
55
+ - Break-room talk uses a small model at most once every two minutes. Turn it
56
+ off with `BANTER=off` if you'd rather it didn't.
@@ -0,0 +1,65 @@
1
+ # Your first job
2
+
3
+ Ten minutes from a fresh install to a change you've reviewed. This assumes
4
+ the office is running — if not, start with [Getting started](../getting-started.md).
5
+
6
+ ## 1. Pick something small
7
+
8
+ The first job should be easy to check by eye: fix a typo, add a test case,
9
+ rename something, tidy a README. You'll learn how the office works without
10
+ wondering whether the agent got something subtle right.
11
+
12
+ ## 2. Check the pickers under the composer
13
+
14
+ - **Clearance** — leave it on **Edit files**. The agent can read and change
15
+ files but not run commands, which is the right amount of trust for a first
16
+ job. ([What each one allows](../jobs.md#clearance).)
17
+ - **Model** — leave it on **Chief picks**. A small job will go to Haiku or
18
+ Sonnet.
19
+
20
+ ## 3. Ask
21
+
22
+ In `#general`, tag a project with `#` and say what you want, as you'd say it
23
+ to a colleague:
24
+
25
+ ```
26
+ #storefront the checkout button says "Procede" — fix the spelling
27
+ ```
28
+
29
+ You can tag someone with `@` too (`@Ada #storefront …`). Without a tag, the
30
+ chief of staff picks whoever is free and replies with who and why.
31
+
32
+ ## 4. Watch
33
+
34
+ The agent gets up and goes to work. Where they walk tells you what they're
35
+ doing: the **library** to read code, their **desk** to write, the **server
36
+ room** to run commands, the **whiteboard** to plan. Their updates collect in a
37
+ thread under your message; open it, or click the agent, to follow along.
38
+
39
+ ## 5. Review what changed
40
+
41
+ When they're done, the result lands in the chat with a chime. Open the job
42
+ (the **Jobs** tab, or the link in the reply) and look at **What changed**:
43
+ every file the job touched, with lines added and removed. Click a file to see
44
+ its patch.
45
+
46
+ The change is in your working tree, not committed. Review it the way you
47
+ would any change — `git diff`, your editor, your tests — and commit it
48
+ yourself when you're happy.
49
+
50
+ ## 6. Follow up
51
+
52
+ Not quite right? Reply in the job's thread: *"also fix it on the receipt
53
+ page"*. The same agent picks it up in the same session, with everything they
54
+ learned the first time. If the chief chose the model and the work was wrong,
55
+ saying so sends it back one model up.
56
+
57
+ If the agent got **blocked** — it tried to run a command its clearance
58
+ doesn't allow — the job's drawer shows what was refused, with a button to
59
+ grant more and carry on.
60
+
61
+ ## Next
62
+
63
+ - [Working with the team](working-with-the-team.md) — briefs that work,
64
+ channels, and keeping costs down.
65
+ - [Jobs](../jobs.md) — clearance, models and what changed in detail.
@@ -0,0 +1,80 @@
1
+ # How the office works
2
+
3
+ ## Jobs are `claude` processes
4
+
5
+ Every job is one headless `claude` process whose stdin stays open, so new
6
+ messages can reach it mid-task. What they do on screen is
7
+ driven by the tool calls in its stream:
8
+
9
+ | Work | Where they go |
10
+ |---|---|
11
+ | Read, Grep, Glob | Library |
12
+ | Bash | Server room |
13
+ | WebSearch, WebFetch, MCP tools | Research window |
14
+ | Plans, todos, sub-agents | Whiteboard |
15
+ | Edits and writing | Their desk |
16
+
17
+ The server (`server/index.js`) keeps the office state, routes chat through the
18
+ chief of staff, starts and supervises those processes, and pushes everything
19
+ to the browser over one websocket. The browser draws the office with three.js
20
+ and moves each agent to wherever their latest tool call says they are.
21
+
22
+ The chief of staff, standup and break-room talk are short `claude -p` calls
23
+ too, with no tools, a JSON schema for the answer and no session kept.
24
+
25
+ ## Agents talk to each other
26
+
27
+ Every agent gets three office tools (a small MCP server, `server/office-mcp.js`):
28
+
29
+ - `office_roster`: who's around and what they're on.
30
+ - `message_colleague`: reaches a working colleague mid-task. With
31
+ `wait_for_reply`, the sender's session pauses until the answer comes (10
32
+ minute limit).
33
+ - `hand_off`: gives work in any project to a free colleague. Their result goes
34
+ back to the sender, who waits for it by default.
35
+
36
+ Hand-offs only go to someone free right now, so two agents can never wait on
37
+ each other. A job can be handed down at most twice. The sender walks over to
38
+ the colleague, and the exchange shows in the chat as "Ada → Tunde".
39
+
40
+ When someone ships you hear a chime, and if the tab is in the background you
41
+ get a desktop notification. The speaker in the top right mutes it.
42
+
43
+ If the server restarts mid-job, jobs with a session resume where they left off.
44
+
45
+ ## Where things are kept
46
+
47
+ | Path | What |
48
+ |---|---|
49
+ | `data/state.json` | jobs, chat, channels, XP, team profiles |
50
+ | `data/activity.json` | per-day jobs, tokens and agent time |
51
+ | `data/leaderboard.json` | leaderboard handle and secret, if you joined (mode 0600) |
52
+ | `data/auth.json` | how Claude is signed in to, and the API key if you gave one (mode `0600`) |
53
+ | `data/uploads/` | attachments and voice notes |
54
+ | `data/whisper/`, `data/piper/` | speech models, if you installed them |
55
+ | `data/terminal.log` | when terminal sessions opened and closed |
56
+
57
+ `data/` is git-ignored. State is written shortly after every change, and the server stops its jobs cleanly on Ctrl-C so they can resume.
58
+
59
+ ## Source layout
60
+
61
+ | Path | What |
62
+ |---|---|
63
+ | `server/index.js` | HTTP + websocket server, jobs, chat, chief, standup, break room |
64
+ | `server/office-mcp.js` | the MCP server that gives agents the office tools |
65
+ | `server/chief.js` | the chief of staff's routing call |
66
+ | `server/standup.js`, `server/banter.js` | standup write-up, break-room small talk |
67
+ | `server/auth.js` | Claude access: login or API key |
68
+ | `server/usage.js` | plan usage meters |
69
+ | `server/leaderboard.js` | the activity ledger and the optional leaderboard |
70
+ | `leaderboard/` | the leaderboard service (a Cloudflare Worker) |
71
+ | `server/changes.js` | the "what changed" snapshots and diffs |
72
+ | `server/voice.js` | whisper.cpp transcription and Piper voices |
73
+ | `server/terminal.js` | the in-app terminal |
74
+ | `server/procstat.js` | agents' CPU and memory |
75
+ | `web/src/main.js` | browser entry: socket, state, wiring |
76
+ | `web/src/office.js`, `figure.js`, `agent.js` | the 3D office and the people in it |
77
+ | `web/src/hud.js` | sidebar, chat, job drawer |
78
+ | `web/src/breakroom.js`, `pool.js`, `pool-sim.js` | break-room talk and eight-ball |
79
+ | `web/public/` | PWA manifest, service worker, icons |
80
+ | `shared/` | code used by both sides |
Binary file
package/docs/jobs.md ADDED
@@ -0,0 +1,54 @@
1
+ # Jobs
2
+
3
+ A job is one piece of work given to one agent in one project folder. You start
4
+ one by asking in the chat; the agent posts its result back there, and the
5
+ job's drawer (click the job, or the agent) shows everything it did.
6
+
7
+ ## Clearance
8
+
9
+ **Clearance** decides what a job may do: *Plan only* changes nothing, *Edit
10
+ files* can edit but shell commands get blocked, *Full autonomy* runs anything.
11
+ When a job gets blocked, its drawer offers to grant clearance and continue the
12
+ same session. A finished plan can be approved and built the same way.
13
+
14
+ ## Sizing the work
15
+
16
+ Most jobs don't need the most capable model, so the chief picks one when the
17
+ model picker is left on **Chief picks**: *Haiku* for small mechanical changes,
18
+ *Sonnet* for ordinary work, *Opus* for genuinely hard work. The rung it chose
19
+ is shown beside its reply in the chat, and in the job's drawer.
20
+
21
+ A job that **fails** on a model the chief picked goes back in the queue one
22
+ rung up — Haiku to Sonnet to Opus — and the chat says so. So does a finished
23
+ job you send back as wrong or incomplete. Escalation stops at Opus, and a job
24
+ that failed before the model ever got a turn (a missing folder, a binary that
25
+ won't start) stays where it is: a dearer model would fail the same way.
26
+
27
+ The retry starts a fresh session carrying the brief and a summary of what the
28
+ last attempt reported, rather than resuming it. The prompt cache belongs to
29
+ the model that filled it, so resuming would have the dearer model read the
30
+ whole failed transcript at full price. A job you picked the model for yourself
31
+ never moves on its own.
32
+
33
+ The drawer shows each job's model and how much context its last turn carried,
34
+ so a session that has grown expensive is visible rather than guessed at.
35
+
36
+ ## What changed
37
+
38
+ When a job starts, the office snapshots the project's working tree; when it
39
+ finishes, it snapshots it again and diffs the two. The drawer shows the result
40
+ as one line — files changed, lines added and removed — that opens into the
41
+ file list, and any file opens into its patch.
42
+
43
+ The snapshots are git tree objects built from a throwaway index, so nothing in
44
+ the repo's own index, stash or history is touched, and untracked files are
45
+ included (ignored ones aren't). A job resumed with a reply keeps its first
46
+ snapshot, so the card covers the whole job. Projects that aren't git
47
+ repositories don't get a card.
48
+
49
+ ## When the server restarts
50
+
51
+ Jobs with a session resume where they left off. A restart asked for from
52
+ inside the office (`/restart`, or an agent's `restart_office`) waits for
53
+ everyone to finish their turn first; see
54
+ [Development](development.md#shipping-a-server-change).
@@ -0,0 +1,65 @@
1
+ # The leaderboard
2
+
3
+ An optional board where offices compare how much they got done. It is off
4
+ until you join, and it needs a leaderboard service somebody hosts (see
5
+ [`leaderboard/`](../leaderboard/README.md)).
6
+
7
+ ## What is ranked
8
+
9
+ Three boards, each for this week (Monday to Sunday, UTC) or all time:
10
+
11
+ - **Jobs**: jobs finished. Failed and stopped jobs don't count.
12
+ - **Tokens**: input plus output tokens your agents used. Cached context is left
13
+ out, since it is the same tokens read again.
14
+ - **Time**: agent time, the time agents spent working on turns, added up. Two
15
+ agents working side by side for an hour is two hours. Waiting on a colleague
16
+ or on you isn't counted.
17
+
18
+ Tokens and time reward using the office more, not doing better work, so treat
19
+ the board as a bit of fun. Counts are reported by each office and can't be
20
+ verified.
21
+
22
+ ## Your own counters
23
+
24
+ The office keeps the day-by-day counters in `data/activity.json` whether or not
25
+ you join, so they survive clearing the job list. They are three numbers per UTC
26
+ day. Nothing leaves your machine until you join.
27
+
28
+ ## Joining
29
+
30
+ 1. Open the trophy button in the sidebar header.
31
+ 2. Pick a handle (3 to 20 letters, numbers, `-` or `_`). Handles are first come,
32
+ first served, and not case-sensitive.
33
+ 3. The office makes a random secret, claims the handle with it, and starts
34
+ sharing.
35
+
36
+ Joining shares the last 14 days of your counters, then each change a minute or
37
+ so after it happens. A day's numbers are set, not added, so a retry never
38
+ counts twice.
39
+
40
+ ## What is shared
41
+
42
+ Per UTC day: jobs finished, tokens, seconds of agent time. Plus the handle.
43
+ That is all: no prompts, project or file names, chat, cost, plan usage, or
44
+ anything that identifies you beyond the handle you picked.
45
+
46
+ The service stores a hash of your secret (never the secret), your handle, and
47
+ those day counters. Boards list handles and totals.
48
+
49
+ ## Leaving
50
+
51
+ "Leave and delete my data" asks the service to delete your handle and counters,
52
+ then forgets the secret here. If the service can't be reached, nothing changes
53
+ and you can try again. Your local `data/activity.json` stays; delete it if you
54
+ want that gone too.
55
+
56
+ ## Setting it up
57
+
58
+ Set the address of your service and restart the office:
59
+
60
+ ```
61
+ OFFICE_LEADERBOARD_URL=https://your-service.example npm start
62
+ ```
63
+
64
+ It must be `https` (plain `http` works only for `localhost`). Without it the
65
+ panel says no leaderboard is set up and nothing is ever sent.
@@ -0,0 +1,49 @@
1
+ # Packaging roadmap
2
+
3
+ How the office gets from "clone the repo" to something people install. This is
4
+ a plan, not shipped work.
5
+
6
+ ## Where it stands
7
+
8
+ The office is a single-user tool that runs locally: one Node server, a web
9
+ build in `dist/`, and the user's own `claude` CLI doing the work. Everyone who
10
+ can use it already has a terminal and Claude Code, which decides the shape of
11
+ the package.
12
+
13
+ ## Options
14
+
15
+ | Option | Fit | Cost | Main problem |
16
+ |---|---|---|---|
17
+ | **npm CLI** (`npx agent-office`) | Best: the audience already has Node and Claude Code | ~1 week | data and project root must move out of the package |
18
+ | **Homebrew tap** | Good extra for Mac users | ~1 day on top of npm | another channel to release to |
19
+ | **Desktop app** (Electron) | Friendlier, but still needs the `claude` CLI | 3–5 weeks | signing and notarisation, auto-update, `node-pty` rebuilds |
20
+ | **Docker** | Poor for a local tool | ~1 week | agents edit *host* repos: bind mounts, file ownership, git/SSH keys, login inside the container |
21
+ | **Hosted** | A different product | months | accounts, a sandbox per user, repos via GitHub, a database, API billing; the local-only security model goes |
22
+
23
+ **Plan:** ship the npm CLI first, with the PWA ([On your phone](phone.md))
24
+ standing in for a desktop window; add Homebrew next; build a desktop app only
25
+ if users ask for one; leave hosted until the local version has users.
26
+
27
+ ## Steps
28
+
29
+ - [x] **Claude access:** users choose the Claude Code login or an API key
30
+ ([Claude access](claude-access.md)).
31
+ - [x] **Licence:** MIT ([`LICENSE`](../LICENSE)).
32
+ - [ ] **npm name:** confirm `agent-office` is free, or pick another.
33
+ - [ ] **Data directory:** `~/.agent-office` (or `$XDG_DATA_HOME`) with an
34
+ `OFFICE_DATA` override, migrating an existing `<app>/data` on first run.
35
+ - [ ] **Project root:** default to the current directory, `--root <dir>`,
36
+ remembered after the first run.
37
+ - [ ] **`bin/agent-office.js`:** `--port`, `--root`, `--open`, `--terminal`;
38
+ pick another port if 4317 is taken; open the browser.
39
+ - [ ] **Preflight:** `claude` on `PATH`, recent enough, and signed in or given a
40
+ key — one clear fix for each problem.
41
+ - [ ] **Package:** publish a prebuilt `dist/`; move the web-only dependencies
42
+ (`three`, `marked`, `xterm`, fonts) to devDependencies so the runtime
43
+ needs only `ws`.
44
+ - [ ] **Terminal:** a `node-pty` build with prebuilt binaries, still optional.
45
+ - [ ] **Voice:** `agent-office voice setup` in place of the two npm scripts.
46
+ - [ ] **Plan meters:** hide quietly if the usage endpoint goes away.
47
+ - [ ] **Platforms:** CI on clean macOS and Ubuntu; Windows via WSL.
48
+ - [ ] **Releases:** on a tag, a smoke test against a stub `claude`, then
49
+ `npm publish --provenance` and a Homebrew bump; a CHANGELOG.
package/docs/phone.md ADDED
@@ -0,0 +1,28 @@
1
+ # On your phone
2
+
3
+ The office is a progressive web app: open it in a phone browser and use
4
+ **Add to Home Screen** (Safari) or **Install app** (Chrome) and it opens
5
+ full-screen with its own icon. The same works on a desktop, in Chrome or Edge,
6
+ for an office in its own window.
7
+
8
+ The app shell is cached so it opens when the connection drops; live office
9
+ state never is, because a stale office is worse than none.
10
+
11
+ ## Reaching your machine
12
+
13
+ The server only listens on `127.0.0.1`, so a phone can't reach it directly.
14
+ The supported way is [Tailscale](https://tailscale.com): put the office behind
15
+ `tailscale serve` on this machine, then tell the office to accept that name.
16
+
17
+ ```bash
18
+ tailscale serve --bg 4317
19
+ OFFICE_ALLOWED_HOSTS=my-mac.tail1234.ts.net npm start
20
+ ```
21
+
22
+ `OFFICE_ALLOWED_HOSTS` takes exact hostnames, comma-separated. Every other
23
+ host and origin is still refused.
24
+
25
+ **Read this first.** Whoever can open that address can run Claude in your
26
+ projects with full autonomy, and — if `OFFICE_TERMINAL=1` — get a shell on
27
+ this machine. Only expose it on a tailnet that is just you. Never put it on
28
+ the open internet. See [Security](security.md).
@@ -0,0 +1,48 @@
1
+ # Security
2
+
3
+ The office starts Claude in your projects, can give it full autonomy, and can
4
+ hand out a shell. It is built to be used by one person, on their own machine.
5
+
6
+ ## Who can reach it
7
+
8
+ - The server listens on `127.0.0.1` only.
9
+ - Every request's `Host` and `Origin` must be local (or a name in
10
+ `OFFICE_ALLOWED_HOSTS`), which keeps other websites and DNS-rebinding
11
+ attacks out of it.
12
+ - Agents call back into the office (the roster, messages, hand-offs) with a
13
+ per-job token that dies with the job.
14
+
15
+ Don't put it behind a public URL. If you reach it from your phone, do it over
16
+ a private network that is only you — see [On your phone](phone.md).
17
+
18
+ ## What jobs may do
19
+
20
+ Each job runs with the clearance you picked — *Plan only*, *Edit files* or
21
+ *Full autonomy* — enforced by Claude Code's own permission modes, and leaves a
22
+ full log in its drawer. Full autonomy means what it says: the agent can run any
23
+ command you could.
24
+
25
+ ## Claude credentials
26
+
27
+ - With the **Claude Code login**, the office never sees your credentials; the
28
+ `claude` it starts reads them. The plan meters read the login's access token
29
+ to ask for usage, and nothing else.
30
+ - With an **API key**, the key is checked with Anthropic, stored in
31
+ `data/auth.json` with mode `0600`, passed only to the `claude` processes the
32
+ office starts, and never sent to the browser, which sees the last four
33
+ characters.
34
+ - `data/` is git-ignored.
35
+
36
+ ## The leaderboard
37
+
38
+ Off until you join, and then the only thing besides Claude that the office
39
+ talks to. It sends a handle and three counters per day (jobs, tokens, agent
40
+ time) to the service named by `OFFICE_LEADERBOARD_URL`, signed with a random
41
+ secret kept in `data/leaderboard.json` (mode `0600`). Never prompts, projects,
42
+ files, chat or cost. Details in [The leaderboard](leaderboard.md).
43
+
44
+ ## The terminal
45
+
46
+ Off unless `OFFICE_TERMINAL=1`. A session needs a single-use ticket from the
47
+ origin-checked API, no agent can open one, and keystrokes are never logged. It
48
+ is not a sandbox. Details in [The terminal](terminal.md).
@@ -0,0 +1,46 @@
1
+ # The terminal
2
+
3
+ There is a real shell in the drawer under the office: `⌃``, or the terminal
4
+ button in the top right. Tabs across the top, `+` opens another, and the picker
5
+ beside it chooses which project folder the next one starts in. Drag the top
6
+ edge to resize — the office makes room rather than hiding behind it. It is a
7
+ proper pty, so `vim`, `top`, `git add -p`, colours and your own prompt all work
8
+ the way they do in a terminal app.
9
+
10
+ It is off until you ask for it:
11
+
12
+ ```bash
13
+ OFFICE_TERMINAL=1 npm start
14
+ ```
15
+
16
+ That switch exists because shell access is the one door in the building that
17
+ doesn't care about clearance. A job runs with the mode you picked and leaves a
18
+ log; a shell is you, with everything you can do, and no record of what it did.
19
+ So:
20
+
21
+ - **Off by default.** No flag, no terminal — the socket won't even open.
22
+ - **This machine's browser only.** The server already refuses any request whose
23
+ host or origin isn't local. On top of that, a session needs a single-use
24
+ ticket that expires in ten seconds, and tickets are only handed out on that
25
+ origin-checked route — the socket accepts nothing else.
26
+ - **Not for the staff.** No agent can open one. There's no office tool and no
27
+ `/api/agent` route that reaches it, and a shell never inherits the job
28
+ credentials the office gives its own children.
29
+ - **Nothing is kept.** Not in `data/state.json`, not in the chat, not on the
30
+ main socket. Scrollback lives in the tab and dies with it. `data/terminal.log`
31
+ records when sessions opened and closed and in which folder — never
32
+ keystrokes, because a log of what you typed into a shell is a file full of
33
+ passwords.
34
+ - **It tidies up.** Closing a tab hangs up the shell, a session with nothing
35
+ happening closes itself after 30 minutes, and there's a cap on how many can
36
+ be open at once.
37
+
38
+ What it is *not* is a sandbox. The shell runs as you and `cd ..` walks out of
39
+ whichever folder it started in; picking the folder is a convenience, not a
40
+ boundary. Leave it off on any machine where "whoever has the browser" isn't
41
+ just you.
42
+
43
+ The terminal needs [`node-pty`](https://github.com/microsoft/node-pty), which
44
+ builds natively — it's an optional dependency, so `npm install` on a machine
45
+ without build tools still gets you the whole office, just without this. On
46
+ macOS: `xcode-select --install`, then `npm install`.