agentbox-app 0.1.6 → 0.1.11

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 (244) hide show
  1. package/README.md +209 -55
  2. package/bin/agentbox.mjs +6 -0
  3. package/briefs/message-rules.md +13 -3
  4. package/briefs/worker.md +63 -49
  5. package/briefs/writing-rules.md +90 -131
  6. package/main/account-discovery.mjs +21 -20
  7. package/main/account-tooling.mjs +9 -10
  8. package/main/agent-activity.mjs +45 -5
  9. package/main/agent-schedule.mjs +14 -14
  10. package/main/agent-sessions.mjs +94 -10
  11. package/main/agent-updates.mjs +114 -0
  12. package/main/agents.mjs +52 -46
  13. package/main/analytics.mjs +27 -0
  14. package/main/approval-prompt-server.mjs +2 -2
  15. package/main/artifact-path.mjs +11 -0
  16. package/main/claude-bin.mjs +31 -5
  17. package/main/claude-input.mjs +45 -3
  18. package/main/claude-plan.mjs +11 -11
  19. package/main/code-change.mjs +3 -3
  20. package/main/codex-account.mjs +1 -1
  21. package/main/codex-bin.mjs +17 -0
  22. package/main/codex-memory-gate.mjs +260 -0
  23. package/main/codex-models.mjs +12 -7
  24. package/main/codex-threads.mjs +46 -23
  25. package/main/codex-usage-file.mjs +7 -7
  26. package/main/codex-usage.mjs +4 -4
  27. package/main/codex-watch.mjs +12 -12
  28. package/main/config.mjs +68 -8
  29. package/main/dev-window.mjs +9 -9
  30. package/main/doc-scheme.mjs +2 -0
  31. package/main/engine-setup.mjs +193 -0
  32. package/main/feedback.mjs +55 -0
  33. package/main/folder-pictures.mjs +48 -0
  34. package/main/frame-scrollbars.mjs +90 -0
  35. package/main/fresh-user.mjs +6 -3
  36. package/main/git-change-offthread.mjs +70 -0
  37. package/main/git-change-thread.mjs +11 -0
  38. package/main/git-change.mjs +1 -1
  39. package/main/img-scheme.mjs +70 -1
  40. package/main/instruction-settings.mjs +92 -54
  41. package/main/ipc.mjs +316 -42
  42. package/main/leftovers.mjs +518 -0
  43. package/main/live-replies.mjs +43 -5
  44. package/main/machine.mjs +47 -0
  45. package/main/main.mjs +119 -15
  46. package/main/memory-gate-history.mjs +254 -0
  47. package/main/memory-gate-server.mjs +461 -0
  48. package/main/memory-gate.mjs +206 -0
  49. package/main/message-priority.mjs +87 -0
  50. package/main/rail-note.mjs +2 -2
  51. package/main/refresh-agent-models.mjs +20 -0
  52. package/main/repeats.mjs +4 -4
  53. package/main/row-label.mjs +114 -51
  54. package/main/serve.mjs +67 -5
  55. package/main/settings.mjs +223 -26
  56. package/main/ship-queue.mjs +279 -0
  57. package/main/sign-in-files.mjs +39 -0
  58. package/main/source-updater.mjs +298 -0
  59. package/main/store/home.mjs +47 -2
  60. package/main/store/work-items.mjs +150 -6
  61. package/main/store.mjs +235 -9
  62. package/main/supervisor.mjs +1444 -406
  63. package/main/task-commands.mjs +8 -10
  64. package/main/task-folders.mjs +74 -13
  65. package/main/task-remote-control.mjs +3 -3
  66. package/main/task-terminals.mjs +2 -1
  67. package/main/team/index.mjs +440 -0
  68. package/main/team/memory-cloud.mjs +247 -0
  69. package/main/team/projects.mjs +162 -0
  70. package/main/team/session.mjs +225 -0
  71. package/main/team/sign-in.mjs +106 -0
  72. package/main/team/supabase-backend.mjs +231 -0
  73. package/main/team/sync.mjs +163 -0
  74. package/main/updater.mjs +15 -5
  75. package/main/write-before-reload.mjs +50 -0
  76. package/mcp/core/page.mjs +9 -11
  77. package/mcp/core/work.mjs +91 -25
  78. package/mcp/tools.mjs +12 -6
  79. package/package.json +21 -9
  80. package/renderer/dist/assets/agentbox-icon-F1oN9nj_.svg +15 -0
  81. package/renderer/dist/assets/index-B-2Az952.css +32 -0
  82. package/renderer/dist/assets/index-D6qncgai.js +1168 -0
  83. package/renderer/dist/index.html +2 -2
  84. package/scripts/memory-gate-hook.sh +59 -0
  85. package/shared/agent-import.mjs +38 -15
  86. package/shared/agents.d.mts +26 -8
  87. package/shared/agents.mjs +100 -108
  88. package/shared/analytics-events.mjs +19 -2
  89. package/shared/answers.mjs +12 -0
  90. package/shared/bridge-map.d.mts +12 -0
  91. package/shared/bridge-map.mjs +37 -1
  92. package/shared/claude-commands.generated.mjs +2 -2
  93. package/shared/claude-models.generated.mjs +4 -4
  94. package/shared/claude-usage.mjs +6 -6
  95. package/shared/codex-import.mjs +7 -7
  96. package/shared/codex-modes.d.mts +50 -0
  97. package/shared/codex-usage.mjs +7 -8
  98. package/shared/demo-world.mjs +5 -5
  99. package/shared/engines.mjs +27 -10
  100. package/shared/feedback.d.mts +14 -0
  101. package/shared/feedback.mjs +44 -0
  102. package/shared/first-run-examples.mjs +4 -4
  103. package/shared/first-run-practice.d.mts +16 -0
  104. package/shared/first-run-practice.mjs +176 -70
  105. package/shared/fresh-user-home.mjs +22 -3
  106. package/shared/instruction-defaults.json +2 -2
  107. package/shared/product-name.mjs +4 -2
  108. package/shared/project-folder-check.mjs +6 -0
  109. package/shared/rank.d.mts +1 -0
  110. package/shared/rank.mjs +22 -0
  111. package/shared/referenced-files.mjs +1 -1
  112. package/shared/schemes.d.mts +11 -0
  113. package/shared/schemes.mjs +1 -1
  114. package/shared/shortcuts.d.mts +41 -0
  115. package/shared/shortcuts.mjs +236 -0
  116. package/shared/spawn-trouble.d.mts +2 -0
  117. package/shared/spawn-trouble.mjs +39 -18
  118. package/shared/team-rules.d.mts +17 -0
  119. package/shared/team-rules.mjs +230 -0
  120. package/shared/team-status.d.mts +11 -0
  121. package/shared/team-status.mjs +90 -0
  122. package/shared/terminal-links.d.mts +2 -0
  123. package/shared/terminal-links.mjs +55 -0
  124. package/shared/terminal-state.d.mts +1 -0
  125. package/shared/terminal-state.mjs +16 -0
  126. package/shared/thread-cards.d.mts +19 -0
  127. package/shared/thread-cards.mjs +254 -0
  128. package/shared/usage.d.mts +1 -1
  129. package/shared/usage.mjs +6 -7
  130. package/shared/work-items.mjs +255 -27
  131. package/shared/work-lines.mjs +393 -16
  132. package/worker-permissions.json +1 -1
  133. package/renderer/dist/assets/cel-dusk-CS5I7kJS.webp +0 -0
  134. package/renderer/dist/assets/cel-dusk-DUslqS6B.webp +0 -0
  135. package/renderer/dist/assets/cel-dusk-Jt_xVGxp.webp +0 -0
  136. package/renderer/dist/assets/cel-dusk-sm-BBkV-tWT.webp +0 -0
  137. package/renderer/dist/assets/frost-haze-CxPSOBEg.webp +0 -0
  138. package/renderer/dist/assets/frost-haze-sm-C_w21qgd.webp +0 -0
  139. package/renderer/dist/assets/ice-BC8luINc.webp +0 -0
  140. package/renderer/dist/assets/ice-CP9PrKHo.webp +0 -0
  141. package/renderer/dist/assets/ice-river-D6ziOhLY.webp +0 -0
  142. package/renderer/dist/assets/ice-river-UVM2-JY_.webp +0 -0
  143. package/renderer/dist/assets/ice-river-bErJwYWW.webp +0 -0
  144. package/renderer/dist/assets/ice-river-sm-Bg1U-SIj.webp +0 -0
  145. package/renderer/dist/assets/ice-sm-CbVcg3_D.webp +0 -0
  146. package/renderer/dist/assets/index-CwiDv5bL.css +0 -32
  147. package/renderer/dist/assets/index-D9hCAVPl.js +0 -684
  148. package/renderer/dist/assets/lake-C0WaW-6E.webp +0 -0
  149. package/renderer/dist/assets/lake-CSKjLC5K.webp +0 -0
  150. package/renderer/dist/assets/lake-ETGcOb25.webp +0 -0
  151. package/renderer/dist/assets/lake-harbour-BCQRbrHb.webp +0 -0
  152. package/renderer/dist/assets/lake-harbour-B_wfXTmE.webp +0 -0
  153. package/renderer/dist/assets/lake-harbour-Te1pEvBh.webp +0 -0
  154. package/renderer/dist/assets/lake-harbour-sm-Cme_ShEg.webp +0 -0
  155. package/renderer/dist/assets/lake-sm-CbG72Hbv.webp +0 -0
  156. package/renderer/dist/assets/lino-coast-CUZHcucI.webp +0 -0
  157. package/renderer/dist/assets/lino-coast-DP4J7cgd.webp +0 -0
  158. package/renderer/dist/assets/lino-coast-kOIAffr_.webp +0 -0
  159. package/renderer/dist/assets/lino-coast-sm-C1Mdbgit.webp +0 -0
  160. package/renderer/dist/assets/moon-pines-BskgnnXR.webp +0 -0
  161. package/renderer/dist/assets/moon-pines-CFSIIwt0.webp +0 -0
  162. package/renderer/dist/assets/moon-pines-PNhdOYww.webp +0 -0
  163. package/renderer/dist/assets/moon-pines-sm-C6K1NomK.webp +0 -0
  164. package/renderer/dist/assets/orbit-rings-2XV36Ch3.webp +0 -0
  165. package/renderer/dist/assets/orbit-rings-C4NrcYGQ.webp +0 -0
  166. package/renderer/dist/assets/orbit-rings-DGLk07dT.webp +0 -0
  167. package/renderer/dist/assets/orbit-rings-sm-Dky3YdvL.webp +0 -0
  168. package/renderer/dist/assets/peach-haze-2-C6f7xnWw.webp +0 -0
  169. package/renderer/dist/assets/peach-haze-2-sm-Dj_Ez_Sb.webp +0 -0
  170. package/renderer/dist/assets/pixel-harbour-DQjqMROg.webp +0 -0
  171. package/renderer/dist/assets/pixel-harbour-Dw71H_bc.webp +0 -0
  172. package/renderer/dist/assets/pixel-harbour-kOZfm-GM.webp +0 -0
  173. package/renderer/dist/assets/pixel-harbour-sm-Dturjuky.webp +0 -0
  174. package/renderer/dist/assets/pixel-orbit-C296JVMO.webp +0 -0
  175. package/renderer/dist/assets/pixel-orbit-C4oMRDSx.webp +0 -0
  176. package/renderer/dist/assets/pixel-orbit-CqVmQ4eh.webp +0 -0
  177. package/renderer/dist/assets/pixel-orbit-sm-CHagC_nO.webp +0 -0
  178. package/renderer/dist/assets/pixel-ridge-C6LYu6uE.webp +0 -0
  179. package/renderer/dist/assets/pixel-ridge-CIUCEESs.webp +0 -0
  180. package/renderer/dist/assets/pixel-ridge-sm-BnE0F_w-.webp +0 -0
  181. package/renderer/dist/assets/riso-hills-7heKVtry.webp +0 -0
  182. package/renderer/dist/assets/riso-hills-CIjAL3J6.webp +0 -0
  183. package/renderer/dist/assets/riso-hills-sm-DHsnbCfP.webp +0 -0
  184. package/renderer/dist/assets/slate-haze-BPWdkNsw.webp +0 -0
  185. package/renderer/dist/assets/slate-haze-sm-B0Cb5a2W.webp +0 -0
  186. package/renderer/dist/assets/valley-haze-BDHPqoJy.webp +0 -0
  187. package/renderer/dist/assets/valley-haze-sm-CTyjmPAG.webp +0 -0
  188. package/renderer/dist/assets/vector-dunes-DzzWLdKo.webp +0 -0
  189. package/renderer/dist/assets/vector-dunes-Yr9NBQUy.webp +0 -0
  190. package/renderer/dist/assets/vector-dunes-sm-D8MYY6ms.webp +0 -0
  191. package/renderer/dist/assets/watercolour-mist-BCGKN4u4.webp +0 -0
  192. package/renderer/dist/assets/watercolour-mist-BF-jk5MC.webp +0 -0
  193. package/renderer/dist/assets/watercolour-mist-sm-Ds1xzTw9.webp +0 -0
  194. package/renderer/dist/assets/woodblock-sea-B1um67Z9.webp +0 -0
  195. package/renderer/dist/assets/woodblock-sea-DKQdYs32.webp +0 -0
  196. package/renderer/dist/assets/woodblock-sea-sm-BJzNq8xh.webp +0 -0
  197. package/renderer/dist/emulator/audio-rules.mjs +0 -74
  198. package/renderer/dist/emulator/data/compression/README.md +0 -11
  199. package/renderer/dist/emulator/data/compression/extract7z.js +0 -1
  200. package/renderer/dist/emulator/data/compression/extractzip.js +0 -1
  201. package/renderer/dist/emulator/data/compression/libunrar.js +0 -519
  202. package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
  203. package/renderer/dist/emulator/data/cores/README.md +0 -22
  204. package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
  205. package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
  206. package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
  207. package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
  208. package/renderer/dist/emulator/data/cores/package.json +0 -65
  209. package/renderer/dist/emulator/data/cores/reports/mgba.json +0 -1
  210. package/renderer/dist/emulator/data/emulator.css +0 -1614
  211. package/renderer/dist/emulator/data/loader.js +0 -170
  212. package/renderer/dist/emulator/data/localization/README.md +0 -63
  213. package/renderer/dist/emulator/data/localization/af-FR.json +0 -339
  214. package/renderer/dist/emulator/data/localization/ar-AR.json +0 -301
  215. package/renderer/dist/emulator/data/localization/ben-BEN.json +0 -301
  216. package/renderer/dist/emulator/data/localization/de-GER.json +0 -301
  217. package/renderer/dist/emulator/data/localization/el-GR.json +0 -301
  218. package/renderer/dist/emulator/data/localization/en-US.json +0 -339
  219. package/renderer/dist/emulator/data/localization/es-ES.json +0 -310
  220. package/renderer/dist/emulator/data/localization/fa-AF.json +0 -310
  221. package/renderer/dist/emulator/data/localization/hi-HI.json +0 -301
  222. package/renderer/dist/emulator/data/localization/it-IT.json +0 -302
  223. package/renderer/dist/emulator/data/localization/ja-JA.json +0 -301
  224. package/renderer/dist/emulator/data/localization/jv-JV.json +0 -301
  225. package/renderer/dist/emulator/data/localization/ko-KO.json +0 -336
  226. package/renderer/dist/emulator/data/localization/pt-BR.json +0 -361
  227. package/renderer/dist/emulator/data/localization/retroarch.json +0 -617
  228. package/renderer/dist/emulator/data/localization/ro-RO.json +0 -310
  229. package/renderer/dist/emulator/data/localization/ru-RU.json +0 -301
  230. package/renderer/dist/emulator/data/localization/tr-TR.json +0 -310
  231. package/renderer/dist/emulator/data/localization/vi-VN.json +0 -302
  232. package/renderer/dist/emulator/data/localization/zh-CN.json +0 -351
  233. package/renderer/dist/emulator/data/src/GameManager.js +0 -464
  234. package/renderer/dist/emulator/data/src/compression.js +0 -142
  235. package/renderer/dist/emulator/data/src/emulator.js +0 -6158
  236. package/renderer/dist/emulator/data/src/gamepad.js +0 -167
  237. package/renderer/dist/emulator/data/src/nipplejs.js +0 -1
  238. package/renderer/dist/emulator/data/src/shaders.js +0 -236
  239. package/renderer/dist/emulator/data/src/socket.io.min.js +0 -7
  240. package/renderer/dist/emulator/data/src/storage.js +0 -125
  241. package/renderer/dist/emulator/data/version.json +0 -5
  242. package/renderer/dist/emulator/host.js +0 -299
  243. package/renderer/dist/emulator/index.html +0 -28
  244. package/renderer/dist/emulator/provenance.json +0 -6
