Getting started
This page is about the first conversation — what happens between somebody saying “I want to create a folio” and a published site they can open. If you already have a folio and want the toolchain set up, skip to §4 Install and verify.
- 1. “Create a folio” is five different requests
- 2. How the agent decides — and why it is a table, not a judgement
- 3. What the conversation looks like
- 4. Install and verify
- 5. Connect your LLM harness
- 6. Converting a repository you already have
- 7. Seeing it published
- 8. Make the landing page yours
- 9. Track the work with
beans - Next steps
1. “Create a folio” is five different requests
Say that sentence to five people and you will get five different pieces of work. The agent’s first job is not to start; it is to find out which one you meant.
| you mean | you have | what the wrong guess costs you |
|---|---|---|
| A new folio in a new repository | nothing yet | — |
| folio-assistant added to the repository you already have | your own project, with its own files | a folio scaffolded on top of work nobody looked at first |
| Another folio in a repository that already has one | a folio-assistant instance | a second repository you did not want, and a split corpus |
| A new document inside the folio you already have | a folio, and a chapter in mind | an entire empty folio, and the chapter still unwritten |
| Something you would rather describe in your own words | — | — |
The fourth row is the one worth pausing on. It is not an error on your part — “folio” is an unfamiliar word, and asking for one when you meant a chapter in one is the most natural mistake available. An agent that scaffolds on it has produced an empty repository and not the paragraph you asked for.
2. How the agent decides — and why it is a table, not a judgement
The triage is a real, readable artefact rather than a habit an agent might have:
- the process is
folio-assistant-core/processes/conduct/getting-started.bpmn; - the decision at its centre is
decisions/folio-intent.dmn, a DMN decision table you can open in any DMN tool and change without touching code.
Source: folio-assistant-core/processes/conduct/getting-started.bpmn — the SVG is generated by bun run cat render:bpmn.
The three facts
The gateway reads exactly three things, and two of them come from looking rather than asking:
| fact | how it is obtained |
|---|---|
isFolio | is there a harness.config.json in this directory? |
repoHasContent | does the working tree hold files that are somebody’s project, as opposed to being bare? |
statedIntent | what you actually said — one of the five, or unstated |
statedIntent is a fact about the conversation. It stays unstated until you
have said which, and inferring it from tone or from what would be convenient is
precisely the failure the table exists to prevent.
isFoliois about the directory, not about you. Somebody who has used folio-assistant for years is still in anisFolio=falsedirectory when they open a fresh one. Experience changes how much the agent explains; it does not change which branch it takes.
The seven rules
| # | said | is a folio | has content | → |
|---|---|---|---|---|
| 1–4 | any of the four | – | – | that branch |
| 5 | unstated | yes | – | ask |
| 6 | unstated | no | yes | ask |
| 7 | unstated | no | no | new folio here |
Hit policy is FIRST, so rules 1–4 come before any inference: a person who
says what they want is never overruled by a heuristic about their filesystem.
Why two rules return “ask”, and why that is the point
Only rule 7 is decidable by looking. A directory that is already a folio is
consistent with three different requests, and a directory with somebody’s
project in it is consistent with two. The table does not paper over that — it
returns ask.
That matters more than it sounds:
askis an outcome of the table, not a decision the agent reaches.
An agent cannot route to a branch the table did not return, so the question becomes obligatory rather than polite. An agent left to decide whether to ask will, under any pressure to seem helpful, decide not to — and the three ambiguous cases are exactly where guessing is most expensive.
When you answer, your answer becomes statedIntent and the same table is
evaluated again. That is why the diagram loops back to Read the repository
facts rather than jumping straight to a branch: your answer is evidence, read
like any other fact.
Changing it
The table is an XML file with seven rules in it. To add a sixth kind of request,
add a rule and add a matching branch to the gateway — the loader refuses to
start a process whose table can return an outcome no branch is named for, so the
two cannot drift apart. Nothing in src/ needs to change.
3. What the conversation looks like
The form of the question comes before its content. The agent establishes how
you would like to be asked — selectable options, ordinary chat, read aloud,
large type — and records it in interaction/interaction.json so no future session
asks you again. See Accessibility.
Then, when the answer is genuinely ambiguous:
You: I want to create a folio
Assistant: This directory already has a folio in it (
content/atlas/), so a few things you could mean —
- Add something to the folio that’s here — a chapter, a document (recommended — it is what “create a …” most often means from inside a folio)
- Add a second folio alongside
atlas- Start a new folio in a new repository
- Tell me more
(No answer is fine — I’ll take 1 and show you before writing anything.)
And then, what to get started on — because “a folio” is not a thing anybody actually wants:
| content type | what it is | needs |
|---|---|---|
| paper | a scientific paper or book, formal claims backed by Lean, typeset through LaTeX | Lean toolchain, TeX |
| document | structured prose — policy guidance, a standard, a report | pandoc; no Lean, no TeX |
| WHO SMART DAK | a Digital Adaptation Kit (L2) — personas, processes, data elements, decision tables | — |
| WHO SMART IG | a FHIR Implementation Guide (L3), built from an L2 DAK | Java, SUSHI, IG Publisher |
See Content types for what each formalism buys you.
4. Install and verify
Follow Installation, then:
bun run cat check-deps
bun should be reported present. Anything your content type needs and does not
have is listed with an install hint — a document folio needs none of the Lean or
TeX rows.
5. Connect your LLM harness
Register folio-assistant as an MCP server — see Connecting an LLM harness for Claude Code, Antigravity, Gemini CLI and generic MCP clients.
The tools most relevant to this page:
| Tool | Purpose |
|---|---|
folio_init | Scaffold a folio. Registered as a generic tool, because it runs before the folio has a content type |
workflow_start / workflow_next / workflow_complete | Run getting-started.bpmn as a real process; workflow_next says what is enabled now and which skill implements it |
work_plan_prime | Surface the work plan (beans) |
check_dependencies | Probe which toolchains are installed |
skill_list / skill_fetch | Discover and load a skill’s instructions |
The full tool list is on the Skills & roles page; content-type tools appear only when the matching adapter is active.
6. Converting a repository you already have
On the overlay branch the agent looks before it touches anything:
bun run cat scan:repo # read-only report
bun run cat scan:repo -- --json # the same, as facts
It sorts what it finds into three buckets — library (source material
somebody else wrote), content (prose authored here), and unclassified.
The third one is deliberate. A classifier that forces every file into one of two buckets has an accuracy nobody can assess, and delivers its mistakes as moved files. This one tells you what it could not place and lets you decide.
Then three questions, all answerable by picking, all asked per directory rather than per file:
- Import at all? — everything, sources only, nothing, or pick by bucket.
- Where does each group go? —
library/orcontent/, for the groups it was unsure about. - Leave in place, or reorganise? — leave in place is the recommendation and is meant. Decluttering is a preference; a broken relative link in your README is a defect.
Nothing moves until question 3 is answered. That step is marked
relaxable="false" in the BPMN, so no content package can declare it away.
Full discipline: the
repo-conversion skill.
7. Seeing it published
Creating a folio should end with a link. Immediately after scaffolding:
bun run cat pages:bootstrap # derive the address, report, no probe
bun run cat pages:bootstrap -- --wait # probe until the site answers (bounded)
It derives the address from harness.config.json or the origin remote, finds
publish workflows by what they do rather than what they are named, and reports
one of three things:
| means | |
|---|---|
| live | the site answered. Here is the link |
| not yet | a measured 404 — the address is right and the first build has not landed there yet |
| could not check | no address could be derived, nothing was probed, or the request failed |
The third is not a softer version of the second, and the agent will not tell you “it should be up shortly” on the strength of it. A measured 404 is evidence; a failed request is the absence of evidence, and an author who is told the wrong one goes looking for a site that was never going to appear.
The same three states are a decision table —
decisions/pages-live-gate.dmn —
and scripts/pages-bootstrap.ts is tested to agree with it exactly, so the
script and the table cannot drift.
8. Make the landing page yours
Your site’s home page opens with your instance’s own description, drawn
inside your own backdrop. Both come from one file — <name>.json at
the repository root — and nothing about the platform’s grumpy cat is written
into the template. Change the file; the page follows.
The markdown node you edit
// <name>.json -- the DECLARATION. Every key below is one of its top-level
// fields, which is what settles this label: it is not the folio config.
{
"title": "My Folio", // the left sidebar's heading
"description": "One line.\nAnother line.", // ← the landing markdown
"icon": "mark-small", // which image is the browser tab's
"images": [ /* … */ ]
}
description is markdown, rendered as-is. It is the node the landing page
draws; there is no separate page to keep in step with it, which is the point —
a description that appears in two places is a description that will disagree
with itself.
Your own backdrop
An image becomes the landing backdrop by declaring role: "landing" and which
viewport it is cut for:
{
"id": "landing-laptop",
"src": "docs/assets/img/my-backdrop.webp",
"role": "landing",
"layout": "laptop", // also: "mobile", "card"
"width": 1671, "height": 941,
"textRegion": { "x": 0.205, "y": 0.285, "w": 0.625, "h": 0.235 }
}
textRegion is where the words may safely go, as fractions of the image. It
is authored, not computed, because it states where the picture is quiet —
a judgement about composition that no pixel analysis substitutes for. The
platform’s own laptop backdrop has a thought-cloud with a clear lower interior,
a mark occupying its top third and a cat’s ear rising into its lower left; the
box that avoids all three was found by rendering candidates and looking at them.
Do the same for yours.
Declare one variant per viewport. Each carries its own region, because the same composition sits differently in a portrait crop.
Then:
bun run cat docs:harness # push the declaration into docs/_data/
bun run cat docs:harness -- --check # ...and fail if stale (for CI)
Three things it will not do
| you declare | the page does |
|---|---|
| a backdrop with a region | draws your description inside it |
| a backdrop with no region | shows the picture, puts the words below it |
| no backdrop | shows the words alone |
The middle row is deliberate. Text positioned by guesswork lands on the cat, so an undeclared region means “do not overlay”, never “anywhere is fine”. And a folio with no art is ordinary, not broken.
If you declare a mobile variant and a phone arrives, it gets that file — and
if you have not, it gets the widest one you do have. That fallback is a real
degradation, because the wide crop’s region is wrong for a narrow screen; it is
reported rather than hidden, so a renderer can decline to overlay instead of
placing text somewhere nobody chose.
9. Track the work with beans
folio-assistant uses beans as the single
work-plan mechanism — durable across sessions, shared between agents, committed
to the repository.
scripts/install-beans.sh # install the CLI if missing
beans prime # emit work-plan priming for agents
beans list # current open items
beans create "draft chapter 1" # open an item
beans <id> --status in-progress # claim an item
Check before you create.
beans createmints a fresh id on every call and dedupes on nothing. Re-entering a scripted step without an existence check produced 14,688 duplicate beans in one folio on a single afternoon. The check is in thetodo-managerskill.
The SessionStart hook surfaces the plan at the start of every session, and the
work_plan_prime MCP tool exposes the same surface to any connected agent.
Next steps
- Accessibility — how the agent asks, and the settings control on this site
- Tutorial — writing a paper
- Writing a document
- Content types — the formalism for each domain
- Publication workflow — every process in the repo
- Architecture — adapters, skills, and the block model