toolroll 0.7.0 → 0.8.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/CHANGELOG.md ADDED
@@ -0,0 +1,435 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ## 0.8.1 — 2026-09-30
6
+
7
+ - **Safer `toolroll update`.** A release is accepted only when its signing
8
+ certificate names ap9000/toolroll, its publish workflow and GitHub
9
+ Actions, checked with the Sigstore verifier npm already ships (found from
10
+ npm itself, so a custom npm global folder works too). A failed
11
+ update puts the commands back before stopping the service, stops and
12
+ restarts per-project watch workers with it, restores even when the live
13
+ database can't be copied aside, and keeps the last good update so
14
+ `--rollback` still works after a refused attempt, including for the update
15
+ that brought 0.8.1. The console's update job
16
+ finds pnpm, bun and npm where they are installed; the desktop app is never
17
+ offered npm.
18
+ - **Safer `toolroll onboard`.** It adds the main checkout rather than a
19
+ temporary worktree, never adds your home folder, and asks before adding a
20
+ project. Run by an agent, `toolroll up` never prints the password. Login
21
+ advice matches how the install actually signs in, and uses the port `up`
22
+ serves on. A skill you have edited is left alone.
23
+ - **Chat opens instantly.** First-run suggestions and the agent sign-in check
24
+ refresh in the background, so a slow network never holds up the page.
25
+ Tapping a suggestion adds to what you typed instead of replacing it.
26
+
27
+ ## 0.8.0 — 2026-09-30
28
+
29
+ - **Install with your agent.** `toolroll onboard`, run by the agent that
30
+ installed Toolroll, adds the repository as a project, says which agent
31
+ CLIs are signed in, and with `--yes` installs a small marked Toolroll
32
+ skill for Claude Code and Codex so the agent knows how to hand work over,
33
+ wait and review (`--remove` takes it out; a skill you wrote yourself is
34
+ never touched). It prints the MCP line rather than running it and ends
35
+ with a handoff for the person: the console address and where the login is
36
+ saved, never the password. `toolroll up` without a terminal prints that
37
+ handoff instead of opening a browser.
38
+ - **A first run that leads to a first result.** Chat and the inbox show three
39
+ plain steps (Agent signed in, Project added, Your first task), each done or
40
+ with one action, until the first Ready result. Until a task exists, Chat
41
+ offers three first tasks: the repository's open GitHub issues, else its
42
+ TODO and FIXME notes, else safe generic ones. A tap only drafts the
43
+ message, and text from issues and notes is kept to what a person can see.
44
+ Settings shows how long the first result took.
45
+ - **Calmer secret alerts.** The commit secret scan looks only at lines a
46
+ change adds and skips documented placeholders, so pushes no longer warn
47
+ about keys that were already there or never real. A real hit still blocks
48
+ publication; the alert names the file and line, once per commit, and says
49
+ what to do.
50
+ - **`toolroll update`: verified, drained, undoable updates.** Installs the
51
+ new release from the npm registry beside the running one, under npm's own
52
+ signature and attestation check; the installed bytes must be the ones
53
+ downloaded and hashed, and their provenance must name ap9000/toolroll and
54
+ its publish workflow. It lets running work finish (`--when-idle`, the
55
+ default; `--now` refuses while work runs and names it; `--at 03:00`
56
+ waits), stops the service and waits for it to exit, backs up the database
57
+ and coding catalog, rehearses, switches the service and every
58
+ `toolroll`/`standing-orders` on PATH, restarts and health-checks. A failed
59
+ check restores the previous version, database and coding catalog on its
60
+ own, keeping what the new version wrote in a named copy;
61
+ `toolroll update --rollback` goes back later. It refuses while a
62
+ foreground `toolroll up` runs, when a command on PATH is a shim it cannot
63
+ switch, and to an older release without `--allow-downgrade`, and keeps two
64
+ release runtimes. Settings → Updates offers Update now, When idle and
65
+ Tonight (03:00) behind your password, shows the steps live, and a one-time
66
+ What's new card afterwards; while update checks are off it asks npm
67
+ nothing until Check now. The console's update job runs once, for that
68
+ update only. Every update, rollback, refusal and failure is in the ledger.
69
+
70
+ ## 0.7.0 — 2026-09-30
71
+
72
+ - **Know when a newer Toolroll exists.** Once a day Toolroll makes one
73
+ anonymous request to npm, plus one to GitHub for that release's notes, and
74
+ keeps the answer beside the database; offline it says nothing.
75
+ `toolroll status` adds one line when a newer version exists, the console
76
+ shows a quiet notice you can dismiss per version, and Settings → Updates
77
+ shows this version, the latest and its notes, the command for how you
78
+ installed it, each worker's version, and a switch to turn the check off
79
+ (or set `TOOLROLL_NO_UPDATE_CHECK=1`). A security release (notes with a
80
+ "Security" line or heading) also messages each operator once. A plane
81
+ deployed from a checkout reads as a source install.
82
+
83
+ ## 0.6.0 — 2026-09-30
84
+
85
+ - **Ink instead of magenta.** The accent for what waits on a person is ink
86
+ by default (#171717 light, #ededed dark), the way Vercel, Linear and
87
+ GitHub work: the console is black, white and grey, and colour is kept for
88
+ status (building, complete, warning, danger). Settings → Appearance
89
+ starts its presets with Ink, Violet and Chart magenta; a colour you chose
90
+ stays.
91
+
92
+ - **The console feels right under a finger.** Hover effects apply only to a
93
+ mouse or trackpad (no stuck hover after a tap), no tap flash or tap delay
94
+ on phones, link-buttons press like buttons, and one stronger ease-out
95
+ curve. The phone navigation drawer slides in and out from the left,
96
+ dialogs and menus get short entrances and exits (menus from their
97
+ trigger), and everything is a plain fade under reduced motion. The ⌘K
98
+ palette opens instantly.
99
+
100
+ - **Rename leftovers.** Deploy picks the state folder that holds the
101
+ database; a new watch installs before the old-named one is removed; the
102
+ setup guide still offers to update stale or old-folder instructions.
103
+
104
+ - **Faster, stricter release checks** (for contributors). `scripts/release-check.mjs`
105
+ runs the unit tests related to a change and the browser journeys only
106
+ when something a page shows changed; `e2e-parallel` retries only failed
107
+ journeys (the whole group when the browser-error check failed), and a
108
+ retry passes only if every first-run failure passed in its report.
109
+
110
+ - **Releases publish themselves.** Pushing a `v*` tag runs
111
+ `.github/workflows/publish.yml`, which publishes to npm through npm's
112
+ trusted publishing (no token, with provenance) and creates the GitHub
113
+ release; the Homebrew tap follows within six hours.
114
+
115
+ - **An expired sign-in pauses that agent instead of burning retries.** A run
116
+ that fails because its sign-in or API key no longer works (Claude's expired
117
+ OAuth session or "Please run /login", a revoked key, Codex or Gemini not
118
+ logged in, a 401) is `auth-expired`: no strike, no retry, never a paid
119
+ fallback. Its task goes back to the queue and new work for that provider
120
+ waits while the others keep running. `status`, `ready`, `task show` and the
121
+ console say "Claude needs you to sign in again" and what to run, and every
122
+ connected channel gets one message per incident. The pause lifts when a run
123
+ or sign-in check on that provider works, or with **Resume** in the console
124
+ or `toolroll providers resume <provider>`; one short message says how many
125
+ tasks resumed.
126
+
127
+ - **An agent that stops before its handoff keeps its work.** Every builder,
128
+ revision and repair prompt now says the agent runs headless (foreground
129
+ commands only, no background-and-wait, wakeups or loops; hand off before
130
+ stopping), and claude runs start with `--disallowedTools
131
+ ScheduleWakeup,CronCreate,Monitor`. When an attempt ends with changes but no
132
+ handoff, its own session is resumed in the same worktree with a short turn
133
+ to finish and hand off. Its changes are saved as a patch in the run's
134
+ evidence folder first; when the session cannot be resumed they become a
135
+ work-in-progress commit on the branch the next attempt continues from, and
136
+ a retry never resets that work. The failure reads "The agent stopped before
137
+ handing off; its work was kept and it is being resumed". A handoff and a
138
+ passing check are still required for success.
139
+
140
+ - **Sign-in pauses and kept work, follow-ups.** Fallback entries, attended
141
+ continuations and resumed race lanes on a paused provider now wait (with the
142
+ same one-trial-every-10-minutes) instead of failing, and the Tasks list
143
+ shows every task the gate holds as waiting for a sign-in — planners and
144
+ tasks on a configured or pinned provider included. A retry now actually
145
+ inherits unhanded work (its admission refused it before); an attempt that
146
+ finds a kept work-in-progress commit already complete and hands off with a
147
+ clean tree succeeds; and once a later attempt fails some other way, the
148
+ saved tree can be reset.
149
+
150
+ ## 0.5.0 on npm as toolroll — 2026-09-30
151
+
152
+ The first `toolroll` package, published from the rename (PR 105). It carries the 0.5.0 notes below plus:
153
+
154
+ - **Toolroll under the hood.** The internal names follow the product name;
155
+ every existing install, database, branch and integration keeps working, and
156
+ nothing is moved. The npm package is `toolroll` (both the `toolroll` and
157
+ `standing-orders` commands remain). A fresh install keeps its state in
158
+ `~/.config/toolroll`, `~/.toolroll` and `~/.cache/toolroll`; a folder that
159
+ already exists under `standing-orders` (or `nightorders`) keeps being used
160
+ until one exists under the new name. Every `STANDING_ORDERS_*` variable has
161
+ a `TOOLROLL_*` twin that wins when both are set; the old name still works
162
+ alone, and processes Toolroll starts get both. New task branches are
163
+ `toolroll/<id>`; `standing-orders/<id>` branches stay the plane's own (a
164
+ retry reuses one, project delete, races, publication grants and coding
165
+ handoffs recognise both). Watches install as `com.toolroll.watch.*`, and
166
+ installing, stopping or removing one also finds, stops and removes the same
167
+ repo's `com.standing-orders.watch.*` job. The skill folder is
168
+ `.claude/skills/toolroll`; a managed `standing-orders` copy is replaced on
169
+ install. Slack buttons send `toolroll_*` action ids and still accept
170
+ `standing_orders_*` ones on older messages. Hash and digest inputs, the
171
+ ledger genesis and stored format ids are unchanged, so existing data
172
+ verifies.
173
+ **Breaking for monitoring:** Prometheus metrics are renamed from
174
+ `standing_orders_*` to `toolroll_*` (for example
175
+ `toolroll_ledger_chain_ok`), and OTLP traces report `service.name` and the
176
+ instrumentation scope as `toolroll`; the monitoring webhook `user-agent` is
177
+ `toolroll/<version>`, and the MCP server and client name is `toolroll`.
178
+ Update dashboards, alerts and collector filters. Span attribute keys
179
+ (`standing_orders.*`) and the audit webhook's signature header are unchanged.
180
+
181
+ - **Retention settings.** An instance operator chooses how long run
182
+ evidence and logs, finished checkout records, chat messages and
183
+ notifications are kept (forever until chosen), on Settings → Retention or
184
+ with `standing-orders retention show|set|preview`. Changes take the
185
+ password and are in the action ledger. The worker sweeps once a day and
186
+ writes one ledger entry saying what it removed and about how much space it
187
+ freed. The ledger, unfinished tasks, results not yet completed and anything
188
+ on hold are never removed; removed evidence says so instead of looking
189
+ damaged.
190
+
191
+ - **Delete a project.** An instance operator can remove everything Standing
192
+ Orders holds for a project: its tasks and their versions, runs and their
193
+ evidence, the checkouts and `standing-orders/` branches it made, chats,
194
+ flows and cards, teammates, budgets, settings and knowledge. Settings →
195
+ Project asks for the project's name, then shows exactly what goes and
196
+ asks for the password; `standing-orders project delete --repo <path>`
197
+ previews and `--yes` deletes. Nothing is deleted while any of the
198
+ project's work is running. The repository, its working copy and its own
199
+ branches are never touched, other projects keep their rows, and the ledger
200
+ keeps every entry (the chain still verifies) and gains one saying who
201
+ deleted what. No undo; no schema change.
202
+
203
+ - **Organisation policy.** Settings → Policy (and `standing-orders policy
204
+ show|set`) sets which providers and models may run, which project tools
205
+ agents may use, and the highest permission level anything runs with
206
+ (safe, standard or escalated). Saving takes your password; each change is
207
+ in the action ledger, before → after, and the page shows that history.
208
+ Scope approval, the tick and the last check before a build, fallback
209
+ entries, race lanes, attended sessions, the lead and project chats,
210
+ teammates and flow steps all obey it and say which rule stopped them.
211
+ New filings are lowered to the ceiling; work approved above it runs
212
+ lowered (the ledger says so), attended sessions are refused, and a
213
+ provider with no setting that low (Codex at Safe) is refused.
214
+
215
+ - **Cost guardrails.** Work on a subscription (a Claude or Codex sign-in)
216
+ counts as $0: what binds it is the plan's usage windows, which Tasks now
217
+ shows as tiles (Claude's 5-hour and weekly windows as Claude reports them
218
+ on every turn, Codex's as its app server answers every five minutes), each
219
+ with when it resets, amber from 80 % and red when used up. How work is
220
+ billed follows what the CLI actually did (Claude's key source on each run,
221
+ Codex's account), not only the setting. Work billed to an API key is
222
+ priced: what the provider reported, or its tokens at the model's price in
223
+ Settings → Models (the provider's highest listed price when the model
224
+ isn't listed), frozen when the run settles; key work that can't be priced
225
+ at all waits under a budget until prices are loaded. The Spend page
226
+ (and `standing-orders spend`) shows each month by project, person,
227
+ teammate and model, with a CSV. Monthly budgets for the whole
228
+ installation, a project, a person or an AI teammate alert at 50, 80 and
229
+ 100 % (once each, again after a change; a person's budget to that person,
230
+ on Telegram too) and, unless set to alert only, stop API work at 100 %:
231
+ queued tasks, fallbacks, resumed races, continuations, repair turns, key
232
+ chats and flow sorts wait (the task page says why), and a Claude run's cap
233
+ shrinks to what's left. Budgets and their limits also show as tiles on
234
+ Tasks, are set on the Spend page or with `standing-orders budget`, with a
235
+ step-up, and every change is in the ledger. Schema 105.
236
+
237
+ - **Stream it out.** Settings → Monitoring sends what Standing Orders does
238
+ to the tools a company already watches. The audit stream delivers every
239
+ sealed ledger entry, in order and at least once (retried, never skipped),
240
+ to a webhook, each request signed with a secret shown once
241
+ (`x-standing-orders-signature: t=…,v1=<HMAC-SHA256 of "t.body">`), and/or
242
+ a folder of JSON Lines files; each batch carries the chain head, so the
243
+ receiver keeps its own copy of the checkpoints. Traces send each run as an
244
+ OpenTelemetry span (OTLP over HTTP) under its task's trace: timings,
245
+ model, tokens and cost, never a prompt or code. `/metrics` serves
246
+ Prometheus metrics to an instance operator's API token.
247
+ `standing-orders monitoring` shows how each destination is doing.
248
+ Schema 104.
249
+
250
+ - **Storage kept in check.** Standing Orders used to keep every build
251
+ checkout and every staged release forever (78 GB here after a week). Now
252
+ the worker removes a finished task's clean checkout two days after it was
253
+ let go (a result marked complete, or a release candidate, a week after,
254
+ since a deploy installs the build in its checkout). Its branch and commits stay; a checkout with
255
+ anybody's changes, or commits on no branch, is never touched, nor is
256
+ anything an unfinished or unplaced task works on. Each removal is in the
257
+ action ledger. A deploy keeps the release it installed, the one before,
258
+ the newest few and any a service or the CLI runs from; older ones go with
259
+ the database backups they hold. `standing-orders storage` shows where
260
+ the disk goes.
261
+
262
+ - **Audit you can prove.** The action ledger is now a hash chain: each entry
263
+ is sealed with the one before it, and the ledger page (or `ledger verify`)
264
+ says whether it still verifies, or the first entry that was changed,
265
+ removed or added. Instance operators make checkpoints to copy off the
266
+ machine (`ledger checkpoint`); `ledger verify --checkpoint` compares one,
267
+ and is what proves history before it wasn't rewritten.
268
+ Every task has an evidence pack, as a printable page and JSON: who filed
269
+ it, the approved terms and approvers, the rules in force, agents and
270
+ cost, changed files, checks, completion, publication and its sealed
271
+ ledger entries (`task evidence <id>`). The ledger page's Audit export (or
272
+ `ledger export --from --to`) downloads a date range with a pack for each
273
+ task. AI teammates' tool calls (and who approved or undid them) and new
274
+ coordinators are in the ledger now too. Schema 103.
275
+
276
+ - **Separation of duties.** Every task records who filed it (the person, or
277
+ the person a coordinator acts for). Settings → Approval rules (or
278
+ `project rules`) lets an instance operator turn on, per project,
279
+ "someone other than the requester approves" and protected work: the whole
280
+ project, or paths like `infra/**`, need two different people to approve
281
+ the same scope ("1 of 2" until the second; a changed scope starts over),
282
+ and never an operating mode, a routine, a watched run or an AI teammate.
283
+ Whoever wrote the scope or made a standing order counts as a requester,
284
+ and a result whose actual diff reaches protected files on a one-person
285
+ approval completes only by someone else. Everything is off until a
286
+ project turns it on. Schema 102.
287
+
288
+ - **Sessions and API tokens.** Settings → Sessions & tokens lists where
289
+ you're signed in and signs any of it out; sessions now survive a restart.
290
+ API tokens (read, or act as you, never approve) replace passwords on
291
+ requests for scripts and CI, expire in 30 to 365 days, are shown once and
292
+ named in the ledger on every request. Coordinator credentials expire (90
293
+ days unless `--days`), and runner tokens a year after registering.
294
+ Schema 101.
295
+
296
+ - **Sign in with your identity provider.** Settings → Sign-in connects Okta,
297
+ Microsoft Entra, Google or any OpenID Connect provider. People sign in
298
+ there; their groups make their account and set its role (Operator or
299
+ Viewer) and projects again at each sign-in. Approvals are confirmed by
300
+ that sign-in (within ten minutes, or "Confirm with …"), not a password.
301
+ Passwords can be kept for instance operators only, as a way in if the
302
+ provider is down, and an existing account can be linked. Schema 100.
303
+
304
+ - **Hardening for teams.** Five wrong passwords lock a name for 15 minutes,
305
+ on every road a password takes (signing in, a request, a step-up), and one
306
+ address guessing across names runs out of tries. The action ledger now
307
+ records sign-ins and policy changes with what changed (the permission
308
+ default "Auto → Full access", a teammate's tool rules, an agent choice, an
309
+ operating mode), and shows installation events to instance operators. A
310
+ person's coordinators end with their standing. `/healthz` answers a probe,
311
+ errors are always logged (`STANDING_ORDERS_LOG_FORMAT=json` for JSON
312
+ lines), and more key shapes (Stripe, Google, GitLab, Telegram and Discord
313
+ tokens, passwords in URLs) are blanked. Schema 99.
314
+
315
+ - **One look on every page.** Board, Inbox, Next, Done, System, Portfolio,
316
+ Code and Settings → Tools now sit in the same workspace as everything else,
317
+ with the same navigation and search. Live pages (System, Activity) refresh
318
+ themselves inside it without disturbing a form you're filling in. Sign-in,
319
+ invites, error pages and "not found" share the look too, and a one-time
320
+ secret (a worker token, an invite link, a pairing code) gets a focused page
321
+ in the same style, still with no script on it.
322
+
323
+ - **Connect a service with one click.** Stripe, Notion, Linear, Sentry, Jira,
324
+ Intercom, Attio and ten more connect by signing in on the service's own
325
+ page: no key to copy. The sign-in stays in the tool's secrets file and is
326
+ renewed before it runs out. A starter kit's Connect also lets its teammate
327
+ use the tool. The lead points you to the right tile instead of asking for a
328
+ key.
329
+
330
+ - **Starter kits.** Support desk, Bug triage, Sales follow-up and Ops
331
+ requests each set up a teammate, the flow it works and its buttons in one
332
+ click. The kit's page lists what's left (email, the tools it uses) and
333
+ **Try it** puts a sample card in front of the teammate so you see it work.
334
+ The lead can set one up too.
335
+
336
+ - **Smoother page changes.** Moving between pages fades the old one out
337
+ before the new one arrives, so text never overlaps mid-change, and the
338
+ sidebar holds still.
339
+
340
+ - **Telegram pushes your messages.** With a public hooks address, Telegram
341
+ delivers each message and tap to Standing Orders the moment you send it,
342
+ signed with a secret, instead of Standing Orders asking for them. No other
343
+ program can take your bot's messages meanwhile, and "Conflict" no longer
344
+ fills the log when one tries.
345
+
346
+ - **A weekly report per teammate, and undo.** Every Monday its manager gets the
347
+ week: what it did, its tool calls, what its turns cost, and what you
348
+ overrode, each linked. Name an action's opposite (remove_label for
349
+ add_label) and its receipts get an Undo that calls it with the same input,
350
+ as you.
351
+
352
+ - **Message a teammate by name, and give it routines.** "@maya where's order
353
+ 2201?" in Telegram, Slack, Discord or Teams lands on Maya's desk, and the
354
+ answer comes back to you there. Routines ("weekdays 09:00: look up
355
+ yesterday's refunds") put a card on its desk on a schedule and report to
356
+ its manager. A code change it's asked for is filed as an ordinary task
357
+ under your approvals.
358
+
359
+ - **Teammates remember, and learn from you.** Each teammate keeps a memory:
360
+ what you tell it, and short facts it keeps from the cards it works, read
361
+ back when a later card is about the same thing. Search, edit or forget any
362
+ of it. Approve the same kind of call five times in a row and it suggests
363
+ the rule that lets it act alone; one tap accepts.
364
+
365
+ - **Teammates that act.** Let a teammate use your project's tools (a shop, a
366
+ CRM, a mailbox) with a rule for each action: do it, do it up to a limit,
367
+ ask first, or never. An ask-first call reaches you on the card and in your
368
+ chat app exactly as it would be made; Approve makes that call, Deny doesn't.
369
+ Every call is a receipt on the card and the teammate's page, and the lead
370
+ can change a rule from plain words.
371
+
372
+ - **AI teammates.** Agents with a soul file you write (who they are, how they
373
+ write, what they decide alone, what they ask first, what they never do)
374
+ decide "Person decides" zones and handle their own zones, write replies,
375
+ move cards on, and bring you what their rules say to ask about, in your chat
376
+ app under their own name. A note for this week, a daily summary, a pause
377
+ button, and templates for support, sales, ops and triage. Answer a
378
+ teammate's question with a tap, or in your own words, in Telegram, Slack,
379
+ Discord or Teams.
380
+
381
+ - **Wait for replies.** A Wait zone after a Send email zone waits for the
382
+ person to answer. Their reply moves the card on and joins its discussion;
383
+ with none in time, the card takes its no-reply path, like a nudge that stays
384
+ in the same thread. Only replies from people the card wrote to count.
385
+
386
+ - **Time limits.** Any zone can remind whoever a card is waiting on after a
387
+ while, and Holding and decision zones can move it on. New templates: Reply
388
+ and follow up, and Decisions that don't stall.
389
+
390
+ - **Send-backs are planned again.** Sending a result back with a note has the
391
+ planner update the plan with it; a note asking for more becomes a change
392
+ you see and approve before anything builds.
393
+
394
+ ## 0.5.0 — 2026-09-25
395
+
396
+ Flows: your process drawn as zones that cards move through, with agents doing
397
+ the work and people deciding.
398
+
399
+ - **Canvas and chat.** Draw flows on a canvas or describe them to the lead;
400
+ every change is a card you confirm. Templates for coding, research, issue
401
+ triage, spam filtering, lead, effort and exception routing, and email replies.
402
+ - **Triggers.** Buttons (and public forms), schedules, GitHub, Linear, other
403
+ flows and webhooks start cards on their own.
404
+ - **People.** Owners, followers, @mentions, and a flow owner whom decisions
405
+ go to, in their chat app.
406
+ - **Steps with and without AI.** Build and Research tasks; scripts with no AI;
407
+ **Sort** with Jev (TypeSafe's decision model, through OpenRouter); **Draft**
408
+ with Claude; web requests with secrets kept to headers; email through your
409
+ own mail server; any of a project's MCP tools; updates to the GitHub or
410
+ Linear issue a card came from.
411
+ - **Decisions from your phone.** Telegram, Slack, Discord and Teams
412
+ messages carry the draft with Approve, Edit and Send back.
413
+ - **Email in.** An Email inbox trigger turns new mail into cards (IMAP, or
414
+ a Google account signed in with Google), and replies to the sender stay
415
+ in the thread. Automatic replies and your own mail never become cards.
416
+ - **Code in flows.** Scripts in Python, Node or shell (or a file in the
417
+ project) get the card as data; what they print is passed on, a `goto:` line
418
+ picks the next zone, saved secrets arrive as variables, and a schedule can
419
+ run a script to make a card of each item it prints.
420
+ - **Chat in.** A Slack, Discord or Teams channel, or a Telegram group, feeds
421
+ a flow after `flow 12` in it: each message is a card, replies in its thread
422
+ join the discussion, and an Update zone answers in that thread.
423
+ - **Live canvas.** A flow open in several browsers changes in all of them
424
+ the moment a card moves, and shows who else has it open and which card
425
+ they're looking at.
426
+ - **Insights.** Where each flow breaks, how scripts do, how well sorting
427
+ sorts, and every step's log.
428
+ - **Linux.** A one-command installer, and Claude and Gemini agents fenced
429
+ with bubblewrap the way Seatbelt fences them on macOS.
430
+ - **First look.** `demo` now includes two flows mid-flight, and an empty
431
+ Flows page offers a working example.
432
+ - **Settings.** An Email section, and "Check again" that really tests an
433
+ API key.
434
+
435
+ Schema 90: the database upgrades itself on first start.
package/README.md CHANGED
@@ -47,6 +47,21 @@ never reaches outside.
47
47
  | yarn | `yarn global add toolroll` |
48
48
  | script | `curl -fsSL https://raw.githubusercontent.com/ap9000/toolroll/main/install.sh \| sh` |
49
49
 
50
+ ## Install with your agent
51
+
52
+ Paste this into Claude Code or Codex:
53
+
54
+ > Install Toolroll with `npm install -g toolroll` and start `toolroll up` in
55
+ > the background; it keeps running. Then run `toolroll onboard` in this
56
+ > repository, and run it again with `--yes` to add it as a project and install
57
+ > Toolroll's skill for you. Tell me the console address, where my login is saved (not the
58
+ > password), how to pair my phone, and what I can ask you next.
59
+
60
+ `toolroll onboard --yes` adds the repository (its main checkout) as a project,
61
+ says which agent CLIs are signed in, and prints the line that adds Toolroll as
62
+ tools (`claude mcp add --scope user toolroll -- toolroll mcp`) without running it.
63
+ `toolroll onboard --remove --yes` takes the skill out again.
64
+
50
65
  Then read [Getting started](docs/guide/getting-started.md), [Flows](docs/guide/flows.md)
51
66
  and [Security](docs/guide/security.md). Coming from Standing Orders? It's the
52
67
  same product renamed; the `standing-orders` command and your data keep working.
@@ -0,0 +1,129 @@
1
+ /**
2
+ * `toolroll onboard`: the agent that installed Toolroll becomes its lead.
3
+ *
4
+ * Run inside a repository, it adds that repository as a project (the same
5
+ * registry and project row Projects → add writes), reports which agent
6
+ * CLIs are signed in (the checks Settings → AI providers makes), installs
7
+ * a thin operator skill for the person's own agent, prints the MCP line
8
+ * without running it, and ends with a handoff the agent can relay.
9
+ *
10
+ * Adding the project and writing the skill both need --yes or one yes
11
+ * typed at a terminal. The project is the main checkout (never a linked
12
+ * worktree, the home folder, or one of Toolroll's own worktrees). The skill
13
+ * is replaced by the next onboard and deleted by `onboard --remove` only
14
+ * while it is exactly a version Toolroll wrote; a file of the same name
15
+ * that is not ours, or ours with the person's edits, is never touched.
16
+ */
17
+ import type { ProviderConnection } from "./provider-connection.js";
18
+ export type OnboardAgent = "claude" | "codex";
19
+ export declare const ONBOARD_AGENTS: readonly OnboardAgent[];
20
+ export declare const AGENT_NAMES: Record<OnboardAgent, string>;
21
+ /** Each agent's user-level home: where its skills folder lives. A relative CODEX_HOME is under the home folder, never
22
+ * wherever onboard happens to run. */
23
+ export declare function agentHome(agent: OnboardAgent, home: string, env: Record<string, string | undefined>): string;
24
+ export declare function operatorSkillPath(agent: OnboardAgent, home: string, env: Record<string, string | undefined>): string;
25
+ /** The agents this person uses: those whose home folder exists, else Claude Code. */
26
+ export declare function detectAgents(home: string, env: Record<string, string | undefined>): OnboardAgent[];
27
+ /** The line that adds Toolroll as tools, for every project. Printed, never run. */
28
+ export declare function mcpLine(agent: OnboardAgent): string;
29
+ /** The thin skill: when to reach for Toolroll, and where the real guides are. */
30
+ export declare function operatorSkillContent(version: string): string;
31
+ /** A skill's fingerprint with the version it names set aside: every release writes the same words. */
32
+ export declare function skillFingerprint(content: string): string;
33
+ export type SkillStep = {
34
+ agent: OnboardAgent;
35
+ path: string;
36
+ /** create/replace/remove change the file; current and absent change nothing; not-ours and edited refuse. */
37
+ action: "create" | "replace" | "current" | "remove" | "absent" | "not-ours" | "edited";
38
+ /** Old guide copies of ours that go with it. */
39
+ alsoRemove: string[];
40
+ };
41
+ /** What install (or --remove) would do, without writing anything. */
42
+ export declare function planOperatorSkill(agents: readonly OnboardAgent[], options: {
43
+ home: string;
44
+ env: Record<string, string | undefined>;
45
+ version: string;
46
+ remove: boolean;
47
+ }): SkillStep[];
48
+ /** Carry out a plan. Steps that are not ours, current, or absent change nothing. */
49
+ export declare function applyOperatorSkill(steps: readonly SkillStep[], version: string): {
50
+ wrote: string[];
51
+ removed: string[];
52
+ };
53
+ /** How to sign in: the account, and the saved login file when one still works. Never the password. */
54
+ export type HandoffLogin = {
55
+ account: string | null;
56
+ file: string | null;
57
+ };
58
+ export type Handoff = {
59
+ console: string;
60
+ /** How to start the console when it is not running. */
61
+ start: string;
62
+ /** null while there is no account yet. */
63
+ login: HandoffLogin | null;
64
+ phone: string;
65
+ next: readonly string[];
66
+ };
67
+ export declare const NEXT_THINGS: readonly ["queue these bugs overnight", "what needs me?", "open the result"];
68
+ export declare function buildHandoff(input: {
69
+ url: string;
70
+ login: HandoffLogin | null;
71
+ }): Handoff;
72
+ export declare function handoffLines(handoff: Handoff): string[];
73
+ /** The account name from a saved login file, never its password. */
74
+ export declare function loginAccount(file: string): string | null;
75
+ export type AgentReport = {
76
+ agent: OnboardAgent;
77
+ name: string;
78
+ state: ProviderConnection["state"];
79
+ words: string;
80
+ plan?: string;
81
+ };
82
+ export declare function agentReport(agent: OnboardAgent, connection: ProviderConnection): AgentReport;
83
+ export type OnboardIo = {
84
+ write: (line: string) => void;
85
+ json: boolean;
86
+ yes: boolean;
87
+ remove: boolean;
88
+ /** --agent, as typed: a comma list of claude and codex. */
89
+ agentFlag: string | undefined;
90
+ url: string;
91
+ login: HandoffLogin | null;
92
+ home: string;
93
+ /** Where Toolroll leases its own worktrees: never a project. */
94
+ worktrees: string;
95
+ env: Record<string, string | undefined>;
96
+ version: string;
97
+ cwd: string;
98
+ /** A person at a terminal who can be asked y/N. */
99
+ interactive: boolean;
100
+ confirm: (question: string) => Promise<boolean>;
101
+ /** The repository containing cwd: its top folder, and its main checkout (the same folder unless cwd is in a linked
102
+ * worktree). null outside one. */
103
+ findRepo: (cwd: string) => Promise<{
104
+ top: string;
105
+ main: string;
106
+ } | null>;
107
+ /** Whether a repository is already a project. */
108
+ enrolled: (repo: string) => Promise<boolean>;
109
+ /** Add a repository as a project, as Projects → add does. */
110
+ enroll: (repo: string) => Promise<{
111
+ ok: true;
112
+ added: boolean;
113
+ } | {
114
+ ok: false;
115
+ message: string;
116
+ }>;
117
+ checkConnection: (agent: OnboardAgent) => Promise<ProviderConnection>;
118
+ };
119
+ /** Why a found repository cannot be the project, or null when it can. */
120
+ export declare function projectRefusal(found: {
121
+ top: string;
122
+ main: string;
123
+ }, where: {
124
+ cwd: string;
125
+ home: string;
126
+ worktrees: string;
127
+ }): string | null;
128
+ /** Returns the exit code: 0 done, 2 usage, 3 a refusal to answer. */
129
+ export declare function runOnboard(io: OnboardIo): Promise<number>;