coworking-agents 0.1.0 → 0.2.1
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/README.md +104 -37
- package/ROADMAP.md +26 -0
- package/bin/coworking-agents.js +9 -3
- package/package.json +10 -3
- package/public/art.js +28 -2
- package/public/favicon.ico +0 -0
- package/public/favicon.png +0 -0
- package/public/favicon.svg +1 -0
- package/public/index.html +20 -3
- package/public/js/achievements.js +287 -0
- package/public/js/actors.js +16 -7
- package/public/js/alerts.js +29 -2
- package/public/js/ambient.js +146 -0
- package/public/js/collection.js +162 -0
- package/public/js/floorplan.js +13 -6
- package/public/js/fun.js +181 -0
- package/public/js/help.js +14 -9
- package/public/js/i18n.js +246 -10
- package/public/js/keys.js +6 -2
- package/public/js/life.js +217 -0
- package/public/js/main.js +4 -2
- package/public/js/overlay.js +44 -2
- package/public/js/panel.js +34 -6
- package/public/js/personal.js +145 -0
- package/public/js/player.js +142 -0
- package/public/js/progress.js +37 -0
- package/public/js/replay.js +1 -0
- package/public/js/report.js +51 -6
- package/public/js/rooms.js +279 -0
- package/public/js/scene.js +45 -35
- package/public/js/talk.js +4 -4
- package/public/js/topbar.js +75 -8
- package/public/js/weather.js +1 -0
- package/public/style.css +132 -1
- package/src/collect.js +4 -1
- package/src/demo.js +20 -3
- package/src/focus.js +2 -2
- package/src/git.js +41 -0
- package/src/prices.js +86 -0
- package/src/progress.js +64 -0
- package/src/server.js +21 -3
- package/src/sources/claude.js +22 -2
- package/src/sources/codex.js +27 -2
- package/src/sources/process.js +1 -1
- package/src/update.js +36 -0
- package/src/usage.js +53 -7
- package/src/util.js +1 -1
package/README.md
CHANGED
|
@@ -1,31 +1,37 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="docs/logo.png" width="128" alt="coworking-agents logo">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/ChaconLucas/coworking-agents/main/docs/logo.png" width="128" alt="coworking-agents logo">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">coworking-agents</h1>
|
|
6
6
|
|
|
7
|
-
<p align="center"><b>A live pixel-art office for your AI coding agents.</b><br>Claude Code · Codex · zero dependencies · local only</p>
|
|
7
|
+
<p align="center"><b>A live pixel-art office for your AI coding agents.</b><br>Claude Code · Codex · walk around · trophies · zero dependencies · local only</p>
|
|
8
|
+
|
|
9
|
+
<p align="center"><a href="https://www.npmjs.com/package/coworking-agents"><img src="https://img.shields.io/npm/v/coworking-agents" alt="npm"></a></p>
|
|
8
10
|
|
|
9
11
|
**A live pixel-art office for your AI coding agents.** Every open session (Claude Code, Codex, …) becomes a person at a desk. At a glance you see who is working, who needs you (and what they are asking), whose turn it is, and which sessions are editing the same checkout, even across different AIs.
|
|
10
12
|
|
|
11
|
-

|
|
13
|
+

|
|
12
14
|
|
|
13
|
-

|
|
15
|
+

