foldrun 0.8.0 → 1.0.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/README.md CHANGED
@@ -114,7 +114,8 @@ declared the same way.
114
114
  |---|---|
115
115
  | `foldrun init [dir]` | create an account folder with one workspace in it (`--flat` for the old shape) |
116
116
  | `foldrun new <name>` | another workspace in this account |
117
- | `foldrun agent new <name>` | one more agent in this workspace — also `flow new <name>` and `tool new <name>` |
117
+ | `foldrun agent new <name>` | one more agent in this workspace — also `flow new <name>` and `tool new <name>`; `--platform` makes it in the deployed workspace instead |
118
+ | `foldrun agent ls` | the agents deployed in a workspace — also `flow ls`, and `agent import --list` for what could be copied in (`--to`) |
118
119
  | `foldrun flow set\|trigger\|move-step\|copy-step\|paste\|draft <flow>` | the Flows page from a terminal: step options, the trigger, a drag, copy and paste, Draft with AI — the same core rewriters, a diff, refused when `check` would call it an error (`--to <ws>` edits the deployed copy) |
119
120
  | `foldrun guide` | the coding-agent rules, as Next.js writes them: a short block in `AGENTS.md` telling Claude Code, Cursor or Codex to read `foldrun docs` before editing, and `CLAUDE.md` importing it (`@AGENTS.md`). `init` writes them, `pull` refreshes them, `check` re-adds them when a coding agent runs it; only the marked block is ever rewritten (`--check`, `--print`) |
120
121
  | `foldrun docs [page]` | foldrun's docs from the copy this CLI ships, so a coding agent reads the version it is driving, offline (`--path` prints where) |
@@ -123,7 +124,7 @@ declared the same way.
123
124
  | `foldrun agent run <name>` | run one agent once on a platform, no flow (`--task "…"`, `--wait`, `--test`) |
124
125
  | `foldrun tool test <name>` | exercise one tool alone — no model, no run (`key=value` for its args) |
125
126
  | `foldrun run <target>` | run an agent or a flow |
126
- | `foldrun eval [name]` | run one eval, or all of them |
127
+ | `foldrun eval [name]` | run one eval, or all of them — `eval new <name> --to <ws>` makes one on the platform |
127
128
  | `foldrun extract [dir]` | move single-file script tools into folders |
128
129
  | `foldrun probe <model>` | live check: can this model hold a tool loop here? |
129
130
  | `foldrun logs [run-id]` | recent runs, or one run's full event trail |
@@ -138,7 +139,7 @@ declared the same way.
138
139
  | `foldrun rerun <run-id>` | the same flow again from a step — `--from <n>` as the flow numbers them, or `--agent <name>` for the first step that agent runs; `--wait` follows it |
139
140
  | `foldrun schedule` | every flow in the account that fires on a clock, its cron line, and the next few times it fires |
140
141
  | `foldrun schedule tick` | fire whatever is due now — Settings' "Run scheduler now" |
141
- | `foldrun backups` | how the account is backed up and the snapshots it is in; `backups request --what runs --at "<when>" [--to <ws>]` asks the platform team for a restore |
142
+ | `foldrun backups` | how the account is backed up and the snapshots it is in; `backups request --what runs --at "<when>" [--to <ws>]` asks the platform team for a restore, `backups requests` lists them |
142
143
  | `foldrun restore <ws> --to <commit\|time\|3d>` | a workspace's source back as it was then — shows the change, asks for the name typed back (`--dry-run`, `--yes`) |
143
144
  | `foldrun onboarding` | the account's getting-started steps, done or not, the next one first |
144
145
  | `foldrun triggers` | why nothing ran: per flow, how often its trigger fired, how often that became a run, and every reason for the difference (`--since <days>`, `--to`) |
@@ -148,6 +149,7 @@ declared the same way.
148
149
  | `foldrun storage put <file>` | upload a file into a workspace's storage (`--as <path>` names it) — also `rm <path>` |
149
150
  | `foldrun storage share <path>` | a public link to one produced file (`--ttl <days>`, default 7; `--forever`) — also `shares` (`--all`) and `unshare <token>` |
150
151
  | `foldrun billing` | the account's balance and its recent ledger entries, with what each was for |
152
+ | `foldrun billing credit <usd>` | credit added by hand — only on an install without Stripe (self-hosted, dev) |
151
153
  | `foldrun billing plans` | the plans and this cycle's credits — also `plan <id>`, `plan cancel`, `plan resume`, `top-up <usd>`, `card` (Stripe's own pages for anything with a card) |
152
154
  | `foldrun account` | the account's defaults: timezone, notify, budget, concurrency — also `set <key> <value>` and `clear <key>` |
153
155
  | `foldrun account providers` | which model providers the account's files use and whether each key still answers (`--check` asks now) |
@@ -155,15 +157,16 @@ declared the same way.
155
157
  | `foldrun secrets clients` | OAuth clients saved on the platform — `add`, `rm`; `connect NAME --client <name>` runs a consent from one. `secrets set NAME --kind file\|ssh\|api\|service-account\|m2m` for the other shapes |
156
158
  | `foldrun deploy [dir]` | push the whole account — or `deploy <workspace>` for one of them |
157
159
  | `foldrun pull [workspace]` | bring the platform's account down here (refuses to clobber local edits) |
158
- | `foldrun status [workspace]` | per workspace: added, changed, and what moved on the platform since your last deploy |
159
- | `foldrun workspaces` | what exists here and there — also `rm <name>` (`--platform --yes` to delete it there) |
160
- | `foldrun library` | the account's shared library on the platform: `ls`, `cat`, `put`, `rm` |
160
+ | `foldrun status [workspace]` | per workspace: added, changed, and what moved on the platform since your last deploy — `--platform` for the platform's health, `--platform --history` for its daily uptime |
161
+ | `foldrun workspaces` | what exists here and there — also `show <name>` (what is deployed in it), `new <name> --platform` (`--starter`), `rm <name>` (`--platform --yes` to delete it there) |
162
+ | `foldrun library` | the account's shared library on the platform: `ls`, `cat`, `put`, `new <kind>/<name>`, `rm` |
161
163
  | `foldrun find <words>` | the dashboard's ⌘K search, across the account |
162
164
  | `foldrun history restore <path> --id <rev>` | one file back as a revision left it, as a new revision |
