toolroll 0.7.0 → 0.8.0

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