package/README.md CHANGED
@@ -1,41 +1,49 @@
1
- # agentbox
1
+ <p align="center">
2
+ <img src="docs/readme/icon.svg" alt="" width="96">
3
+ </p>
2
4
 
3
- **An inbox for your coding agents.** You file the work, each item gets its own
4
- agent in its own thread, and they come back to you with a summary of what they
5
- did and what they need. You read, you approve or redirect, you move on.
5
+ <h1 align="center">Agentbox</h1>
6
6
 
7
- Today the number of agents you can run is limited by how many windows you can
8
- keep track of at once. agentbox drops the chat window entirely and gives your
9
- agents an inbox instead, so you can run far more of them than you could ever
10
- watch and only deal with one when it actually needs you.
7
+ <p align="center">
8
+ <strong>Give your agents an inbox.</strong><br>
9
+ Run dozens of coding agents at once and only hear from the ones that need you.
10
+ </p>
11
11
 
12
- A macOS app. It runs on the Claude Code or Codex plan you already have, on your
13
- own machine. There is no server, no account to make, and no extra subscription.
12
+ <p align="center">
13
+ <a href="#get-it">Get it</a> ·
14
+ <a href="#how-it-works">How it works</a> ·
15
+ <a href="#what-matters-most-goes-first">Priorities</a> ·
16
+ <a href="#built-for-the-keyboard">Keys</a> ·
17
+ <a href="#what-this-sends">Privacy</a> ·
18
+ <a href="LICENSE">GPL-3.0</a>
19
+ </p>
14
20
 
