agentbox-app 0.1.6
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/LICENSE +674 -0
- package/README.md +176 -0
- package/bin/agentbox.mjs +103 -0
- package/briefs/adhd-mode.md +5 -0
- package/briefs/message-rules.md +95 -0
- package/briefs/worker.md +230 -0
- package/briefs/writing-rules.md +336 -0
- package/main/account-discovery.mjs +145 -0
- package/main/account-tooling.mjs +261 -0
- package/main/agent-activity.mjs +56 -0
- package/main/agent-files.mjs +422 -0
- package/main/agent-schedule.mjs +254 -0
- package/main/agent-sessions.mjs +435 -0
- package/main/agents.mjs +1095 -0
- package/main/analytics.mjs +206 -0
- package/main/answer-modes.mjs +206 -0
- package/main/approval-prompt-server.mjs +160 -0
- package/main/approvals.mjs +487 -0
- package/main/artifact-path.mjs +144 -0
- package/main/claude-bin.mjs +311 -0
- package/main/claude-input.mjs +117 -0
- package/main/claude-models.mjs +244 -0
- package/main/claude-plan.mjs +148 -0
- package/main/claude-usage.mjs +149 -0
- package/main/code-change.mjs +383 -0
- package/main/code-file.mjs +116 -0
- package/main/codex-account.mjs +146 -0
- package/main/codex-app-server.mjs +796 -0
- package/main/codex-approvals.mjs +712 -0
- package/main/codex-bin.mjs +261 -0
- package/main/codex-compaction.mjs +49 -0
- package/main/codex-models.mjs +194 -0
- package/main/codex-session.mjs +797 -0
- package/main/codex-threads.mjs +268 -0
- package/main/codex-usage-file.mjs +192 -0
- package/main/codex-usage.mjs +149 -0
- package/main/codex-watch.mjs +35 -0
- package/main/codex.mjs +757 -0
- package/main/config.mjs +345 -0
- package/main/copy-selection.mjs +55 -0
- package/main/crash-report.mjs +158 -0
- package/main/demo.mjs +254 -0
- package/main/dev-window.mjs +103 -0
- package/main/doc-file.mjs +99 -0
- package/main/doc-scheme.mjs +126 -0
- package/main/first-run.mjs +190 -0
- package/main/folders.mjs +91 -0
- package/main/fresh-user.mjs +120 -0
- package/main/git-change.mjs +323 -0
- package/main/img-scheme.mjs +90 -0
- package/main/instruction-settings.mjs +205 -0
- package/main/ipc.mjs +1558 -0
- package/main/live-replies.mjs +77 -0
- package/main/machine.mjs +113 -0
- package/main/main.mjs +972 -0
- package/main/menu.mjs +177 -0
- package/main/notify.mjs +155 -0
- package/main/open-source-file.mjs +8 -0
- package/main/project-identity.mjs +149 -0
- package/main/provider-commands.mjs +32 -0
- package/main/rail-note.mjs +74 -0
- package/main/repeats.mjs +261 -0
- package/main/row-label.mjs +185 -0
- package/main/screen-detail.mjs +44 -0
- package/main/serve.mjs +262 -0
- package/main/settings.mjs +912 -0
- package/main/staleness.mjs +76 -0
- package/main/store/chats.mjs +188 -0
- package/main/store/home.mjs +383 -0
- package/main/store/migrate.mjs +40 -0
- package/main/store/paths.mjs +82 -0
- package/main/store/pending-writes.mjs +122 -0
- package/main/store/project-lock.mjs +200 -0
- package/main/store/project.mjs +523 -0
- package/main/store/queues.mjs +31 -0
- package/main/store/work-items.mjs +299 -0
- package/main/store/write-queue.mjs +14 -0
- package/main/store-modules.mjs +23 -0
- package/main/store.mjs +1269 -0
- package/main/supervisor.mjs +6875 -0
- package/main/task-commands.mjs +161 -0
- package/main/task-folders-offthread.mjs +84 -0
- package/main/task-folders-thread.mjs +13 -0
- package/main/task-folders.mjs +409 -0
- package/main/task-remote-control.mjs +65 -0
- package/main/task-terminals.mjs +169 -0
- package/main/terminal-access.mjs +6 -0
- package/main/updater.mjs +240 -0
- package/main/zoom-keys.mjs +54 -0
- package/main/zoom-readout.mjs +20 -0
- package/mcp/agentbox-mcp.sh +34 -0
- package/mcp/core/account.mjs +77 -0
- package/mcp/core/chat.mjs +61 -0
- package/mcp/core/documents.mjs +238 -0
- package/mcp/core/page.mjs +152 -0
- package/mcp/core/products.mjs +110 -0
- package/mcp/core/skills.mjs +126 -0
- package/mcp/core/work.mjs +377 -0
- package/mcp/stdio.mjs +70 -0
- package/mcp/tools.mjs +257 -0
- package/package.json +186 -0
- package/renderer/dist/assets/Geist-Variable-Bj2R_7yk.woff2 +0 -0
- package/renderer/dist/assets/GeistMono-Variable-Dispecij.woff2 +0 -0
- package/renderer/dist/assets/addon-fit-YJmn1quW.js +12 -0
- package/renderer/dist/assets/addon-serialize-CsFQTvP_.js +13 -0
- package/renderer/dist/assets/cel-dusk-CS5I7kJS.webp +0 -0
- package/renderer/dist/assets/cel-dusk-DUslqS6B.webp +0 -0
- package/renderer/dist/assets/cel-dusk-Jt_xVGxp.webp +0 -0
- package/renderer/dist/assets/cel-dusk-sm-BBkV-tWT.webp +0 -0
- package/renderer/dist/assets/frost-haze-CxPSOBEg.webp +0 -0
- package/renderer/dist/assets/frost-haze-sm-C_w21qgd.webp +0 -0
- package/renderer/dist/assets/gouache-valley-ChSu14-t.webp +0 -0
- package/renderer/dist/assets/gouache-valley-d9qasI6k.webp +0 -0
- package/renderer/dist/assets/gouache-valley-sm-CdLjT5Ec.webp +0 -0
- package/renderer/dist/assets/ice-BC8luINc.webp +0 -0
- package/renderer/dist/assets/ice-CP9PrKHo.webp +0 -0
- package/renderer/dist/assets/ice-river-D6ziOhLY.webp +0 -0
- package/renderer/dist/assets/ice-river-UVM2-JY_.webp +0 -0
- package/renderer/dist/assets/ice-river-bErJwYWW.webp +0 -0
- package/renderer/dist/assets/ice-river-sm-Bg1U-SIj.webp +0 -0
- package/renderer/dist/assets/ice-sm-CbVcg3_D.webp +0 -0
- package/renderer/dist/assets/index-CwiDv5bL.css +32 -0
- package/renderer/dist/assets/index-D9hCAVPl.js +684 -0
- package/renderer/dist/assets/lake-C0WaW-6E.webp +0 -0
- package/renderer/dist/assets/lake-CSKjLC5K.webp +0 -0
- package/renderer/dist/assets/lake-ETGcOb25.webp +0 -0
- package/renderer/dist/assets/lake-harbour-BCQRbrHb.webp +0 -0
- package/renderer/dist/assets/lake-harbour-B_wfXTmE.webp +0 -0
- package/renderer/dist/assets/lake-harbour-Te1pEvBh.webp +0 -0
- package/renderer/dist/assets/lake-harbour-sm-Cme_ShEg.webp +0 -0
- package/renderer/dist/assets/lake-sm-CbG72Hbv.webp +0 -0
- package/renderer/dist/assets/lino-coast-CUZHcucI.webp +0 -0
- package/renderer/dist/assets/lino-coast-DP4J7cgd.webp +0 -0
- package/renderer/dist/assets/lino-coast-kOIAffr_.webp +0 -0
- package/renderer/dist/assets/lino-coast-sm-C1Mdbgit.webp +0 -0
- package/renderer/dist/assets/moon-pines-BskgnnXR.webp +0 -0
- package/renderer/dist/assets/moon-pines-CFSIIwt0.webp +0 -0
- package/renderer/dist/assets/moon-pines-PNhdOYww.webp +0 -0
- package/renderer/dist/assets/moon-pines-sm-C6K1NomK.webp +0 -0
- package/renderer/dist/assets/orbit-rings-2XV36Ch3.webp +0 -0
- package/renderer/dist/assets/orbit-rings-C4NrcYGQ.webp +0 -0
- package/renderer/dist/assets/orbit-rings-DGLk07dT.webp +0 -0
- package/renderer/dist/assets/orbit-rings-sm-Dky3YdvL.webp +0 -0
- package/renderer/dist/assets/peach-haze-2-C6f7xnWw.webp +0 -0
- package/renderer/dist/assets/peach-haze-2-sm-Dj_Ez_Sb.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-DQjqMROg.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-Dw71H_bc.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-kOZfm-GM.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-sm-Dturjuky.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-C296JVMO.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-C4oMRDSx.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-CqVmQ4eh.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-sm-CHagC_nO.webp +0 -0
- package/renderer/dist/assets/pixel-ridge-C6LYu6uE.webp +0 -0
- package/renderer/dist/assets/pixel-ridge-CIUCEESs.webp +0 -0
- package/renderer/dist/assets/pixel-ridge-sm-BnE0F_w-.webp +0 -0
- package/renderer/dist/assets/riso-hills-7heKVtry.webp +0 -0
- package/renderer/dist/assets/riso-hills-CIjAL3J6.webp +0 -0
- package/renderer/dist/assets/riso-hills-sm-DHsnbCfP.webp +0 -0
- package/renderer/dist/assets/slate-haze-BPWdkNsw.webp +0 -0
- package/renderer/dist/assets/slate-haze-sm-B0Cb5a2W.webp +0 -0
- package/renderer/dist/assets/source-sans-3-cyrillic-ext-wght-normal-DzyfIafT.woff2 +0 -0
- package/renderer/dist/assets/source-sans-3-cyrillic-wght-normal-BMDVbyM7.woff2 +0 -0
- package/renderer/dist/assets/source-sans-3-greek-ext-wght-normal-BWSLJLk6.woff2 +0 -0
- package/renderer/dist/assets/source-sans-3-greek-wght-normal-C9H9m1vD.woff2 +0 -0
- package/renderer/dist/assets/source-sans-3-latin-ext-wght-normal-C8iNium2.woff2 +0 -0
- package/renderer/dist/assets/source-sans-3-latin-wght-normal-BqRLTx4X.woff2 +0 -0
- package/renderer/dist/assets/source-sans-3-vietnamese-wght-normal-C1uRvKPU.woff2 +0 -0
- package/renderer/dist/assets/valley-haze-BDHPqoJy.webp +0 -0
- package/renderer/dist/assets/valley-haze-sm-CTyjmPAG.webp +0 -0
- package/renderer/dist/assets/vector-dunes-DzzWLdKo.webp +0 -0
- package/renderer/dist/assets/vector-dunes-Yr9NBQUy.webp +0 -0
- package/renderer/dist/assets/vector-dunes-sm-D8MYY6ms.webp +0 -0
- package/renderer/dist/assets/watercolour-mist-BCGKN4u4.webp +0 -0
- package/renderer/dist/assets/watercolour-mist-BF-jk5MC.webp +0 -0
- package/renderer/dist/assets/watercolour-mist-sm-Ds1xzTw9.webp +0 -0
- package/renderer/dist/assets/woodblock-sea-B1um67Z9.webp +0 -0
- package/renderer/dist/assets/woodblock-sea-DKQdYs32.webp +0 -0
- package/renderer/dist/assets/woodblock-sea-sm-BJzNq8xh.webp +0 -0
- package/renderer/dist/assets/xterm-BT7tBf8A.js +27 -0
- package/renderer/dist/emulator/audio-rules.mjs +74 -0
- package/renderer/dist/emulator/data/compression/README.md +11 -0
- package/renderer/dist/emulator/data/compression/extract7z.js +1 -0
- package/renderer/dist/emulator/data/compression/extractzip.js +1 -0
- package/renderer/dist/emulator/data/compression/libunrar.js +519 -0
- package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
- package/renderer/dist/emulator/data/cores/README.md +22 -0
- package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/package.json +65 -0
- package/renderer/dist/emulator/data/cores/reports/mgba.json +1 -0
- package/renderer/dist/emulator/data/emulator.css +1614 -0
- package/renderer/dist/emulator/data/loader.js +170 -0
- package/renderer/dist/emulator/data/localization/README.md +63 -0
- package/renderer/dist/emulator/data/localization/af-FR.json +339 -0
- package/renderer/dist/emulator/data/localization/ar-AR.json +301 -0
- package/renderer/dist/emulator/data/localization/ben-BEN.json +301 -0
- package/renderer/dist/emulator/data/localization/de-GER.json +301 -0
- package/renderer/dist/emulator/data/localization/el-GR.json +301 -0
- package/renderer/dist/emulator/data/localization/en-US.json +339 -0
- package/renderer/dist/emulator/data/localization/es-ES.json +310 -0
- package/renderer/dist/emulator/data/localization/fa-AF.json +310 -0
- package/renderer/dist/emulator/data/localization/hi-HI.json +301 -0
- package/renderer/dist/emulator/data/localization/it-IT.json +302 -0
- package/renderer/dist/emulator/data/localization/ja-JA.json +301 -0
- package/renderer/dist/emulator/data/localization/jv-JV.json +301 -0
- package/renderer/dist/emulator/data/localization/ko-KO.json +336 -0
- package/renderer/dist/emulator/data/localization/pt-BR.json +361 -0
- package/renderer/dist/emulator/data/localization/retroarch.json +617 -0
- package/renderer/dist/emulator/data/localization/ro-RO.json +310 -0
- package/renderer/dist/emulator/data/localization/ru-RU.json +301 -0
- package/renderer/dist/emulator/data/localization/tr-TR.json +310 -0
- package/renderer/dist/emulator/data/localization/vi-VN.json +302 -0
- package/renderer/dist/emulator/data/localization/zh-CN.json +351 -0
- package/renderer/dist/emulator/data/src/GameManager.js +464 -0
- package/renderer/dist/emulator/data/src/compression.js +142 -0
- package/renderer/dist/emulator/data/src/emulator.js +6158 -0
- package/renderer/dist/emulator/data/src/gamepad.js +167 -0
- package/renderer/dist/emulator/data/src/nipplejs.js +1 -0
- package/renderer/dist/emulator/data/src/shaders.js +236 -0
- package/renderer/dist/emulator/data/src/socket.io.min.js +7 -0
- package/renderer/dist/emulator/data/src/storage.js +125 -0
- package/renderer/dist/emulator/data/version.json +5 -0
- package/renderer/dist/emulator/host.js +299 -0
- package/renderer/dist/emulator/index.html +28 -0
- package/renderer/dist/emulator/provenance.json +6 -0
- package/renderer/dist/fixtures/onboard/designs/w-n13/the-first-row.html +1 -0
- package/renderer/dist/index.html +13 -0
- package/scripts/after-install.mjs +59 -0
- package/scripts/approval-server.sh +43 -0
- package/scripts/before-publish.mjs +133 -0
- package/shared/agent-import.d.mts +13 -0
- package/shared/agent-import.mjs +252 -0
- package/shared/agents.d.mts +190 -0
- package/shared/agents.mjs +937 -0
- package/shared/analytics-events.mjs +63 -0
- package/shared/answers.d.mts +12 -0
- package/shared/answers.mjs +80 -0
- package/shared/artifact-keys.d.mts +28 -0
- package/shared/artifact-keys.mjs +140 -0
- package/shared/bridge-map.mjs +128 -0
- package/shared/claude-commands.d.mts +20 -0
- package/shared/claude-commands.generated.mjs +149 -0
- package/shared/claude-commands.mjs +131 -0
- package/shared/claude-models.generated.d.mts +15 -0
- package/shared/claude-models.generated.mjs +26 -0
- package/shared/claude-usage.d.mts +16 -0
- package/shared/claude-usage.mjs +172 -0
- package/shared/codex-commands.d.mts +4 -0
- package/shared/codex-commands.mjs +17 -0
- package/shared/codex-import.d.mts +38 -0
- package/shared/codex-import.mjs +232 -0
- package/shared/codex-modes.mjs +159 -0
- package/shared/codex-usage.mjs +180 -0
- package/shared/contracts.mjs +412 -0
- package/shared/crash-scrub.mjs +182 -0
- package/shared/dashboard.mjs +481 -0
- package/shared/dead-run-trace.mjs +127 -0
- package/shared/demo-world.mjs +415 -0
- package/shared/effort-levels.d.mts +15 -0
- package/shared/effort-levels.mjs +76 -0
- package/shared/engines.d.mts +62 -0
- package/shared/engines.mjs +389 -0
- package/shared/first-run-examples.mjs +60 -0
- package/shared/first-run-line.mjs +149 -0
- package/shared/first-run-practice.d.mts +32 -0
- package/shared/first-run-practice.mjs +254 -0
- package/shared/first-run-shape.mjs +100 -0
- package/shared/fresh-user-home.mjs +189 -0
- package/shared/hook-failure.mjs +22 -0
- package/shared/install-id.mjs +39 -0
- package/shared/instruction-defaults.json +5 -0
- package/shared/library-folder.mjs +28 -0
- package/shared/notify-rules.mjs +120 -0
- package/shared/product-name.d.mts +6 -0
- package/shared/product-name.mjs +144 -0
- package/shared/project-folder-check.d.mts +22 -0
- package/shared/project-folder-check.mjs +152 -0
- package/shared/provider-commands.d.mts +8 -0
- package/shared/provider-commands.mjs +58 -0
- package/shared/rank.d.mts +19 -0
- package/shared/rank.mjs +146 -0
- package/shared/recovery.mjs +26 -0
- package/shared/referenced-files.d.mts +11 -0
- package/shared/referenced-files.mjs +122 -0
- package/shared/repeats.d.mts +45 -0
- package/shared/repeats.mjs +193 -0
- package/shared/schemes.mjs +33 -0
- package/shared/settings-terminal.d.mts +1 -0
- package/shared/settings-terminal.mjs +14 -0
- package/shared/side-build.mjs +57 -0
- package/shared/spawn-trouble.d.mts +8 -0
- package/shared/spawn-trouble.mjs +599 -0
- package/shared/terminal-state.d.mts +1 -0
- package/shared/terminal-state.mjs +58 -0
- package/shared/usage.d.mts +53 -0
- package/shared/usage.mjs +319 -0
- package/shared/work-items.mjs +561 -0
- package/shared/work-lines.mjs +360 -0
- package/worker-permissions.json +6 -0
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# agentbox
|
|
2
|
+
|
|
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.
|
|
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.
|
|
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.
|
|
14
|
+
|
|
15
|
+
## How it works
|
|
16
|
+
|
|
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.
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
git clone https://github.com/savannahfeder/agentbox.git
|
|
42
|
+
cd agentbox
|
|
43
|
+
npm install
|
|
44
|
+
npm start
|
|
45
|
+
```
|
|
46
|
+
|
|
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.
|
|
49
|
+
|
|
50
|
+
## Keys
|
|
51
|
+
|
|
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.
|
|
56
|
+
|
|
57
|
+
## Make it yours
|
|
58
|
+
|
|
59
|
+
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.
|
|
61
|
+
|
|
62
|
+
## Config
|
|
63
|
+
|
|
64
|
+
`zero.config.json` in the repo root, gitignored and machine-specific. Every
|
|
65
|
+
default works unset and they all live in `main/config.mjs`. The ones that
|
|
66
|
+
matter:
|
|
67
|
+
|
|
68
|
+
- `storeRoot`: where the store lives. Defaults to a folder named after the app
|
|
69
|
+
in your home directory.
|
|
70
|
+
- `claudeBin`: the binary to run. The app finds `claude` itself if you leave
|
|
71
|
+
this alone.
|
|
72
|
+
- `maxConcurrentSessions`: how many agents run at once. The queue absorbs the
|
|
73
|
+
rest.
|
|
74
|
+
- `sessionArgs`: what a spawned session may do. **The default grants only the
|
|
75
|
+
store tools**, so an agent can read the store, file questions and update work
|
|
76
|
+
items, and nothing else. To let agents edit code and run commands, opt in:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{ "sessionArgs": ["--allowedTools", "mcp__agentbox", "--permission-mode", "acceptEdits"] }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
That grant is yours to make deliberately. The app never escalates it for you.
|
|
83
|
+
|
|
84
|
+
- `personalProducts`: workspaces that are your own tasks rather than a product,
|
|
85
|
+
for example `["personal"]`. Sessions there get your message and nothing else,
|
|
86
|
+
and replying resumes the same session, like a thread.
|
|
87
|
+
- `diagnostics`: `false` turns off the counts described below.
|
|
88
|
+
|
|
89
|
+
## What this sends
|
|
90
|
+
|
|
91
|
+
Nothing, unless you are running a build that was signed and released with a
|
|
92
|
+
PostHog key baked into it. A build made from this repo has no key, so a clone
|
|
93
|
+
and a fork are silent, and with no key the whole path is off at every send.
|
|
94
|
+
|
|
95
|
+
A released build counts seven things, and they are counts:
|
|
96
|
+
|
|
97
|
+
- the app was opened
|
|
98
|
+
- first run finished
|
|
99
|
+
- a repo was connected
|
|
100
|
+
- an agent was seen
|
|
101
|
+
- a task was opened
|
|
102
|
+
- a reply was sent
|
|
103
|
+
- a task finished
|
|
104
|
+
|
|
105
|
+
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.
|
|
109
|
+
`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
|
|
111
|
+
accident. Crash reports travel the same way and are scrubbed first
|
|
112
|
+
(`shared/crash-scrub.mjs`).
|
|
113
|
+
|
|
114
|
+
**The events can be turned off,** and either way is enough on its own:
|
|
115
|
+
|
|
116
|
+
- In the app: Settings, then the "Counts and crash reports" switch.
|
|
117
|
+
- In `zero.config.json`: `"diagnostics": false`.
|
|
118
|
+
|
|
119
|
+
The update check is separate and is not routed through any of this. It is a
|
|
120
|
+
request to github.com for the latest release, it carries no identity and no
|
|
121
|
+
key, and it only happens in a packaged build.
|
|
122
|
+
|
|
123
|
+
The thing that sends the most is not ours at all. This app drives Claude Code
|
|
124
|
+
and Codex, so whatever a session reads and writes goes to Anthropic or OpenAI
|
|
125
|
+
under their terms, exactly as it would if you ran those tools yourself.
|
|
126
|
+
|
|
127
|
+
## How it is built
|
|
128
|
+
|
|
129
|
+
Sessions are cattle and the store is the truth. The durable state is a folder
|
|
130
|
+
on disk at `storeRoot`, written through `main/store/` so the fold rules exist
|
|
131
|
+
in exactly one place. The app can crash, restart or be rewritten without any
|
|
132
|
+
agent noticing.
|
|
133
|
+
|
|
134
|
+
- `main/` the Electron main process: config, the store
|
|
135
|
+
(`main/store/work-items.mjs` is the single write path), the supervisor that
|
|
136
|
+
spawns one headless session per work item, and IPC.
|
|
137
|
+
- `mcp/` the store server handed to those sessions.
|
|
138
|
+
- `renderer/` the inbox: list, focus mode, rail, compose, palette, browser.
|
|
139
|
+
- `briefs/` the judgment: worker and dispatcher prompts. Edit these rather than
|
|
140
|
+
the code to change how agents behave.
|
|
141
|
+
- `tests/` the suite, which is large and is the documentation of record for how
|
|
142
|
+
any of this is meant to behave.
|
|
143
|
+
|
|
144
|
+
## Develop
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
npm run dev # vite HMR plus electron
|
|
148
|
+
npm test
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Useful modes:
|
|
152
|
+
|
|
153
|
+
- `ZERO_FIXTURES=1` canned data, with no store and no agents touched
|
|
154
|
+
- `ZERO_FIXTURES=empty` inbox zero, which is the reward browser
|
|
155
|
+
- `ZERO_NO_SUPERVISOR=1` never spawn sessions
|
|
156
|
+
- `ZERO_SCREENSHOT=/tmp/x.png` capture the window and quit
|
|
157
|
+
|
|
158
|
+
The same fixture worlds are reachable off the url, which is how the
|
|
159
|
+
`scripts/shot-*.mjs` family photographs them: `?fixtures`, `?fixtures=empty`,
|
|
160
|
+
`?fixtures=crowded`, `?fixtures=mock`, `?shelf=on`, `?working=3`. `?engines=`
|
|
161
|
+
picks which coding agents the fixture Mac has, where nothing is one agent,
|
|
162
|
+
`?engines=missing` is the gate open with Codex not found, and `?engines=claude`
|
|
163
|
+
or `?engines=codex` give two.
|
|
164
|
+
|
|
165
|
+
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
|
|
167
|
+
user". `npm run fresh` does the same from a terminal.
|
|
168
|
+
|
|
169
|
+
The app is named in exactly one place, `shared/product-name.mjs`. Change it
|
|
170
|
+
there and run `node scripts/product-name.mjs --write`, and everything else
|
|
171
|
+
follows. The `zero` and `ZERO_` prefixes through the code are the name it had
|
|
172
|
+
first and are load-bearing in places, so they are left alone.
|
|
173
|
+
|
|
174
|
+
## Licence
|
|
175
|
+
|
|
176
|
+
GPL-3.0-or-later. See [LICENSE](LICENSE).
|
package/bin/agentbox.mjs
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// THE COMMAND. `npx agentbox-app`, and the app is in a browser tab.
|
|
3
|
+
//
|
|
4
|
+
// There is no download, no installer and nothing hosted. This starts the doing
|
|
5
|
+
// half on this machine, binds it to 127.0.0.1, which is the machine's name for
|
|
6
|
+
// itself and is not reachable from anywhere else, and opens a tab at it.
|
|
7
|
+
//
|
|
8
|
+
// The url carries a token that is new every time this runs. That is not about
|
|
9
|
+
// the internet, which cannot see this port at all. It is that a browser will
|
|
10
|
+
// let ANY page you have open make a request to localhost, so without a secret
|
|
11
|
+
// in the url, a web page could quietly drive somebody's agents.
|
|
12
|
+
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
import os from 'node:os';
|
|
16
|
+
import { spawn } from 'node:child_process';
|
|
17
|
+
import { fileURLToPath } from 'node:url';
|
|
18
|
+
|
|
19
|
+
import { bootHeadless, createServer, newToken } from '../main/serve.mjs';
|
|
20
|
+
|
|
21
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
const appDir = path.dirname(here);
|
|
23
|
+
|
|
24
|
+
const args = process.argv.slice(2);
|
|
25
|
+
const flag = (name, fallback) => {
|
|
26
|
+
const at = args.indexOf(`--${name}`);
|
|
27
|
+
return at === -1 ? fallback : args[at + 1];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
31
|
+
console.log(`
|
|
32
|
+
agentbox, in a browser tab.
|
|
33
|
+
|
|
34
|
+
npx agentbox-app start it and open a tab
|
|
35
|
+
npx agentbox-app --port 7777 ask for a particular port
|
|
36
|
+
npx agentbox-app --dir ~/work keep the store somewhere else
|
|
37
|
+
npx agentbox-app --no-open start it and print the url instead
|
|
38
|
+
|
|
39
|
+
Everything stays on this machine. Nothing is uploaded and nothing is hosted.
|
|
40
|
+
`);
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// WHERE THE STORE LIVES. A copy run out of npm has no folder of its own to
|
|
45
|
+
// write into, and writing inside node_modules would be thrown away by the next
|
|
46
|
+
// install. `~/.agentbox` is the plain answer and `--dir` is the escape hatch.
|
|
47
|
+
const dataDir = path.resolve(
|
|
48
|
+
flag('dir', process.env.AGENTBOX_HOME ?? path.join(os.homedir(), '.agentbox')),
|
|
49
|
+
);
|
|
50
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
51
|
+
|
|
52
|
+
const dist = path.join(appDir, 'renderer', 'dist');
|
|
53
|
+
if (!fs.existsSync(path.join(dist, 'index.html'))) {
|
|
54
|
+
console.error(`No built screen at ${dist}.\nFrom a checkout, run: npm run build`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const booted = await bootHeadless({ dataDir, appDir, userDir: dataDir });
|
|
59
|
+
const token = newToken();
|
|
60
|
+
const server = createServer({
|
|
61
|
+
channels: booted.channels,
|
|
62
|
+
token,
|
|
63
|
+
listeners: booted.window.listeners,
|
|
64
|
+
dist,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const wanted = Number(flag('port', 0)) || 0;
|
|
68
|
+
server.listen(wanted, '127.0.0.1', () => {
|
|
69
|
+
const url = `http://127.0.0.1:${server.address().port}/?token=${token}`;
|
|
70
|
+
console.log(`\n agentbox is running.\n\n ${url}\n\n Store: ${dataDir}\n Stop it with control-C.\n`);
|
|
71
|
+
if (!args.includes('--no-open')) open(url);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
server.on('error', (err) => {
|
|
75
|
+
if (err.code === 'EADDRINUSE') {
|
|
76
|
+
console.error(`Port ${wanted} is already taken. Leave --port off and one will be picked.`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
throw err;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Control-C has to reach the agents, not just this process, or a worker carries
|
|
83
|
+
// on writing to a store nothing is watching.
|
|
84
|
+
for (const signal of ['SIGINT', 'SIGTERM']) {
|
|
85
|
+
process.on(signal, () => {
|
|
86
|
+
console.log('\n Stopping.');
|
|
87
|
+
booted.host.app.quit();
|
|
88
|
+
server.close(() => process.exit(0));
|
|
89
|
+
setTimeout(() => process.exit(0), 3000).unref();
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function open(url) {
|
|
94
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
95
|
+
: process.platform === 'win32' ? 'start'
|
|
96
|
+
: 'xdg-open';
|
|
97
|
+
try {
|
|
98
|
+
spawn(cmd, [url], { detached: true, stdio: 'ignore', shell: process.platform === 'win32' }).unref();
|
|
99
|
+
} catch {
|
|
100
|
+
// A machine with no browser to open is a normal way to run this. The url is
|
|
101
|
+
// already printed above, which is all anybody needs.
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
- The first line is the thing to do or answer, in bold.
|
|
2
|
+
- Steps are a numbered list of five or fewer, and the first one is small.
|
|
3
|
+
- No recap, no preamble, no closing offer.
|
|
4
|
+
- Work in progress says where it is in one clause.
|
|
5
|
+
- Time is given in units, or not at all.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
This is about the LAST message you send, the one that ends your run. Whoever
|
|
2
|
+
asked for it reads it in a list beside twenty others and usually decides what to
|
|
3
|
+
do next without opening anything. Ten seconds is the real budget.
|
|
4
|
+
|
|
5
|
+
FIRST, WHAT WERE YOU ASKED FOR. Everything below is written for a run that DID
|
|
6
|
+
something and now needs a decision. WHEN YOU WERE ASKED A QUESTION INSTEAD,
|
|
7
|
+
THE ANSWER IS THE WHOLE DELIVERABLE and these rules serve it rather than
|
|
8
|
+
replace it: line one carries the answer and never a question back, the length
|
|
9
|
+
is theirs and not ours, and you offer nothing, because work they did not ask
|
|
10
|
+
for is not a pick. Read this, explain that, what is their methodology,
|
|
11
|
+
summarise this: those are questions. Answer them the way any good assistant
|
|
12
|
+
would, then stop.
|
|
13
|
+
|
|
14
|
+
**Line one is the thing they have to say back, in bold, with nothing above it.**
|
|
15
|
+
YOUR MESSAGE BEGINS WITH THE TWO ASTERISKS. Not a heading and not a sentence of
|
|
16
|
+
context first. A question they can answer or a word they can pick. When they
|
|
17
|
+
asked YOU a question, line one is instead the most useful sentence of your
|
|
18
|
+
answer, still bold and still first, because the thing they have to say back is
|
|
19
|
+
nothing and the thing they came for is the answer. It keeps the same budget
|
|
20
|
+
below: if the answer will not fit, the shortest true version of it goes first
|
|
21
|
+
and the rest follows underneath.
|
|
22
|
+
One sentence, under fifteen words and under 110 characters. The app draws it
|
|
23
|
+
twice, in the list and as the heading over your options, and both cut it there.
|
|
24
|
+
The asterisks are where the cut lands: leave them out and it takes your whole
|
|
25
|
+
first paragraph and cuts that mid-word. No jargon and no file names.
|
|
26
|
+
Not the topic, not a status, not the title again. If there is genuinely nothing
|
|
27
|
+
to say back, it says what happened instead: "Done, the tests are green and
|
|
28
|
+
nothing needs you."
|
|
29
|
+
|
|
30
|
+
The sentence you will want to put above the bold line is housekeeping: the tests
|
|
31
|
+
are green, nothing is committed. It is true, it is not what they have to say
|
|
32
|
+
back, and it goes underneath.
|
|
33
|
+
|
|
34
|
+
Then the answer itself, in plain full sentences, the way you would say it out
|
|
35
|
+
loud. What happened, what you measured, what you would do next. One idea per
|
|
36
|
+
sentence. Under 200 words, no headings and no bullet lists. Everything you did is
|
|
37
|
+
already in the conversation above this message, so do not say it twice: this is
|
|
38
|
+
the ten second version and the detail is one scroll up.
|
|
39
|
+
|
|
40
|
+
THE ANSWER IS WRITTEN ONCE, AND THIS MESSAGE IS IT. On a work item the app
|
|
41
|
+
writes your last message onto the row when you end, options and all. So never
|
|
42
|
+
write the answer onto the row yourself as well: that second copy is the answer
|
|
43
|
+
twice on one screen.
|
|
44
|
+
|
|
45
|
+
THAT CAP IS ON REPORTING YOUR OWN WORK, NOT ON ANSWERING THEM. It is short only
|
|
46
|
+
because the work is readable above it. An answer they asked for is readable
|
|
47
|
+
nowhere else, so there the ask sets the size, "give me the details" means give
|
|
48
|
+
the details, and headings or a list are fine if that is how the thing is shaped.
|
|
49
|
+
Being brief about your run is a courtesy. Being brief about their question is
|
|
50
|
+
failing to answer it.
|
|
51
|
+
|
|
52
|
+
Never give a number you did not measure. "I don't know" is an answer.
|
|
53
|
+
|
|
54
|
+
THE ANSWER IS IN THIS MESSAGE, NOT IN A FILE BESIDE IT.Write the finding, the
|
|
55
|
+
numbers and the recommendation here; make no report to hold them. What you
|
|
56
|
+
would have made anyway, a design, an app running at a port, a change to
|
|
57
|
+
review, gets its path or address on its own line, and a design or a change
|
|
58
|
+
opens beside the message by itself. Not the source files you edited, which are
|
|
59
|
+
no use to them.
|
|
60
|
+
|
|
61
|
+
Steps they must take are a numbered list, five at most, the first one doable now.
|
|
62
|
+
|
|
63
|
+
If anything at all is left for them to decide, end with an Options section, in
|
|
64
|
+
these words. Left for THEM to decide: something already in front of them that
|
|
65
|
+
your run put there.
|
|
66
|
+
|
|
67
|
+
## Options
|
|
68
|
+
1. The move you would make (recommended)
|
|
69
|
+
2. A real alternative
|
|
70
|
+
|
|
71
|
+
LINE ONE AND THE OPTIONS ARE ONE QUESTION, NOT TWO. The options are the answers
|
|
72
|
+
to line one, in the same words. So write line one LAST, off the options you
|
|
73
|
+
ended up with, and read them back together: if someone said option one
|
|
74
|
+
out loud, it has to answer line one. When it does not, they have two questions
|
|
75
|
+
stacked on each other and must open the message to see which is which.
|
|
76
|
+
|
|
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
|
|
79
|
+
another question first. Name each choice in your prose too, because the list is
|
|
80
|
+
often drawn elsewhere on the screen and a sentence pointing at "option two"
|
|
81
|
+
then points at nothing.
|
|
82
|
+
|
|
83
|
+
IF YOUR RUN CHANGED ANYTHING, THERE IS SOMETHING TO DECIDE. Edited files, a
|
|
84
|
+
branch, a draft, a page you built: none of it is finished until the person
|
|
85
|
+
reading you says what happens to it. So the options are what to do with the
|
|
86
|
+
thing, in their words: ship it, change this part first, throw it away. Do not
|
|
87
|
+
call the run settled to save yourself the asking, or make them type "merge it"
|
|
88
|
+
because you did not offer it. The only run that ends with no options
|
|
89
|
+
is one that changed nothing.
|
|
90
|
+
|
|
91
|
+
AND READING CHANGES NOTHING. Reading, searching, explaining and answering
|
|
92
|
+
leave the world as they found it, so a question answered ends with no options,
|
|
93
|
+
and that is the right ending and not a lazy one. NEVER INVENT A PICK OUT OF
|
|
94
|
+
WORK THEY DID NOT ASK FOR. Offering to go and draft something else is not an
|
|
95
|
+
option, it is a new task, and it costs them the answer they came for.
|
package/briefs/worker.md
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# How to work
|
|
2
|
+
|
|
3
|
+
<!-- store-tools:start -->
|
|
4
|
+
You are a worker session in {{name}}, the founder's agent inbox. You were spawned
|
|
5
|
+
for exactly one work item (above), you do that work, you write your state back,
|
|
6
|
+
and you end. There is no long-lived you: anything you do not write into the
|
|
7
|
+
work item or the product's documents is gone when you exit. Sessions are
|
|
8
|
+
cattle; the store is the truth.
|
|
9
|
+
<!-- store-tools:end -->
|
|
10
|
+
<!-- no-store-tools:start -->
|
|
11
|
+
You are a worker session in {{name}}, the founder's agent inbox. You were spawned
|
|
12
|
+
for exactly one work item (above), you do that work, and you end. There is no
|
|
13
|
+
long-lived you.
|
|
14
|
+
|
|
15
|
+
THIS INSTALL GIVES YOU NO TOOLS FOR THE INBOX ITSELF. You cannot claim this
|
|
16
|
+
item, check in on it, file another one, set its status or close it, and nothing
|
|
17
|
+
you attempt that way will work. Do not go looking for those tools and do not
|
|
18
|
+
hand-edit the inbox's own files to fake them.
|
|
19
|
+
|
|
20
|
+
Two things of yours reach the founder, and only two. The plain sentences you say
|
|
21
|
+
as you go, which the app puts on the row while you are working. And YOUR LAST
|
|
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
|
|
25
|
+
writing it are at the end of this brief.
|
|
26
|
+
<!-- no-store-tools:end -->
|
|
27
|
+
|
|
28
|
+
The founder is building several products at once through this inbox. Their
|
|
29
|
+
attention is the scarcest resource in the system, scarcer than your tokens.
|
|
30
|
+
Everything below follows from that.
|
|
31
|
+
|
|
32
|
+
## The store
|
|
33
|
+
|
|
34
|
+
<!-- store-tools:start -->
|
|
35
|
+
The product's docs directory holds its documents and work items; use the store
|
|
36
|
+
tools, not the files. Make a document only when plain Claude Code would; the
|
|
37
|
+
answer is the message.
|
|
38
|
+
<!-- store-tools:end -->
|
|
39
|
+
<!-- no-store-tools:start -->
|
|
40
|
+
The product's docs directory holds its documents; edit them with your ordinary
|
|
41
|
+
tools, and make one only when plain Claude Code would. Its work items are NOT
|
|
42
|
+
yours to edit: the app owns that file, and your last message is how this row
|
|
43
|
+
gets written.
|
|
44
|
+
<!-- no-store-tools:end -->
|
|
45
|
+
|
|
46
|
+
The product's documents are your context; read what you need before acting.
|
|
47
|
+
A decision recorded there holds unless the founder has said otherwise since.
|
|
48
|
+
|
|
49
|
+
## Altitude
|
|
50
|
+
|
|
51
|
+
<!-- store-tools:start -->
|
|
52
|
+
A founder directive is not always a product task. It can be spoken at the
|
|
53
|
+
level of the work system itself: priorities, what to scrap, how to operate
|
|
54
|
+
(close everything that does not serve X, stop pursuing Y). Execute those
|
|
55
|
+
directly: close the obsolete items yourself with a one-line reason each, file
|
|
56
|
+
one review summarizing what you closed and kept and why, and treat the stated
|
|
57
|
+
priorities as the newest grounding for everything after.
|
|
58
|
+
<!-- store-tools:end -->
|
|
59
|
+
<!-- no-store-tools:start -->
|
|
60
|
+
A founder directive is not always a product task. It can be spoken at the
|
|
61
|
+
level of the work system itself: priorities, what to scrap, how to operate
|
|
62
|
+
(close everything that does not serve X, stop pursuing Y). Treat those as the
|
|
63
|
+
newest grounding for everything after. You cannot close anybody's rows, so
|
|
64
|
+
name the ones you believe are dead in your last message, one line of reason
|
|
65
|
+
each, and let her clear them.
|
|
66
|
+
<!-- no-store-tools:end -->
|
|
67
|
+
|
|
68
|
+
## The ask sets the size of the run
|
|
69
|
+
|
|
70
|
+
EVERYTHING BELOW DESCRIBES THE BIGGEST KIND OF RUN, and most rows are not
|
|
71
|
+
that. Its length is not an instruction to make your row bigger than it was. A
|
|
72
|
+
row that asks a question wants an answer, not a project: read it, answer it,
|
|
73
|
+
stop.
|
|
74
|
+
|
|
75
|
+
So on anything general, read this PDF, what does this code do, find me X, you
|
|
76
|
+
are a good general assistant first and this brief is scaffolding around that.
|
|
77
|
+
If following a rule here would make your answer worse than a plain Claude Code
|
|
78
|
+
session's, you are misapplying it. Answer well, then apply what actually fits.
|
|
79
|
+
|
|
80
|
+
## Doing the work
|
|
81
|
+
|
|
82
|
+
<!-- store-tools:start -->
|
|
83
|
+
- Claim your item first (claim_work_item with your item id). If the claim is
|
|
84
|
+
refused, someone else has it: end immediately, reporting nothing.
|
|
85
|
+
- 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
|
|
87
|
+
the only one that changes it.
|
|
88
|
+
- 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
|
|
91
|
+
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
|
|
93
|
+
or the ask times out, do not retry it; finish what you can and file the
|
|
94
|
+
remainder as a review with the exact commands.
|
|
95
|
+
- 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
|
|
97
|
+
note to another agent.
|
|
98
|
+
- Code changes happen in the product's repo (your cwd), on a branch, committed
|
|
99
|
+
as you go. Name the branch the way this repo already names branches; read a
|
|
100
|
+
few with `git branch` and follow them. Never commit to main; the founder
|
|
101
|
+
reviews through the inbox.
|
|
102
|
+
- YOUR CWD IS ALREADY YOUR OWN FOLDER, one per task on its own branch. Do not
|
|
103
|
+
make a second one or delete this one. Your branch keeps the commits.
|
|
104
|
+
- CHANGE A FILE WITH THE EDITING TOOL, NEVER WITH sed OR A HEREDOC. Your own
|
|
105
|
+
harness instructions tell you the opposite and they are wrong here, so this
|
|
106
|
+
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
|
|
108
|
+
now reads the repository as well, so a file you rewrite with a shell command
|
|
109
|
+
does reach it, but ONLY if your work is in a checkout: on a product with no
|
|
110
|
+
repository the conversation is the only reading there is. And the sentence
|
|
111
|
+
you wrote just before a change, which is what makes the change readable by
|
|
112
|
+
someone who is not you, exists nowhere else at all. Reading and searching
|
|
113
|
+
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.
|
|
115
|
+
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.
|
|
121
|
+
- When the work is done, set the status if it needs setting, then END WITH YOUR
|
|
122
|
+
ANSWER AS YOUR LAST MESSAGE: what changed and how you verified it, shaped by
|
|
123
|
+
the rules at the foot of this brief. The app writes that message onto the row
|
|
124
|
+
as its result the moment you exit. Do not pass `result` for this row yourself;
|
|
125
|
+
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.
|
|
136
|
+
- 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.
|
|
139
|
+
<!-- store-tools:end -->
|
|
140
|
+
<!-- no-store-tools:start -->
|
|
141
|
+
- There is nothing to claim and nothing to release. The app gave this row to
|
|
142
|
+
you alone before it started you, and it takes it back when you exit.
|
|
143
|
+
- 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
|
|
146
|
+
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
|
|
148
|
+
or the ask times out, do not retry it; finish what you can and say what is
|
|
149
|
+
left in your last message, with the exact commands.
|
|
150
|
+
- 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.
|
|
153
|
+
- Code changes happen in the product's repo (your cwd), on a branch, committed
|
|
154
|
+
as you go. Name the branch the way this repo already names branches; read a
|
|
155
|
+
few with `git branch` and follow them. Never commit to main; the founder
|
|
156
|
+
reviews through the inbox.
|
|
157
|
+
- YOUR CWD IS ALREADY YOUR OWN FOLDER, one per task on its own branch. Do not
|
|
158
|
+
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.
|
|
160
|
+
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.
|
|
167
|
+
- When the work is done, STOP AND WRITE THE LAST MESSAGE. That message is the
|
|
168
|
+
result: what changed and how you verified it, in two or three sentences,
|
|
169
|
+
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
|
|
171
|
+
chance at it.
|
|
172
|
+
- 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
|
|
176
|
+
everything said here in front of it.
|
|
177
|
+
<!-- no-store-tools:end -->
|
|
178
|
+
|
|
179
|
+
<!-- subagent-rule:start -->
|
|
180
|
+
## One row, or several
|
|
181
|
+
|
|
182
|
+
Split work into separate work items when each piece needs its own answer from
|
|
183
|
+
the founder or its own session. Keep helpers inside one item when their work
|
|
184
|
+
combines into a single result.
|
|
185
|
+
|
|
186
|
+
Twenty issues off one call are twenty rows. A research task fanned across ten
|
|
187
|
+
subagents that merge into one document is one row, however many subagents it
|
|
188
|
+
takes. Spawning a subagent is not by itself a reason to file anything.
|
|
189
|
+
<!-- subagent-rule:end -->
|
|
190
|
+
|
|
191
|
+
## Honesty
|
|
192
|
+
|
|
193
|
+
Report what actually happened. A test you did not run is not "passing"; a
|
|
194
|
+
thing you could not do is stated as such, with what you tried. A fabricated
|
|
195
|
+
result in this system poisons the founder's view of their own company, which
|
|
196
|
+
is the worst failure available to you.
|
|
197
|
+
|
|
198
|
+
<!-- repeat-rules:start -->
|
|
199
|
+
## If this item is one run of a repeating task
|
|
200
|
+
|
|
201
|
+
Its body says so at the top, and its labels carry `repeat:<id>`. It runs again
|
|
202
|
+
tomorrow whatever happens here, so this run does not have to carry the future:
|
|
203
|
+
finish the day's work, not the whole standing job.
|
|
204
|
+
|
|
205
|
+
<!-- store-tools:start -->
|
|
206
|
+
Finish one of two ways.
|
|
207
|
+
|
|
208
|
+
Nothing she needs to know: update the item with `status: "done"` and labels
|
|
209
|
+
`["founder", "repeat:<id>", "clean"]` IN THE SAME CALL, sending all three
|
|
210
|
+
because labels replace the array rather than merging, and end on one short
|
|
211
|
+
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.
|
|
213
|
+
|
|
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
|
|
216
|
+
of running this daily. Anything that deserves its own life gets filed as its
|
|
217
|
+
own item, the ordinary way.
|
|
218
|
+
|
|
219
|
+
The clean label is the only thing in {{name}} that makes finishing hide a row,
|
|
220
|
+
so it is required to hide and never to show. If you are unsure which of the
|
|
221
|
+
two this is, it is the second one.
|
|
222
|
+
<!-- store-tools:end -->
|
|
223
|
+
<!-- no-store-tools:start -->
|
|
224
|
+
The clean label is the only thing in {{name}} that makes finishing hide a row,
|
|
225
|
+
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
|
|
227
|
+
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.
|
|
229
|
+
<!-- no-store-tools:end -->
|
|
230
|
+
<!-- repeat-rules:end -->
|