163
165
  | `foldrun invoke <flow>` | start a flow on a running platform (`--watch` streams its trace; `--once <key>` makes a retry a no-op rather than a second run) |
164
166
  | `foldrun open [page]` | the dashboard for this workspace, in the browser |
165
167
  | `foldrun login` | sign this machine in from the browser — no key to copy |
166
168
  | `foldrun whoami` | who you are on the platform: account, role, workspaces |
169
+ | `foldrun team` | who is in the account, their roles and workspaces — read-only; invites and role changes are a person's, in the dashboard |
167
170
  | `foldrun preferences` | your theme on the platform — `set theme system\|light\|dark` |
168
171
  | `foldrun api version` | the API version pin and rate limits — `pin <date>`, `unpin` |
169
172
  | `foldrun changelog` | the platform's release notes |
package/bin/foldrun.mjs CHANGED
@@ -22,24 +22,29 @@
22
22
  // foldrun triggers why nothing ran: fired vs started per flow, and each reason
23
23
  // foldrun webhooks <verb> deliveries / redeliver <id> — the notify: webhooks a workspace sent, and each attempt
24
24
  // foldrun notifications what mail you get, per category — set <category> on|off
25
- // foldrun backups how the account is backed up, its snapshots — request a restore from one
25
+ // foldrun flags the feature flags for this account — on or off, and why (read-only)
26
+ // foldrun backups how the account is backed up, its snapshots — request a restore from one, requests lists them
27
+ // foldrun team who is in the account, their roles and workspaces (read-only)
26
28
  // foldrun restore <ws> a workspace's source back to a point in its history (shows the change, asks)
27
29
  // foldrun onboarding the account's getting-started steps, the next one first
28
- // foldrun billing the balance, and what the money went on
30
+ // foldrun billing the balance, and what the money went on — credit <usd> on an install without Stripe
29
31
  // foldrun gallery the tools the platform ships to every account — list, pull, upgrade <tool>
30
32
  // foldrun storage <verb> ls / cat / get / put / rm / share / shares / unshare — what the agents produced, and public links to it
31
33
  // foldrun runtimes the environments a workspace's agents need, and whether each is built
32
34
  // foldrun secrets <verb> set / ls / rm — the vault, from the terminal
33
35
  // foldrun new <name> another workspace in this account
34
- // foldrun agent new <name> one more agent in this workspace — also flow new, tool new
36
+ // foldrun agent new <name> one more agent in this workspace — also flow new, tool new (--platform: in the deployed one)
37
+ // foldrun agent ls the agents deployed in a workspace — also flow ls
38
+ // foldrun eval new <name> a new eval in a deployed workspace
35
39
  // foldrun agent run <name> run one agent once on a platform, no flow
36
40
  // foldrun tool test <name> exercise one tool alone — no model, no run
41
+ // foldrun hook <verb> ls / add / test / rm — your own code at every tool call and step
37
42
  // foldrun deploy [dir] push this account — or one workspace — into an installation
38
43
  // foldrun pull bring the platform's account down into this folder
39
- // foldrun status what differs here from what is deployed
40
- // foldrun workspaces what exists here, and there
44
+ // foldrun status what differs here from what is deployed — --platform [--history]: is the platform up
45
+ // foldrun workspaces what exists here, and there — show <name>, new <name> --platform
41
46
  // foldrun invoke <flow> start a flow on a running platform
42
- // foldrun source <verb> ls / cat / put / mv / rm one workspace file on a platform
47
+ // foldrun source <verb> ls / cat / put / new / mv / rm one workspace file on a platform
43
48
  // foldrun open [page] the dashboard for this workspace
44
49
  // foldrun login sign this machine in from the browser
45
50
  // foldrun login <site> a browser window to sign in to a site by hand; the session
@@ -48,7 +53,7 @@
48
53
  // foldrun doctor what is between this terminal and the platform, checked
49
54
  // foldrun accounts every account signed in here; `use <name>` switches
50
55
  // foldrun keys <verb> ls / create / revoke — the account's API keys
51
- // foldrun library <verb> ls / cat / put / rm — the account's shared shelf on the platform
56
+ // foldrun library <verb> ls / cat / put / new / rm — the account's shared shelf on the platform
52
57
  // foldrun find <words> search the account the way the dashboard's ⌘K does
53
58
  // foldrun changelog what each release of the platform changed
54
59
  // foldrun preferences your own settings on the platform — the theme
@@ -60,6 +65,11 @@ import { fileURLToPath } from "node:url";
60
65
  import fs from "node:fs";
61
66
  import path from "node:path";
62
67
  import process from "node:process";
68
+ import { guardTerminal } from "../src/terminal.mjs";
69
+
70
+ // Before anything prints: a platform's text never writes escape sequences to
71
+ // a person's terminal (src/terminal.mjs). Pipes and files are untouched.
72
+ guardTerminal();
63
73
 
64
74
  const HERE = path.dirname(fileURLToPath(import.meta.url));
65
75
 