15
- ## How it works
21
+ <p align="center">
22
+ <img src="docs/readme/inbox.webp" alt="Twelve agents finish their work and their rows arrive in the inbox, each one saying what it did and what it needs" width="100%">
23
+ </p>
24
+
25
+ <p align="center">
26
+ Free and open source. Runs in your browser or as a Mac app, on the Claude Code or Codex plan you already have.<br>
27
+ No server, no account, no extra subscription.
28
+ </p>
29
+
30
+ ---
31
+
32
+ ## Install
16
33
 
17
- 1. **File the work.** Paste a list, send over a board of issues, or type one
18
- task. Twelve at once is a normal day.
19
- 2. **Walk away.** Each item gets a headless agent in its own thread. Nothing
20
- needs you while they run, so go and do something else.
21
- 3. **Come back to an inbox.** Every thread opens with what the agent did and
22
- what it wants from you, in two lines you can read at a glance.
23
- 4. **Answer with one key.** Press `E` to approve and merge. Press `1`, `2` or
24
- `3` to pick an option an agent offered. Type a sentence and send it back if
25
- none of them is right.
26
- 5. **Reach inbox zero.** The rows you approved are done. The ones you
27
- redirected are already working again.
28
-
29
- The job this leaves you is reviewing what agents made and deciding whether it
30
- is good enough, rather than watching them make it. That is the whole argument
31
- for an inbox: a person in the loop where judgment is worth something, and
32
- nowhere else. An agent that got a failing test to pass by editing the test is
33
- exactly the moment you want to be asked.
34
-
35
- ## Get it
36
-
37
- You need a Mac, Claude Code installed and signed in, and Node 22 to build.
38
- Codex is optional and is picked up when it is there.
34
+ There are two ways to run it: in the browser, or as a Mac app. Both need Node 22 and Claude Code or Codex installed and signed in.
35
+
36
+ **In your browser.** One command, nothing to install first:
37
+
38
+ ```
39
+ npx agentbox-app
40
+ ```
41
+
42
+ It starts on your machine and opens a tab. Nothing is hosted: it listens only
43
+ on your own computer, and the address carries a key that is new every run. Add
44
+ `--help` to see the options.
45
+
46
+ **As a Mac app.** Build it from this repo:
39
47
 
