toolroll 0.6.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 +413 -0
- package/README.md +15 -0
- package/dist/agent-onboard.d.ts +106 -0
- package/dist/agent-onboard.js +282 -0
- package/dist/browser/workspace.css +2 -2
- package/dist/browser/workspace.js +23 -23
- package/dist/browser-shell.js +5 -3
- package/dist/browser-workspace.d.ts +45 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +8 -1
- package/dist/control-setup.d.ts +4 -4
- package/dist/daemon.d.ts +4 -0
- package/dist/daemon.js +28 -4
- package/dist/desktop-host.js +2 -2
- package/dist/desktop-update.d.ts +7 -1
- package/dist/desktop-update.js +39 -22
- package/dist/evidence.d.ts +24 -0
- package/dist/evidence.js +103 -5
- package/dist/first-run.d.ts +54 -0
- package/dist/first-run.js +101 -0
- package/dist/install-method.d.ts +17 -0
- package/dist/install-method.js +65 -0
- package/dist/operate.d.ts +14 -0
- package/dist/operate.js +114 -18
- package/dist/provider-auth.d.ts +33 -8
- package/dist/provider-auth.js +54 -13
- package/dist/releases.d.ts +85 -0
- package/dist/releases.js +238 -0
- package/dist/serve.d.ts +18 -0
- package/dist/serve.js +237 -81
- package/dist/skills.d.ts +2 -0
- package/dist/skills.js +3 -1
- package/dist/store.d.ts +3 -3
- package/dist/store.js +9 -4
- package/dist/surface.js +2 -0
- package/dist/toolroll-update-cli.d.ts +15 -0
- package/dist/toolroll-update-cli.js +155 -0
- package/dist/toolroll-update-ui.d.ts +38 -0
- package/dist/toolroll-update-ui.js +89 -0
- package/dist/toolroll-update.d.ts +235 -0
- package/dist/toolroll-update.js +929 -0
- package/dist/update-notice.d.ts +5 -0
- package/dist/update-notice.js +4 -0
- package/dist/work-index.js +5 -3
- package/package.json +2 -1
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>;
|