@@ -85,20 +95,26 @@ if (command === "--version" || command === "-v") {
85
95
  const HELP = `foldrun — agents are just folders
86
96
 
87
97
  foldrun init [dir] create an account folder: AGENTS.md, library/ and workspaces/<name>
88
- foldrun new <name> another workspace in this account
98
+ foldrun new <name> another workspace in this account — blank (--starter for the example researcher, writer and flow)
89
99
  foldrun agent new <name> one more agent in this workspace (--to <workspace> in an account)
100
+ foldrun agent new <name> --platform make it in the DEPLOYED workspace, as the dashboard's New agent does (--to, --description, --model)
90
101
  foldrun flow new <name> one more flow — its first step names an agent you already have
91
- foldrun tool new <name> one more tool: a folder with its program beside it (--transport, --language)
102
+ foldrun flow new <name> --platform make it in the deployed workspace from a shape (--pattern pipeline|review-loop|fan-out|debate|router, --to)
103
+ foldrun tool new <name> one more tool: a folder with its program beside it (--transport, --language; --platform in the deployed workspace, --template <gallery entry>)
104
+ foldrun agent ls the agents deployed in a workspace: model, description (--to, --json) — flow ls the flows and how each fires
92
105
  foldrun check [dir] validate every workspace here, and the shared library
93
106
  foldrun check --to <ws> validate the DEPLOYED copy instead — fetched from the platform, checked here
94
107
  foldrun agent run <name> run one agent once on the platform (--task "…", --to, --wait, --test)
95
108
  foldrun agent link <agent> add to its team, in its frontmatter: --subagent <worker>, --consult <agent> or --can-ask (--description for a worker with none)
96
109
  foldrun agent unlink <agent> take one away: --subagent <name>, --consult <name> or --can-ask
110
+ foldrun agent import <workspace>/<agent> copy an agent you already have in another workspace into this one — its agent.md, own skills and scripts, not its memory (--as <name>, --workspace <name>; --to <ws> on the platform)
111
+ foldrun agent import --list what could be imported into a deployed workspace: every other workspace you can read, and its agents (--to, --json)
97
112
  foldrun flow add <flow> <pattern> one canvas block as a markdown edit: chain, parallel, router, fan-out, loop, approval, ask, wait, rescue, subflow — diff shown, checked, --dry-run
98
113
  foldrun flow rm-step <flow> --step <n|agent> delete one step (its options too); groups renumber, agent file untouched — says what else changes, diff, checked, asks (--yes), --dry-run
99
114
  foldrun flow dup-step <flow> --step <n|agent> copy one step (marker and options) directly under it, in parallel with it — diff, checked, --dry-run
100
115
  foldrun flow show <flow> the flow as the canvas draws it: trigger, groups, step chips, each agent's team, check problems in place
101
116
  foldrun flow run <flow> start a flow on the platform — the same command as invoke
117
+ foldrun flow hook <flow> the flow's webhook URL as it is now, changing nothing (--json) — the URL is a credential
102
118
  foldrun flow rotate-hook <flow> a new webhook URL for a flow; the old one stops at once — asks first, --yes means it
103
119
  foldrun flow set <flow> --step <n|agent> key=value … the step editor: model, effort, retry, timeout, verify, when, case, else, loop, until, each, max, limits, instruction (key= clears) — diff, checked, --dry-run
104
120
  foldrun flow trigger <flow> manual|webhook|schedule the trigger picker (--schedule "<cron>", --timezone <zone>) — diff, checked, --dry-run
@@ -107,9 +123,14 @@ const HELP = `foldrun — agents are just folders
107
123
  foldrun flow paste <flow> step markdown from stdin or --file in as new groups (--after <g>, default last) or beside one (--group <g>) — diff, checked, --dry-run
108
124
  foldrun flow draft "<what it should do>" Draft with AI on the platform (--to; --flow <name> redrafts one): shows the files and the check, saves on yes (--yes, --dry-run)
109
125
  foldrun tool test <name> exercise one tool alone, no model and no run (key=value args, --to)
126
+ foldrun hook ls the hooks in this workspace and the account library: on, tool, description — invalid ones with the reason (--json); --to <ws>: the DEPLOYED workspace's, who turns each on, and what they denied, rewrote or failed lately (--runs <n>, --all)
127
+ foldrun hook add <name> --on <event> a hook folder: hook.md and a run.mjs that allows everything, the contract in its comments (--tool <pattern>, --library, --to)
128
+ foldrun hook test <name> run one hook here on a sample event, as a step would: its answer and how long it took (--event '<json>'|@file; --to <workspace>: the deployed one, on the platform)
129
+ foldrun hook rm <name> delete a hook folder — says which agents still turn it on, asks (--yes, --library)
110
130
  foldrun extract [dir] move single-file script tools into folders (tool.md + run.*)
111
131
  foldrun run <target> run an agent or flow HERE (target: name, or flow:name) — on the platform: flow run / invoke a flow, agent run one agent
112
132
  foldrun eval [name] run one eval, or all of them (--to <workspace>: the deployed evals, run on the platform)
133
+ foldrun eval new <name> a new eval in the deployed workspace, its agent the first one there — edit its cases, then eval <name> --to (--to)
113
134
  foldrun promote <run-id> keep a finished run as a regression case in evals/ (--eval <name>, --expect "contains: …" repeatable, --case <name>)
114
135
  foldrun probe <model> live check: can this model hold a tool loop here?
115
136
  foldrun logs [run-id] recent runs in one workspace, or one run's full event trail (--local: this machine's)
@@ -119,14 +140,14 @@ const HELP = `foldrun — agents are just folders
119
140
  foldrun report <run-id> get <agent>/<path> download a file the run archived from that agent's outputs/ (--file <path>|-, --force)
120
141
  foldrun report <run-id> live the live browser view: which agents have a frame; --agent <name> saves the newest as a JPEG (--file <path>|-)
121
142
  foldrun approvals every gate waiting on a person, with its question (--to <workspace> for one)
122
- foldrun approve <run-id> release a waiting gate — asks first, --yes means it, --note "…" steers the step
143
+ foldrun approve <run-id> release a waiting gate — asks first, --yes means it, --note "…" steers the step; --payload releases a wait: event step
123
144
  foldrun reject <run-id> refuse one, with --note as the reason
124
145
  foldrun stop <run-id> kill a run in flight — asks first, --yes means it
125
- foldrun stop --status running [--since 2h] [--flow f] every run a filter matches (runs/bulk): lists them, asks, stops only those (--dry-run, --to)
146
+ foldrun stop --status running [--since 2h] [--until 1h] [--flow f] every run a filter matches (runs/bulk): lists them, asks, stops only those (--dry-run, --to)
126
147
  foldrun answer <run-id> "…" answer the question an agent is asking mid-step (--option <n> picks a choice)
127
148
  foldrun message <run-id> "…" say something to a running agent — it hears it after its next tool call
128
149
  foldrun rerun <run-id> run it again from a step (--from <n>) or from an agent's step (--agent <name>); --wait
129
- foldrun rerun --status failed [--since 24h] [--flow f] rerun every run a filter matches, from --from <n> (default 1) — lists, asks (--dry-run, --to)
150
+ foldrun rerun --status failed [--since 24h] [--until 2h] [--flow f] rerun every run a filter matches, from --from <n> (default 1) — lists, asks (--dry-run, --to)
130
151
  foldrun observe where the account fails, retries and spends, per workspace (--to <workspace> in full, --since <days>, --json)
131
152
  foldrun usage what the account consumed, and what it was charged week by week (--days <n>, --json)
132
153
  foldrun schedule every flow that fires on a clock, its cron line and the next times (--to <workspace>)
@@ -144,9 +165,11 @@ const HELP = `foldrun — agents are just folders
144
165
  foldrun billing plans the plans, which one the account is on and this cycle's credits — also plan <id>, plan cancel, plan resume (asks first)