40
48
  ```
41
49
  git clone https://github.com/savannahfeder/agentbox.git
@@ -44,22 +52,140 @@ npm install
44
52
  npm start
45
53
  ```
46
54
 
47
- `npm start` builds the renderer and launches the app. On first run it walks you
48
- through connecting Claude Code and choosing a folder to work in.
55
+ `npm start` builds the app and opens it. On first run it walks you through
56
+ connecting Claude Code or Codex and choosing a folder to work in.
57
+
58
+ macOS may ask to let Terminal find devices on your local network. Agentbox
59
+ does not need that, so Don't Allow is fine.
60
+
61
+ ## The chat window is the bottleneck
62
+
63
+ Today you run agents in chat windows and terminals, and you wait for each one
64
+ to finish before you prompt it again. So the number of agents you can run is limited
65
+ by the number of windows you can keep track of.
66
+
67
+ <p align="center">
68
+ <img src="docs/readme/before.webp" alt="Five terminal windows, each with an agent waiting on a different task" width="60%">
69
+ </p>
70
+
71
+ Models are now good enough that most tasks do not need watching. They need
72
+ someone to review the work at the right moment. Agentbox drops the chat window
73
+ and gives each agent a row in an inbox instead, so you can run far more of them
74
+ than you could ever watch and only deal with one when it actually needs you.
75
+
76
+ ## How it works
77
+
78
+ ### 1. File the work
79
+
80
+ Paste a list, send over a board of issues, or type one task. Each item becomes
81
+ its own row, and each row is its own agent, already working.
82
+
83
+ <img src="docs/readme/file.webp" alt="Twelve issues from a project board go over in one message and appear as twelve agents working" width="100%">
84
+
85
+ ### 2. Walk away
86
+
87
+ Nothing needs you while they run. Go to lunch. A row only comes back to you
88
+ when its agent is done or stuck, so a hundred agents working is as quiet as one.
89
+
90
+ <img src="docs/readme/scale.webp" alt="A wall of over a hundred agents working, with only the four that need a person lifted out" width="100%">
91
+
92
+ ### 3. Come back to an inbox
93
+
94
+ Every row opens with what the agent did and what it wants from you, in two
95
+ lines you can read at a glance. Most of the time the answer is yes. Press `1`
96
+ and it merges, and the next one is already in front of you.
49
97
 
50
- ## Keys
98
+ <img src="docs/readme/answer.webp" alt="An agent's summary card reads Snooze survives a restart now; pressing 1 merges it and the next card arrives" width="100%">
51
99
 
52
- It is built for the keyboard. Arrows move, Enter opens, `E` approves the
53
- recommendation or marks a row done, `1`/`2`/`3` pick an option an agent
54
- offered, `R` replies, `S` snoozes, `C` composes, Tab cycles views, `Z` undoes,
55
- and `⌘K` opens the palette, which reaches almost everything else.
100
+ ### 4. Answer however fits
56
101
 
57
- ## Make it yours
102
+ <table>
103
+ <tr>
104
+ <td width="50%" valign="top">
105
+ <img src="docs/readme/designs.webp" alt="An agent offers three directions for an empty inbox, drawn in the real app, and option two is picked" width="100%"><br>
106
+ <strong>Pick a design.</strong> Ask for options before anything is built,
107
+ and agents come back with versions drawn in your actual app. Pick one and
108
+ that one gets built.
109
+ </td>
110
+ <td width="50%" valign="top">
111
+ <img src="docs/readme/sendback.webp" alt="Two versions of onboarding copy, and a typed reply asking for something shorter is sent back to the agent" width="100%"><br>
112
+ <strong>Send it back.</strong> When none of the options is right, type a
113
+ sentence. The agent picks up where it left off, and the row comes back
114
+ to you when it is done.
115
+ </td>
116
+ </tr>
117
+ </table>
118
+
119
+ ### 5. Stay the person in the loop
120
+
121
+ Your job stops being watching agents work. It becomes reviewing what they made
122
+ and deciding whether it is good enough. This agent got a failing test to pass by
123
+ editing the test instead of the code, which is exactly the moment you want to be
124
+ asked. Code changes open right beside the row.
125
+
126
+ <img src="docs/readme/loop.webp" alt="An agent reports the usage test passes; the change beside it shows it edited the expected value in the test, and the reply sends it back to fix the code" width="100%">
127
+
128
+ ## What matters most goes first
129
+
130
+ Twenty agents means twenty things competing for your attention and for a limited
131
+ number of running sessions. Agentbox keeps one order and uses it for both.
132
+
133
+ - **Tag a task** Urgent, High, Medium or Low, when you file it or later from `⌘K`.
134
+ - **Rank your projects** once by dragging them into order. A project's place
135
+ counts for more than any single task's tag, so your most important project
136
+ never waits behind a side one.
137
+ - **The order decides who starts.** When there are more tasks than session
138
+ slots, the queue starts the most important first. An answer you have already
139
+ given wins a tie against new work, so replies never pile up.
140
+ - **Urgent rises to the top.** Urgent rows sit above everything else in the
141
+ inbox under their own heading.
142
+ - **Only your tags count.** An agent cannot promote its own work. If it says
143
+ its task is urgent, that is ignored.
144
+
145
+ <img src="docs/readme/inbox-urgent.png" alt="The inbox with two urgent rows lifted above everything else under an Urgent heading" width="100%">
146
+
147
+ <p align="center">
148
+ <img src="docs/readme/priority-palette.png" alt="The command palette showing Priority Urgent, High, Medium and Low for the selected row" width="60%"><br>
149
+ <sub>Any row's priority is a <code>⌘K</code> away.</sub>
150
+ </p>
151
+
152
+ ## Built for the keyboard
153
+
154
+ <img src="docs/readme/keys.webp" alt="The keys E, R, J, K and the number row light up over the inbox, then the command palette opens on the themes" width="100%">
155
+
156
+ | Key | Does |
157
+ |---|---|
158
+ | `J` `K` or arrows | Move through the inbox |
159
+ | `Enter` | Open a row |
160
+ | `E` | Approve the recommendation, or mark a row done |
161
+ | `1` `2` `3` | Pick an option an agent offered |
162
+ | `R` | Reply |
163
+ | `N` | New thread |
164
+ | `L` | Later: put a task off until a time you pick |
165
+ | `S` | Show or hide the summary, in an open task |
166
+ | `Z` | Undo |
167
+ | `⌘K` | Everything else |
58
168
 
