foldrun 0.5.0 → 0.7.2

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.
@@ -0,0 +1,224 @@
1
+ # Working with a coding agent
2
+
3
+ The page a coding agent (Claude Code, Cursor, Codex) should read first in a
4
+ foldrun account, and the one `foldrun init` points it to. A foldrun account
5
+ is agents, flows and knowledge as markdown. There is no build — the files ARE
6
+ the program — so the loop is edit, check, run, deploy.
7
+
8
+ `foldrun init` writes a short block into the account's `AGENTS.md`, between
9
+ `<!-- BEGIN:foldrun-agent-rules -->` markers, telling the coding agent to
10
+ read these docs before it writes anything, and a `CLAUDE.md` that imports it.
11
+ The block is for the tool editing the folder: the runtime strips it before
12
+ the rest of `AGENTS.md` reaches your agents. `foldrun guide` re-adds or
13
+ refreshes it; `foldrun docs <page>` prints any page of these docs, from the
14
+ copy that ships with your CLI, so a coding agent always reads the version it
15
+ is working against.
16
+
17
+ ## The loop
18
+
19
+ ```sh
20
+ foldrun check # validate everything, offline, no model calls
21
+ foldrun run <flow> # run it locally against real models
22
+ foldrun eval # run the evals
23
+ foldrun deploy # push the account (or `deploy <workspace>`) to the platform
24
+ ```
25
+
26
+ `check` is cheap and catches a broken flow before a schedule fires it at
27
+ 3am. Run it after every edit, the way you would run a typecheck.
28
+
29
+ ## Where things go
30
+
31
+ | Path | What |
32
+ |---|---|
33
+ | `AGENTS.md` | the account's shared context and defaults — every agent in every workspace reads it (except the managed coding-agent block, which the runtime strips) |
34
+ | `workspaces/<name>/` | one workspace: a desk, a pipeline, a product |
35
+ | `workspaces/<name>/AGENTS.md` | that workspace's context and settings |
36
+ | `workspaces/<name>/agents/<name>/agent.md` | one role: its persona, model, tools |
37
+ | `workspaces/<name>/flows/<name>.md` | steps, in order, naming the agents that run them |
38
+ | `workspaces/<name>/knowledge/` | reference material agents read |
39
+ | `workspaces/<name>/memory/` | what past runs learned — agents write here themselves |
40
+ | `workspaces/<name>/evals/` | tests for agents, same idea as unit tests |
41
+ | `workspaces/<name>/skills/` | a procedure an agent can follow, named in `skills:` |
42
+ | `workspaces/<name>/tools/` | a folder tool: its definition and its code together |
43
+ | `workspaces/<name>/scripts/` | code the agents call, referenced by `scripts:` |
44
+ | `workspaces/<name>/state/` | what runs accumulate. Yours to read, never deployed over |
45
+ | `library/` | skills, tools, scripts and knowledge shared by every workspace here |
46
+ | `.claude/agents/<name>.md` | a Claude Code subagent — deploys AS an agent |
47
+
48
+ `knowledge/` is what you tell the agents; `memory/` is what they worked out.
49
+ Regenerated every run means a file; accumulated across runs means `state/`.
50
+
51
+ A subagent you write in Claude Code is imported as `agents/<name>/agent.md`
52
+ at deploy, no conversion. Write it either way.
53
+
54
+ ## What a deploy does NOT touch
55
+
56
+ `runs/`, `state/`, `storage/`, `secrets.json`, the trigger log, and any
57
+ memory an agent wrote that your push does not mention. Those belong to the platform, not to git — a deploy
58
+ that reverted what an agent learned would make every run a little dumber.
59
+
60
+ Secrets never go in these files. `foldrun secrets set NAME` puts them in the
61
+ vault, and agents reference them by name.
62
+
63
+ ## Talking to the platform
64
+
65
+ The CLI is local except for `deploy`, `pull`, `runs`, `logs`, `invoke` and
66
+ friends, which talk to the platform you signed in to (`foldrun login`, or
67
+ `FOLDRUN_URL` + `FOLDRUN_TOKEN`). Everything the CLI does, the HTTP API does
68
+ too, with the same key:
69
+
70
+ ```sh
71
+ api() { p=$1; shift; curl -sS -H "authorization: Bearer $FOLDRUN_TOKEN" "$FOLDRUN_URL/api/$p" "$@"; }
72
+
73
+ api workspaces/$WS/runs # recent runs, newest first
74
+ api workspaces/$WS/runs/<id> # the full trail of one
75
+ api workspaces/$WS/runs/<id>/stream # follow a live one (SSE)
76
+ api workspaces/$WS/flows/<flow>/run -X POST # start one
77
+ ```
78
+
79
+ | Route (`/api/workspaces/<ws>` unless noted) | Methods | For |
80
+ |---|---|---|
81
+ | `/` | GET DELETE PATCH | the workspace itself |
82
+ | `/deploy` | POST | what `foldrun deploy` calls |
83
+ | `/source` | GET PUT PATCH DELETE | read and write single files |
84
+ | `/runs` · `/runs/<id>` | GET · GET DELETE | list runs; one run, every step |
85
+ | `/runs/<id>/stream` | GET | live events, server-sent |
86
+ | `/runs/<id>/stop` · `/rerun` · `/approve` | POST | kill it; again from a step; release a gate |
87
+ | `/flows` · `/flows/<f>` · `/flows/<f>/run` | GET POST · POST DELETE PATCH · POST | list, create, edit, start |
88
+ | `/agents` · `/agents/<a>/run` | GET POST · POST | list agents, run one |
89
+ | `/evals` · `/evals/<e>/run` | GET POST · POST | list evals, run one |
90
+ | `/tools/<t>/test` | POST | exercise one tool alone |
91
+ | `/storage` · `/storage/download` · `/storage/upload-url` · `/storage/preview` · `/shares` | GET POST PUT DELETE · GET · POST · GET · POST GET DELETE | files agents produced and people uploaded, any type; a file parsed for reading; public links to them |
92
+ | `/triggers?since=` | GET | why nothing ran: fired vs started per flow, with reasons |
93
+ | `/hooks/<f>/rotate` | POST | new webhook token for a flow |
94
+ | `/restore` | POST | the workspace's source back to a point in its history — `dryRun` first, then `confirm` |
95
+ | `/notify/deliveries` · `/notify/deliveries/<id>/redeliver` | GET · POST | every notify: webhook sent and each attempt; send one again |
96
+ | `/api/secrets` · `/api/schedule` · `/api/account` · `/api/keys` | account-level | the vault, the clock, defaults, API keys |
97
+ | `/api/me/notifications` | GET PATCH | what mail you get, per category; a key acts for whoever minted it |
98
+
99
+ A key carries a role (viewer, editor, admin) and a workspace scope no wider
100
+ than the person who minted it. Team, profile and MFA routes are a person's
101
+ alone and refuse a key. The full reference with request and response shapes
102
+ is the platform's `docs/api.md`.
103
+
104
+ Debugging a failed run is usually: `foldrun runs --status failed`, `foldrun
105
+ report <id>` to read which step failed and what it cost, fix the markdown,
106
+ `foldrun deploy`, then `foldrun rerun <id> --from <step>`. `foldrun triggers`
107
+ answers "why did nothing run".
108
+
109
+ ## Writing a flow
110
+
111
+ A numbered list of steps. The number is the GROUP: same number means those
112
+ steps run in parallel, and the flow waits for all of them before the next.
113
+
114
+ ```markdown
115
+ ---
116
+ trigger: manual # manual | schedule | webhook
117
+ schedule: "0 9 * * 1" # cron, when trigger: schedule
118
+ timezone: Australia/Sydney
119
+ model: default # a default for every step here
120
+ effort: low
121
+ overlap: skip # skip | queue — what a second run does while one is live
122
+ priority: normal # high | normal | low — where its runs stand in the queue
123
+ ---
124
+
125
+ 1. [[researcher]] — Find three sources on {{topic}}.
126
+ 2. [[writer]] — Draft from what the researcher found.
127
+ model: max
128
+ verify: judge: the draft cites every source
129
+ 3?. [[editor]] — Tighten it.
130
+ 4!. [[publisher]] — Publish it.
131
+ ```
132
+
133
+ `3?.` is optional — it may be skipped. `4!.` needs a human to approve before
134
+ it runs. `[[flow:other-flow]]` in place of an agent runs another flow as a
135
+ step.
136
+
137
+ Indented under a step, any of:
138
+
139
+ | | |
140
+ |---|---|
141
+ | `approve: true` | stop for a human (`!` is shorthand for this) |
142
+ | `when: <condition>` | run only if it holds |
143
+ | `case: <value>` / `else: true` | branch on the previous step's result |
144
+ | `retry: 2` | re-run on failure, up to 5 |
145
+ | `timeout: 900` | seconds before the step is cut off |
146
+ | `verify: <shell>` | the step fails unless the command exits 0 |
147
+ | `verify: judge: <claim>` | a model grades the claim against the output |
148
+ | `verify: contains:` / `not-contains:` / `matches:` / `file:` | the cheap checks, no shell |
149
+ | `model:` / `effort:` | override the flow's default for this step |
150
+ | `loop: 3` / `until: <condition>` | repeat until it holds, at most 5 |
151
+ | `each: lines` · `each: rows of <path>` · `each: items` | run once per line / CSV row / JSON element of the previous result |
152
+ | `max: 10` | cap how many iterations `each:` produces |
153
+ | `on-fail: [[agent]]` | who handles it when this step fails |
154
+ | `wait: 30m` · `wait: event` | pause; or hold until something POSTs the run's event URL |
155
+ | `ask: <question>` | ask a human, use the answer |
156
+ | `preview: draft/*.mdx` | what the approval box shows — paths under `storage/`, globs allowed |
157
+ | `delegate: [[a]], [[b]]` | hand the step to whichever fits, up to 5 |
158
+ | `output: json` | the reply ends with one JSON value; the next step gets it as data |
159
+
160
+ A `verify:` with no assertion prefix is a **shell command**, not a sentence.
161
+ `verify: the reply names the file it wrote` runs a program called `the` and
162
+ fails every run with `command not found`. The prefixes are `contains:`,
163
+ `not-contains:`, `matches:`, `file:` and `judge:` — put `judge: ` in front of
164
+ a claim in English. `foldrun check` errors on this.
165
+
166
+ `matches:` and `contains:` test the step's **last turn**, so they grade the
167
+ agent's prose. Where the step writes the artefact, verify the artefact
168
+ instead — the stronger check, and the one that does not depend on how the
169
+ model phrased itself.
170
+
171
+ ## Writing an agent
172
+
173
+ Frontmatter then prose. The prose IS the system prompt, so write it to be
174
+ read by a model: what this role is for, what it must not do, what good looks
175
+ like.
176
+
177
+ ```markdown
178
+ ---
179
+ name: researcher
180
+ description: Finds and summarises sources.
181
+ model: default # fast | default | max
182
+ effort: low # how hard to think about it
183
+ size: large # small | large | heavy — the sandbox it rents
184
+ tools: [web, read, my-folder-tool] # built-ins and your own tools/, one list
185
+ disallowedTools: [Bash] # subtract from what it would otherwise have
186
+ skills: [house-style] # from skills/
187
+ scripts: [summarise.py] # from scripts/, each becomes a callable tool
188
+ apis: [{ name: crm }] # an HTTP API, as a tool
189
+ mcpServers: {} # an MCP server, as a tool
190
+ agents: [writer] # colleagues this one may consult
191
+ secrets: [CRM_TOKEN] # from the vault — never written in these files
192
+ provider: {} # BYOK: your own model credential
193
+ permissionMode: plan # plan first, act once approved
194
+ runtime: # only if scripts need packages
195
+ packages: [requests]
196
+ ---
197
+
198
+ You research a topic and report what you found...
199
+ ```
200
+
201
+ Only `name` and the prose are required. Every other field widens or narrows
202
+ what the agent can reach, and the default is narrow.
203
+
204
+ `runtime:` installs pip/npm packages in the sandbox each agent runs in. Pin
205
+ versions the normal way (`pandas>=2`, `lodash@^4`). Python and Node are
206
+ supported; anything else should ship as a committed binary.
207
+
208
+ Link documents to each other with `[[wikilinks]]` — the name, not the path.
209
+
210
+ ## The CLI, in one screen
211
+
212
+ ```
213
+ foldrun init [dir] · new <name> · agent new · flow new · tool new
214
+ foldrun check [--to <ws>] · run <target> · eval [name] · probe <model>
215
+ foldrun deploy [dir|ws] · pull [ws] · status [ws] · workspaces · source <verb>
216
+ foldrun runs · logs [id] · report <id> · triggers · schedule · approvals
217
+ foldrun invoke <flow> [--wait|--watch|--once <key>] · rerun <id> --from <n> · stop <id>
218
+ foldrun approve <id> · reject <id> · storage ls|cat|get|put|rm|share|shares|unshare
219
+ foldrun secrets set|ls|rm|status · connect NAME · account [providers] · billing
220
+ foldrun login · logout · whoami · keys ls|create|revoke · doctor
221
+ ```
222
+
223
+ `foldrun <command> --help` explains any of them, and `foldrun docs cli` is the
224
+ whole reference.
@@ -0,0 +1,77 @@
1
+ # Deploying
2
+
3
+ A workspace deploys by pushing files. Two doors, one mechanism: `foldrun
4
+ deploy` from a folder, or `git push` to the remote every workspace has.
5
+ Both are checked before anything goes live, both refuse to swap files under
6
+ a run in flight, and neither touches what the platform owns.
7
+
8
+ ## From a folder
9
+
10
+ ```sh
11
+ foldrun login # once per machine: approve in the browser
12
+ foldrun check # first, always — it costs nothing
13
+ foldrun deploy # this folder → the workspace named after it
14
+ foldrun deploy --to leads --commit $(git rev-parse HEAD)
15
+ ```
16
+
17
+ In CI there is no browser: set `FOLDRUN_URL` and `FOLDRUN_TOKEN` (a key from
18
+ Settings → API keys, or `foldrun keys create`) and the same commands run.
19
+
20
+ ## From git
21
+
22
+ Every workspace is a git remote:
23
+
24
+ ```sh
25
+ git clone https://foldrun:<api-key>@app.example.com/git/<account>/<workspace>.git
26
+ # edit, commit
27
+ git push origin main # deploys, and runs the evals
28
+ ```
29
+
30
+ Any username, an API key as the password. A **deploy key** — minted for one
31
+ workspace, read or write, with `foldrun keys create ci --for <workspace>
32
+ --access write` or on the Settings page — is what a CI job or a contractor
33
+ should hold; it is refused on every other workspace and on every other route.
34
+
35
+ Push a branch other than `main` and you get a **preview**: a workspace named
36
+ `<workspace>-preview-<branch>` deployed from that branch, with its evals run
37
+ there, its schedules never fired, and its source's secrets. Deleting the
38
+ branch deletes it.
39
+
40
+ ## What a deploy checks
41
+
42
+ The tree is validated the way `foldrun check` validates it — a step naming an
43
+ agent that does not exist, a tool that resolves to nothing, a knowledge
44
+ concept with no `type:` — and a push with issues is refused with the list.
45
+ Git says so at push time; the workspace on disk is unchanged.
46
+
47
+ ## What a deploy never touches
48
+
49
+ `runs/`, `state/`, `secrets.json`, and any memory an agent wrote that the
50
+ push does not mention. A deploy that reverted what an agent learned would
51
+ make every run a little dumber, and a deploy that reset a cursor would make
52
+ the next run redo a fortnight.
53
+
54
+ ## Runs in flight
55
+
56
+ A push while a run is in flight — including one parked at an approval gate
57
+ — is **accepted but not applied**. Git warns at push time, and the platform
58
+ applies it the moment those runs finish. Swapping files under a running flow
59
+ would mean step 3 reads agents step 1 never saw. `foldrun deploy --force`
60
+ overrides that when you mean it.
61
+
62
+ ## History and rollback
63
+
64
+ Every change to a workspace is a revision — a push, a dashboard edit, an
65
+ agent's memory write — with who, when, and a diff, on the workspace's
66
+ History page and at `/api/workspaces/<ws>/history`. A deploy's revision id
67
+ is its commit.
68
+
69
+ A rollback is a deploy of an earlier ref (`POST …/repo {action: deploy, ref}`
70
+ or the History page), and it lands as a **new commit on `main`** — history
71
+ moves forward, never rewrites.
72
+
73
+ ## Mirroring
74
+
75
+ A workspace can mirror to a repository you host — GitHub, GitLab — over
76
+ https with a token held as the `MIRROR_TOKEN` secret. The platform's remote
77
+ stays the mechanism; the mirror is the copy you read elsewhere.
package/docs/evals.md ADDED
@@ -0,0 +1,90 @@
1
+ # Evals
2
+
3
+ An eval is a markdown file under `evals/` that runs an agent or a flow against
4
+ a task and asserts something about the reply. It is how a change to a prompt
5
+ stops being a guess.
6
+
7
+ ```markdown
8
+ ---
9
+ name: writer-quality
10
+ agent: writer # or `flow: publish`
11
+ model: fast # the judge's model, not the agent's
12
+ ---
13
+
14
+ ## mentions the audience
15
+ task: Write a short draft about cleaning a rain gauge.
16
+ expect:
17
+ - contains: farmer
18
+ - not-contains: leverage
19
+ - judge: speaks to working farmers, not to gardeners
20
+
21
+ ## quotes the real price
22
+ task: Write one line quoting the price of the RG-40.
23
+ expect:
24
+ - contains: $34
25
+ ```
26
+
27
+ Each `##` heading is one case: a `task:` and the `expect:` list it must
28
+ satisfy. The heading is the case's name, so make it the thing being checked.
29
+
30
+ ## Frontmatter
31
+
32
+ | field | |
33
+ |---|---|
34
+ | `name` | the eval's identity |
35
+ | `agent` **or** `flow` | what runs. A flow eval runs the whole flow per case |
36
+ | `model` | the **judge's** tier, not the subject's — cases run the agent on its own model |
37
+ | `effort` | the judge's effort. PASS/FAIL against one sentence is not deep work |
38
+ | `trigger` | `deploy` (default) or `manual` |
39
+ | `inputs` | `true` makes the file a flow's saved inputs, not a test: its cases are named tasks for [Run with…](flows#run-with-saved-inputs) and `foldrun invoke --inputs`, and nothing runs them as an eval |
40
+ | `live` | an eval's runs are [test runs](runs#test-runs) — nothing outward, `state/` untouched — unless this says `true`. A flow eval that must really send to prove itself opts in; nothing opts in by accident |
41
+
42
+ ## Assertions
43
+
44
+ | | |
45
+ |---|---|
46
+ | `contains:` | the text must appear |
47
+ | `not-contains:` | the text must not appear |
48
+ | `matches:` | a regular expression over the reply |
49
+ | `file:` | the path exists and is non-empty |
50
+ | `run:` | a shell command that must exit 0 |
51
+ | `judge:` | a model grades the reply against this sentence |
52
+
53
+ **Deterministic checks run first and cost nothing.** The judge only runs if they
54
+ pass — there is no point paying a model to grade output already known to be
55
+ wrong. The same vocabulary is a step's `verify:`, so a flow and an eval say
56
+ "the output must mention the price" in one sentence.
57
+
58
+ ## When they run
59
+
60
+ `trigger: deploy` — the default — runs the eval on every deploy of the
61
+ workspace, which is what makes it a regression test rather than a thing someone
62
+ remembers to click. Results land in `evals/.results/`, and a dated line goes to
63
+ `history.jsonl` so movement is visible across weeks.
64
+
65
+ On a platform an eval's run goes through the same queue as every other run,
66
+ so it counts against the account's `concurrency:` and waits its turn.
67
+
68
+ `trigger: manual` keeps it off every push. **Use it for `flow:` evals**: a flow
69
+ eval runs the entire flow once per case, so a three-case eval on an hour-long
70
+ flow is three hours and the full cost, on every deploy.
71
+
72
+ ## Promoting a run
73
+
74
+ A run that went wrong is a case you already have — the task is on record, and
75
+ so is the answer. **Promote to eval** on the run page writes it into `evals/`
76
+ with the task filled in, so the fix has a test before it has a diff. A run that
77
+ was itself an eval case is refused: promote the run it was checking.
78
+
79
+ ## The loop
80
+
81
+ ```sh
82
+ foldrun check # free — no model is called
83
+ foldrun eval # the assertions
84
+ foldrun run <agent> # the real thing
85
+ ```
86
+
87
+ `check` is the typecheck: a step naming an agent that does not exist, a tool or
88
+ skill that resolves to nothing, a `delegate:` or `on-fail:` that names nobody,
89
+ a cron that fires eleven times where you meant once. It costs nothing, so run
90
+ it on every edit and let evals cover what only a model can answer.
package/docs/faq.md ADDED
@@ -0,0 +1,53 @@
1
+ # FAQ
2
+
3
+ **Is this a framework?** No. There is nothing to import. An agent is a folder,
4
+ a flow is a numbered list in a markdown file, and the CLI or the platform
5
+ reads them. You can write a working workspace in an editor with no
6
+ dependency installed.
7
+
8
+ **Do I need an account to try it?** No. `npm install -g foldrun`, a model key,
9
+ and `foldrun init` gives you a workspace that runs on your machine. The
10
+ account is for running it somewhere that is not your laptop, on a schedule,
11
+ with a team.
12
+
13
+ **Which models does it use?** Whatever you point it at. `model:` takes a
14
+ tier — `fast`, `default`, `max` — and the platform resolves the tier to a
15
+ model. Bring your own key for any provider that speaks the Anthropic or the
16
+ Chat Completions API, per account or per workspace, and the platform bills
17
+ you nothing for those tokens. See [Providers](providers).
18
+
19
+ **Can agents reach the internet?** Yes — the public internet, as themselves,
20
+ with the secrets they were granted. Not private networks, not the cloud
21
+ metadata endpoint, not the platform's own API or database.
22
+
23
+ **Can an agent change my website / my CRM / my repository?** Only if its
24
+ file names a tool that can, and the reference pattern is to give that tool
25
+ only to the step after a human gate. An agent with no tool that writes cannot
26
+ write, whatever it is told.
27
+
28
+ **What stops a runaway?** Three caps — per run, per workspace per month, per
29
+ account per month — and the stop button, which destroys the sandbox. A
30
+ step with no `timeout:` runs until it finishes; that is deliberate, and the
31
+ caps are the ceiling.
32
+
33
+ **How do I know what happened while I was asleep?** The run's headline: the
34
+ first line of the last step's reply, which is the runs-list row and the
35
+ subject of the notification. Ask your agents to open with a verdict and the
36
+ inbox becomes a status board.
37
+
38
+ **Can two flows write to the same repository?** Yes, and they should not do
39
+ it in the same hour. Give each writer its own day, or chain one after the
40
+ other with `trigger: flow`.
41
+
42
+ **I use Claude Code. Does that help?** A subagent at
43
+ `.claude/agents/<name>.md` deploys as a foldrun agent with no conversion.
44
+ The scaffolded `CLAUDE.md` tells your editor the layout.
45
+
46
+ **Where is my data?** In your workspace's folder, as files — on your machine,
47
+ or on the hosted platform's data volume — and its blobs in the
48
+ file store. Nothing is hidden in a database only the platform can read, and
49
+ a deploy never touches what an agent learned or a run recorded.
50
+
51
+ **Can I run it on my own hardware?** The CLI and runtime, yes — that is
52
+ what they are for, and they are open source. The platform itself is hosted
53
+ only. See [Running it yourself](self-hosting).