|
|
14
16
|
|
|
15
17
|
## Tour
|
|
16
18
|
|
|
17
19
|
| | |
|
|
18
20
|
|---|---|
|
|
19
|
-
|  | **Top bar.** One HUD with the counters and the usage meters; the counter below is where agents waiting on you sit (4 per office, **+** slides to the next). |
|
|
20
|
-
|  | **Talk.** Click a waiting agent: it says what it wants at its desk. Reply right there (
|
|
21
|
-
|  | **Camera.** Click an agent and the camera flies in to its desk with a spotlight; the side panel shows everything about the session. |
|
|
22
|
-
|  | **Agent panel.** Now, last request and reply, last-hour timeline, today's numbers, tokens, context, files, subagents, certificates. |
|
|
23
|
-
|  | **Usage report.** Tokens per day for 14 days, all-time totals per AI and per model, rate-limit windows with reset times. |
|
|
24
|
-
|  | **Arrivals and departures.** A new session gets its room boarded up and built (planks, dust, caution tape); a closed one walks out and its desk is demolished. |
|
|
25
|
-
|  | **Top bar.** One HUD with the counters and the usage meters; the counter below is where agents waiting on you sit (4 per office, **+** slides to the next). |
|
|
22
|
+
|  | **Talk.** Click a waiting agent: it says what it wants at its desk. Reply right there (typed into its Terminal/iTerm tab for Claude Code and Codex CLI) or jump to it. |
|
|
23
|
+
|  | **Camera.** Click an agent and the camera flies in to its desk with a spotlight; the side panel shows everything about the session. |
|
|
24
|
+
|  | **Agent panel.** Now, last request and reply, last-hour timeline, today's numbers, tokens, context, files, subagents, certificates. |
|
|
25
|
+
|  | **Usage report.** Tokens per day for 14 days, all-time totals per AI and per model, rate-limit windows with reset times. |
|
|
26
|
+
|  | **Arrivals and departures.** A new session gets its room boarded up and built (planks, dust, caution tape); a closed one walks out and its desk is demolished. |
|
|
27
|
+
|  | **Achievements.** 74 of them, five tiers each, coins for every tier, the agent of the month on top. |
|
|
28
|
+
|  | **The Office Times.** Your week in headlines, written from measured history. |
|
|
29
|
+
|  | **Trophy room.** Glass cabinets with lit shelves, legend trophies in a glass case under spotlights, a crown under a dome for Legend of Legends. Click a trophy for its card. |
|
|
30
|
+
|  | **Holidays.** Lights, snow and Santa hats at Christmas; pumpkins, bats and witch hats at Halloween; flags at Festa Junina. |
|
|
31
|
+
|  | **Building view.** Many agents? Floors, each a live thumbnail. |
|
|
32
|
+
|  | **House wall.** Podium of the most used skills, installed skills, MCP servers and plugins. |
|
|
33
|
+
|  | **Day and night.** Lighting follows your clock; a wall switch turns the ceiling lights on or off; the rest room stays dark. |
|
|
34
|
+
|  | **Phone.** Works on small screens too. |
|
|
29
35
|
|
|
30
36
|
## Why
|
|
31
37
|
|
|
@@ -40,9 +46,10 @@ npx coworking-agents --private # hide names, branches, repos, titles and path
|
|
|
40
46
|
npx coworking-agents --port 5000 # pick a port (default 4777; falls back to a free one if taken)
|
|
41
47
|
npx coworking-agents --no-open # don't open the browser
|
|
42
48
|
npx coworking-agents --json # print one snapshot of the state as JSON and exit
|
|
49
|
+
npx coworking-agents@latest # make sure you run the newest release (npx caches the last one)
|
|
43
50
|
```
|
|
44
51
|
|
|
45
|
-
Requires Node 18+. Zero dependencies.
|
|
52
|
+
Requires Node 18+. Zero dependencies. When a newer release is on npm, the terminal and the office tell you once (`--no-update-check` or `COWORKING_NO_UPDATE_CHECK=1` turns that off).
|
|
46
53
|
|
|
47
54
|
### Access token
|
|
48
55
|
|
|
@@ -78,7 +85,7 @@ Running `npx coworking-agents` a second time reuses the office that is already r
|
|
|
78
85
|
- **Nap corner:** sessions idle for a long time (20+ min) lie down on bean bags.
|
|
79
86
|
- **Floors and Building view.** With many rooms the office gains floors, each with its own shared wing. A floor picker appears at the top, and **Building view** shows every floor as a live thumbnail with counts of who is working and who needs you; click one to go there.
|
|
80
87
|
|
|
81
|
-

|
|
88
|
+

|
|
82
89
|
|
|
83
90
|
## States
|
|
84
91
|
|
|
@@ -99,7 +106,7 @@ Running `npx coworking-agents` a second time reuses the office that is already r
|
|
|
99
106
|
|
|
100
107
|
Click a person for the side panel: repository, branch, worktree, model, context size, turns, recent actions, subagents, most-used tools and certificates.
|
|
101
108
|
|
|
102
|
-

|
|
109
|
+

|
|
103
110
|
|
|
104
111
|
## Help toasts
|
|
105
112
|
|
|
@@ -109,36 +116,76 @@ Each toast has **Show** (switches floor, opens the panel and scrolls to the desk
|
|
|
109
116
|
|
|
110
117
|
Agents away from their desks (kitchen, meeting room, nap corner) carry a name tag over their heads. Optional sound and system notifications can be turned on from the top bar.
|
|
111
118
|
|
|
112
|
-
##
|
|
119
|
+
## Working with your agents
|
|
120
|
+
|
|
121
|
+
- **Talk and reply:** click a waiting agent to read what it wants; type the next instruction and send it straight to its Terminal/iTerm tab (Claude Code, and Codex CLI when its terminal process can be matched), or copy it and jump there. Sessions in the Claude or Codex desktop apps can't be typed into: the button copies and opens the app.
|
|
122
|
+
- **Answer questions:** a single-choice question from Claude Code can be answered by clicking an option.
|
|
123
|
+
- **Compact:** when a Claude session that finished its turn passes 75% of its context window, a **Compact** button shows over it and sends `/compact` to its terminal tab (macOS).
|
|
124
|
+
- **Alerts:** a toast and a system notification when a rate limit crosses 80% / 95%, a context passes 85%, or an agent has waited 5 minutes for you; chiptunes for requests, done work, arrivals and departures.
|
|
125
|
+
- **Same file, same repo:** a red banner when two sessions edit the same file or checkout.
|
|
126
|
+
- **Git on the door:** each room sign shows uncommitted files (●), commits to push (↑) and to pull (↓), read with `git status` in the background (no fetch).
|
|
127
|
+
- **History and daily report:** the last 24 hours of arrivals, departures, requests and finished work; a daily report with active time, tools and files that copies as Markdown for a standup; your reply times.
|
|
128
|
+
- **Estimated cost:** what the tokens would cost at official API list prices (table in `src/prices.js`, dated; override in `~/.config/coworking-agents/prices.json`), priced per reply with Claude's cache-write split. Unknown models are never guessed. On a subscription this is not what you pay.
|
|
129
|
+
- **Focus mode:** sounds and system notifications pause for 25 or 50 minutes.
|
|
130
|
+
- **Replay:** scrub or play back the last hour.
|
|
131
|
+
|
|
132
|
+
## Walk around (Gather-style)
|
|
133
|
+
|
|
134
|
+
You're in the office too, with a **YOU** tag. **WASD** or the arrow keys walk (hold **Shift** to run), a click on the floor walks you there through the doors, and walls stop you. Near an agent, a prop or a door, **Enter** talks, opens or enters. Turn it off in the ☰ menu.
|
|
135
|
+
|
|
136
|
+
## The game room and the trophy room
|
|
137
|
+
|
|
138
|
+

|
|
139
|
+
|
|
140
|
+
Under the team rooms there's a game room with four doors: arcades, foosball, a pool table, an aquarium, a water cooler and bean bags, where idle agents hang out. Its props open the reports: the **newspaper rack** (the weekly paper), the **vending machine** (the shop), the **easel** (customise), the **guestbook** (history) and the **cork board** (today's date, files edited today, the daily report).
|
|
141
|
+
|
|
142
|
+
A marble portal leads to the **trophy room**, its own screen: legends with wings and a flame in lit niches between marble columns, a stained-glass arch over the crown of **Legend of Legends**, every other trophy under its own glass dome or in the side cabinets, locked ones as silhouettes. Each tier has its own award (bronze cup, silver star cup, gold ruby cup, diamond crystal, winged legend). Click one for its card.
|
|
143
|
+
|
|
144
|
+

|
|
113
145
|
|
|
114
|
-
|
|
115
|
-
- **Whiteboard:** a live bar chart of who is working, needs you, has the turn, or is asleep.
|
|
116
|
-
- **Cork board:** skills installed on the machine and the most-used ones, per AI, plus MCP servers and plugins.
|
|
117
|
-
- **Day/night lighting:** the light follows your local time (day, dusk, night with monitors and lamps glowing).
|
|
118
|
-
- **The office cat** wanders around and naps next to sleeping agents.
|
|
119
|
-
- **Languages:** English and Brazilian Portuguese, picked from your browser and switchable in the top bar.
|
|
146
|
+
## Achievements, coins and the shop
|
|
120
147
|
|
|
121
|
-
|
|
148
|
+
- **74 achievements**, each with five tiers from bronze to legend, measured from your history (hours, actions, streaks, nights, Friday evenings, weeks and months with work, tokens, cache, models, cost), the live office (parallel sessions, subagents, giant contexts, commits and pushes, repos and branches, quick answers, clean desks) and what you do in the office (walking, talking, the radio, the shop, customising). A few are secret.
|
|
149
|
+
- **Legend of Legends** when every achievement is at legend.
|
|
150
|
+
- **Coins:** each tier pays 10 to 50 coins (the super achievement 1000). Spend them in the **shop** on decor that appears in the office: corridor plants, a rug, a COFFEE neon, floor lamps, a disco ball, a golden statue of the agent of the month, a piano, a fountain.
|
|
151
|
+
- **Agent of the month:** a framed portrait on the wall of the conversation with the most active time this month; the top 5 are in the achievements tab.
|
|
152
|
+
- **The weekly paper**, *The Office Times*, tells your week in headlines, all from measured data.
|
|
153
|
+
- **Progress file:** achievements, coins, purchases, avatars and settings live in `~/.config/coworking-agents/progress.json` (mode `0600`). No account needed: the app runs on your machine, so the progress is yours.
|
|
122
154
|
|
|
155
|
+
## Make it yours
|
|
123
156
|
|
|
124
|
-
|
|
157
|
+

|
|
158
|
+
|
|
159
|
+
☰ → **Customise** has 13 options: the office name (on a plaque by the elevator and in the top bar), your own look, floor (wood, dark wood, carpet, concrete, tiles, checker, marble, grass), walls (10 colours), room carpets (5 palettes), desks (5), the window view (city, beach, mountains, forest, space), the sky (automatic, always day, sunset, always night), lighting (natural, warm, cool, neon), the mascot (cat, dog, robot, fox, penguin, bunny), plants (normal or jungle), the radio station and the accent colour. The die next to an agent's face in its panel gives that agent a new look.
|
|
160
|
+
|
|
161
|
+
## A living office
|
|
162
|
+
|
|
163
|
+
- **Life:** after a long task an agent goes for a coffee or celebrates with confetti; at lunch idle agents eat a sandwich; idle ones play ping-pong and foosball or chat at the water cooler; a request waiting 2+ minutes rings the desk phone; uncommitted files pile up as paper on the desk; the desk plant grows with the session's age; a week-old session gets a cake; a room where everyone works hangs a do-not-disturb sign; after 6pm idle rooms turn their lights off; a janitor mops at night; Friday evenings bring pizza; newcomers step out of the elevator next to a punch clock; long-idle agents think funny thoughts.
|
|
164
|
+
- **Sky, seasons and weather:** the sun crosses the windows, the moon shows tonight's real phase, city lights follow the hour, leaves and petals fall by season (hemisphere from your time zone). Real weather is opt-in: click a window and the browser fetches it from Open-Meteo (coordinates rounded to ~1 km); rain slides down the glass.
|
|
165
|
+
- **Chiptune radio** (off by default): the station follows the AI working the most, the beat follows the office mood; an **ON AIR** sign lights up while anyone works.
|
|
166
|
+
- **Holidays:** Christmas, New Year, Halloween, Festa Junina, Carnaval and the office's birthday decorate the room and put hats on everyone (`E` turns decor off).
|
|
167
|
+
- **Pets:** the mascot visits whoever has waited on you the longest and likes being petted; a dog joins at 8 achievements at gold, a parrot at 16.
|
|
168
|
+
- **Certificates** for the skills and MCP servers each session used hang on its partition.
|
|
169
|
+
- **Office photo:** ☰ → Office photo saves the scene as a PNG. And something happens if you click the `</>` neon three times.
|
|
170
|
+
- **Languages:** English and Brazilian Portuguese.
|
|
171
|
+
|
|
172
|
+
<p align="center"><img src="https://raw.githubusercontent.com/ChaconLucas/coworking-agents/main/docs/mobile.png" alt="The office on a phone" width="300"></p>
|
|
173
|
+
|
|
174
|
+
## Shortcuts
|
|
125
175
|
|
|
126
176
|
| Key | Does |
|
|
127
177
|
|---|---|
|
|
128
178
|
| `1`–`9` | open the n-th agent |
|
|
129
179
|
| `N` | next agent that needs you (opens its talk modal) |
|
|
130
180
|
| `/` | quick search by name, title, repository or state |
|
|
131
|
-
| `R` / `
|
|
132
|
-
|
|
|
181
|
+
| `R` / `T` / `G` / `C` | usage report / daily report (today) / history / achievements |
|
|
182
|
+
| WASD or arrows, Shift, Enter | walk, run, interact with what's near you |
|
|
183
|
+
| `F` | focus mode (25 min, again 50, again off) |
|
|
184
|
+
| `H` | replay the last hour |
|
|
133
185
|
| `L` | ceiling lights on/off |
|
|
186
|
+
| `E` | holiday decor on/off |
|
|
134
187
|
| `B` | building view (when there are floors) |
|
|
135
188
|
|
|
136
|
-
- **Compact:** when a Claude session's context passes 75% and it finished its turn, a **Compact** button shows over it; it sends `/compact` to that session's terminal tab (macOS).
|
|
137
|
-
- **Alerts:** a toast and a system notification when a rate limit crosses 80% / 95% or a context passes 85%; distinct chiptunes for requests, done, arrivals and departures.
|
|
138
|
-
- **Real weather (opt-in):** click a window; the browser asks for your location and, if you allow it, fetches the current weather from Open-Meteo directly (coordinates rounded to ~1 km). Off by default; nothing goes through the server.
|
|
139
|
-
- **Same file:** a red banner when two sessions edit the same file, not just the same repository.
|
|
140
|
-
- **New certificates** are hung on the partition with a little animation.
|
|
141
|
-
|
|
142
189
|
## Platforms
|
|
143
190
|
|
|
144
191
|
| | macOS | Linux | Windows |
|
|
@@ -147,20 +194,40 @@ Agents away from their desks (kitchen, meeting room, nap corner) carry a name ta
|
|
|
147
194
|
| Go to terminal | exact tab (Terminal, iTerm2) | window (needs `xdotool` or `wmctrl`) | window |
|
|
148
195
|
| Reply / answer / compact from the office | ✓ | copy and go | copy and go |
|
|
149
196
|
|
|
150
|
-
Linux and Windows support is written against their process tools but has not been tested on real machines yet; reports welcome.
|
|
197
|
+
Linux and Windows support is written against their process tools but has not been tested on real machines yet; reports welcome. See the [roadmap](https://github.com/ChaconLucas/coworking-agents/blob/main/ROADMAP.md) for what's waiting on testing and what's next.
|
|
151
198
|
|
|
152
199
|
## Privacy and security
|
|
153
200
|
|
|
154
201
|
- **Read-only.** No hooks, nothing installed into the AIs, no configuration changed.
|
|
155
|
-
- **No tokens spent.** It never calls a model
|
|
202
|
+
- **No tokens spent.** It never calls a model. The only network calls are the update check (asks npm for the latest version number, nothing else is sent; `--no-update-check` turns it off) and, only if you turn on real weather, the forecast your browser fetches from Open-Meteo.
|
|
156
203
|
- **Local only.** The server binds to `127.0.0.1`.
|
|
157
204
|
- **Host allowlist.** Requests whose `Host` header isn't `127.0.0.1`, `localhost` or `[::1]` are rejected, which blocks DNS-rebinding attacks.
|
|
158
205
|
- **Access token.** Every request needs the per-run token cookie (see [Access token](#access-token)). The "Go to terminal" endpoint additionally requires a custom header and a local origin.
|
|
159
|
-
- **Strict CSP.** `default-src 'self'`, no frames, no external scripts
|
|
206
|
+
- **Strict CSP.** `default-src 'self'`, no frames, no external scripts or fonts; the only outside connection allowed is Open-Meteo for the opt-in weather.
|
|
160
207
|
- **Never reads credentials.** Not Claude Code's `*.key` files, not Codex's `auth.json`. From `~/.claude.json` it reads only `skillUsage`, `pluginUsage` and `mcpServers`.
|
|
161
208
|
- **Secrets are masked.** Tokens, passwords, API keys and `Bearer` values inside commands are replaced with `•••` before display.
|
|
162
209
|
- **`--private` mode** for screen sharing hides agent names, branches, repo names (replaced by aliases like `repo A`), session titles, paths, file names, questions, skills, MCP names and the host name.
|
|
163
210
|
|
|
211
|
+
## Claude rate limits and context window
|
|
212
|
+
|
|
213
|
+
Claude Code only hands these numbers to your **status line** script, so the office reads a copy that the script saves. Add this to your status line (Python; `d` is the JSON Claude Code sends on stdin):
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
import os, json, time
|
|
217
|
+
base = os.path.expanduser('~/.config/coworking-agents'); os.makedirs(base, exist_ok=True)
|
|
218
|
+
rl = d.get('rate_limits') or {}
|
|
219
|
+
if rl:
|
|
220
|
+
json.dump({'at': int(time.time() * 1000), 'five_hour': rl.get('five_hour'), 'seven_day': rl.get('seven_day')}, open(base + '/claude-limits.json', 'w'))
|
|
221
|
+
size = (d.get('context_window') or {}).get('context_window_size')
|
|
222
|
+
if size and d.get('session_id'):
|
|
223
|
+
p = base + '/claude-context.json'
|
|
224
|
+
try: m = json.load(open(p))
|
|
225
|
+
except Exception: m = {}
|
|
226
|
+
m[d['session_id']] = size; json.dump(dict(list(m.items())[-200:]), open(p, 'w'))
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Without it, the context percentage shows only once it is measurable (a reply past 200k tokens proves a 1M window); until then the panel shows the token count and "window size unknown", and no compact button appears.
|
|
230
|
+
|
|
164
231
|
## Limitations
|
|
165
232
|
|
|
166
233
|
- **Codex has no live-session registry.** "Open" means a Codex process is running and the conversation was touched in the last 3 hours, so a closed Codex chat can linger for a while.
|
package/ROADMAP.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
What is planned, what is waiting on something we can't test here, and ideas. Pull requests and reports welcome.
|
|
4
|
+
|
|
5
|
+
## Waiting on real machines or real transcripts
|
|
6
|
+
|
|
7
|
+
These are written or designed, but can't be verified without hardware or data we don't have. If you can help, open an issue with what you saw.
|
|
8
|
+
|
|
9
|
+
- **Windows, real-machine test.** The process table (PowerShell/CIM), snapshot and server have never run on a real Windows box. Needed: someone running `npx coworking-agents` and `npx coworking-agents --json` there.
|
|
10
|
+
- **Windows CPU per process.** Other AI CLIs always show "idle" on Windows because CIM doesn't give CPU %. Needs a cheap measurement (e.g. two `Get-Process` samples) tested on a real machine.
|
|
11
|
+
- **Linux, real-machine test.** `ps`, `/proc/<pid>/cwd` and the "go to terminal" path (xdotool / wmctrl) were written blind.
|
|
12
|
+
- **Typing into a terminal on Linux and Windows.** Reply, answer and `/compact` are macOS only (AppleScript into Terminal/iTerm). Linux would need per-terminal support (tmux `send-keys` is the most portable start); Windows would need Windows Terminal/conhost support.
|
|
13
|
+
- **Full readers for other AIs.** Gemini CLI, OpenCode, Aider, Cursor Agent, Amp, Goose, Qwen Code, Crush, Droid and Kimi are detected by process only (working/idle). Showing what they are doing (tool, file, question, tokens) needs their on-disk session format, read from real transcripts. Share a sample (redacted) to get one added.
|
|
14
|
+
|
|
15
|
+
## Next
|
|
16
|
+
|
|
17
|
+
- **Status-line copy of the context window** set up automatically (opt-in), so the context percentage is exact from the first reply instead of only after a reply passes 200k.
|
|
18
|
+
- **1.0.0** once the above settles.
|
|
19
|
+
|
|
20
|
+
## Done recently
|
|
21
|
+
|
|
22
|
+
Estimated cost · wait reminder · git state on the door · daily report as Markdown · history · focus mode · avatar picker.
|
|
23
|
+
|
|
24
|
+
## Ideas
|
|
25
|
+
|
|
26
|
+
- **Seasonal decor** by date (subtle, off with a toggle).
|
package/bin/coworking-agents.js
CHANGED
|
@@ -18,14 +18,16 @@ if (flag('-h') || flag('--help')) {
|
|
|
18
18
|
--no-open don't open the browser
|
|
19
19
|
--private hide session titles, paths and file names (screen sharing)
|
|
20
20
|
--demo [N] show a fake office with every state and N agents (default 10)
|
|
21
|
-
--json print one snapshot and exit
|
|
21
|
+
--json print one snapshot and exit
|
|
22
|
+
--no-update-check don't ask npm whether a newer version is out`);
|
|
22
23
|
process.exit(0);
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
if (flag('--json')) {
|
|
26
27
|
const { snapshot } = require('../src/collect');
|
|
27
|
-
|
|
28
|
-
process.
|
|
28
|
+
// write and let Node exit on its own: process.exit() cuts a big snapshot short when stdout is a pipe
|
|
29
|
+
process.stdout.write(JSON.stringify(snapshot({ privacy: flag('--private') }), null, 2) + '\n');
|
|
30
|
+
return;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
function open(url) {
|
|
@@ -75,4 +77,8 @@ async function reuse() {
|
|
|
75
77
|
}
|
|
76
78
|
console.log(`coworking-agents → ${hq.url}${privacy ? ' (private mode)' : ''}\nCtrl+C to close.`);
|
|
77
79
|
if (!flag('--no-open')) open(hq.url);
|
|
80
|
+
if (!demo && !flag('--no-update-check')) {
|
|
81
|
+
const up = await require('../src/update').startChecks();
|
|
82
|
+
if (up) console.log(`New version ${up.latest} (you have ${up.current}): npx coworking-agents@latest`);
|
|
83
|
+
}
|
|
78
84
|
})();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coworking-agents",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "A pixel-art coworking office for your AI coding agents (Claude Code, Codex,
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "A pixel-art coworking office for your AI coding agents (Claude Code, Codex, …): see who's working, who needs you, and who's editing the same checkout.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"coworking-agents": "bin/coworking-agents.js"
|
|
7
7
|
},
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"LICENSE",
|
|
15
15
|
"commands",
|
|
16
16
|
"skills",
|
|
17
|
-
"AGENTS.md"
|
|
17
|
+
"AGENTS.md",
|
|
18
|
+
"ROADMAP.md"
|
|
18
19
|
],
|
|
19
20
|
"engines": {
|
|
20
21
|
"node": ">=18"
|
|
@@ -36,5 +37,11 @@
|
|
|
36
37
|
"monitor"
|
|
37
38
|
],
|
|
38
39
|
"author": "Lucas Chacon",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/ChaconLucas/coworking-agents.git"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/ChaconLucas/coworking-agents#readme",
|
|
45
|
+
"bugs": "https://github.com/ChaconLucas/coworking-agents/issues",
|
|
39
46
|
"license": "MIT"
|
|
40
47
|
}
|
package/public/art.js
CHANGED
|
@@ -29,8 +29,11 @@ function shade(hex, f) {
|
|
|
29
29
|
const c = [n >> 16, (n >> 8) & 255, n & 255].map(v => Math.max(0, Math.min(255, Math.round(v * f))));
|
|
30
30
|
return '#' + c.map(v => v.toString(16).padStart(2, '0')).join('');
|
|
31
31
|
}
|
|
32
|
+
// a chosen look replaces the one derived from the id (see setLookSeeds)
|
|
33
|
+
let lookSeeds = new Map();
|
|
34
|
+
function setLookSeeds(m) { lookSeeds = m; }
|
|
32
35
|
function look(id) {
|
|
33
|
-
const h = hash(id);
|
|
36
|
+
const h = hash(lookSeeds.get(id) || id);
|
|
34
37
|
const skin = SKIN[h % SKIN.length], hair = HAIR[(h >>> 3) % HAIR.length], shirt = SHIRT[(h >>> 7) % SHIRT.length];
|
|
35
38
|
return {
|
|
36
39
|
s: skin[0], S: skin[1], h: hair[0], H: hair[1], c: shirt, C: shade(shirt, .72), p: PANTS[(h >>> 11) % PANTS.length],
|
|
@@ -125,6 +128,29 @@ function hairExtras(lk, x, y, front) {
|
|
|
125
128
|
}
|
|
126
129
|
// hair highlight
|
|
127
130
|
r(x + 5, y + 1, 3, 1, shade(lk.h, 1.35));
|
|
131
|
+
if (HAT) drawHat(HAT, x, y);
|
|
132
|
+
}
|
|
133
|
+
// holiday hats over the head (16px wide, top at y)
|
|
134
|
+
let HAT = null;
|
|
135
|
+
function setHat(k) { HAT = k; }
|
|
136
|
+
function drawHat(k, x, y) {
|
|
137
|
+
const o = PAL.ink;
|
|
138
|
+
if (k === 'santa') {
|
|
139
|
+
r(x + 3, y - 4, 10, 4, o); r(x + 4, y - 3, 8, 3, '#e43b44'); r(x + 7, y - 6, 6, 3, o); r(x + 8, y - 5, 4, 2, '#e43b44'); r(x + 11, y - 7, 4, 3, o); r(x + 12, y - 6, 2, 2, '#ffffff');
|
|
140
|
+
r(x + 1, y - 1, 14, 3, o); r(x + 2, y, 12, 1, '#ffffff'); r(x + 2, y - 1, 12, 1, '#e8e8f0');
|
|
141
|
+
} else if (k === 'witch') {
|
|
142
|
+
r(x - 1, y, 18, 3, o); r(x, y + 1, 16, 1, '#3b2a5a');
|
|
143
|
+
r(x + 4, y - 4, 8, 5, o); r(x + 5, y - 3, 6, 3, '#3b2a5a'); r(x + 5, y - 1, 6, 1, '#feae34');
|
|
144
|
+
r(x + 7, y - 8, 4, 5, o); r(x + 8, y - 7, 2, 4, '#3b2a5a'); r(x + 10, y - 9, 3, 2, o); r(x + 11, y - 9, 1, 1, '#3b2a5a');
|
|
145
|
+
} else if (k === 'party') {
|
|
146
|
+
r(x + 5, y - 2, 6, 3, o); r(x + 6, y - 1, 4, 1, '#ff6ec7'); r(x + 6, y, 4, 1, '#2ce8f5');
|
|
147
|
+
r(x + 6, y - 5, 4, 3, o); r(x + 7, y - 4, 2, 1, '#ffd84d'); r(x + 7, y - 3, 2, 1, '#ff6ec7');
|
|
148
|
+
r(x + 7, y - 7, 2, 2, '#ffd84d');
|
|
149
|
+
} else if (k === 'straw') {
|
|
150
|
+
r(x - 2, y, 20, 3, o); r(x - 1, y + 1, 18, 1, '#e8c170');
|
|
151
|
+
r(x + 3, y - 4, 10, 5, o); r(x + 4, y - 3, 8, 3, '#e8c170'); r(x + 4, y - 1, 8, 1, '#e43b44');
|
|
152
|
+
for (let i = 0; i < 4; i++) r(x + 4 + i * 2, y - 3, 1, 1, '#c99a4a');
|
|
153
|
+
}
|
|
128
154
|
}
|
|
129
155
|
|
|
130
156
|
// Person seated with their back to us, facing the monitor.
|
|
@@ -733,7 +759,7 @@ function aiIconEl(id, color) {
|
|
|
733
759
|
|
|
734
760
|
window.Art = {
|
|
735
761
|
aiIcon, aiIconEl, portrait, drawArcade, drawDiagramBoard, drawNeon, drawPoster, drawServerRack, drawDuck, drawSideMonitor, drawStickies, drawBeanSack, drawPizza, drawCupStack,
|
|
736
|
-
PAL, SKIN, HAIR, SHIRT, SCREEN_GLOW, hash, shade, look, setCtx, r, sprite, blit,
|
|
762
|
+
PAL, SKIN, HAIR, SHIRT, SCREEN_GLOW, hash, shade, look, setLookSeeds, setHat, setCtx, r, sprite, blit,
|
|
737
763
|
drawSeatedBack, drawFront, drawStanding, drawSleeping, drawChairBack, drawChairBase, drawCat, bubble, drawScreen,
|
|
738
764
|
drawPlant, drawCertificate, drawLamp, drawWhiteboard, drawCork, drawClock, skyFor, drawWindow, drawSofa, drawCoffeeMachine,
|
|
739
765
|
drawCooler, drawRug, drawFloor, applyLight, LEGS_SIT,
|
package/public/favicon.ico
CHANGED
|
Binary file
|
package/public/favicon.png
CHANGED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" shape-rendering="crispEdges"><rect x="2" y="0" width="12" height="1" fill="#1b1622"/><rect x="1" y="1" width="1" height="1" fill="#1b1622"/><rect x="2" y="1" width="12" height="1" fill="#f4dfc6"/><rect x="14" y="1" width="1" height="1" fill="#1b1622"/><rect x="0" y="2" width="1" height="1" fill="#1b1622"/><rect x="1" y="2" width="2" height="1" fill="#f4dfc6"/><rect x="3" y="2" width="10" height="1" fill="#1b1622"/><rect x="13" y="2" width="2" height="1" fill="#f4dfc6"/><rect x="15" y="2" width="1" height="1" fill="#1b1622"/><rect x="0" y="3" width="1" height="1" fill="#1b1622"/><rect x="1" y="3" width="1" height="1" fill="#f4dfc6"/><rect x="2" y="3" width="1" height="1" fill="#1b1622"/><rect x="3" y="3" width="10" height="1" fill="#2b2336"/><rect x="13" y="3" width="1" height="1" fill="#1b1622"/><rect x="14" y="3" width="1" height="1" fill="#f4dfc6"/><rect x="15" y="3" width="1" height="1" fill="#1b1622"/><rect x="0" y="4" width="1" height="1" fill="#1b1622"/><rect x="1" y="4" width="1" height="1" fill="#f4dfc6"/><rect x="2" y="4" width="1" height="1" fill="#1b1622"/><rect x="3" y="4" width="3" height="1" fill="#2b2336"/><rect x="6" y="4" width="1" height="1" fill="#2ce8f5"/><rect x="7" y="4" width="2" height="1" fill="#2b2336"/><rect x="9" y="4" width="1" height="1" fill="#ff5fd2"/><rect x="10" y="4" width="3" height="1" fill="#2b2336"/><rect x="13" y="4" width="1" height="1" fill="#1b1622"/><rect x="14" y="4" width="1" height="1" fill="#f4dfc6"/><rect x="15" y="4" width="1" height="1" fill="#1b1622"/><rect x="0" y="5" width="1" height="1" fill="#1b1622"/><rect x="1" y="5" width="1" height="1" fill="#f4dfc6"/><rect x="2" y="5" width="1" height="1" fill="#1b1622"/><rect x="3" y="5" width="2" height="1" fill="#2b2336"/><rect x="5" y="5" width="1" height="1" fill="#2ce8f5"/><rect x="6" y="5" width="4" height="1" fill="#2b2336"/><rect x="10" y="5" width="1" height="1" fill="#ff5fd2"/><rect x="11" y="5" width="2" height="1" fill="#2b2336"/><rect x="13" y="5" width="1" height="1" fill="#1b1622"/><rect x="14" y="5" width="1" height="1" fill="#f4dfc6"/><rect x="15" y="5" width="1" height="1" fill="#1b1622"/><rect x="0" y="6" width="1" height="1" fill="#1b1622"/><rect x="1" y="6" width="1" height="1" fill="#f4dfc6"/><rect x="2" y="6" width="1" height="1" fill="#1b1622"/><rect x="3" y="6" width="1" height="1" fill="#2b2336"/><rect x="4" y="6" width="1" height="1" fill="#2ce8f5"/><rect x="5" y="6" width="6" height="1" fill="#2b2336"/><rect x="11" y="6" width="1" height="1" fill="#ff5fd2"/><rect x="12" y="6" width="1" height="1" fill="#2b2336"/><rect x="13" y="6" width="1" height="1" fill="#1b1622"/><rect x="14" y="6" width="1" height="1" fill="#f4dfc6"/><rect x="15" y="6" width="1" height="1" fill="#1b1622"/><rect x="0" y="7" width="1" height="1" fill="#1b1622"/><rect x="1" y="7" width="1" height="1" fill="#f4dfc6"/><rect x="2" y="7" width="1" height="1" fill="#1b1622"/><rect x="3" y="7" width="2" height="1" fill="#2b2336"/><rect x="5" y="7" width="1" height="1" fill="#2ce8f5"/><rect x="6" y="7" width="4" height="1" fill="#2b2336"/><rect x="10" y="7" width="1" height="1" fill="#ff5fd2"/><rect x="11" y="7" width="2" height="1" fill="#2b2336"/><rect x="13" y="7" width="1" height="1" fill="#1b1622"/><rect x="14" y="7" width="1" height="1" fill="#f4dfc6"/><rect x="15" y="7" width="1" height="1" fill="#1b1622"/><rect x="0" y="8" width="1" height="1" fill="#1b1622"/><rect x="1" y="8" width="1" height="1" fill="#f4dfc6"/><rect x="2" y="8" width="1" height="1" fill="#1b1622"/><rect x="3" y="8" width="3" height="1" fill="#2b2336"/><rect x="6" y="8" width="1" height="1" fill="#2ce8f5"/><rect x="7" y="8" width="2" height="1" fill="#2b2336"/><rect x="9" y="8" width="1" height="1" fill="#ff5fd2"/><rect x="10" y="8" width="3" height="1" fill="#2b2336"/><rect x="13" y="8" width="1" height="1" fill="#1b1622"/><rect x="14" y="8" width="1" height="1" fill="#f4dfc6"/><rect x="15" y="8" width="1" height="1" fill="#1b1622"/><rect x="0" y="9" width="1" height="1" fill="#1b1622"/><rect x="1" y="9" width="1" height="1" fill="#f4dfc6"/><rect x="2" y="9" width="1" height="1" fill="#1b1622"/><rect x="3" y="9" width="10" height="1" fill="#2b2336"/><rect x="13" y="9" width="1" height="1" fill="#1b1622"/><rect x="14" y="9" width="1" height="1" fill="#f4dfc6"/><rect x="15" y="9" width="1" height="1" fill="#1b1622"/><rect x="0" y="10" width="1" height="1" fill="#1b1622"/><rect x="1" y="10" width="2" height="1" fill="#f4dfc6"/><rect x="3" y="10" width="10" height="1" fill="#1b1622"/><rect x="13" y="10" width="2" height="1" fill="#f4dfc6"/><rect x="15" y="10" width="1" height="1" fill="#1b1622"/><rect x="1" y="11" width="1" height="1" fill="#1b1622"/><rect x="2" y="11" width="12" height="1" fill="#f4dfc6"/><rect x="14" y="11" width="1" height="1" fill="#1b1622"/><rect x="2" y="12" width="2" height="1" fill="#1b1622"/><rect x="4" y="12" width="2" height="1" fill="#f4dfc6"/><rect x="6" y="12" width="8" height="1" fill="#1b1622"/><rect x="3" y="13" width="1" height="1" fill="#1b1622"/><rect x="4" y="13" width="1" height="1" fill="#f4dfc6"/><rect x="5" y="13" width="1" height="1" fill="#1b1622"/><rect x="3" y="14" width="2" height="1" fill="#1b1622"/></svg>
|
package/public/index.html
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>coworking-agents</title>
|
|
7
|
-
<link rel="icon" href="favicon.ico?v=
|
|
8
|
-
<link rel="icon" href="favicon.png?v=
|
|
9
|
-
<link rel="icon" href="
|
|
7
|
+
<link rel="icon" href="favicon.ico?v=4" sizes="any">
|
|
8
|
+
<link rel="icon" href="favicon.png?v=4" type="image/png" sizes="64x64">
|
|
9
|
+
<link rel="icon" href="favicon.svg?v=4" type="image/svg+xml">
|
|
10
10
|
<link rel="apple-touch-icon" href="apple-touch-icon.png?v=3">
|
|
11
11
|
<link rel="stylesheet" href="style.css">
|
|
12
12
|
</head>
|
|
@@ -20,11 +20,19 @@
|
|
|
20
20
|
<div class="counts" id="counts"></div>
|
|
21
21
|
</div>
|
|
22
22
|
<div class="tools">
|
|
23
|
+
<button id="btn-menu" class="icon-btn menu" aria-expanded="false" aria-controls="tools-menu"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M2 3h12v2H2zM2 7h12v2H2zM2 11h12v2H2z"/></svg><span class="sr"></span><i class="menu-dot" hidden></i></button>
|
|
24
|
+
<div id="tools-menu" class="tools-menu" hidden>
|
|
23
25
|
<button id="btn-notify" class="icon-btn" aria-pressed="false"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M7 1h2v1h2v1h1v5h1v2h1v2H2v-2h1V8h1V3h1V2h2zM6 13h4v1H9v1H7v-1H6z"/></svg><span class="sr"></span></button>
|
|
24
26
|
<button id="btn-sound" class="icon-btn" aria-pressed="false"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M2 6h3l4-4h1v12H9l-4-4H2zM12 5h1v1h1v4h-1v1h-1V5z"/></svg><span class="sr"></span></button>
|
|
27
|
+
<button id="btn-focus" class="icon-btn" aria-pressed="false"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M6 1h4v1h2v1h1v2h1v6h-1v2h-1v1h-2v1H6v-1H4v-1H3v-2H2V5h1V3h1V2h2zm0 3v1H5v1H4v4h1v1h1v1h4v-1h1v-1h1V6h-1V5h-1V4zm1 2h2v1h1v2H9v1H7V9H6V7h1z"/></svg><span class="sr"></span><em class="focus-left" hidden></em></button>
|
|
28
|
+
<button id="btn-walk" class="icon-btn" aria-pressed="true"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M7 1h2v3H7zM5 5h6v5h-1v5H8v-4H8v4H6v-5H5z"/></svg><span class="sr"></span></button>
|
|
29
|
+
<button id="btn-radio" class="icon-btn" aria-pressed="false"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M11 1h2v2h-2v2h3v10H2V5h7V3h2zM4 7v6h4V7zm6 1v1h2V8zm0 3v1h2v-1z"/></svg><span class="sr"></span></button>
|
|
25
30
|
<button id="btn-replay" class="icon-btn"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M6 1h4v1h2v1h1v2h1v6h-1v2h-1v1h-2v1H6v-1H4v-1H3v-2H2V9h2v2h1v1h1v1h4v-1h1v-1h1V5h-1V4h-1V3H6v1H5v1H4v1h2v2H1V3h2v1h1V3h1V2h1zM7 5h2v3h2v2H7z"/></svg><span class="sr"></span></button>
|
|
26
31
|
<button id="btn-search" class="icon-btn"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M5 1h4v1h1v1h1v4h-1v1H9v1H5V8H4V7H3V3h1V2h1zm0 2v4h4V3zM10 9h1v1h1v1h1v1h1v1h-1v1h-1v-1h-1v-1h-1v-1H9v-1h1z"/></svg><span class="sr"></span></button>
|
|
32
|
+
<button id="btn-photo" class="icon-btn"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M5 2h6v2h3v10H2V4h3zm3 4H7v1H6v3h1v1h2v-1h1V7H9V6z"/></svg><span class="sr"></span></button>
|
|
33
|
+
<button id="btn-office" class="icon-btn"><svg viewBox="0 0 16 16" shape-rendering="crispEdges" aria-hidden="true"><path fill="currentColor" d="M7 1h2v2h2v1h2v2h-1v2h1v2h-2v2h-1v1H9v2H7v-2H5v-1H4v-2H3V8h1V6H3V4h2V3h2zm0 5v1H6v2h1v1h2V9h1V7H9V6z"/></svg><span class="sr"></span></button>
|
|
27
34
|
<button id="btn-lang" class="icon-btn lang"></button>
|
|
35
|
+
</div>
|
|
28
36
|
</div>
|
|
29
37
|
</header>
|
|
30
38
|
<div id="clashes" class="clashes" hidden></div>
|
|
@@ -42,6 +50,7 @@
|
|
|
42
50
|
<div id="offline" class="offline" hidden></div>
|
|
43
51
|
<script src="art.js"></script>
|
|
44
52
|
<script src="js/i18n.js"></script>
|
|
53
|
+
<script src="js/progress.js"></script>
|
|
45
54
|
<script src="js/palette.js"></script>
|
|
46
55
|
<script src="js/floorplan.js"></script>
|
|
47
56
|
<script src="js/building.js"></script>
|
|
@@ -57,6 +66,14 @@
|
|
|
57
66
|
<script src="js/topbar.js"></script>
|
|
58
67
|
<script src="js/replay.js"></script>
|
|
59
68
|
<script src="js/keys.js"></script>
|
|
69
|
+
<script src="js/achievements.js"></script>
|
|
70
|
+
<script src="js/fun.js"></script>
|
|
71
|
+
<script src="js/ambient.js"></script>
|
|
72
|
+
<script src="js/life.js"></script>
|
|
73
|
+
<script src="js/collection.js"></script>
|
|
74
|
+
<script src="js/personal.js"></script>
|
|
75
|
+
<script src="js/rooms.js"></script>
|
|
76
|
+
<script src="js/player.js"></script>
|
|
60
77
|
<script src="js/main.js"></script>
|
|
61
78
|
</body>
|
|
62
79
|
</html>
|