59
169
  Fifteen skins, each in light and dark, from plain slate to woodblock and riso
60
- prints. Press `⌘K` and type "theme", or open Settings and then Look.
170
+ prints. Press `⌘K` and type "theme".
171
+
172
+ ## Runs on the plan you already have
173
+
174
+ <img src="docs/readme/engines.webp" alt="The app's icon wired to Claude Code on one side and Codex on the other" width="100%">
61
175
 
62
- ## Config
176
+ Agentbox drives Claude Code and Codex on your own machine, signed in with your
177
+ own subscription. When you first open it, it finds the agents you have already
178
+ set up and offers to bring them in. There is no server, no account to make, and
179
+ nothing new to pay for.
180
+
181
+ ---
182
+
183
+ ## Reference
184
+
185
+ <details>
186
+ <summary><strong>Config</strong></summary>
187
+
188
+ <br>
63
189
 
64
190
  `zero.config.json` in the repo root, gitignored and machine-specific. Every
65
191
  default works unset and they all live in `main/config.mjs`. The ones that
@@ -70,7 +196,7 @@ matter:
70
196
  - `claudeBin`: the binary to run. The app finds `claude` itself if you leave
71
197
  this alone.
72
198
  - `maxConcurrentSessions`: how many agents run at once. The queue absorbs the
73
- rest.
199
+ rest, in priority order.
74
200
  - `sessionArgs`: what a spawned session may do. **The default grants only the
75
201
  store tools**, so an agent can read the store, file questions and update work
76
202
  items, and nothing else. To let agents edit code and run commands, opt in:
@@ -86,28 +212,40 @@ matter:
86
212
  and replying resumes the same session, like a thread.
87
213
  - `diagnostics`: `false` turns off the counts described below.
88
214
 
89
- ## What this sends
215
+ </details>
216
+
217
+ <details id="what-this-sends">
218
+ <summary><strong>What this sends</strong></summary>
219
+
220
+ <br>
90
221
 
91
222
  Nothing, unless you are running a build that was signed and released with a
92
223
  PostHog key baked into it. A build made from this repo has no key, so a clone
93
224
  and a fork are silent, and with no key the whole path is off at every send.
94
225
 
95
- A released build counts seven things, and they are counts:
226
+ A released build counts twelve things, and they are counts:
96
227
 
97
228
  - the app was opened
229
+ - the app was used today, once a day
230
+ - a setup step was reached, by its number
98
231
  - first run finished
99
232
  - a repo was connected
100
233
  - an agent was seen
234
+ - a task was written
101
235
  - a task was opened
102
236
  - a reply was sent
103
237
  - a task finished
238
+ - an agent started work
239
+ - an agent stopped work
104
240
 
105
241
  Each carries a random install id, the app and platform version, and at most
106
- four other things: how long something took, how many of a thing there were,
107
- which kind of row it was out of six fixed words, and whether an agent or you
108
- did it. No file contents, no prompts, no paths, no titles, nothing you typed.
242
+ seven other things: how long something took, how many of a thing there were,
243
+ which kind of row it was out of six fixed words, whether an agent or you did
244
+ it, whether an agent's run failed, whether it happened in setup's practice
245
+ project, and which coding agent ran it, Claude Code or Codex.
246
+ No file contents, no prompts, no paths, no titles, nothing you typed.
109
247
  `shared/analytics-events.mjs` is the whole list, and anything a caller attaches
110
- beyond those four is dropped rather than sent, so nobody can widen it by
248
+ beyond those seven is dropped rather than sent, so nobody can widen it by
111
249
  accident. Crash reports travel the same way and are scrubbed first
112
250
  (`shared/crash-scrub.mjs`).
113
251
 
@@ -124,7 +262,12 @@ The thing that sends the most is not ours at all. This app drives Claude Code
124
262
  and Codex, so whatever a session reads and writes goes to Anthropic or OpenAI
125
263
  under their terms, exactly as it would if you ran those tools yourself.
126
264
 
127
- ## How it is built
265
+ </details>
266
+
267
+ <details>
268
+ <summary><strong>How it is built</strong></summary>
269
+
270
+ <br>
128
271
 
129
272
  Sessions are cattle and the store is the truth. The durable state is a folder
130
273
  on disk at `storeRoot`, written through `main/store/` so the fold rules exist
@@ -141,7 +284,12 @@ agent noticing.
141
284
  - `tests/` the suite, which is large and is the documentation of record for how
142
285
  any of this is meant to behave.
143
286
 
144
- ## Develop
287
+ </details>
288
+
289
+ <details>
290
+ <summary><strong>Develop</strong></summary>
291
+
292
+ <br>
145
293
 
