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.
- package/CHANGELOG.md +57 -0
- package/LICENSE +21 -0
- package/README.md +85 -2
- package/bin/agentoffice.js +38 -0
- package/dist/apple-touch-icon.png +0 -0
- package/dist/assets/_commonjsHelpers-CqkleIqs.js +1 -0
- package/dist/assets/addon-fit-BwprjgOP.js +1 -0
- package/dist/assets/index-CozPk6R9.js +4457 -0
- package/dist/assets/index-i7sU9SN-.css +32 -0
- package/dist/assets/inter-cyrillic-ext-wght-normal-B2xhLi22.woff2 +0 -0
- package/dist/assets/inter-cyrillic-wght-normal-CMZtQduZ.woff2 +0 -0
- package/dist/assets/inter-greek-ext-wght-normal-CGAr0uHJ.woff2 +0 -0
- package/dist/assets/inter-greek-wght-normal-CaVNZxsx.woff2 +0 -0
- package/dist/assets/inter-latin-ext-wght-normal-CFHvXkgd.woff2 +0 -0
- package/dist/assets/inter-latin-wght-normal-C2S99t-D.woff2 +0 -0
- package/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-400-normal-CIEtRijs.woff +0 -0
- package/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/assets/jetbrains-mono-greek-400-normal-CNojz0t3.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-400-normal-B11XCQ5g.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-400-normal-DHMOLxAi.woff +0 -0
- package/dist/assets/jetbrains-mono-vietnamese-400-normal-BeU3T8wf.woff +0 -0
- package/dist/assets/xterm-C7kOH91j.js +9 -0
- package/dist/icon-192.png +0 -0
- package/dist/icon-512.png +0 -0
- package/dist/icon.svg +9 -0
- package/dist/index.html +240 -0
- package/dist/manifest.webmanifest +16 -0
- package/dist/sw.js +39 -0
- package/docs/README.md +26 -0
- package/docs/claude-access.md +31 -0
- package/docs/configuration.md +53 -0
- package/docs/development.md +76 -0
- package/docs/getting-started.md +54 -0
- package/docs/guides/troubleshooting.md +99 -0
- package/docs/guides/updating.md +36 -0
- package/docs/guides/working-with-the-team.md +56 -0
- package/docs/guides/your-first-job.md +65 -0
- package/docs/how-it-works.md +80 -0
- package/docs/images/office.jpg +0 -0
- package/docs/jobs.md +54 -0
- package/docs/leaderboard.md +65 -0
- package/docs/packaging.md +49 -0
- package/docs/phone.md +28 -0
- package/docs/security.md +48 -0
- package/docs/terminal.md +46 -0
- package/docs/using-the-office.md +109 -0
- package/docs/voice.md +44 -0
- package/package.json +64 -4
- package/server/auth.js +89 -0
- package/server/banter.js +53 -0
- package/server/changes.js +72 -0
- package/server/chief.js +130 -0
- package/server/index.js +1952 -0
- package/server/leaderboard.js +190 -0
- package/server/office-mcp.js +101 -0
- package/server/procstat.js +85 -0
- package/server/standup.js +78 -0
- package/server/supervise.js +51 -0
- package/server/terminal.js +255 -0
- package/server/tools.js +52 -0
- package/server/usage.js +40 -0
- package/server/voice.js +172 -0
- 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).
|
package/docs/security.md
ADDED
|
@@ -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).
|
package/docs/terminal.md
ADDED
|
@@ -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`.
|