145
166
  foldrun billing top-up <usd> Stripe's checkout page for adding credit (owner only; --no-browser prints it)
146
167
  foldrun billing card Stripe's page for saving a card for auto top-up (owner only)
168
+ foldrun billing credit <usd> put credit on the balance by hand (--note "…") — only on an install without Stripe (self-hosted, dev); refused once billing is live
147
169
  foldrun gallery the platform's built-in tools (web) and whether you keep your own copy — also pull (a copy for offline runs), upgrade <tool>
148
170
  foldrun account the account's defaults — also set <key> <value>, clear <key>, providers (--check) (singular; accounts lists logins)
149
171
  foldrun account export everything the platform holds about the account as one JSON file (owner only; --file <path>, --force)
172
+ foldrun account model the account's own model key — set <provider> --key <api key> (--key - reads stdin; custom --base-url --format), remove
150
173
  foldrun workspace one deployed workspace's settings (--to) — also set <name|description|timezone|budget|notify> <value>, clear <key>
151
174
  foldrun workspace vocabulary the names the dashboard's editor completes in a workspace: agents, flows, skills, tools, secrets, scripts, types, documents (--to, --json)
152
175
  foldrun notify test send one test notification from a workspace and say what happened (--to <workspace>)
@@ -154,28 +177,37 @@ const HELP = `foldrun — agents are just folders
154
177
  foldrun webhooks redeliver <id> send one delivery again now, same X-Foldrun-Delivery id; exits 1 when refused (--to)
155
178
  foldrun notifications what mail you get, category by category, and which are always sent (--json)
156
179
  foldrun notifications set <category> on|off turn one off or back on — account-wide, or --to <workspace> for run-alerts and approvals
180
+ foldrun flags the feature flags for this account: each on or off, and why — set for this account, for every account, a staged rollout, or the default (--json). Read-only: the platform's super admin changes them
157
181
  foldrun history [path] every change to a deployed workspace, newest first (--id <revision> for its diff, --limit, --to)
158
182
  foldrun history restore <path> --id <revision> put one file back as that revision left it, as a new revision — diff, asks (--yes, --dry-run, --to)
159
183
  foldrun repo ls a workspace's branches and tags — also diff <branch>, deploy <ref>, merge <branch> (both ask first), rm-branch <branch>, mirror <git-url|off>, mirror-now (--to)
160
- foldrun restore <ws> --to <commit|time|3d> put a workspace's source back as it was then — shows the change, asks for the name typed back (--dry-run: the diff only, --yes)
184
+ foldrun restore <ws> --to <commit|time|age> put a workspace's source back as it was then — shows the change, asks for the name typed back (--dry-run: the diff only, --yes)
161
185
  foldrun backups how the account is backed up (encrypted?), when it last was, the snapshots it is in — also request --what runs|state|storage|everything --at "<when>" [--to <ws>] [--note]
186
+ foldrun backups requests every restore asked of the platform team, and where each stands (--json)
162
187
  foldrun secrets set NAME store a secret (prompted, never echoed) — also ls, rm, status; --kind file|ssh|api|service-account|m2m for the other shapes
163
188
  foldrun secrets clients the OAuth clients saved on the platform — also add <name> (--provider or --authorize-url/--token-url, --client-id, --scopes), rm <name>
164
189
  foldrun connect NAME OAuth sign-in from the terminal, stored as an auto-refreshing secret — --client <saved> runs it from a saved client through the platform
165
190
  foldrun deploy [dir] push the whole account, or deploy <workspace> for one of them
166
191
  foldrun pull [workspace] bring the platform's account down here (refuses to clobber; --force overrides)
192
+ foldrun export [workspace] a deployed workspace as a .zip — agents, flows, tools, skills, scripts, evals, knowledge; never memory, state or secret values (--flow <name> or --agent <name> for one, with what it needs; --file <path>|-, --force)
193
+ foldrun import <file.zip> take a package in: shows what it adds, would replace and still needs, then asks (--to <workspace>; a new name makes a workspace; --dry-run, --overwrite, --yes, --json)
167
194
  foldrun status [workspace] per workspace: what is added, changed or gone since the last deploy
168
195
  foldrun status --platform is the platform up: each component, and any incident or maintenance posted (--json)
169
- foldrun workspaces what exists here and on the platform — also rm <name> (--platform --yes)
196
+ foldrun status --platform --history uptime per component per day and the incidents in the window, as the status page's bars (--days 1-90, default 90; --json)
197
+ foldrun workspaces what exists here and on the platform (--json for a script) — also rm <name> (--platform --yes)
198
+ foldrun workspaces show <name> what is deployed in one: its agents, flows and how each fires, its files by folder (--json)
199
+ foldrun workspaces new <name> --platform make it on the platform: blank (an AGENTS.md), or --starter for the example researcher, writer and flow
170
200
  foldrun workspaces demo make the demo pipeline workspace on the platform — "Try the demo pipeline"
171
- foldrun library the account's shared library on the platform: ls [skills|tools|scripts|knowledge], cat <kind>/<path>, put <kind>/<path> (--file, else stdin), rm <kind>/<path> (asks)
201
+ foldrun library the account's shared library on the platform: ls [skills|tools|hooks|scripts|knowledge|memory], cat <kind>/<path>, put <kind>/<path> (--file, else stdin), rm <kind>/<path> (asks)
202
+ foldrun library new <kind>/<name> a new one from the platform's template, as the Library page's New (--template <transport or gallery entry>, --language)
172
203
  foldrun find <words> search the account as the dashboard's ⌘K does: workspaces, agents, flows, tools, skills, knowledge, memory, runs (--json)
173
204
  foldrun invoke <flow> start a flow on a running platform (--to <workspace>; --once <key> so a retry never starts a second run; --tag <t> repeatable)
174
205
  foldrun source <verb> the files on a platform, one at a time: ls, cat <path>, put <path>, mv, rm (--to <workspace>)
206
+ foldrun source new <kind> <name> the dashboard's New for any document — tools, knowledge, memory, skills, scripts (agents, flows, evals too): the platform writes the template (--agent <a> inside one agent, --template, --language, --to)
175
207
  foldrun open [page] the dashboard for this workspace, in the browser
176
208
  foldrun api spec the platform's OpenAPI 3.1 document (GET /api/openapi.json) — stdout, or --out <file>
177
- foldrun api version the API version this account's requests get, the versions served, the rate limits — also pin <YYYY-MM-DD>, unpin (admin; --json)
178
- foldrun changelog the platform's release notes, newest first: features, fixes, docs (--limit <n>, --json)
209
+ foldrun api version the API version this account's requests get, the versions served, the rate limits, your last 30 days by version and any deprecated route you still call — also pin <YYYY-MM-DD>, unpin (admin; --json)
210
+ foldrun changelog the platform's release notes, newest first: features, fixes, docs — and the API's versions, breaking changes and deprecations (--limit <n>, --json)
179
211
  foldrun version this CLI's version, its core's, and the platform's: release, API version, component shas — warns when the platform ships a newer CLI (--json)
180
212
 
181
213
  Signing in
@@ -185,6 +217,7 @@ Signing in
185
217
  session: cookies, storage and the browser identity it needs
186
218
  foldrun logout forget this machine's key, and revoke it where allowed
187
219
  foldrun whoami who you are on the platform: account, role, workspaces
220
+ foldrun team who is in the account: role, the workspaces each may open, when they joined (--json). Read-only: invites, roles, removal and transfer are a signed-in person's, in Settings → Team
188
221
  foldrun onboarding the account's getting-started steps, done or not, the next one first (--json)
189
222
  foldrun preferences your own settings on the platform — the theme; set theme system|light|dark (a key acts for whoever minted it)
190
223
  foldrun doctor check the path to the platform: node, CLI, model credential, account, DNS, a timed /api/healthz
@@ -198,9 +231,10 @@ Signing in
198
231
  Options
199
232
  --workspace <dir> the workspace folder (default: .) — on init, the first workspace's name
200
233
  --flat init: the old single-folder shape, no account around it
201
- --from <template> init: start from a shipped template, e.g. templates/hello
234
+ --from <template> init: start from a shipped template, e.g. templates/hello (new takes it too)
235
+ --starter new, workspaces new: include the example researcher, writer and publish flow (a new workspace is blank)
202
236
  --transport <k> tool new: script (default), http or mcp
203
- --language <l> tool new: the script's language — javascript, python, bash
237
+ --language <l> tool new, source new, library new: the script's language — javascript, python, bash
204
238
  --task "<text>" the instruction for a manual run
205
239
  --test run, invoke: a test run — nothing outward, state/ untouched, receipts on the run page
206
240
  --follow logs: keep tailing a live run (with --url: on the platform)
@@ -210,9 +244,10 @@ Options
210
244
  --action <a> audit: one action (apikey.created) or a family (apikey, secret, member, support)
211
245
  --actor <who> audit: one person or key — an email, key:<label>, support:<email>
212
246
  --since <days> observe, triggers: the window in days (observe default 30, triggers 7)
247
+ --until <span|date> stop, rerun (bulk): only runs started before then — 2h ago, or a date
213
248
  --verdict <v> runs: only completed runs whose summary leads with it — good, bad, quiet, blocked (comma-separated)
214
- --flow <name> stop, rerun: only that flow's runs; flow add: the other flow a subflow step runs; flow draft: the existing flow to redraft
215
- --agent <name> flow add: the agent a chain, parallel or router step runs; rerun: from the first step that agent runs; report live: whose browser frame
249
+ --flow <name> export: that flow and everything it runs; stop, rerun: only that flow's runs; flow add: the other flow a subflow step runs; flow draft: the existing flow to redraft
250
+ --agent <name> export: that agent and what it grants; flow add: the agent a chain, parallel or router step runs; rerun: from the first step that agent runs; report live: whose browser frame; source new: the agent the document belongs to
216
251
  --instruction "<text>" flow add: what a new step (chain, parallel, router) is told to do
217
252
  --after <n> flow add, flow move-step, flow paste: put the new group after the nth (0 = first); --before <n> before it (flow add); default last
218
253
  --group <n> flow add, flow move-step, flow paste: the group a step joins, in parallel
@@ -230,7 +265,12 @@ Options
230
265
  --subagent <name> agent link, agent unlink: a worker it delegates to (subagents:)
231
266
  --consult <name> agent link, agent unlink: a colleague it asks (agents:)
232
267
  --can-ask agent link, agent unlink: ask in its tools — it may ask you mid-step
233
- --description "<text>" agent link: what a --subagent is for, when its file has no description:
268
+ --description "<text>" agent link: what a --subagent is for, when its file has no description:; agent new --platform: its one line
269
+ --model <tier> agent new --platform: fast, default or max
270
+ --pattern <p> flow new --platform: pipeline (default), review-loop, fan-out, debate or router
271
+ --template <t> tool new --platform, source new, library new: a transport (script, http, mcp) or a gallery entry to start from
272
+ --list agent import: list what could be imported, import nothing
273
+ --history status --platform: the daily uptime and incidents, not just now
234
274
  --eval <name> promote: the eval file to write to (default <target>-regressions)
235
275
  --expect "<line>" promote: an assertion in eval syntax (contains: …, judge: …) — repeatable
236
276
  --case <name> promote: the case's name
@@ -241,24 +281,29 @@ Options
241
281
  --csv audit: the log as CSV, for an auditor (--file <path> to save it)
242
282
  --threshold / --amount billing wallet set: auto top-up refills --amount (5-500 USD) when the balance falls below --threshold
243
283
  --name / --abn / --address / --email billing details set: the invoice's legal name, ABN, "line1, city, state, postcode, AU", receipt email
244
- --days <n> usage: the window the charges cover (default 56)
284
+ --days <n> usage: the window the charges cover (default 56); status --platform --history: 1-90 (default 90)
245
285
  --id <revision> history: one revision in full, as diffs
246
286
  --engine <e> login: (with a site) the browser to sign in with — chrome (default: real Google Chrome, Chromium when it is not installed), chromium, firefox or safari
247
287
  --new-client connect: enter a new OAuth client even when one is saved for the secret
248
288
  --step <n> approve, reject: decide only that step; default is every step that is waiting
249
- --note "<text>" approve, reject: guidance the agent reads — or the reason for a refusal
250
- --yes approve, stop, rerun (bulk), flow rotate-hook, flow draft, history restore, restore <ws>, billing plan, repo, workspace set name, and every rm/revoke/unshare: skip the confirmation, deliberately (required with no terminal)
251
- --json report: the raw run record instead of the report; observe, usage, api version, changelog, find, preferences, workspace vocabulary: the raw document; version: {cli, core, platform}
289
+ --payload <json|text|@f> approve: release a step waiting on wait: event with this body, recorded as you
290
+ --note "<text>" approve, reject: guidance the agent reads — or the reason for a refusal; billing credit: the ledger line's note
291
+ --yes approve, stop, rerun (bulk), flow rotate-hook, flow draft, history restore, restore <ws>, import, billing plan, repo, workspace set name, and every rm/revoke/unshare: skip the confirmation, deliberately (required with no terminal)
292
+ --json report: the raw run record instead of the report; observe, usage, api version, changelog, find, preferences, workspace vocabulary, flags, workspaces, workspaces show, agent ls, flow ls, agent import --list, backups requests, team, hook ls: the raw document; version: {cli, core, platform}
252
293
  --events <a,b> account set notify: failed, awaiting-approval, completed
253
294
  --failed webhooks deliveries: only the ones that gave up
254
295
  --limit <n> runs, billing, history, changelog: how many rows
255
296
  --value "<text>" secrets set: skip the prompt (careful with shell history)
256
297
  --out <file> api spec: where to write the OpenAPI document (default: stdout)
257
- --file <path> source put, library put, flow paste: the local file to send (default: stdin); secrets set --kind file|service-account: the file it holds; storage get, report get, report live, account export, billing statement: where to write it (- for stdout)
298
+ --file <path> source put, library put, flow paste: the local file to send (default: stdin); secrets set --kind file|service-account: the file it holds; storage get, report get, report live, account export, export, billing statement: where to write it (- for stdout)
258
299
  --message "<why>" source put: recorded on the file's revision
259
300
  --account secrets: account scope instead of the workspace's
260
301
  --wait invoke, agent run: hold on and print the result
261
302
  --path <p> tool test: the path an http tool should probe, appended to its base:
303
+ --on <event> hook add: what it listens for — tool.call, tool.result, step.start or step.end
304
+ --tool <pattern> hook add: which tools a tool.call or tool.result hook sees — Bash, Write|Edit, mcp__* (default all)
305
+ --library hook add, hook rm: in the account library (every workspace), not this workspace
306
+ --event <json|@file> hook test: the event the hook reads on stdin (default: a sample for its on:)
262
307
  --watch invoke: follow the run's trace here as it happens
263
308
  --print open: print the URL only
264
309
  --from <n> invoke, flow run, rerun: start at step n; earlier steps are recorded as skipped (a bulk rerun defaults to 1)
@@ -274,7 +319,7 @@ Options
274
319
  --grace <span> keys rotate: keep the old key working for 1h or 24h while you swap the new one in (default 0: revoked now)
275
320
 
276
321
  Platform options (deploy, invoke, secrets, logs, keys)
277
- --to <workspace> workspace on the platform (deploy default: folder name); flow add/show, agent link: edit or show the deployed copy instead of this folder; restore <ws>: the commit, date or age to put it back to (3d, 2026-09-28T14:00)
322
+ --to <workspace> workspace on the platform (deploy default: folder name); flow add/show, agent link: edit or show the deployed copy instead of this folder; hook test: run the deployed hook on the platform; hook ls: list the deployed workspace's hooks and what they did lately; restore <ws>: the commit, date or age to put it back to (3d, 2026-09-28T14:00)
278
323
  --tenant <name> account to deploy into (default: default, local only)
279
324
  --data <dir> the installation's data directory
280
325
  --url <url> a running platform (or FOLDRUN_URL, or where you last signed in)
@@ -285,11 +330,13 @@ Platform options (deploy, invoke, secrets, logs, keys)
285
330
  --quiet leave out the dim "acting as …" line a platform command prints on stderr
286
331
  --local deploy: into the installation on this machine, even when signed in
287
332
  --commit <sha> deploy: record which commit this is
288
- --dry-run deploy: check and report, change nothing; flow add, flow set, flow trigger, flow move-step, flow paste, flow draft, history restore, agent link, agent unlink: show the diff, write nothing; restore <ws>: the diff only, restore nothing; stop, rerun (bulk): list what matches, touch nothing
333
+ --overwrite import: replace files the workspace already has with different text (refused otherwise)
334
+ --dry-run deploy: check and report, change nothing; flow add, flow set, flow trigger, flow move-step, flow paste, flow draft, history restore, agent link, agent unlink: show the diff, write nothing; restore <ws>: the diff only, restore nothing; import: the preview only, write nothing; stop, rerun (bulk): list what matches, touch nothing
289
335
  --no-runtimes deploy: do not wait for the workspace's environments to be built
290
336
  --force deploy: deploy even while runs are in flight; pull, storage get: overwrite local files
291
337
  --yes deploy: allow deleting files this folder no longer has (asked otherwise; required with no terminal)
292
338
  --platform --yes workspaces rm: delete it on the platform, deliberately
339
+ --platform workspaces new, agent new, flow new, tool new: make it on the platform, not in this folder
293
340
 
294
341
  Nothing here needs an account. Set ANTHROPIC_API_KEY to run; init and check
295
342
  work without one. \`foldrun login\` is for the hosted platform, or your own.`;
