# Prompts, versions & files

How Sufleur organizes your prompts and what publishing actually does.

A prompt in Sufleur is a named, versioned template that your code can call by name — like an npm package, but for a piece of LLM input. This page explains the three concepts you'll work with daily: **prompts**, **versions**, and **files**.

## Prompts

A prompt is the top-level thing — a stable name like `@acme/welcome-message` that lives in your workspace. The name is what you reference everywhere: in the web app, in `sufleur.yaml`, and in your generated code. The prompt itself doesn't hold any template content; it's the container.

You'll typically have one prompt per logical task: one for "summarize a support ticket", one for "extract user details", and so on.

## Versions

Every change to a prompt's templates produces a new version. Versions come in two flavors:

- **Drafts** are your work-in-progress. You edit a draft freely — change the templates, add files, tweak the output schema — and nothing your application uses changes until you publish. There's only ever one draft per prompt at a time.
- **Published versions** are immutable snapshots, stamped with a [semver](https://semver.org/) (`1.0.0`, `2.3.1`, etc.). Once published, a version can never change. Your application code resolves against published versions, so this immutability is what makes the system safe.

To roll out a change, you:

1. Edit the draft.
2. Publish it as the next semver. Sufleur enforces that your new version is strictly greater than the latest published.
3. Run `sufleur update` and `sufleur generate` in your project to pick up the new version.

The next time you want to change something, you start a new draft. A fresh draft begins as a copy of the latest published version, so you only edit what changed.

> [!TIP] Why immutable versions matter
>
> Your `sufleur-lock.yaml` pins each prompt by version and hash. If a published version could
> mutate, two engineers with the same lockfile could produce different generated code, and
> your prod deploy could behave differently from your local dev. Locking the versions makes
> the whole pipeline reproducible.

## Files

A version is made up of one or more files. Each file is a single Mustache template — typically one per LLM message role:

- a `systemPrompt` file for the system message
- a `userPrompt` file for the user message
- assistant or tool messages if your flow needs them

You can also add **partial files** — reusable fragments included by other files via Mustache's `{{>partial}}` syntax. Partials are a great fit for boilerplate that several entrypoints share.

### Entrypoints vs partials

Each file is either an **entrypoint** or a **partial**:

- **Entrypoints** are the files your code can render directly. They show up in the generated SDK as named choices: `prompt.render('systemPrompt', input)`, `prompt.render('userPrompt', input)`.
- **Partials** are not directly renderable; they're only included from other files.

You toggle this per file in the web app. Entrypoints get their own typed input schema (inferred from the Mustache variables they reference plus any [`@type`, `@doc`, and `@optional` annotations](/docs/mustache)), and that schema flows through to your generated code as the input type for `render()`.

A version must have at least one entrypoint to be publishable.

## Output schemas

If your prompt is meant to produce structured output — say a JSON object the rest of your code consumes — you can attach an **output schema** to the version. The schema is standard [JSON Schema](https://json-schema.org/) describing the expected shape.

The schema is used in two complementary places:

- **Inside the template**, via the [`{{@outputSchema}}` directive](/docs/mustache#outputschema), which gets replaced with the JSON of your schema so the model sees exactly what's expected.
- **In your code**, via a `parseOutput()` function the SDK generates for you, which validates the model's response against the schema and returns a typed object.

Output schemas are per-version: one prompt produces one response shape, regardless of which entrypoint started the conversation.

## Discovery

Prompts can be public or private. Public prompts show up on the [Explore page](/explore) — a no-account-required browser of every shared prompt on Sufleur. Private prompts are scoped to your workspace and only readable with a workspace-scoped API key.
