@dirwin517/bot-farm 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,437 +1,299 @@
1
- # botfarm
1
+ <div align="center">
2
2
 
3
- A kanban style process manager for [opencode](https://opencode.ai) sessions: run several agents at once,
4
- watch what they are burning, steer them without entering them, and — if you allow it — let them talk
5
- to each other.
3
+ # 🌾 BotFarm
6
4
 
7
- ```
8
- npm link # or: node src/cli.mjs up
9
- botfarm up # starts opencode serve if needed, opens the dashboard
10
- ```
5
+ ### Run a whole team of AI coding agents — and watch them work the field.
11
6
 
12
- The dashboard is at `http://127.0.0.1:4777`. No dependencies; Node 20+ and `git`.
7
+ A kanban-style process manager and dashboard for [opencode](https://opencode.ai) sessions.
8
+ Run several agents at once, see what they're burning, steer them without jumping in,
9
+ and — if you allow it — let them talk to each other.
13
10
 
14
- ---
11
+ [![npm](https://img.shields.io/npm/v/@dirwin517/bot-farm?color=4c6ef5&label=npm)](https://www.npmjs.com/package/@dirwin517/bot-farm)
12
+ [![node](https://img.shields.io/badge/node-%E2%89%A520-3c873a)](https://nodejs.org)
13
+ [![dependencies](https://img.shields.io/badge/dependencies-0-f59f00)](package.json)
14
+ [![license](https://img.shields.io/badge/license-MIT-7950f2)](LICENSE)
15
15
 
16
- ## BotFarm: workspaces and workstreams
17
-
18
- The dashboard is organised around two things:
19
-
20
- - **Workspace** — a folder and its opencode config. The first one is the folder you start BotFarm in
21
- (change it with `"defaultWorkspace"` in `~/.botfarm/config.json` or `botfarm up --workspace <dir>`); open
22
- more with the folder browser under the workspace name. A workspace's bots are defined at
23
- its root, created with the built-in set if missing — a `botfarm/` folder with one file per definition,
24
- named after its id:
25
- - `botfarm/<id>.agent.botfarm.yml` — one agent: `{ title, role, prompt, model?, variant?, tools?, tiers?, may_spawn? }`
26
- - `botfarm/<id>.pipeline.botfarm.yml` — one pipeline: `{ title, description?, limits?, stages: [{ id, title?, persona | human: true, receives: [stage ids], after?: [stage ids], split?: tasks, parallel?, difficulty?, limits?: { minutes, tokens, usd }, prompt }] }`
27
- - `botfarm/routing.botfarm.yml` — model routing by difficulty (off until `enabled: true`)
28
- - `botfarm/mcps/*.js` — your own tools, served to every bot in the workspace (see below)
29
-
30
- Older `botfarm-agents.yml` / `botfarm-pipeline.yml` files are split into these on first start and kept as
31
- `.bak`. Edit them in the app (Pipelines / Agents in the sidebar, as a form or as that one file's YAML) or
32
- by hand; hand edits are picked up without a restart.
33
- - **Workstream** — one story going through one pipeline. Starting a pipeline always makes a new
34
- workstream with its own branch and worktree, its own team of bots, its own channel and its own board.
35
- Two DoUserStory runs are two workstreams side by side. A workstream keeps the pipeline definition it
36
- started with, so editing the pipeline later changes only new workstreams.
37
-
38
- **Parallel work.** A stage normally starts when the one before it hands off. Give it
39
- `after: [stage ids]` to start as soon as those are done instead — dev and QA both `after: [analyse]`
40
- build and write tests side by side (TDD), and a stage `after: [build, tests]` waits for both.
41
- `split: tasks` on a stage fans it out: the stage it waits on is asked for a `tasks` list
42
- (`[{ title, detail }]`) on its handoff, each item becomes its own card, and up to `parallel: N` bots of
43
- that kind (default 3, max 10; overridable when you start the workstream) work them at once in the same
44
- worktree — extra bots are added to the team as needed. The next stage waits for every piece and gets
45
- their handoffs joined. Use `{{#item}}{{title}} {{detail}}{{/item}}` in the split stage's prompt, or let
46
- BotFarm add "Your part — n of N" itself. See the `story-parallel` example.
47
-
48
- **Limits.** `limits: { minutes, tokens, usd }` on a stage applies to each of its cards (each piece of a
49
- split); `limits:` on a pipeline, or the Limits box when you start one, applies to the whole workstream.
50
- When a card reaches a limit its bot is stopped and the card waits in Needs you (Continue gives half as
51
- much again, Set limits… for exact numbers, or Stop); when the workstream reaches one every bot on it
52
- stops until you raise it. Limits can be changed any time from the workstream header.
53
-
54
- The workstream page has the team down the left (grouped by kind, live status and spend), the board
55
- with the chat under it, and a **Farm** view of the same board: cards are crops moving from the shed to
56
- the field to the silo, and each bot walks to the card it is working on.
57
-
58
- **BotFarm's MCP server** is called `botfarm`: bots see `botfarm_task_complete`, `botfarm_room_post`,
59
- `botfarm_notes_read` and so on (it used to be `botfarm`; old worktrees are renamed automatically).
60
-
61
- **Your own tools.** Every `.js` file in `botfarm/mcps/` exports `name`, `description`, `inputSchema` and
62
- `execute(args, ctx)` and becomes `botfarm_<name>` for the workspace's bots. `ctx.repoRoot` is the calling
63
- bot's worktree, `ctx.exec(cmd, args)` runs a program there, `ctx.log(...)` writes to the test bench. Saving
64
- a file reloads it; bots get the new list on their next idle moment. **Tools** in the sidebar is the test
65
- bench: a form from the schema (or raw JSON), where to run it, the result and log, and the source to edit.
16
+ #### Install as easy as
17
+ ```
18
+ npm i -g @dirwin517/bot-farm
19
+ ```
20
+ #### Running as easy as
21
+ ```
22
+ bot-farm
23
+ ```
66
24
 
67
- **Switching a bot's model.** Model… in a bot's panel picks another model and reasoning level for that bot
68
- from its next turn (Opus for a hard fix, Sonnet or Haiku to save money), kept across restarts, without
69
- touching the agent file.
70
-
71
- **Keeping it cheap — no paid model involved in any of these:**
72
- - *Routing by difficulty*: each card is sized easy / normal / hard from its words, length and criteria
73
- (or `difficulty:` on a stage or split piece) and gets the model from `routing.botfarm.yml` or the agent's
74
- `tiers:`. The card shows its size and model. All of it is editable in the app: **Model routing** in
75
- the sidebar, **Difficulty** on each stage in the pipeline editor, **Model by difficulty** in the agent editor.
76
- A tier can cap its model — *Quota and fallback*: e.g. up to $5 a day on Opus, then Sonnet (also tokens or
77
- minutes, per day / week / month / workstream). Spend is counted per workspace per model; once it runs out,
78
- new cards take the fallback and bots already on it move over, at once or on their next turn.
79
- *Per agent*: an agent's `tiers:` override the workspace rules size by size (give only the reviewer its
80
- own `hard:` and it still uses the workspace's easy/normal), and apply even with workspace routing off.
81
- An agent's own quota counts only that agent's spend (e.g. "the reviewer gets $3/day of Opus"); a
82
- workspace quota counts everyone's. **Model routing → What each agent gets** shows the effective model,
83
- reasoning, quota and where each came from, per agent and size. One-line YAML maps
84
- (`quota: { usd: 3, per: day }`) work in hand-edited files.
85
- - *Apply to my repos*: from the harvest (**Apply to my repos…**) or any time after (**Apply to repos…** in the
86
- workstream header), every repo in the workstream — parent, services, linked repos — becomes a patch of what
87
- its worktree has that your checkout does not (edits, new files, commits on the branch, from the merge-base),
88
- leaving out BotFarm's own files. The dialog shows, per repo, where it goes (path and current branch), the
89
- files, whether it applies cleanly / needs a 3-way merge / will conflict / is already there, and warns about
90
- your own uncommitted edits to the same files. Applying never commits or stages a clean patch: it lands as
91
- working-tree changes to review and commit yourself. Otherwise it falls back to a 3-way apply (conflict
92
- markers) and then `--reject` (.rej files). **Undo last apply** reverses the clean ones. Patches are kept in
93
- `.botfarm/workstreams/<id>.patches/` and can be downloaded. API: `GET /api/projects/:id/patches`,
94
- `…/patches/file?rel=`, `POST …/patches/apply {repos?}`, `POST …/patches/undo`.
95
- - *Repos from anywhere*: a workstream's worktree can hold repos from outside the workspace. **Add repo**
96
- in the new-workstream dialog (e.g. `~/workspace/spt`, optional folder name) links it to the workspace;
97
- each workstream it is ticked for gets a worktree of it on the same branch, mounted at `<worktree>/spt/`
98
- (hidden from the parent's git status via `info/exclude`). **+ Repo** on a running workstream adds one after
99
- the fact; the bots are told in the chat, the team notes and every card ("Repos in this worktree").
100
- Card diffs, snapshots, PR stats and deleting the workstream (worktrees and `botfarm/` branches) cover them.
101
- API: `POST /api/workspaces/:id/repos {path, as?, running?}`, `DELETE …/repos?path=`, `POST /api/projects/:id/repos {path, as?}`.
102
- Docker MCPs see it only if the path is under a mounted folder (`~/workspace`, `~/worktrees`).
103
- - *Send back (fix loops)*: Plan → Code → Verify → Fail → Code → Verify → Pass. A checker that finds a
104
- failing test, broken build or missed criterion calls `botfarm_send_back { task_id, to, reason, failures, files }`
105
- instead of fixing it. The earlier card goes back to To do with what failed and its last handoff kept
106
- ("↩ round 2"), preferring the bot that did it (another bot of that kind takes it after ~90s if that one is
107
- busy or gone); the checker's card waits and comes back to the same checker to verify ("↻ verify 2"). For a
108
- split stage only the pieces that touched the named files go back, or a new "Fix:" piece is added. Any
109
- earlier stage is a valid target unless the stage says `send_back: [build]` or `send_back: false`;
110
- `max_rounds` (per stage or pipeline, default 3, also in the pipeline editor as *Fix rounds*) caps it, and
111
- the same failure twice stops too — then you choose *One more round*, *Accept as is* or *Stop*. You can
112
- send a done card back yourself: drag it to To do, or *Send back…* on the card. Fix rounds earn little XP;
113
- the checker gets a little for catching them.
114
- - *Loop detection* counts a call as repeated only when the tool **and every argument** match (a fingerprint of
115
- the whole input, key order ignored) — three greps for different things are work. An edit in between resets
116
- the count, so build → fix → build is fine.
117
- - *Trimmed handoffs*: the next bot reads a brief (long code blocks become pointers, repeats go, cut at
118
- ~1800 characters); `botfarm_handoff(stage)` fetches the full text. For a local model instead, set
119
- `"handoffs": { "local": { "url": "http://localhost:11434", "model": "qwen2.5:3b" } }` in
120
- `~/.botfarm/config.json` (falls back to the rules).
121
- - *Team notes*: `botfarm_notes_write` / `botfarm_notes_read`; every card lists the notes and the files
122
- teammates already read.
123
- - *Loop stop*: the same call three times, five failures in a row, or ~250k tokens without an edit pauses
124
- the card and asks you (`"loops": { "tokensWithoutEdits": N }` to tune).
25
+ <img src="imgs/FARM.png" alt="The Farm view: bots walk from the farmhouse to the crops they're working on" width="100%">
125
26
 
126
- **Card events in the chat.** Every finished card posts a card to the channel: who did it, how long it
127
- took, tokens, cost, model, XP, every file that changed on disk while it ran, with the diff from where the file stood when the card
128
- began — whatever changed it: opencode's tools, an MCP server, a script (files it did not list in its
129
- handoff are marked) — open *Changes*, and any screenshots (images among its files, or image results from its tools; click to
130
- enlarge). Split stages post one more when all their pieces are in. These never wake the other bots.
131
-
132
- **Pause / Resume** in a workstream's header stops every bot on it (mid-card) until you resume; resuming
133
- tells each stopped bot to pick its card up again.
134
-
135
- **When a workstream finishes**: a *PR packet* (`.botfarm/workstreams/<id>.pr.md` — criteria with the tests
136
- behind them, files, commits, how to test, open questions, cost; **Open PR…** pushes and runs `gh pr
137
- create`), a *harvest* (a small celebration and a line in the home page's harvest log) and XP.
27
+ <sub>The <b>Farm</b> view — every card is a crop, every bot walks to the one it's working on.</sub>
138
28
 
139
- **Levels.** Each kind of bot earns XP per workspace for clean work only — a handoff, no pauses, under
140
- budget, nothing left open. Levels bring hats on the farm and small perks: level 3 +10% card limits,
141
- level 5 the first limit hit extends itself once, level 8 +20%.
29
+ </div>
142
30
 
143
- **Replays.** Replay on a workstream scrubs through everything that happened (farm, team, chat). Save
144
- replay file gives one portable JSON; open it from the home page of any BotFarm.
31
+ ---
145
32
 
146
- A stage with open questions still hands off: the questions go to the next stage with its card. Set
147
- `hold_on_questions: true` on a stage (or "wait for me" in the editor) to stop there until you press
148
- **Continue** on the card, optionally with answers that every later stage receives.
33
+ > ## ⚠️ Big, important, please-actually-read-this disclaimer
34
+ >
35
+ > **BotFarm drives AI agents. AI makes mistakes.** Sometimes small ones, sometimes confident,
36
+ > creative, spectacular ones.
37
+ >
38
+ > These bots can run commands, edit and delete files, push branches and talk to each other,
39
+ > all with whatever access *you* give them. If a bot:
40
+ >
41
+ > - 🔥 deletes everything you own (your repo, your home folder, your will to live on a Friday afternoon),
42
+ > - 🤗 decides to "just quickly" hack into Hugging Face, or anywhere else,
43
+ > - 💸 burns through your cloud budget chasing a flaky test for six hours,
44
+ > - 🐐 orders 400 goats to your house because the acceptance criteria said "herd the requests",
45
+ > - 🤖 or does anything else unexpected, unwise or illegal,
46
+ >
47
+ > …**that is not my fault.** You started the farm; you own what it harvests.
48
+ >
49
+ > **Use it at your own discretion, and with supervision:**
50
+ >
51
+ > - Keep an eye on your bots. Don't leave them unattended with access you'd regret.
52
+ > - Run them in worktrees, containers or sandboxes, never with production credentials.
53
+ > - Set [limits](#limits) so they stop and ask before spending too much.
54
+ > - Review every change before it reaches your real repos. That's why [Apply to my repos](#apply-to-my-repos) never commits for you.
55
+ >
56
+ > BotFarm is provided **"as is", without warranty of any kind**. See the [MIT License](LICENSE).
57
+ > By using it you accept all responsibility for what your bots do.
149
58
 
150
- Questions for you look like the ones Claude and opencode ask: a bot's `botfarm_ask_human` (or a held
151
- stage's open questions) can offer choices per question — pick one, or several — and every question can
152
- also be answered in your own words; a question without choices is open-ended. They appear at the bottom
153
- of the chat and on the card, answerable in place.
59
+ ---
154
60
 
155
- An agent's `tools:` list is enforced on every turn (everything else built in is switched off; the botfarm
156
- tools stay on). The built-in product agent is read-only and told to polish the criteria it is given,
157
- not to study the code — that is the dev's job. Unedited built-ins in an existing workspace are moved to
158
- the current ones on start; anything you changed is left alone.
61
+ ## ✨ Why BotFarm?
159
62
 
160
- A workstream's page is a kanban (To do, Doing, Needs you, Done — drag cards between them) next to its
161
- group chat. Posting there reaches the whole team, or only the bots you @mention; bots whose stage has
162
- not started read it with their first card. Click a bot to watch its transcript live, or a card for its
163
- handoff, criteria and open questions. `+ Card` and `+ Bot` add work and teammates by hand; Archive
164
- stops the bots and puts the workstream away.
63
+ - 🧑‍🤝‍🧑 **A team, not a chat window.** Product, dev, QA and reviewer bots work one story together, each on its own card, handing off to the next.
64
+ - 🗂️ **One board per story.** Every workstream gets its own branch, worktree, team, chat and kanban.
65
+ - 💸 **Always know the bill.** Live tokens, cost and limits per card and per workstream — bots stop and ask before they overspend.
66
+ - 🧠 **Cheap by default.** Route easy cards to cheap models and save the big one for hard work. No paid model decides.
67
+ - 🔁 **Real fix loops.** QA can send work back to dev with what failed — Plan → Code → Verify → Fail → Code → Pass.
68
+ - 🙋 **You stay in charge.** Questions land in *Needs you*; stages can wait for your sign-off; nothing is applied to your real repo until you say so.
69
+ - 🪶 **Zero dependencies.** Node 20+ and `git`. That's it.
165
70
 
166
- Each workstream also writes `.botfarm/workstreams/<id>.yml` in the workspace (excluded from git
167
- locally): its branch, worktree, story, stage statuses, and the opencode session id of every bot — plus
168
- the ones they replaced. On start botfarm re-adopts any bot its own state has forgotten, and recreates a
169
- workstream it has no record of, so a lost `~/.botfarm` or a new machine gets the team back.
71
+ ---
170
72
 
171
- The previous dashboard is still at `/classic` for everything else (adopting sessions, rooms, the
172
- global board).
73
+ ## 🚀 Quick start
173
74
 
174
- ## The board is a registry, not a listing
75
+ ```bash
76
+ npm install -g @dirwin517/bot-farm # or, from a clone: npm link
77
+ botfarm up # starts opencode serve if needed and opens the dashboard
78
+ ```
175
79
 
176
- opencode accumulates every session you have ever opened. Listing them all turns the dashboard into an
177
- archive browser — 250 cards, none of them what you are working on. botfarm shows only sessions it
178
- manages: ones it started, plus ones you explicitly add with **Add existing…**. The rest sit behind a
179
- one-line banner offering them. `Remove` puts a session back in that pool; it never deletes anything.
80
+ Then open **http://127.0.0.1:4777** and hit **Start a workstream**.
180
81
 
181
- The registry is also where botfarm keeps the metadata opencode has no place for: group, label, mesh
182
- policy, lineage, disabled tools. It lives in `~/.botfarm/registry.json`.
82
+ > **Want to try it without spending tokens?** Run `node test/mock-opencode.mjs` in one terminal and
83
+ > `botfarm up` in another — you'll get a fully populated board driven by a fake opencode server.
183
84
 
184
- ## Projects
85
+ ---
185
86
 
186
- A project is the thing you actually work on: a checkout, the sessions working in it, the tasks they
187
- are working through, and the conversation they are having about it. Those used to be four separate
188
- ideas here — a group, a worktree, a board and a room — which meant four things to create before
189
- anything could happen. They are one object now.
87
+ ## 🖼️ A quick tour
190
88
 
191
- Opening a project gives you all of it on one screen: who is working and what they are doing, that
192
- project's kanban board, and that project's chat with a composer, side by side. Creating a project
193
- creates its chat; moving a session into a project moves it into that chat; the project's board is
194
- its tasks. The global board is still there as a view across every project, rather than as the
195
- primary one.
89
+ ### 1. Pick a workspace, see all your workstreams
196
90
 
197
- A pipeline run creates its project, so starting one is the only step.
91
+ A **workspace** is a folder and its opencode config. Each **workstream** is one story on its own branch,
92
+ with its own bots, chat and board — run as many side by side as you like.
198
93
 
199
- ## The board
94
+ <img src="imgs/MultiTeamRuns.png" alt="Workspace home page showing four workstreams, each with its own team of bots" width="100%">
200
95
 
201
- Every session is a card: identity, worktree, two sparklines (tokens/min and tools/min over the last
202
- hour), the closing sentences of the last message so you can see what you would be continuing, and the
203
- controls you actually reach for. Click one and you get a centred modal: the full scrollable
204
- transcript with a composer on the left, stats, cost, tools and mesh settings on the right.
96
+ ### 2. Start a workstream
205
97
 
206
- - **Continue without entering** — type into the box on the card and press enter. The prompt is queued
207
- on that session; you never leave the board.
208
- - **Abort** — one session, or all running sessions from the header.
209
- - **Inspect** — slides open the usage breakdown, tool timeline with durations, changed files, peers
210
- and transcript.
211
- - Cards sort by attention: running, then waiting on a permission, then errored, then idle.
98
+ Choose a pipeline, paste the story (with its acceptance criteria), pick which repos go in the worktree,
99
+ and optionally set a budget. Every bot gets the full story.
212
100
 
213
- ### Transport
101
+ <img src="imgs/StartWorkStream.png" alt="Start a workstream dialog: pipeline, story, branch, repos and limits" width="100%">
214
102
 
215
- The dashboard is pushed to over a websocket (`/api/socket`), falling back to server-sent events if
216
- the socket will not connect. Neither polls. Actions stay on plain HTTP: they are one-shot, they want
217
- status codes and retries, and multiplexing them over the socket would mean reinventing request ids
218
- and error handling that `fetch` already has.
103
+ ### 3. Watch the board
219
104
 
220
- botfarm's own traffic to opencode is event-driven too. Session status comes from the event stream, and
221
- the periodic checks are reconciliation rather than the mechanism — they run when the stream goes
222
- quiet or a session looks stale. A board with nothing happening makes **zero** requests per second;
223
- with the stream down the polling loop comes back automatically.
105
+ The team runs down the left with live status and spend. The board shows every card moving through
106
+ **To do → Doing → Needs you → Done**, with the team's group chat underneath. Flip to **Farm** for the fun version.
224
107
 
225
- Request bodies are negotiated rather than pinned. opencode's prompt endpoint moved from
226
- `{parts: [...]}` to `{prompt: {text}}`, so botfarm tries the known shapes, keeps the index of the one
227
- that worked, and reports clearly if none is accepted.
108
+ <img src="imgs/KanBan.png" alt="Kanban board with the team list, cards per stage and the group chat" width="100%">
228
109
 
229
- Metrics come from each session's message list, not from event payloads. opencode's HTTP surface is
230
- experimental and event names have already changed once; assistant messages always carry their own
231
- usage and tool calls are always parts with stable ids. The event stream only says *something changed
232
- in session X* — the message diff does the counting. The client also sniffs the v1/v2 path dialect at
233
- connect time, so a rename of `/session` to `/api/session` doesn't break it.
110
+ ### 4. Look over a bot's shoulder
234
111
 
235
- ## Worktrees and multi-repo projects
112
+ Click any bot to see its live transcript, tokens, cost, MCP servers and worktree. Talk to it directly,
113
+ switch its model, stop it, or move its card.
236
114
 
237
- A session is a pod; a pod can own a git worktree so parallel agents never fight over one checkout.
115
+ <img src="imgs/KanBanChat.png" alt="A bot's live transcript panel with model, tokens, tool calls and a direct-message box" width="100%">
238
116
 
239
- Paths are expanded the way a shell would: `~/workspace/app`, `$HOME/app` and relative paths all work.
240
- Before anything is created, the dialogs probe the path and tell you what is there — a missing
241
- directory and a directory that is not a repository are different problems and say so.
117
+ ### 5. Shape your pipelines and agents
242
118
 
243
- **Projects that contain other repositories** — a parent repo with the services cloned into a
244
- gitignored folder — get one worktree per repository, laid out exactly like the original tree: a
245
- worktree of the parent, and a worktree of each selected service at the same relative path inside it.
246
- Every repo ends up on its own branch and the agent sees the directory structure it expects. The
247
- dialog lists the nested repositories it found (git will not mention them, since the parent ignores
248
- them) and you tick the ones in scope; leaving them all unticked gives you the parent alone.
119
+ Pipelines and agents are plain YAML files in your repo — edit them as forms in the app, or flip to the
120
+ YAML tab for anything the form doesn't cover.
249
121
 
250
- Changed-files and diffs aggregate across all of them, each file tagged with the repo it belongs to,
251
- and removing a session removes every worktree it created without touching your original checkouts.
122
+ <table>
123
+ <tr>
124
+ <td width="50%"><img src="imgs/WorkStreams.png" alt="Pipeline editor with stages, owners, difficulty, limits and prompt"></td>
125
+ <td width="50%"><img src="imgs/BotConfig.png" alt="Agent editor with name, role, model, reasoning, tools and instructions"></td>
126
+ </tr>
127
+ <tr>
128
+ <td align="center"><sub><b>Pipeline editor</b> — stages, who does them, what they receive</sub></td>
129
+ <td align="center"><sub><b>Agent editor</b> — model, reasoning, tools and brief</sub></td>
130
+ </tr>
131
+ </table>
252
132
 
253
- ```
254
- botfarm new ~/code/app --branch fix/auth-redirect --task "Fix the redirect loop after SSO login"
255
- ```
133
+ ### 6. Keep it cheap
256
134
 
257
- That creates the worktree (under `~/worktrees/<repo>/<branch>` unless you set `BOT_FARM_WORKTREE_ROOT`),
258
- opens a session located there, and sends the first instruction. Each card shows the branch and a live
259
- `+142 −18 · 7 files` from `git status`. `botfarm rm <id> --worktree` removes both.
135
+ Route each card to a model by difficulty, cap spend with quotas and fallbacks, and set hard limits
136
+ on any workstream. When a limit is hit, the bots stop and wait for you.
260
137
 
261
- ## The mesh
138
+ <table>
139
+ <tr>
140
+ <td width="60%"><img src="imgs/BotRouting.png" alt="Model routing: easy, normal and hard tiers with model, reasoning and quota"></td>
141
+ <td width="40%"><img src="imgs/SetLimits.png" alt="Workstream limits dialog: dollars, tokens and minutes"></td>
142
+ </tr>
143
+ <tr>
144
+ <td align="center"><sub><b>Model routing</b> by difficulty</sub></td>
145
+ <td align="center"><sub><b>Limits</b> per workstream or per card</sub></td>
146
+ </tr>
147
+ </table>
262
148
 
263
- Sessions are isolated by default. **Nothing is shared until you turn it on, per session.**
149
+ ### 7. Harvest the work
264
150
 
265
- Each session has an identity: a stable handle like `@prying-heron` and an avatar that *is* the
266
- creature in the handle, on a colour drawn from the adjective. **The adjective carries the job** —
267
- testers draw from a suspicious vocabulary (prying, nervous, squinting, needling), builders from a
268
- making one (stacking, moulding, polishing, welding), product from a shaping one (framing, scoping,
269
- sketching), reviewers from a weighing one (tallying, auditing, squaring). `@prying-heron` reads as a
270
- tester before you have looked at anything else on the card, and in a four-bot room the handle is
271
- doing the work a job title would. A persona can supply its own `adjectives:` list. The handle isn't decoration — it's the
272
- addressing scheme. A model copies a three-syllable handle reliably and a 26-character ulid
273
- unreliably, and you can hold six handles in your head at once.
151
+ When a workstream finishes you get a PR packet, a small celebration 🎉, and XP for the bots.
152
+ **Apply to my repos** turns each worktree into a patch and lands it in your real checkout as
153
+ unstaged changes — ready to review in your IDE. Nothing is committed for you.
274
154
 
275
- Avatars are two axes a person can name out loud ("the orange badger"), which is what makes forty
276
- cards scannable — sixty-four creatures against sixteen backgrounds, so a thousand sessions come and
277
- go before two of them wear the same face. They are generated locally, instantly, and
278
- deterministically — no model, no download, no network.
155
+ <img src="imgs/ApplyChanges.png" alt="Apply the work to your repos dialog showing each repo, target branch and patch status" width="100%">
279
156
 
280
- In the inspector, each session gets two switches:
157
+ ---
281
158
 
282
- | Setting | Effect |
283
- | --- | --- |
284
- | `Off` (default) | Invisible to other sessions and unreachable by them. |
285
- | `Receive only` | Appears in other sessions' rosters and can be messaged; cannot initiate. |
286
- | `Send and receive` | Full participant. |
287
- | `Can open sessions` | May create new sessions for unrelated topics. Off by default. |
159
+ ## 📚 Table of contents
160
+
161
+ - [Core concepts](#-core-concepts)
162
+ - [Pipelines](#-pipelines)
163
+ - [Keeping it cheap](#-keeping-it-cheap)
164
+ - [Working with your repos](#-working-with-your-repos)
165
+ - [Needs you: questions & sign-offs](#-needs-you-questions--sign-offs)
166
+ - [Fun stuff: XP, levels & replays](#-fun-stuff-xp-levels--replays)
167
+ - [The mesh: bots talking to bots](#-the-mesh-bots-talking-to-bots)
168
+ - [Extending BotFarm](#-extending-botfarm)
169
+ - [CLI](#-cli)
170
+ - [Configuration](#%EF%B8%8F-configuration)
171
+ - [Under the hood](#-under-the-hood)
172
+ - [Development & tests](#-development--tests)
173
+ - [Known limits](#%EF%B8%8F-known-limits)
288
174
 
289
- ### How a session gets the tools
175
+ ---
290
176
 
291
- botfarm exposes an MCP server at `/mcp/<token>`, with **a distinct token per session**. That token is
292
- the whole authentication story: a tool call arrives already bound to one caller, so an agent cannot
293
- claim to be a peer. When you enable the mesh for a session, botfarm registers the server with opencode
294
- at runtime and also writes it into `<worktree>/.opencode/opencode.json`:
177
+ ## 🧭 Core concepts
295
178
 
296
- ```json
297
- {
298
- "mcp": {
299
- "botfarm": { "type": "remote", "url": "http://127.0.0.1:4777/mcp/<token>", "enabled": true }
300
- }
301
- }
302
- ```
179
+ | Concept | What it is |
180
+ | --- | --- |
181
+ | **Workspace** | A folder and its opencode config. Its bots and pipelines live in a `botfarm/` folder at its root. |
182
+ | **Workstream** | One story going through one pipeline — its own branch, worktree, team, chat and board. |
183
+ | **Pipeline** | A recipe of stages (e.g. `analyse → build → verify → check → signoff`). |
184
+ | **Agent** | A bot definition: role, model, tools and brief. |
185
+ | **Card** | One task on the board — a pipeline stage, a piece of a split stage, or ad-hoc work. |
303
186
 
304
- Runtime registration lets an already-open session pick the tools up immediately; the project config
305
- is the reliable fallback (restart that session). `.opencode/` is added to `.git/info/exclude` so
306
- flipping a toggle never dirties the branch the agent is about to commit from.
187
+ ### Workspaces
307
188
 
308
- ### Tools an agent sees
189
+ The first workspace is the folder you start BotFarm in. Change it with `"defaultWorkspace"` in
190
+ `~/.botfarm/config.json` or `botfarm up --workspace <dir>`, and open more with the folder browser under
191
+ the workspace name.
309
192
 
310
- `botfarm_whoami`, `botfarm_roster`, `botfarm_send`, `botfarm_ask`, `botfarm_reply`, `botfarm_inbox`, `botfarm_spawn`,
311
- `botfarm_notify`. Tools you have switched off are not listed at all — a session with messaging off does
312
- not see a `send` tool and then get refused, it simply has no such tool.
193
+ A workspace's definitions live at its root in `botfarm/` (created with the built-in set if missing),
194
+ one file per definition, named after its id:
313
195
 
314
- `spawn` is the "I found a defect, this doesn't belong in this conversation" case:
196
+ | File | Holds |
197
+ | --- | --- |
198
+ | `botfarm/<id>.agent.botfarm.yml` | One agent: `{ title, role, prompt, model?, variant?, tools?, tiers?, may_spawn? }` |
199
+ | `botfarm/<id>.pipeline.botfarm.yml` | One pipeline: `{ title, description?, limits?, stages: [...] }` |
200
+ | `botfarm/routing.botfarm.yml` | Model routing by difficulty (off until `enabled: true`) |
201
+ | `botfarm/mcps/*.js` | Your own tools, served to every bot in the workspace |
315
202
 
316
- ```
317
- botfarm_spawn(title: "flaky date test",
318
- task: "tests/date.spec.ts fails on the first of the month. Fix it.",
319
- branch: "fix/flaky-date")
320
- ```
203
+ Edit them in the app (**Pipelines** / **Agents** in the sidebar, as a form or as YAML) or by hand —
204
+ hand edits are picked up without a restart.
321
205
 
322
- A new pod appears on the board with its own worktree, marked *opened by @velvet-shrew*. The child
323
- starts empty — it cannot see the parent's conversation — so the tool refuses a spawn without a brief
324
- that stands on its own.
206
+ <details>
207
+ <summary>Migrating from older single-file configs</summary>
325
208
 
326
- ### What stops it going wrong
209
+ Older `botfarm-agents.yml` / `botfarm-pipeline.yml` files are split into the per-definition files on
210
+ first start and kept as `.bak`. Unedited built-in agents in an existing workspace are moved to the
211
+ current versions on start; anything you changed is left alone.
327
212
 
328
- Agent-to-agent messaging fails in four specific ways, and each has a guard:
213
+ </details>
329
214
 
330
- - **Smuggled instructions.** A peer message arrives as a *synthetic* message, framed with its
331
- provenance and an explicit caution that it is untrusted input from another agent, not from the
332
- operator. Without that framing, one compromised session drives all the others.
333
- - **Ping-pong.** Two agents will happily trade "thanks, and one more thing" forever on your money.
334
- After six consecutive exchanges with no operator input, botfarm pauses the channel and says so on the
335
- board. Typing into either session resets the counter; you can resume the channel explicitly.
336
- - **Fork bombs.** Delegation is capped at depth 2, three children per session, eight agent-created
337
- sessions per hour across the mesh, and a spawned session cannot itself spawn.
338
- - **Volume.** 24 messages per ordered pair per hour.
215
+ ### Workstreams
339
216
 
340
- Everything that crosses between sessions is logged to the activity feed and to both mailboxes, so the
341
- mesh is never doing something you cannot see afterwards.
217
+ Starting a pipeline always makes a new workstream. Two runs of the same pipeline are two workstreams
218
+ side by side. A workstream keeps the pipeline definition it started with, so editing the pipeline later
219
+ only changes new workstreams.
342
220
 
343
- ## Group chats
221
+ The workstream page has:
344
222
 
345
- Two sessions coordinating once should use `send`. Work that genuinely spans several — a migration, a
346
- contract between two services — gets a room.
223
+ - **The team** down the left — grouped by kind, with live status and spend. Click a bot to watch its transcript live.
224
+ - **The board** — To do, Doing, Needs you, Done. Drag cards between columns; click one for its handoff, criteria and open questions.
225
+ - **The chat** — posting reaches the whole team, or only the bots you `@mention`. Bots whose stage hasn't started read it with their first card.
226
+ - **The Farm** — the same board, but cards are crops moving from the shed to the field to the silo.
347
227
 
348
- Rooms live on the board as a strip above the sessions. Open one and you get the conversation, the
349
- member list, and a composer: **the operator is a full member**, so you can drop one line into
350
- `#auth-refactor` and every agent in it sees it, without visiting three sessions.
228
+ `+ Card` and `+ Bot` add work and teammates by hand. **Pause / Resume** stops every bot mid-card until
229
+ you resume. **Archive** stops the bots and puts the workstream away.
351
230
 
352
- ### Fan-out is the whole problem
231
+ **Card events in the chat.** Every finished card posts a summary: who did it, how long it took, tokens,
232
+ cost, model, XP, every file that changed on disk while it ran (with the diff — whatever changed it), and
233
+ any screenshots. Files it didn't mention in its handoff are marked. These posts never wake the other bots.
353
234
 
354
- A pairwise message costs one delivery. A message in a six-agent room costs five, and every delivery
355
- is real input tokens on someone's next step. So a room does not broadcast by default:
235
+ <details>
236
+ <summary>Workstream state & recovery</summary>
356
237
 
357
- | | What happens |
358
- | --- | --- |
359
- | You are `@mentioned` | Delivered straight into your next step, with any backlog you had riding along in the same delivery. |
360
- | You are not mentioned | Queued. You get **one batched digest the moment you go idle** — never mid-task. |
361
- | The operator posts | Always delivered to everyone. |
362
- | Queue reaches six | Delivered anyway; waiting longer would mean working on stale information. |
238
+ Each workstream writes `.botfarm/workstreams/<id>.yml` in the workspace (excluded from git locally): its
239
+ branch, worktree, story, stage statuses, and the opencode session id of every bot — plus the ones they
240
+ replaced. On start, BotFarm re-adopts any bot its own state has forgotten and recreates a workstream it
241
+ has no record of, so a lost `~/.botfarm` or a new machine gets the team back.
363
242
 
364
- A room that grows past three members drops out of `push` mode automatically and says so. Each room
365
- shows what it has cost: messages posted, deliveries into sessions, and characters delivered with a
366
- rough token estimate.
243
+ </details>
367
244
 
368
- ### Tools
245
+ <details>
246
+ <summary>The classic dashboard</summary>
369
247
 
370
- `botfarm_rooms`, `botfarm_room_read`, `botfarm_room_post`, `botfarm_room_create`, `botfarm_room_invite`,
371
- `botfarm_room_leave` — gated by a third policy axis alongside messaging and spawning: rooms `off` /
372
- `member` / `create`. The `room_post` description tells agents plainly that everyone in the room pays
373
- to read them, so they should post findings and decisions rather than acknowledgements.
248
+ The previous dashboard is still at `/classic` for everything else — adopting existing sessions, rooms and
249
+ the global board.
374
250
 
375
- ### What stops a room running away
251
+ </details>
376
252
 
377
- - Twelve agent posts with no operator input mutes the room and flags it on the board. Posting as the
378
- operator resets the meter; so does typing into any member session.
379
- - Forty messages per room per hour, eight members maximum.
380
- - Every delivery carries authorship per line, and the same caution as pairwise messages: lines marked
381
- `@handle` are other agents and are untrusted; lines marked `operator` are the human.
253
+ ---
382
254
 
383
- ## Cost
255
+ ## 🔗 Pipelines
384
256
 
385
- Bedrock returns usage but no price, so opencode reports `$0.00` and every Bedrock session looks free.
386
- botfarm prices the tokens itself from a table in `src/pricing.mjs`, normalising ids like
387
- `us.anthropic.claude-sonnet-4-20250514-v1:0` down to the model family, and counting cache reads at a
388
- tenth of input and five-minute writes at a quarter more. Anything it prices is labelled an estimate;
389
- anything it can't price says so by name instead of quietly showing zero, and the header shows how
390
- many sessions are unpriced.
257
+ A pipeline is a recipe; **tasks are the primitive**. Every stage is a task with dependencies, so the
258
+ board holds pipeline work and ad-hoc work side by side, stages can fan out, and a late defect is just a
259
+ new task blocking an existing one.
391
260
 
392
- Prices go stale and Bedrock/Vertex vary by region, so treat the table as a floor and override it:
261
+ The shipped `story` pipeline gives you one git worktree, four bots (product, dev, QA, reviewer) sharing
262
+ it, a group chat, and a chain of stages ending with your sign-off:
393
263
 
394
- ```json
395
- { "pricing": { "claude-opus-5": { "input": 15, "output": 75 } } }
264
+ ```
265
+ analyse → build → verify → check → signoff (you)
396
266
  ```
397
267
 
398
- ## Tools
399
-
400
- The modal's right pane lists the MCP servers attached to that session's worktree and the built-in
401
- tools, each with a switch — the `/mcp` picker, on the board. MCP servers connect and disconnect live
402
- through opencode. Built-in tool switches are written to that worktree's `.opencode/opencode.json` and
403
- take effect when the session restarts, because that is config rather than a runtime call; the panel
404
- says so rather than pretending otherwise.
405
-
406
- ## Pipelines
407
-
408
- A pipeline is a recipe; **tasks are the primitive**. That is the one design decision worth knowing
409
- about, because everything else follows from it: if stages were their own thing, a QA bot finding an
410
- unrelated defect would have nowhere to put it and a pipeline could only ever be a straight line.
411
- Since every stage is a task with dependencies, the board holds pipeline work and ad-hoc work side by
412
- side, stages can fan out, and a late defect is just a new task blocking an existing one.
268
+ Only the first stage is queued; the rest wait until a handoff lands.
413
269
 
414
- Running the shipped `story` pipeline gives you: one git worktree, four sessions (product, dev, QA,
415
- reviewer) sharing it, a group chat between them, and four chained tasks.
270
+ ### Stage options
416
271
 
272
+ ```yaml
273
+ stages:
274
+ - id: build
275
+ title: Build the pieces
276
+ persona: dev # or `human: true` for a stage you do yourself
277
+ receives: [analyse] # which earlier handoffs it gets
278
+ after: [analyse] # start as soon as these are done (optional)
279
+ split: tasks # fan out into one card per task (optional)
280
+ parallel: 3 # how many bots at once for a split stage (default 3, max 10)
281
+ difficulty: hard # easy / normal / hard — overrides auto-sizing
282
+ limits: { minutes: 30, tokens: 500000, usd: 2 }
283
+ max_rounds: 3 # fix-loop cap
284
+ send_back: [build] # which stages a checker here may send work back to (or false)
285
+ hold_on_questions: true # wait for you if it has open questions
286
+ prompt: |
287
+ ...
417
288
  ```
418
- analyse → build → verify → check
419
- ```
420
-
421
- Only the first is queued; the rest are blocked until a handoff lands.
422
289
 
423
290
  ### Handoffs
424
291
 
425
- A stage ends with `botfarm_task_complete(task_id, summary, acceptance_criteria, artifacts,
426
- open_questions)`. Structured on purpose — prose alone gives the next bot nothing to template against,
427
- and "what did you actually change" is the first question every downstream stage asks. Listing an open
428
- question parks the task in **review** instead of `done`, so it reaches you before it reaches the next
429
- bot.
292
+ A stage ends with `botfarm_task_complete(task_id, summary, acceptance_criteria, artifacts, open_questions)`.
293
+ It's structured on purpose — prose alone gives the next bot nothing to template against, and "what did
294
+ you actually change?" is the first question every downstream stage asks.
430
295
 
431
- ### Which handoffs a stage receives
432
-
433
- Each stage declares `receives`, and its prompt is a mustache template over those handoffs. Dropping
434
- QA's write-up from the reviewer's prompt is a one-line YAML edit:
296
+ Each stage declares what it `receives`, and its prompt is a mustache template over those handoffs:
435
297
 
436
298
  ```yaml
437
299
  - id: verify
@@ -450,135 +312,491 @@ QA's write-up from the reviewer's prompt is a one-line YAML edit:
450
312
  {{/handoffs.build}}
451
313
  ```
452
314
 
453
- A stage that receives a nonexistent stage, or whose prompt uses handoffs it never gets, is reported
454
- on load rather than silently rendering empty.
455
-
456
- ### Tasks are yours too
315
+ Also available: `{{story}}`, and `{{#received}}…{{/received}}` for everything a stage receives. A stage
316
+ that receives a nonexistent stage, or uses handoffs it never gets, is reported on load rather than
317
+ silently rendering empty.
457
318
 
458
- `New task` on any board does exactly what a bot's `botfarm_task_create` does: title, brief, project,
459
- assignee. Work you raise and work a bot raises land in the same column, and clicking any card opens
460
- the task next to the assignee's live conversation — what was asked on the left, what is happening on
461
- the right, with a composer, rather than one being a click away from the other.
319
+ ### Parallel work
462
320
 
463
- ### Tasks are enqueued, never interrupting
321
+ - **`after:`** — a stage normally starts when the one before it hands off. With `after: [ids]` it starts
322
+ as soon as those are done. Dev and QA both `after: [analyse]` build and write tests side by side (TDD);
323
+ a stage `after: [build, tests]` waits for both.
324
+ - **`split: tasks`** — the stage it waits on is asked for a `tasks` list (`[{ title, detail }]`); each item
325
+ becomes its own card, and up to `parallel: N` bots work them at once in the same worktree. The next stage
326
+ waits for every piece and gets their handoffs joined. Use `{{#item}}{{title}} {{detail}}{{/item}}` in the
327
+ prompt, or let BotFarm add "Your part — n of N" itself. See the `story-parallel` example.
464
328
 
465
- A queued task is handed to its assignee **when that session next goes idle** — the same rule as room
466
- digests. Two exceptions, because waiting for an idle event is not always right: the first stage of a
467
- fresh pipeline goes out immediately (its bot is only "busy" because it was just briefed), and a task
468
- nobody has picked up for 45 seconds is delivered anyway, since opencode queues prompts durably and a
469
- missed idle event should not strand a run. An agent mid-thought is never derailed by new work. `botfarm_task_create` lets a bot raise work
470
- for someone else (by handle, or by persona name within its own run) and optionally block an existing
471
- task on it, which is how a defect found at QA reaches the dev bot and holds up the reviewer.
329
+ ### Fix loops (send back)
472
330
 
473
- ### Config is YAML, state is a database
331
+ Plan → Code → Verify → **Fail** → Code → Verify → **Pass**.
474
332
 
475
- Definitions live in `~/.botfarm/personas/*.yaml` and `~/.botfarm/pipelines/*.yaml` — config that people
476
- edit and share in git should not live inside a binary. Runtime state (runs, tasks, handoffs) goes
477
- into `~/.botfarm/botfarm.db` via `node:sqlite`, falling back to a JSON file on older runtimes. The split is
478
- by kind, so there is never a question of which copy is authoritative. A finished run exports back to
479
- pipeline YAML for sharing.
333
+ A checker that finds a failing test, broken build or missed criterion calls
334
+ `botfarm_send_back { task_id, to, reason, failures, files }` instead of fixing it itself.
480
335
 
481
- Four personas and one pipeline are written on first run and never overwritten. The YAML parser is a
482
- deliberate subset — maps, lists, scalars, and `|` block scalars for prompts — and throws with a line
483
- number on anything else rather than misreading it.
336
+ - The earlier card goes back to To do with what failed and its last handoff (`↩ round 2`), preferring the
337
+ bot that did it (another bot of that kind takes it after ~90s if that one is busy or gone).
338
+ - The checker's card waits and comes back to the same checker to verify (`↻ verify 2`).
339
+ - For a split stage, only the pieces that touched the named files go back — or a new "Fix:" piece is added.
340
+ - `max_rounds` (default 3, *Fix rounds* in the editor) caps it, and the same failure twice stops too — then
341
+ you choose **One more round**, **Accept as is** or **Stop**.
342
+ - You can send a done card back yourself: drag it to To do, or **Send back…** on the card.
484
343
 
485
- ## Colour
344
+ <details>
345
+ <summary>How tasks are dispatched & owned</summary>
486
346
 
487
- Status is carried by amber, violet and blue — never red against green, the one pair a red-green
488
- colour blind operator cannot separate. Red appears only for failure, where it never has to be told
489
- apart from success. Diffs use `+`/`-` prefixes with blue and amber rather than green and red, toggles
490
- say "on"/"off" beside the switch, and every status is spelled out in words next to its colour.
347
+ **Tasks are enqueued, never interrupting.** A queued task is handed to its assignee when that session
348
+ next goes idle. Two exceptions: the first stage of a fresh pipeline goes out immediately, and a task nobody
349
+ has picked up for 45 seconds is delivered anyway (opencode queues prompts durably, so a missed idle event
350
+ shouldn't strand a run). An agent mid-thought is never derailed by new work.
491
351
 
492
- ## Who owns a task
352
+ **Bots can raise work too.** `botfarm_task_create` lets a bot raise work for someone else (by handle, or by
353
+ persona name within its run) and optionally block an existing task on it — that's how a defect found at QA
354
+ reaches the dev bot and holds up the reviewer. **New task** on any board does exactly the same for you.
493
355
 
494
- Ownership has three shapes, and conflating them is what makes agent boards brittle:
356
+ **Who owns a task:**
495
357
 
496
- | | |
358
+ | Owner | Meaning |
497
359
  | --- | --- |
498
- | **session** | one named session does this |
499
- | **role** | whoever is playing that part picks it up — a dev task does not die because one dev session was closed |
500
- | **human** | you do it, or you answer it; it is never dispatched |
360
+ | **session** | One named session does this. |
361
+ | **role** | Whoever is playing that part picks it up — a dev task doesn't die because one dev session was closed. |
362
+ | **human** | You do it, or you answer it; it's never dispatched. |
363
+
364
+ A role task becomes a session's task the moment it's picked up, so two bots playing the same part can't both take it.
365
+
366
+ **Tool restrictions.** An agent's `tools:` list is enforced on every turn (everything else built in is
367
+ switched off; the BotFarm tools stay on). The built-in product agent is read-only and told to polish the
368
+ criteria, not study the code — that's the dev's job.
369
+
370
+ </details>
371
+
372
+ ---
373
+
374
+ ## 💰 Keeping it cheap
375
+
376
+ None of these involve a paid model making decisions.
377
+
378
+ ### Limits
379
+
380
+ `limits: { minutes, tokens, usd }` on a stage applies to each of its cards (each piece of a split).
381
+ `limits:` on a pipeline — or the Limits box when you start one — applies to the whole workstream.
501
382
 
502
- A role task becomes a session's task the moment it is picked up, so two bots playing the same part
503
- cannot both take it.
383
+ - When a **card** hits a limit, its bot stops and the card waits in *Needs you*: **Continue** gives half as
384
+ much again, **Set limits…** for exact numbers, or **Stop**.
385
+ - When a **workstream** hits one, every bot on it stops until you raise it.
504
386
 
505
- ## Needs you
387
+ Limits can be changed any time from the workstream header.
506
388
 
507
- `botfarm_ask_human(question, options, wait_seconds)` puts a question at the top of your board with the
508
- asker's face on it and the choices it offered as buttons. Answering delivers the answer straight back
509
- into that session, marked as coming from the human running it rather than from a peer. By default
510
- the bot does not block: it asks, carries on with what it can, and the answer arrives as a message.
389
+ ### Model routing by difficulty
511
390
 
512
- Pipelines can have stages that are yours — `human: true` on a stage, like the sign-off that ships at
513
- the end of the `story` pipeline. They land in Needs you and the run waits.
391
+ Each card is sized **easy / normal / hard** from its words, length and criteria (or `difficulty:` on a
392
+ stage or split piece) and gets the model from `routing.botfarm.yml` or the agent's `tiers:`. The card shows
393
+ its size and model. Edit it all in the app: **Model routing** in the sidebar, **Difficulty** on each stage,
394
+ **Model by difficulty** in the agent editor.
514
395
 
515
- ## Editing pipelines and personas
396
+ - **Quota and fallback** — cap a tier's model, e.g. up to $5/day on Opus, then Sonnet (also tokens or
397
+ minutes; per day / week / month / workstream). Once it runs out, new cards take the fallback and bots
398
+ already on it move over — at once or on their next turn.
399
+ - **Per agent** — an agent's `tiers:` override the workspace rules size by size, and apply even with
400
+ workspace routing off. An agent's own quota counts only that agent's spend ("the reviewer gets $3/day of
401
+ Opus"). **Model routing → What each agent gets** shows the effective model, reasoning and quota and where
402
+ each came from.
403
+ - One-line YAML maps (`quota: { usd: 3, per: day }`) work in hand-edited files.
516
404
 
517
- The pipeline dialog has an editor: add, remove and reorder phases, change who does each one, tick
518
- which earlier handoffs it receives, and edit its prompt. Personas have their own form — model, tools
519
- it may use, mesh permissions, handle vocabulary, and the brief it gets before any task.
405
+ ### Switching a bot's model
520
406
 
521
- Both write back to the same YAML file you could have edited by hand, and a **YAML tab** sits next to
522
- the form for anything the form does not cover, so the form never becomes a ceiling. Problems (a stage
523
- receiving a phase that does not exist, a persona that is not defined) are reported on save rather
524
- than swallowed.
407
+ **Model…** in a bot's panel picks another model and reasoning level for that bot from its next turn (Opus
408
+ for a hard fix, Sonnet or Haiku to save money). It's kept across restarts and doesn't touch the agent file.
525
409
 
526
- ## The task board
410
+ ### Smaller context, fewer wasted turns
527
411
 
528
- The kanban board holds every task: pipeline stages and ad-hoc work together. Columns are backlog,
529
- blocked, queued, active, review, done, cancelled. Clicking a card shows the brief, the handoff it
530
- received, the files changed in its worktree with clickable diffs, and controls to move it between
531
- columns. Moving something to queued offers it to the assignee at their next idle moment.
412
+ - **Trimmed handoffs** — the next bot reads a brief (long code blocks become pointers, repeats go, cut at
413
+ ~1800 characters); `botfarm_handoff(stage)` fetches the full text. To use a local model for trimming, set
414
+ `"handoffs": { "local": { "url": "http://localhost:11434", "model": "qwen2.5:3b" } }` in
415
+ `~/.botfarm/config.json` (falls back to the rules).
416
+ - **Team notes** — `botfarm_notes_write` / `botfarm_notes_read`; every card lists the notes and the files
417
+ teammates already read.
418
+ - **Loop detection** — a call counts as repeated only when the tool **and every argument** match. An edit in
419
+ between resets the count, so build → fix → build is fine.
420
+ - **Loop stop** — the same call three times, five failures in a row, or ~250k tokens without an edit pauses
421
+ the card and asks you (tune with `"loops": { "tokensWithoutEdits": N }`).
422
+
423
+ <details>
424
+ <summary>How cost is calculated</summary>
532
425
 
533
- ## CLI
426
+ Bedrock returns usage but no price, so opencode reports `$0.00` and every Bedrock session looks free.
427
+ BotFarm prices the tokens itself from a table in `src/pricing.mjs`, normalising ids like
428
+ `us.anthropic.claude-sonnet-4-20250514-v1:0` down to the model family, counting cache reads at a tenth of
429
+ input and five-minute writes at a quarter more. Anything it prices is labelled an estimate; anything it
430
+ can't price says so by name instead of quietly showing zero, and the header shows how many sessions are
431
+ unpriced.
432
+
433
+ Prices go stale and Bedrock/Vertex vary by region, so treat the table as a floor and override it:
534
434
 
435
+ ```json
436
+ { "pricing": { "claude-opus-5": { "input": 15, "output": 75 } } }
535
437
  ```
536
- botfarm up [--port 4777] [--server URL] [--repo PATH]... dashboard (default)
537
- botfarm ls list sessions
538
- botfarm new <repo> [task] --branch NAME [--agent A] new session in a worktree
539
- botfarm send <id> <text...> queue a prompt
540
- botfarm stop [id...] interrupt (all busy if omitted)
541
- botfarm rm <id> [--worktree] [--force] delete session and its worktree
542
- botfarm attach <id> open the session in the opencode TUI
438
+
439
+ </details>
440
+
441
+ ---
442
+
443
+ ## 🌳 Working with your repos
444
+
445
+ ### Worktrees
446
+
447
+ Every workstream gets its own git worktree (under `~/worktrees/<repo>/<branch>` unless you set
448
+ `BOT_FARM_WORKTREE_ROOT`), so parallel agents never fight over one checkout. Paths are expanded the way a
449
+ shell would — `~/workspace/app`, `$HOME/app` and relative paths all work — and dialogs tell you up front if a
450
+ path is missing or isn't a repository.
451
+
452
+ **Parent repos with nested services** (services cloned into a gitignored folder) get one worktree per repo,
453
+ laid out exactly like the original tree, each on its own branch. The dialog lists the nested repos it found
454
+ and you tick the ones in scope. Changed files and diffs aggregate across all of them, tagged by repo.
455
+
456
+ ### Repos from anywhere
457
+
458
+ A workstream can include repos from outside the workspace. **Add repo** in the new-workstream dialog
459
+ (e.g. `~/workspace/spt`) links it to the workspace; each workstream it's ticked for gets a worktree of it on
460
+ the same branch, mounted at `<worktree>/spt/`. **+ Repo** adds one to a running workstream, and the bots are
461
+ told in the chat, team notes and every card.
462
+
463
+ <details>
464
+ <summary>API & Docker notes</summary>
465
+
466
+ - `POST /api/workspaces/:id/repos {path, as?, running?}`
467
+ - `DELETE /api/workspaces/:id/repos?path=`
468
+ - `POST /api/projects/:id/repos {path, as?}`
469
+
470
+ Linked repos are hidden from the parent's git status via `info/exclude`. Docker MCPs see them only if the
471
+ path is under a mounted folder (`~/workspace`, `~/worktrees`).
472
+
473
+ </details>
474
+
475
+ ### Apply to my repos
476
+
477
+ From the harvest (**Apply to my repos…**) or any time after (**Apply to repos…** in the workstream header),
478
+ every repo in the workstream becomes a patch of what its worktree has that your checkout doesn't — edits,
479
+ new files, commits on the branch — leaving out BotFarm's own files.
480
+
481
+ - The dialog shows per repo where it goes (path and current branch), the files, and whether it applies
482
+ cleanly, needs a 3-way merge, will conflict, or is already there. It warns about your own uncommitted edits
483
+ to the same files.
484
+ - A clean patch lands as **unstaged working-tree changes** — never committed for you. Otherwise it falls back
485
+ to a 3-way apply (conflict markers), then `--reject` (`.rej` files).
486
+ - **Undo last apply** reverses the clean ones.
487
+ - Patches are kept in `.botfarm/workstreams/<id>.patches/` and can be downloaded.
488
+
489
+ <details>
490
+ <summary>Patches API</summary>
491
+
492
+ - `GET /api/projects/:id/patches`
493
+ - `GET /api/projects/:id/patches/file?rel=`
494
+ - `POST /api/projects/:id/patches/apply {repos?}`
495
+ - `POST /api/projects/:id/patches/undo`
496
+
497
+ </details>
498
+
499
+ ### When a workstream finishes
500
+
501
+ - A **PR packet** (`.botfarm/workstreams/<id>.pr.md`) — criteria with the tests behind them, files, commits,
502
+ how to test, open questions and cost. **Open PR…** pushes and runs `gh pr create`.
503
+ - A **harvest** — a small celebration and a line in the home page's harvest log.
504
+ - **XP** for the bots.
505
+
506
+ ---
507
+
508
+ ## 🙋 Needs you: questions & sign-offs
509
+
510
+ - **Bots can ask you things.** `botfarm_ask_human(question, options, wait_seconds)` puts a question at the top
511
+ of your board with the asker's face on it. Questions can offer choices (pick one or several) and can always
512
+ be answered in your own words. The answer goes straight back into that session, marked as coming from you.
513
+ By default the bot doesn't block — it carries on and the answer arrives as a message.
514
+ - **Stages can be yours.** `human: true` on a stage — like the sign-off at the end of the `story` pipeline —
515
+ lands it in *Needs you* and the run waits.
516
+ - **Open questions travel.** A stage with open questions still hands off; the questions go to the next stage
517
+ with its card. Set `hold_on_questions: true` (or "wait for me" in the editor) to stop there until you press
518
+ **Continue**, optionally with answers every later stage receives.
519
+
520
+ ---
521
+
522
+ ## 🎮 Fun stuff: XP, levels & replays
523
+
524
+ - **Levels.** Each kind of bot earns XP per workspace for clean work only — a handoff, no pauses, under budget,
525
+ nothing left open. Fix rounds earn little XP; the checker gets a little for catching them. Levels bring hats on
526
+ the farm 🎩 and small perks: level 3 = +10% card limits, level 5 = the first limit hit extends itself once,
527
+ level 8 = +20%.
528
+ - **Replays.** **Replay** on a workstream scrubs through everything that happened (farm, team, chat).
529
+ **Save replay file** gives one portable JSON you can open from the home page of any BotFarm.
530
+ - **Handles & avatars.** Every bot gets a handle like `@prying-heron` and an avatar that *is* the creature in the
531
+ handle. The adjective carries the job — testers are *prying, nervous, squinting*; builders are *stacking,
532
+ welding, polishing*; reviewers are *tallying, auditing* — so you can tell who's who at a glance. A persona can
533
+ supply its own `adjectives:` list.
534
+
535
+ ---
536
+
537
+ ## 🕸️ The mesh: bots talking to bots
538
+
539
+ Sessions are isolated by default. **Nothing is shared until you turn it on, per session.**
540
+
541
+ | Setting | Effect |
542
+ | --- | --- |
543
+ | `Off` (default) | Invisible to other sessions and unreachable by them. |
544
+ | `Receive only` | Appears in other sessions' rosters and can be messaged; can't initiate. |
545
+ | `Send and receive` | Full participant. |
546
+ | `Can open sessions` | May create new sessions for unrelated topics. Off by default. |
547
+
548
+ **Tools a bot sees:** `botfarm_whoami`, `botfarm_roster`, `botfarm_send`, `botfarm_ask`, `botfarm_reply`,
549
+ `botfarm_inbox`, `botfarm_spawn`, `botfarm_notify`. Tools you've switched off aren't listed at all.
550
+
551
+ `spawn` is for "I found a defect that doesn't belong in this conversation":
552
+
553
+ ```
554
+ botfarm_spawn(title: "flaky date test",
555
+ task: "tests/date.spec.ts fails on the first of the month. Fix it.",
556
+ branch: "fix/flaky-date")
543
557
  ```
544
558
 
545
- Config lives in `~/.botfarm/config.json`:
559
+ A new pod appears on the board with its own worktree, marked *opened by @velvet-shrew*. The child starts
560
+ empty, so the tool refuses a spawn without a brief that stands on its own.
561
+
562
+ ### Group chats (rooms)
563
+
564
+ Work that spans several sessions — a migration, a contract between two services — gets a room. **You're a
565
+ full member**, so one line in `#auth-refactor` reaches every agent in it.
566
+
567
+ Because every delivery costs real input tokens, rooms don't broadcast by default:
568
+
569
+ | | What happens |
570
+ | --- | --- |
571
+ | You're `@mentioned` | Delivered straight into your next step, with any backlog riding along. |
572
+ | You're not mentioned | Queued — one batched digest the moment you go idle, never mid-task. |
573
+ | The operator posts | Always delivered to everyone. |
574
+ | Queue reaches six | Delivered anyway, so nobody works on stale information. |
575
+
576
+ Room tools: `botfarm_rooms`, `botfarm_room_read`, `botfarm_room_post`, `botfarm_room_create`,
577
+ `botfarm_room_invite`, `botfarm_room_leave` — gated by a rooms policy of `off` / `member` / `create`.
578
+
579
+ ### Guardrails
580
+
581
+ | Risk | Guard |
582
+ | --- | --- |
583
+ | **Smuggled instructions** | Peer messages arrive framed with their provenance and marked as untrusted input from another agent, not the operator. |
584
+ | **Ping-pong** | After six exchanges with no operator input, the channel pauses. Typing into either session resets it. |
585
+ | **Fork bombs** | Delegation capped at depth 2, three children per session, eight agent-created sessions per hour; spawned sessions can't spawn. |
586
+ | **Volume** | 24 messages per ordered pair per hour; 40 messages per room per hour, 8 members max. |
587
+ | **Runaway rooms** | Twelve agent posts with no operator input mutes the room. Posting as the operator resets it. |
588
+
589
+ Everything that crosses between sessions is logged to the activity feed and both mailboxes — the mesh never
590
+ does something you can't see afterwards.
591
+
592
+ <details>
593
+ <summary>How a session gets the mesh tools</summary>
594
+
595
+ BotFarm exposes an MCP server at `/mcp/<token>`, with **a distinct token per session**. That token is the whole
596
+ authentication story: a tool call arrives already bound to one caller, so an agent can't claim to be a peer.
597
+ Enabling the mesh registers the server with opencode at runtime and writes it into
598
+ `<worktree>/.opencode/opencode.json`:
546
599
 
547
600
  ```json
548
- { "server": "http://127.0.0.1:4096", "port": 4777, "repos": ["~/code/app"] }
601
+ {
602
+ "mcp": {
603
+ "botfarm": { "type": "remote", "url": "http://127.0.0.1:4777/mcp/<token>", "enabled": true }
604
+ }
605
+ }
606
+ ```
607
+
608
+ Runtime registration lets an open session pick the tools up immediately; the project config is the reliable
609
+ fallback (restart that session). `.opencode/` is added to `.git/info/exclude`, so flipping a toggle never dirties
610
+ the branch.
611
+
612
+ </details>
613
+
614
+ ---
615
+
616
+ ## 🧩 Extending BotFarm
617
+
618
+ ### Your own tools
619
+
620
+ Every `.js` file in `botfarm/mcps/` becomes a tool called `botfarm_<name>` for the workspace's bots:
621
+
622
+ ```js
623
+ export const name = "worktree_status"
624
+ export const description = "Show git status for the calling bot's worktree"
625
+ export const inputSchema = { type: "object", properties: {} }
626
+
627
+ export async function execute(args, ctx) {
628
+ // ctx.repoRoot – the calling bot's worktree
629
+ // ctx.exec(cmd, args) – run a program there
630
+ // ctx.log(...) – write to the test bench
631
+ return ctx.exec("git", ["status", "--short"])
632
+ }
633
+ ```
634
+
635
+ Saving a file reloads it; bots get the new list on their next idle moment. **Tools** in the sidebar is a test
636
+ bench: a form from the schema (or raw JSON), where to run it, the result and log, and the source to edit.
637
+
638
+ ### BotFarm's MCP server
639
+
640
+ It's called `botfarm`, so bots see `botfarm_task_complete`, `botfarm_room_post`, `botfarm_notes_read` and so
641
+ on. Old worktrees are renamed automatically.
642
+
643
+ ### Per-session tools
644
+
645
+ A bot's panel lists the MCP servers attached to its worktree and the built-in tools, each with a switch — the
646
+ `/mcp` picker, on the board. MCP servers connect and disconnect live; built-in tool switches are written to the
647
+ worktree's `.opencode/opencode.json` and take effect when the session restarts.
648
+
649
+ ---
650
+
651
+ ## ⌨️ CLI
652
+
653
+ ```
654
+ bot-farm up [--port 4777] [--server URL] [--repo PATH]... dashboard (default)
655
+ bot-farm ls list sessions
656
+ bot-farm new <repo> [task] --branch NAME [--agent A] new session in a worktree
657
+ bot-farm send <id> <text...> queue a prompt
658
+ bot-farm stop [id...] interrupt (all busy if omitted)
659
+ bot-farm rm <id> [--worktree] [--force] delete session and its worktree
660
+ bot-farm attach <id> open the session in the opencode TUI
549
661
  ```
550
662
 
551
- Rolling metrics are snapshotted to `~/.botfarm/metrics.json` every 30s, so restarting botfarm keeps the
552
- hour of history.
663
+ Example — spin up a single bot on a fresh branch:
664
+
665
+ ```bash
666
+ bot-farm new ~/code/app --branch fix/auth-redirect --task "Fix the redirect loop after SSO login"
667
+ ```
668
+
669
+ That creates the worktree, opens a session there and sends the first instruction. The card shows the branch and
670
+ a live `+142 −18 · 7 files`. `botfarm rm <id> --worktree` removes both.
671
+
672
+ ---
673
+
674
+ ## ⚙️ Configuration
553
675
 
554
- ## Tests
676
+ Global config lives in `~/.botfarm/config.json`:
555
677
 
678
+ ```json
679
+ {
680
+ "server": "http://127.0.0.1:4096",
681
+ "port": 4777,
682
+ "repos": ["~/code/app"],
683
+ "defaultWorkspace": "~/code/app"
684
+ }
556
685
  ```
557
- node test/smoke.mjs # discovery, metrics, abort, continue, SSE, persistence
558
- node test/mesh.mjs # MCP handshake, policy gating, messaging, loop limits, delegation
559
- node test/rooms.mjs # rooms: membership, mention vs digest delivery, operator posts, mute
560
- node test/board.mjs # registry, adoption, groups, cost estimation, tool toggles
561
- node test/pipelines.mjs # YAML, templates, runs, handoffs, dispatch, defects flowing backwards
562
- node test/repos.mjs # path expansion, nested repositories, multi-repo worktrees
563
- node test/transport.mjs # websocket handshake, pushes, and idle traffic to opencode
564
- node test/projects.mjs # a run starts its bots; projects own sessions, board and chat
565
- node test/roles.mjs # role-flavoured handles, role and human ownership, editing definitions
566
- node test/flow.mjs # late briefing, held mentions, handoff watchdog, shared-worktree callers, live transcripts
567
- node test/workspaces.mjs # workspace files, editing definitions, one workstream per run, archive, folder browser
568
- node test/handoff.mjs # open questions travel with the handoff, holding stages, continue with answers
569
- node test/shot.mjs # renders the dashboard in headless chrome (needs CHROME_PATH)
686
+
687
+ | Path | What's there |
688
+ | --- | --- |
689
+ | `~/.botfarm/config.json` | Server, port, repos, pricing overrides, handoff & loop tuning |
690
+ | `~/.botfarm/registry.json` | Sessions BotFarm manages, plus groups, labels, mesh policy, lineage, disabled tools |
691
+ | `~/.botfarm/metrics.json` | Rolling metrics, snapshotted every 30s so a restart keeps the last hour |
692
+ | `~/.botfarm/botfarm.db` | Runtime state (runs, tasks, handoffs) via `node:sqlite`, or JSON on older runtimes |
693
+ | `<workspace>/botfarm/` | Agents, pipelines, routing and your tools |
694
+ | `<workspace>/.botfarm/workstreams/` | Workstream state, PR packets and patches |
695
+
696
+ | Env var | Effect |
697
+ | --- | --- |
698
+ | `BOT_FARM_WORKTREE_ROOT` | Where worktrees are created (default `~/worktrees`) |
699
+ | `CHROME_PATH` | Chrome binary for `test/shot.mjs` |
700
+
701
+ ---
702
+
703
+ ## 🔍 Under the hood
704
+
705
+ <details>
706
+ <summary>The board is a registry, not a listing</summary>
707
+
708
+ opencode accumulates every session you've ever opened. Listing them all turns the dashboard into an archive
709
+ browser. BotFarm shows only sessions it manages — ones it started, plus ones you explicitly add with
710
+ **Add existing…**. The rest sit behind a one-line banner. `Remove` puts a session back in that pool; it never
711
+ deletes anything.
712
+
713
+ </details>
714
+
715
+ <details>
716
+ <summary>Transport</summary>
717
+
718
+ The dashboard is pushed to over a websocket (`/api/socket`), falling back to server-sent events. Neither polls.
719
+ Actions stay on plain HTTP — they're one-shot and want status codes and retries.
720
+
721
+ BotFarm's own traffic to opencode is event-driven too. Periodic checks are reconciliation, not the mechanism:
722
+ a board with nothing happening makes **zero** requests per second, and if the event stream goes down the polling
723
+ loop comes back automatically.
724
+
725
+ Request bodies are negotiated rather than pinned: opencode's prompt endpoint moved from `{parts: [...]}` to
726
+ `{prompt: {text}}`, so BotFarm tries the known shapes and remembers the one that worked. Metrics come from each
727
+ session's message list rather than event payloads, and the client sniffs the v1/v2 path dialect at connect time,
728
+ so a rename of `/session` to `/api/session` doesn't break it.
729
+
730
+ </details>
731
+
732
+ <details>
733
+ <summary>Config is YAML, state is a database</summary>
734
+
735
+ Definitions people edit and share in git are YAML; runtime state goes in `~/.botfarm/botfarm.db`. The split is by
736
+ kind, so there's never a question of which copy is authoritative. A finished run exports back to pipeline YAML for
737
+ sharing.
738
+
739
+ The YAML parser is a deliberate subset — maps, lists, scalars and `|` block scalars — and throws with a line number
740
+ on anything else rather than misreading it.
741
+
742
+ </details>
743
+
744
+ <details>
745
+ <summary>Colour & accessibility</summary>
746
+
747
+ Status is carried by amber, violet and blue — never red against green, the one pair a red-green colour-blind
748
+ operator can't separate. Red appears only for failure. Diffs use `+`/`-` prefixes with blue and amber, toggles say
749
+ "on"/"off" beside the switch, and every status is spelled out in words next to its colour.
750
+
751
+ </details>
752
+
753
+ ---
754
+
755
+ ## 🧪 Development & tests
756
+
757
+ No build step, no dependencies. The tests run against `test/mock-opencode.mjs`, a fake server that streams
758
+ plausible sessions, so you can develop without burning tokens.
759
+
760
+ ```bash
761
+ node test/mock-opencode.mjs # fake opencode server
762
+ botfarm up # a populated board to play with
570
763
  ```
571
764
 
572
- Both suites run against `test/mock-opencode.mjs`, a fake server that streams plausible sessions, so
573
- you can develop without burning tokens — `node test/mock-opencode.mjs` then `botfarm up` gives you a
574
- populated board.
765
+ | Test | Covers |
766
+ | --- | --- |
767
+ | `node test/smoke.mjs` | Discovery, metrics, abort, continue, SSE, persistence |
768
+ | `node test/board.mjs` | Registry, adoption, groups, cost estimation, tool toggles |
769
+ | `node test/repos.mjs` | Path expansion, nested repositories, multi-repo worktrees |
770
+ | `node test/transport.mjs` | Websocket handshake, pushes, idle traffic to opencode |
771
+ | `node test/roles.mjs` | Role-flavoured handles, role and human ownership, editing definitions |
772
+ | `node test/flow.mjs` | Late briefing, held mentions, handoff watchdog, shared worktrees, live transcripts |
773
+ | `node test/workspaces.mjs` | Workspace files, one workstream per run, archive, folder browser |
774
+ | `node test/handoff.mjs` | Open questions in handoffs, holding stages, continue with answers |
775
+ | `node test/parallel.mjs` | Split stages, `after:` (TDD), time/token/$ limits |
776
+ | `node test/loop.mjs` | Send-back fix loops |
777
+ | `node test/craft.mjs` | Routing, trimmed handoffs, notes, loop detection, XP, harvests, PR packets, replays |
778
+ | `node test/extend.mjs` | Per-file definitions, workspace tools, switching a bot's model |
779
+ | `node test/linked.mjs` | Repos from anywhere in a workstream |
780
+ | `node test/patches.mjs` | Applying the work as patches to real checkouts |
781
+ | `node test/shot.mjs` | Renders the dashboard in headless Chrome (needs `CHROME_PATH`) |
782
+
783
+ ---
784
+
785
+ ## ⚠️ Known limits
786
+
787
+ - **Identity is per location.** The MCP token is registered against a directory, so two sessions sharing one
788
+ directory share a token. Pods with their own worktrees — the intended setup — are cleanly separated.
789
+ - **Tested mostly against a mock.** Usage fields are checked in several shapes, but a new opencode version may
790
+ need a tweak.
791
+ - `botfarm attach` assumes `opencode --session <id>` is right for your opencode version.
792
+ - Cost is only as good as what the provider reports back.
793
+
794
+ ---
795
+
796
+ <div align="center">
797
+
798
+ Made with 🌱 for people who'd rather watch the crops grow than babysit a terminal.
575
799
 
576
- ## Known limits
800
+ **[MIT License](LICENSE)** · Provided as is. Supervise your bots. Not responsible for goats. 🐐
577
801
 
578
- - **Identity is per location.** The MCP token is registered against a directory, so two sessions
579
- sharing one directory share a token; botfarm resolves the caller to whichever of them is running.
580
- Pods with their own worktrees — the intended setup — are cleanly separated.
581
- - **Tested against a mock**, not yet against a live opencode server. Field names in the usage object
582
- are checked in several shapes before giving up, but the first real run may need a tweak.
583
- - `botfarm attach` assumes `opencode --session <id>` is the right incantation for your version.
584
- - Cost is only as good as what the provider reports back in the message.
802
+ </div>