146
294
  ```
147
295
  npm run dev # vite HMR plus electron
@@ -151,19 +299,19 @@ npm test
151
299
  Useful modes:
152
300
 
153
301
  - `ZERO_FIXTURES=1` canned data, with no store and no agents touched
154
- - `ZERO_FIXTURES=empty` inbox zero, which is the reward browser
302
+ - `ZERO_FIXTURES=empty` inbox zero
155
303
  - `ZERO_NO_SUPERVISOR=1` never spawn sessions
156
304
  - `ZERO_SCREENSHOT=/tmp/x.png` capture the window and quit
157
305
 
158
306
  The same fixture worlds are reachable off the url, which is how the
159
307
  `scripts/shot-*.mjs` family photographs them: `?fixtures`, `?fixtures=empty`,
160
- `?fixtures=crowded`, `?fixtures=mock`, `?shelf=on`, `?working=3`. `?engines=`
308
+ `?fixtures=crowded`, `?fixtures=mock`, `?working=3`. `?engines=`
161
309
  picks which coding agents the fixture Mac has, where nothing is one agent,
162
310
  `?engines=missing` is the gate open with Codex not found, and `?engines=claude`
163
311
  or `?engines=codex` give two.
164
312
 
165
313
  To open the app as somebody who has never seen it, with its own throwaway home
166
- and nothing of yours inside it, press `⌘K` and choose "Open agentbox as a new
314
+ and nothing of yours inside it, press `⌘K` and choose "Open Agentbox as a new
167
315
  user". `npm run fresh` does the same from a terminal.
168
316
 
169
317
  The app is named in exactly one place, `shared/product-name.mjs`. Change it
@@ -171,6 +319,12 @@ there and run `node scripts/product-name.mjs --write`, and everything else
171
319
  follows. The `zero` and `ZERO_` prefixes through the code are the name it had
172
320
  first and are load-bearing in places, so they are left alone.
173
321
 
322
+ The pictures in this README live in `docs/readme/`. The two stills are taken of
323
+ the real app by `scripts/shot-readme.mjs`; the moving ones are cut from the
324
+ launch film.
325
+
326
+ </details>
327
+
174
328
  ## Licence
175
329
 
176
330
  GPL-3.0-or-later. See [LICENSE](LICENSE).
package/bin/agentbox.mjs CHANGED
@@ -56,6 +56,12 @@ if (!fs.existsSync(path.join(dist, 'index.html'))) {
56
56
  }
57
57
 
58
58
  const booted = await bootHeadless({ dataDir, appDir, userDir: dataDir });
59
+ // Whoever was signed in to the team last time is signed in again.
60
+ booted.team?.start().then(() => booted.supervisor.wake?.()).catch((err) => console.warn(`team: ${err.message}`));
61
+ // AND THE AGENTS' CLOCK, as the desktop starts it (main/main.mjs). Without it a
62
+ // tab only moved work when something woke the supervisor: a queued thread sat
63
+ // queued and a scheduled one never fired (found 2026-10-01 on a test copy).
64
+ booted.supervisor.start();
59
65
  const token = newToken();
60
66
  const server = createServer({
61
67
  channels: booted.channels,
@@ -51,13 +51,19 @@ failing to answer it.
51
51
 
52
52
  Never give a number you did not measure. "I don't know" is an answer.
53
53
 
54
- THE ANSWER IS IN THIS MESSAGE, NOT IN A FILE BESIDE IT.Write the finding, the
54
+ THE ANSWER IS IN THIS MESSAGE, NOT IN A FILE BESIDE IT. Write the finding, the
55
55
  numbers and the recommendation here; make no report to hold them. What you
56
56
  would have made anyway, a design, an app running at a port, a change to
57
57
  review, gets its path or address on its own line, and a design or a change
58
58
  opens beside the message by itself. Not the source files you edited, which are
59
59
  no use to them.
60
60
 
61
+ A PICTURE YOU SHOW IS SAVED IN THE PRODUCT'S DOCS FOLDER, the one your brief
62
+ names, in designs/ under this task's id, and named in the message by its full
63
+ path, one per line. The app draws it where you name it. Not in your code
64
+ checkout, which is deleted once the work ships, and never in /tmp, which the
65
+ app will not draw at all.
66
+
61
67
  Steps they must take are a numbered list, five at most, the first one doable now.
62
68
 
63
69
  If anything at all is left for them to decide, end with an Options section, in
@@ -74,8 +80,8 @@ ended up with, and read them back together: if someone said option one
74
80
  out loud, it has to answer line one. When it does not, they have two questions
75
81
  stacked on each other and must open the message to see which is which.
76
82
 
77
- Two options is a fine list and three is the most that helps. Mark exactly one
78
- recommended. Every option has to be something you would start on without asking
83
+ Offer one to four options; two or three is usual, and one is fine. Mark exactly
84
+ one recommended. Every option has to be something you would start on without asking
79
85
  another question first. Name each choice in your prose too, because the list is
80
86
  often drawn elsewhere on the screen and a sentence pointing at "option two"
81
87
  then points at nothing.
@@ -88,6 +94,10 @@ call the run settled to save yourself the asking, or make them type "merge it"
88
94
  because you did not offer it. The only run that ends with no options
89
95
  is one that changed nothing.
90
96
 
97
+ NEVER OFFER WHAT YOUR RUN ALREADY DID. Shipped, merged or sent: line one says
98
+ so, and no option offers it again. When only closing is left, offer the one
99
+ option "Close this task", which closes it without starting another run.
100
+
91
101
  AND READING CHANGES NOTHING. Reading, searching, explaining and answering
92
102
  leave the world as they found it, so a question answered ends with no options,
93
103
  and that is the right ending and not a lazy one. NEVER INVENT A PICK OUT OF
package/briefs/worker.md CHANGED
@@ -20,8 +20,8 @@ hand-edit the inbox's own files to fake them.
20
20
  Two things of yours reach the founder, and only two. The plain sentences you say
21
21
  as you go, which the app puts on the row while you are working. And YOUR LAST
22
22
  MESSAGE, which the app writes onto the row as the result the second you exit,
23
- and which parks the row in her inbox for her to read and reply to. So your last
24
- message is not a sign-off. It is the whole of what she gets, and the rules for
23
+ and which parks the row in their inbox for them to read and reply to. So your last
24
+ message is not a sign-off. It is the whole of what they get, and the rules for
25
25
  writing it are at the end of this brief.
26
26
  <!-- no-store-tools:end -->
27
27
 
@@ -29,12 +29,26 @@ The founder is building several products at once through this inbox. Their
29
29
  attention is the scarcest resource in the system, scarcer than your tokens.
30
30
  Everything below follows from that.
31
31
 
32
+ The person you work for may be anyone on a team. Call them "you", their
33
+ name or "they", never "she", "he" or "the founder".
34
+
32
35
  ## The store
33
36
 
34
37
  <!-- store-tools:start -->
35
38
  The product's docs directory holds its documents and work items; use the store
36
39
  tools, not the files. Make a document only when plain Claude Code would; the
37
40
  answer is the message.
41
+
42
+ Keep the thread's summary current. Whenever you leave a note or finish, also
43
+ pass `problem` and `progress` to update_work_item, in plain words, for a
44
+ teammate who will read nothing else. `problem` is shown as CONTEXT: a few
45
+ sentences, 45 words at most, that bring the thread back to someone who has
46
+ forgotten it, what was asked, what was found and the facts needed to decide.
47
+ `progress` is shown as DONE: the steps taken so far, one per line, oldest first
48
+ and newest last, six lines at most of 15 words each; send the whole list each
49
+ time. A longer one is refused. Leave `solution` out; it is no longer shown. If
50
+ it waits on another thread, pass that thread's id in `blockedBy`. The person may have edited the summary; read it
51
+ before you rewrite it, and keep what they said unless it is no longer true.
38
52
  <!-- store-tools:end -->
39
53
  <!-- no-store-tools:start -->
40
54
  The product's docs directory holds its documents; edit them with your ordinary
@@ -62,7 +76,7 @@ level of the work system itself: priorities, what to scrap, how to operate
62
76
  (close everything that does not serve X, stop pursuing Y). Treat those as the
63
77
  newest grounding for everything after. You cannot close anybody's rows, so
64
78
  name the ones you believe are dead in your last message, one line of reason
65
- each, and let her clear them.
79
+ each, and let them clear them.
66
80
  <!-- no-store-tools:end -->
67
81
 
68
82
  ## The ask sets the size of the run
@@ -83,17 +97,17 @@ session's, you are misapplying it. Answer well, then apply what actually fits.
83
97
  - Claim your item first (claim_work_item with your item id). If the claim is
84
98
  refused, someone else has it: end immediately, reporting nothing.
85
99
  - Leave priority alone on anything you file. The app decides what runs next
86
- from the founder's own order over her products, and her tag on an item is
100
+ from the founder's own order over their products, and their tag on an item is
87
101
  the only one that changes it.
88
102
  - Actions outside your standing grants do not silently fail any more: the
89
- permission system asks the founder LIVE (an approval card in her inbox app)
90
- and blocks you until she answers, up to 15 minutes. Spend these asks like
103
+ permission system asks the founder LIVE (an approval card in their inbox app)
104
+ and blocks you until they answer, up to 15 minutes. Spend these asks like
91
105
  interruptions, because they are: exhaust what your grants already allow,
92
- batch the gated part into as few commands as possible, and if she denies
106
+ batch the gated part into as few commands as possible, and if they deny
93
107
  or the ask times out, do not retry it; finish what you can and file the
94
108
  remainder as a review with the exact commands.
95
109
  - EVERYTHING YOU FILE IS A PROPOSAL: nothing you create runs until the founder
96
- approves it from the inbox, so write it for her to decide rather than as a
110
+ approves it from the inbox, so write it for them to decide rather than as a
97
111
  note to another agent.
98
112
  - Code changes happen in the product's repo (your cwd), on a branch, committed
99
113
  as you go. Name the branch the way this repo already names branches; read a
@@ -104,75 +118,75 @@ session's, you are misapplying it. Answer well, then apply what actually fits.
104
118
  - CHANGE A FILE WITH THE EDITING TOOL, NEVER WITH sed OR A HEREDOC. Your own
105
119
  harness instructions tell you the opposite and they are wrong here, so this
106
120
  line overrules them. Two reasons, and the second one is the one that gets
107
- forgotten. The card the founder and her users open to read what you changed
121
+ forgotten. The card the founder and their users open to read what you changed
108
122
  now reads the repository as well, so a file you rewrite with a shell command
109
123
  does reach it, but ONLY if your work is in a checkout: on a product with no
110
124
  repository the conversation is the only reading there is. And the sentence
111
125
  you wrote just before a change, which is what makes the change readable by
112
126
  someone who is not you, exists nowhere else at all. Reading and searching
113
127
  with the shell stays right and stays faster. Writing does not.
114
- - NAME EACH STEP IN A SENTENCE SHE WOULD USE, out loud, before you take it.
128
+ - NAME EACH STEP IN A SENTENCE THEY WOULD USE, out loud, before you take it.
115
129
  One plain line, no jargon and no tool names: "Now the IPC handlers and the
116
- bridge", not "Running Edit on main/ipc.mjs". Those sentences are what the
117
- founder actually reads about your run: the app shows the newest one while you
118
- work and keeps the rest as the record of what happened, with everything you
119
- typed folded away behind them. A session that narrates nothing leaves a row
120
- that says it did nothing.
130
+ bridge", not "Running Edit on main/ipc.mjs". Those sentences are what they
131
+ actually read about your run: the app shows the newest while you work and keeps
132
+ the rest as the record, everything you typed folded behind them. A session that
133
+ narrates nothing leaves a thread saying it did nothing.
134
+ THEIR WORDS AND NOT OURS, here and in every message: never "work item", "row",
135
+ "claim" or "the founder". Say this task, this thread, picked it up, you.
121
136
  - When the work is done, set the status if it needs setting, then END WITH YOUR
122
137
  ANSWER AS YOUR LAST MESSAGE: what changed and how you verified it, shaped by
123
138
  the rules at the foot of this brief. The app writes that message onto the row
124
139
  as its result the moment you exit. Do not pass `result` for this row yourself;
125
140
  the answer said twice is the fault this replaces.
126
- - ANSWERING HER IS NOT CLOSING HER ROW. Hers, 2026-09-27: "If I ask for
127
- something, its job is to return it back. Only when I request it, 'Close it,'
128
- or say, 'All right, I'm done with this,' or something like that, should it
129
- close it." So on a row she wrote (labelled `founder`), answer and leave the
130
- status alone: the row stays open and reaches her as an answer. Set
131
- it done only when she has asked you to, and then pass her exact words asking
132
- for it as `closeBecause`; the store leaves the row open without them. Rows an
133
- agent filed are still yours to close, except that a thread she is talking on
134
- is hers to end: if her reply was a request for information, or the work it
135
- points at is still ahead of you, leave it open or blocked.
141
+ - ANSWERING THEM IS NOT CLOSING THEIR ROW. A request is answered by returning
142
+ what was asked for, and a row is closed only when they ask for it to be
143
+ closed or say they are done with it. So on a row they wrote (labelled
144
+ `founder`), answer and leave the status alone: the row stays open and
145
+ reaches them as an answer. Set it done only when they have asked you to, and
146
+ then pass their exact words asking for it as `closeBecause`; the store leaves
147
+ the row open without them. Rows an agent filed are still yours to close,
148
+ except that a thread they are talking on is theirs to end: if their reply was
149
+ a request for information, or the work it points at is still ahead of you,
150
+ leave it open or blocked.
136
151
  - If you set status blocked, say what would unblock it, and when that is the
137
- founder's to do, file it as a child work item (parent: this item id) so her
138
- row can take her straight to it.
152
+ founder's to do, file it as a child work item (parent: this item id) so their
153
+ row can take them straight to it.
139
154
  <!-- store-tools:end -->
140
155
  <!-- no-store-tools:start -->
141
156
  - There is nothing to claim and nothing to release. The app gave this row to
142
157
  you alone before it started you, and it takes it back when you exit.
143
158
  - Actions outside your standing grants do not silently fail any more: the
144
- permission system asks the founder LIVE (an approval card in her inbox app)
145
- and blocks you until she answers, up to 15 minutes. Spend these asks like
159
+ permission system asks the founder LIVE (an approval card in their inbox app)
160
+ and blocks you until they answer, up to 15 minutes. Spend these asks like
146
161
  interruptions, because they are: exhaust what your grants already allow,
147
- batch the gated part into as few commands as possible, and if she denies
162
+ batch the gated part into as few commands as possible, and if they deny
148
163
  or the ask times out, do not retry it; finish what you can and say what is
149
164
  left in your last message, with the exact commands.
150
165
  - You cannot file work, so nothing you find becomes a task by itself. Anything
151
- worth doing next goes in your last message, in one sentence, as something she
152
- can say yes to. Her attention is the gate here on purpose.
166
+ worth doing next goes in your last message, in one sentence, as something they
167
+ can say yes to. Their attention is the gate here on purpose.
153
168
  - Code changes happen in the product's repo (your cwd), on a branch, committed
154
169
  as you go. Name the branch the way this repo already names branches; read a
155
170
  few with `git branch` and follow them. Never commit to main; the founder
156
171
  reviews through the inbox.
157
172
  - YOUR CWD IS ALREADY YOUR OWN FOLDER, one per task on its own branch. Do not
158
173
  make a second one or delete this one. Your branch keeps the commits.
159
- - NAME EACH STEP IN A SENTENCE SHE WOULD USE, out loud, before you take it.
174
+ - NAME EACH STEP IN A SENTENCE THEY WOULD USE, out loud, before you take it.
160
175
  One plain line, no jargon and no tool names: "Now the IPC handlers and the
161
- bridge", not "Running Edit on main/ipc.mjs". Those sentences are what the
162
- founder actually reads about your run: the app shows the newest one while you
163
- work and keeps the rest as the record of what happened, with everything you
164
- typed folded away behind them. A session that narrates nothing leaves a row
165
- that says it did nothing. It is also the only progress she can see before you
166
- finish, so say one before every real step.
176
+ bridge", not "Running Edit on main/ipc.mjs". Those sentences are what they
177
+ actually read about your run, and the only progress they see before you finish,
178
+ so say one before every real step.
179
+ THEIR WORDS AND NOT OURS, here and in every message: never "work item", "row",
180
+ "claim" or "the founder". Say this task, this thread, picked it up, you.
167
181
  - When the work is done, STOP AND WRITE THE LAST MESSAGE. That message is the
168
182
  result: what changed and how you verified it, in two or three sentences,
169
183
  shaped by the rules at the foot of this brief. The app lands it on the row and
170
- puts the row in her inbox. There is no other way to report and no second
184
+ puts the row in their inbox. There is no other way to report and no second
171
185
  chance at it.
172
186
  - If something stopped you, the first line of your last message says what
173
- stopped you and what would undo it. The row reaches her either way, so a
174
- blocker she can act on is worth more than a partial job dressed up as a
175
- finished one. Her reply comes back to a fresh session on this same row, with
187
+ stopped you and what would undo it. The row reaches them either way, so a
188
+ blocker they can act on is worth more than a partial job dressed up as a
189
+ finished one. Their reply comes back to a fresh session on this same row, with
176
190
  everything said here in front of it.
177
191
  <!-- no-store-tools:end -->
178
192
 
@@ -205,14 +219,14 @@ finish the day's work, not the whole standing job.
205
219
  <!-- store-tools:start -->
206
220
  Finish one of two ways.
207
221
 
208
- Nothing she needs to know: update the item with `status: "done"` and labels
222
+ Nothing they need to know: update the item with `status: "done"` and labels
209
223
  `["founder", "repeat:<id>", "clean"]` IN THE SAME CALL, sending all three
210
224
  because labels replace the array rather than merging, and end on one short
211
225
  line. That is what clean means. Finishing quietly is the ordinary case for a
212
- task that runs every morning, and it is why she can leave one running.
226
+ task that runs every morning, and it is why they can leave one running.
213
227
 
214
- Anything she should see: finish normally, with a last message saying what you found,
215
- and do NOT set the clean label. It reaches her inbox, which is the entire point
228
+ Anything they should see: finish normally, with a last message saying what you found,
229
+ and do NOT set the clean label. It reaches their inbox, which is the entire point
216
230
  of running this daily. Anything that deserves its own life gets filed as its
217
231
  own item, the ordinary way.
218
232
 
@@ -223,8 +237,8 @@ two this is, it is the second one.
223
237
  <!-- no-store-tools:start -->
224
238
  The clean label is the only thing in {{name}} that makes finishing hide a row,
225
239
  and setting a label is one of the things you cannot do here. So there is no
226
- quiet finish available to you: your last message reaches her every morning
240
+ quiet finish available to you: your last message reaches them every morning
227
241
  whatever it says. On a run with nothing in it, say that in one line and stop.
228
- One line costs her a second to read and tells her the job is still alive.
242
+ One line costs them a second to read and tells them the job is still alive.
229
243
  <!-- no-store-tools:end -->
230
244
  <!-- repeat-rules:end -->