@@ -305,7 +352,7 @@ if (!command || command === "--help" || command === "-h") {
305
352
  // `--value` as the account's argument and stored an empty secret; `--force
306
353
  // ./dir` swallowed the directory. A flag followed by another flag is also
307
354
  // boolean, so an unlisted switch at least does not eat its neighbour.
308
- const BOOLEAN_FLAGS = new Set(["account", "follow", "force", "oauth2", "wait", "watch", "print", "dry-run", "help", "no-browser", "local", "test", "flat", "yes", "platform", "json", "forever", "all", "check", "new-client", "quiet", "off", "can-ask", "preview", "csv", "failed"]);
355
+ const BOOLEAN_FLAGS = new Set(["account", "follow", "force", "oauth2", "wait", "watch", "print", "dry-run", "help", "no-browser", "local", "test", "flat", "yes", "platform", "json", "forever", "all", "check", "new-client", "quiet", "off", "can-ask", "preview", "csv", "failed", "starter", "history", "list", "library"]);
309
356
  // Flags said more than once collect into a list: `--tag a --tag b`.
310
357
  const REPEATABLE = new Set(["tag", "expect", "header"]);
311
358
  // `--wait` is a switch everywhere but `flow add <flow> wait`, where it takes
package/docs/agents.md CHANGED
@@ -60,6 +60,7 @@ the point of the week; a step that weighs two arguments and picks one is not.
60
60
  | `agents` | colleagues it may consult mid-run — an answer, no tools |
61
61
  | `subagents` | colleagues it may delegate a whole job to — own context, own tools, never more than its own ([below](#delegating-to-a-sub-agent)) |
62
62
  | `scripts` | programs in `scripts/`, each becoming a callable tool |
63
+ | `hooks` | your own code at every tool call, step start and step end — refuse, rewrite, add context — the same on every model ([Hooks](hooks)). Also in a workspace's or the account's `AGENTS.md` for every agent under it |
63
64
  | `apis` | an HTTP API declared inline, as one tool |
64
65
  | `mcpServers` | an MCP server declared inline |
65
66
  | `secrets` | vault entries its tools may use — names only, never values |
@@ -75,11 +76,12 @@ only Web takes a provider:
75
76
  | **Web** | `web` | eight actions — search, fetch, browse, crawl, map, extract, answer, monitor | one per action under `web:` — unset is ours |
76
77
  | **Files** | `read` | Read, Glob, Grep — inspect but never modify | — |
77
78
  | | `write` | Read, Write, Edit, Glob, Grep | — |
78
- | **Code** | `code` | Bash — runs anything in the sandbox: Python and Node (packages via `runtime:`), or a binary you ship | — |
79
+ | **Code** | `code` | Bash — runs anything in the sandbox: Python and Node (packages via `runtime:`), Debian programs (`runtime: system:`), or a binary you ship | — |
79
80
  | **Memory** | `search` | `search_files(query)` over knowledge, memory, state and storage at every scope | — |
80
81
  | | `history` | `recall_runs()` and `read_run(id)` — the workspace's last thirty finished runs | — |
81
82
  | | `desks` | `recall_desk_runs()` and `read_desk_run(id)` — the same, across the account's *other* workspaces: ten recent runs each, named per line, up to 100 runs in all. Run records, not files: the way a digest agent reads what every desk concluded this week | — |
82
83
  | **People** | `ask` | `ask_person(question, options?)` — asks the person running the desk mid-step and waits for the answer ([below](#asking-a-person-mid-step)) | — |
84
+ | **Installing** | `install` — every agent has it | `install(manager, packages)` — installs a missing program or library mid-step: Debian packages (`apt`), Python (`pip`), Node (`npm`) ([below](#installing-what-a-step-needs)) | `disallowedTools: [install]` removes it |
83
85
  | **Colleagues** | `agents:` · `subagents:` | not in `tools:` — their own fields: consult a colleague for an answer, or delegate a job to one that works with its own tools ([consult](#consulting-colleagues), [delegate](#delegating-to-a-sub-agent)) | — |
84
86
 
85
87
  ### Asking a person mid-step
@@ -197,7 +199,7 @@ its tools inside the delegating agent's.
197
199
  | field | |
198
200
  |---|---|
199
201
  | `size` | `small` \| `large` (default) \| `heavy` — the sandbox reservation |
200
- | `runtime` | language runtimes and packages the agent's own scripts need |
202
+ | `runtime` | language runtimes, packages and Debian system packages the agent's own scripts need |
201
203
 
202
204
  `size` is a price, not just a limit. Memory is a **hard ceiling** because it is
203
205
  not compressible: a step over it is killed, which on a single-node host
@@ -212,14 +214,42 @@ runtime:
212
214
  packages: [pandas] # pip, installed with uv
213
215
  node: true
214
216
  npm: [cheerio]
217
+ system: [ffmpeg, libcairo2-dev] # Debian packages, installed with apt
215
218
  ```
216
219
 
220
+ `system:` takes Debian (trixie) package names — a program (`ffmpeg`), a
221
+ library's headers for a pip package that compiles (`libcairo2-dev`,
222
+ `python3-dev`), a compiler (`build-essential`), `pkg-config`. They are
223
+ installed by the run container's start-up, as root, **before** anything the
224
+ model directs runs, and the step then runs as the unprivileged agent user as
225
+ always. A name is checked against Debian's own naming rule, so it can never
226
+ become an apt option. The first step that needs a set installs it with apt and
227
+ saves the result as a snapshot in the account's runtime cache; every later
228
+ step restores the snapshot instead, in about a second (154 packages, 432 MB:
229
+ 30 s through apt, under 1 s from the snapshot). A new runner image gets new
230
+ snapshots of its own, never the old one's files. The run log says
231
+ `system packages ready: … (snapshot, 1s)` or `(apt, 30s)`, or fails the step
232
+ with apt's own reason. On a laptop (`foldrun run` with no container) there is nothing to
233
+ install into: the list is reported as assumed present.
234
+
235
+ Manim, for one, needs all four of its kinds at once:
236
+
237
+ ```yaml
238
+ runtime:
239
+ system: [build-essential, pkg-config, python3-dev, libcairo2-dev, libpango1.0-dev]
240
+ packages: [manim]
241
+ ```
242
+
243
+ A package that fails to install says why on the first line of the run log —
244
+ `` `pycairo` has to be compiled and this runner has no C compiler — add
245
+ `system: [build-essential]` … `` — with the installer's last lines under it.
246
+
217
247
  An agent's own runtime and the runtimes of the tools it grants merge into one
218
248
  environment per step, so a tool carries its own dependencies and the agent
219
249
  does not repeat them.
220
250
 
221
251
  The image a step runs in is small on purpose: an interpreter, `uv`, `npm`,
222
- and none of the world's packages. What a step needs arrives through
252
+ and none of the world's packages — no compiler, no media tools. What a step needs arrives through
223
253
  `runtime:` — built once per distinct declaration, kept in the account's
224
254
  cache, and reused by every later step and every agent that declares the same
225
255
  thing. The environment comes first on `PATH`, so a tool file that says
@@ -238,9 +268,40 @@ none — no environment is built for them.
238
268
  On a platform, a deploy builds the environments its agents need before any
239
269
  step does: `foldrun deploy` waits for them and prints each one, ready or
240
270
  failed with the installer's own error, and `foldrun runtimes` asks again
241
- later. A package that will not install is heard at deploy, not from the
271
+ later — as does the **Runtimes** panel on the workspace's overview page. A package that will not install is heard at deploy, not from the
242
272
  first scheduled run.
243
273
 
274
+ ## Installing what a step needs
275
+
276
+ An agent does not have to know in advance what it will need. Every agent has
277
+ `install`, and when a command says `ffmpeg: command not found` or a script
278
+ says `No module named manim`, the agent installs it and carries on:
279
+
280
+ ```
281
+ install(manager: "apt", packages: ["ffmpeg"]) # Debian programs and libraries
282
+ install(manager: "pip", packages: ["manim>=0.19"]) # Python packages
283
+ install(manager: "npm", packages: ["sharp"]) # Node packages
284
+ ```
285
+
286
+ What it installs is usable by its next command — on `PATH`, importable — and
287
+ lasts for the step: the step's container, and everything installed in it, is
288
+ destroyed when the step ends.
289
+
290
+ The agent is never root. A Debian package is installed by a small helper the
291
+ container's root start-up leaves running before it drops to the agent user;
292
+ the agent can only ask it, by name, and each name is checked against Debian's
293
+ naming rule, so nothing but a package name reaches apt. It uses the same cache
294
+ and snapshots as `runtime: system:`, so a package anyone in the account
295
+ installed before is back in about a second. pip and npm packages need no root
296
+ and are installed as the agent, into a directory of the step's own.
297
+
298
+ Each install is in the run log with the line that would have it ready before
299
+ the step starts — `install: apt ffmpeg — ready (snapshot, 1s). To have it
300
+ before the step starts: runtime: system: [ffmpeg]`. Moving it into `runtime:`
301
+ is a speed-up, never a requirement. `disallowedTools: [install]` takes the
302
+ tool away; `permissionMode: plan` has no `install`, being read-only. On a
303
+ laptop (`foldrun run`, no container) pip and npm work and apt says it can't.
304
+
244
305
  ## Its own model credential
245
306
 
246
307
  ```yaml
@@ -416,7 +477,7 @@ take, like `eval` or `download`; a misspelt one is refused by `check`).
416
477
  Beside them: `boundaries: true` marks the page's words in every reply,
417
478
  `init:` runs workspace scripts before each page's own, `extensions:` loads
418
479
  unpacked Chrome extensions, `webgpu: true`, `ignore_https_errors: true`, and
419
- `state_key:` names a secret that encrypts saved logins; `video: true`
480
+ `state_key:` names a secret that encrypts saved logins; `state:` names a saved login every call uses (beside `cookies:` it needs `state_key:`, and the secret then seeds it once — see tools.md); `video: true`
420
481
  records every call for the run page to play, and `live_view: false` stops
421
482
  the page being shown live there. See
422
483
  [What this agent's browser may do](tools#what-this-agents-browser-may-do).
package/docs/api-usage.md CHANGED
@@ -50,8 +50,22 @@ The CLI sends the version it was built for on every call.
50
50
  replaces it is released. A pin to a retired version is answered as the
51
51
  current version, never refused.
52
52
  - Every breaking change is announced in **What's new** (the dashboard's
53
- changelog, and `GET /api/changelog`) on the day it ships, with the date the
54
- previous shape stops being served.
53
+ changelog, `GET /api/changelog` and `foldrun changelog`) on the day it
54
+ ships: the version that brought it and what changed, and every deprecated
55
+ route with the date it stops answering.
56
+ - **Checked before it ships.** Every change to the platform is compared with
57
+ the version that is deployed. A route or documented field taken away, a
58
+ type changed, or a request field made required cannot ship unless it comes
59
+ as a new dated version, with the old shape kept for older pins. A route
60
+ can only be removed once its deprecation has passed its sunset date.
61
+ - **You are told if it affects you.** Every request is counted by the
62
+ version that answered it, and a call to a deprecated route by the key or
63
+ person that made it. **Settings → API** and `foldrun api version` show the
64
+ last 30 days. An account that called a deprecated route in the last 30
65
+ days is emailed when it is first seen doing so, and again 90, 30 and 7
66
+ days before the sunset — one email per step, naming the keys that still
67
+ call it. This is required mail: it cannot be switched off, because it is
68
+ the only warning before something you rely on stops.
55
69
  - A route on its way out answers with
56
70
  [`Deprecation`](https://www.rfc-editor.org/rfc/rfc9745) (`@<unix time>` it
57
71
  was deprecated) and, once the date is fixed,
@@ -98,8 +112,9 @@ behind its own gateway).
98
112
  ## Retrying safely: Idempotency-Key
99
113
 
100
114
  The `POST`s that start or change something — run a flow, agent or eval,
101
- rerun, deploy, upload an asset, create a flow, set a secret, mint a key,
102
- approve, answer or message a run, billing actions — accept
115
+ rerun, stop, deploy, upload an asset, create, draft or append to a flow,
116
+ set a secret, mint a key, rotate a webhook, send a test notify, connect an
117
+ OAuth client, approve, answer or message a run, billing actions — accept
103
118
 
104
119
  ```
105
120
  Idempotency-Key: <a UUID you generate, one per operation>
@@ -117,7 +132,7 @@ Idempotency-Key: <a UUID you generate, one per operation>
117
132
  key for at most two minutes, then the key is free for a real retry.
118
133
  - Minting or rotating a key: a replay says what was done but its `key` is
119
134
  `null` — the secret is shown once and never stored. Revoke that key and
120
- mint another.
135
+ mint another. Rotating a webhook is the same: a replay's `path` is `null`.
121
136
 
122
137
  Keys belong to the caller — your account and the API key or person sending
123
138
  them; another key of the same account never gets your stored answer — and to