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. 1. “Create a folio” is five different requests
  2. 2. How the agent decides — and why it is a table, not a judgement
    1. The three facts
    2. The seven rules
    3. Why two rules return “ask”, and why that is the point
    4. Changing it
  3. 3. What the conversation looks like
  4. 4. Install and verify
  5. 5. Connect your LLM harness
  6. 6. Converting a repository you already have
  7. 7. Seeing it published
  8. 8. Make the landing page yours
    1. The markdown node you edit
    2. Your own backdrop
    3. Three things it will not do
  9. 9. Track the work with beans
  10. 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 meanyou havewhat the wrong guess costs you
A new folio in a new repositorynothing yet—
folio-assistant added to the repository you already haveyour own project, with its own filesa folio scaffolded on top of work nobody looked at first
Another folio in a repository that already has onea folio-assistant instancea second repository you did not want, and a split corpus
A new document inside the folio you already havea folio, and a chapter in mindan 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:

BPMN process: a user asks to create a folio; the agent detects the interaction modality, reads the repository facts, and an exclusive gateway computed from folio-intent.dmn routes to one of five branches — ask, overlay, new-repo, add-folio, or a hand-off to content authoring. The scaffold seeds the work plan, then the Pages build reports live, not-yet, or unknown.

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:

facthow it is obtained
isFoliois there a harness.config.json in this directory?
repoHasContentdoes the working tree hold files that are somebody’s project, as opposed to being bare?
statedIntentwhat 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.

isFolio is about the directory, not about you. Somebody who has used folio-assistant for years is still in an isFolio=false directory when they open a fresh one. Experience changes how much the agent explains; it does not change which branch it takes.

The seven rules

#saidis a foliohas content→
1–4any of the four––that branch
5unstatedyes–ask
6unstatednoyesask
7unstatednononew 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:

ask is 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 —

  1. 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)
  2. Add a second folio alongside atlas
  3. Start a new folio in a new repository
  4. 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 typewhat it isneeds
papera scientific paper or book, formal claims backed by Lean, typeset through LaTeXLean toolchain, TeX
documentstructured prose — policy guidance, a standard, a reportpandoc; no Lean, no TeX
WHO SMART DAKa Digital Adaptation Kit (L2) — personas, processes, data elements, decision tables—
WHO SMART IGa FHIR Implementation Guide (L3), built from an L2 DAKJava, 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:

ToolPurpose
folio_initScaffold a folio. Registered as a generic tool, because it runs before the folio has a content type
workflow_start / workflow_next / workflow_completeRun getting-started.bpmn as a real process; workflow_next says what is enabled now and which skill implements it
work_plan_primeSurface the work plan (beans)
check_dependenciesProbe which toolchains are installed
skill_list / skill_fetchDiscover 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:

  1. Import at all? — everything, sources only, nothing, or pick by bucket.
  2. Where does each group go? — library/ or content/, for the groups it was unsure about.
  3. 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
livethe site answered. Here is the link
not yeta measured 404 — the address is right and the first build has not landed there yet
could not checkno 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 declarethe page does
a backdrop with a regiondraws your description inside it
a backdrop with no regionshows the picture, puts the words below it
no backdropshows 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 create mints 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 the todo-manager skill.

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


folio-assistant — code under the Apache License 2.0, documentation under CC BY 3.0. Generated schema and API references are rebuilt from source on every push to main.

deployed dev