# Tellscript documentation > A Tellscript records what your software does, how it looks and why, with numbered rules and tests. Any AI agent builds the code from it, and every new model a better edition. Source: https://tellscript.com/docs · 2026-09-27 # Introduction Tellscript is an open format for the part of your software that should outlive its code. A Tellscript is a folder of Markdown files next to your code. It records what the product must do, how it must look, what other systems rely on and why things are the way they are. Every rule has a stable id and a check that fails when the rule breaks. Any coding agent can read it. Claude Code, Codex, Cursor, Gemini CLI or an open model builds the code from it, and when a better model arrives, it builds the next **edition** of the same app: the fixed rules stay, the free parts get better. ## Why a new format AI writes code, images and documents in minutes. How and why they came out that way is forgotten the moment they exist. The next agent tidies up and brings back the bug that was the reason for an odd rule. The tenth image no longer matches the first. Every rebuild copies the last one, flaws included. Tellscript keeps the mould instead of the cast. The code becomes an output you can throw away; the Tellscript is the source. ## How it works 1. **Write it down.** One file per feature: intent, numbered statements, the look as a reference image, the reasons as decisions. 2. **Bind it.** Every statement points to the test, reference image or recipe that proves it. 3. **Build and rebuild.** Any agent builds an edition from the Tellscript. The checks decide whether it is accepted. ```tell file=tell/features/cart.tell.md ## Behaviour · fixed C1 When the goods reach €50.00, shipping is free. → cart.spec#free-shipping C2 When a second voucher arrives, it is declined with a notice. → cart.spec#one-voucher ``` ## What is in these docs | Section | Read it when | |---|---| | [Quickstart](/docs/quickstart) | you want a first Tellscript in an afternoon | | [Teach your agent](/docs/agents) | you want Claude Code, Codex, Cursor or another agent to know the format | | [The format](/docs/files) | you write or review Tellscripts and want the exact rules | | [Checks](/docs/checks) and [editions](/docs/editions) | you rebuild with a new model or guard an app against drift | | [Example](/docs/example) | you learn best from a complete, working set of files | > [!NOTE] > Tellscript is plain Markdown in your repository. There is no service to sign up for and nothing to install to start. Tools that make it more comfortable are in development; see [the CLI preview](/docs/cli). # Quickstart You need no new tool. A Tellscript is Markdown, and the agent you already use can read and write it. Start with one feature, the one that hurts most when it breaks: checkout, sign-up, billing. ## Copy the prompt Paste this into Claude Code, Codex, Cursor, Gemini CLI or any agent that can read your repository. It writes a first draft and marks what it cannot give a reason for. ```prompt Write a Tellscript for this project under tell/. One Markdown file per feature, with front matter (tell, checks, face, rationale) and the sections Intent, Behaviour, Face, Why and Free. Every rule gets a stable id (C1, C2 …) and a link to the test that checks it. Every section carries a ring: fixed, guided or free. Mark rules whose reason you cannot find as open. Follow the format at https://tellscript.com/llms.txt ``` Then review the draft with the five steps below. They are the same steps you would take by hand. ## 1. Start with the product file Create `tell/product.tell.md`. Write down what the product is for, who uses it, and the few principles that hold on every screen. ```tell file=tell/product.tell.md --- tell: product/shop features: [product-page, cart, checkout] tokens: tokens/brand.json edition: 5 --- # Castwell, cast-concrete homeware ## Intent Find the right piece and buy it in three steps, on a phone as well. ## Principles · fixed P1 Prices always show shipping. → checks/price.spec#shipping P2 No page loads longer than 1 second. → checks/perf.spec#p95 ``` ## 2. Describe one feature Write its intent in two lines, then its behaviour as numbered statements. Add the look as a reference image and the reasons as decisions. See [statements](/docs/statements) for how to phrase them. ## 3. Bind every statement to a check For each id, find the test that proves it, or write one. Name the test after the statement and point to it from the arrow line. A statement you cannot check yet stays in the file as *described*; its check is your next task. ```ts file=checks/shop.spec.ts test("one-voucher", async ({ cart }) => { // C2 await cart.redeem("SUMMER10"); const second = await cart.redeem("LOYAL5"); expect(second.error).toBe("cart.voucher.used"); }); ``` ## 4. Mark the rings Decide per section: what must stay exactly as it is (**fixed**), what a model may propose to change (**guided**), what it may improve freely (**free**). When in doubt, fix less; you can tighten later. See [rings](/docs/rings). ## 5. Run the rebuild test Ask your agent to build the feature from the Tellscript alone, in an empty folder, and run the checks against it. Every failure is a missing statement or a missing check. Add it and run again. See [the rebuild test](/docs/rebuild-test). > [!TIP] > Download the complete [Castwell example](/downloads/castwell.tell.md) and keep it open while you write. It has four files and a check. # Teach your agent Every coding agent already reads instruction files from your repository. Tellscript needs only a few lines in the file your agent reads, and the agent keeps the Tellscript up to date as it works. ## Install the skill The Tellscript skill teaches your agent the whole format and when to use it. One command installs it for Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and other agents that read [Agent Skills](https://agentskills.io): ```text file=Terminal npx skills add tellscript-dev/tellscript ``` In Claude Code you can add it as a plugin instead: ```text file=Claude Code /plugin marketplace add tellscript-dev/tellscript /plugin install tellscript@tellscript ``` The skill, the spec and the schema live in the [tellscript-dev/tellscript](https://github.com/tellscript-dev/tellscript) repository. ## One prompt, any agent No installer at hand? Paste this into the agent you use. It teaches the agent the format from this site and writes the instructions into your repository, so the next session knows them too. ```prompt Learn the Tellscript format from https://tellscript.com/llms-full.txt Then add a short "Tellscript" section to the instruction file you read here (AGENTS.md, CLAUDE.md, GEMINI.md, .cursor/rules or .github/copilot-instructions.md): - tell/ is the source of truth for what this app must do and look like. Read the matching file before changing behaviour. - Never break a fixed statement. Propose changes to guided sections; improve free sections freely. - New or changed behaviour updates tell/ in the same change: a stable id and a check per statement. ``` ## The lines to add If you prefer to write it yourself, this is the section. It is the same for every agent; only the file differs. ```text file=AGENTS.md ## Tellscript tell/ is the source of truth for what this app must do, how it looks and why. Format: https://tellscript.com/docs - Before changing behaviour, read the matching file in tell/. - Fixed sections are rebuilt exactly. Never change a fixed statement to make a test pass; propose a decision instead. - Guided sections: propose improvements with a measurable gain. - Free sections: improve them freely; only the checks decide. - New or changed behaviour updates tell/ in the same change: a stable id, one checkable sentence, and a → line to its check. ``` ## Where each agent reads it | Agent | File | Notes | |---|---|---| | Codex | `AGENTS.md` | Read from the repository root and from folders on the way to the file being edited | | Cursor | `AGENTS.md` or `.cursor/rules/tellscript.mdc` | A project rule can apply to `tell/**` only | | GitHub Copilot | `AGENTS.md` or `.github/copilot-instructions.md` | Used by Copilot chat and the coding agent | | Gemini CLI | `GEMINI.md`, or `AGENTS.md` | Add `AGENTS.md` to `context.fileName` in `.gemini/settings.json` to keep one source | | Claude Code | `CLAUDE.md`, or `AGENTS.md` when there is no `CLAUDE.md` | A line `@AGENTS.md` in `CLAUDE.md` imports the shared file | | OpenCode and others | `AGENTS.md` | The cross-agent convention; one file for all | > [!TIP] > Keep one source. Write the section into `AGENTS.md` and let the agent-specific files import or point to it, so every agent follows the same rules. ## For agents: the format as plain text Agents do not need the website. Every docs page is also available as Markdown, and the whole format fits in one file: - [llms.txt](/llms.txt): an index of all docs pages, for agents that browse. - [llms-full.txt](/llms-full.txt): every docs page in one file, to paste into a context window. - Any docs page with `.md` appended, for example [/docs/statements.md](/docs/statements.md). # Files and folders A Tellscript is not one long document. It is a folder called `tell/` in your repository, with one file per thing that must survive a rebuild. Checks stay where your tests already live. ```text file=your-repo/ tell/ product.tell.md purpose, users, principles features/ product-page.tell.md one flow: statements, states, texts cart.tell.md contracts/ http.tell.md routes and types, byte-exact decisions/ one-voucher.md why a rule exists, what was rejected recipes/ product-photos.tell.md how pictures are made reference/ product.png how a screen must look checks/ shop.spec.ts one test per statement ``` ## File names - Tellscript files end in `.tell.md`, so every Markdown viewer renders them and tools can find them. - The path mirrors the `tell` key in the front matter: `tell: feature/cart` lives in `tell/features/cart.tell.md`. - Decisions are ordinary Markdown in `tell/decisions/`, one decision per file, named after the decision. - Reference images live in `tell/reference/`, named after the screen and state they show, for example `cart-empty.png`. ## One file per feature, not per code file Group by what the user experiences, not by how the code is split. A feature file describes one flow; the next edition may implement it in one file or in twenty. File-level Tellscripts exist, but only for files other code depends on directly; see [levels](/docs/proof#levels). ## Size A good feature file is 30 to 80 lines. If it grows past 150, it usually holds two features. As a rule of thumb, a Tellscript is about a third as long as the code it describes. > [!NOTE] > Everything is plain text or an image. No service, no database, no lock-in: any agent that can read files can read a Tellscript. # Front matter Every Tellscript file starts with a short YAML block between two lines of dashes. It names the file and points to everything that proves or explains it. An agent reads this block first and knows which tests, images and decisions belong to the feature. ```tell file=tell/features/cart.tell.md --- tell: feature/cart binds: [contract/http#POST /api/cart/voucher] checks: [checks/cart.spec.ts] face: [reference/cart.png, tokens/brand.json] rationale: [decision/one-voucher] proof: proven · edition 4 --- ``` ## Keys | Key | Required | Points to | |---|---|---| | `tell` | yes | Name and level: `product/`, `feature/`, `contract/`, `recipe/` or `file/`, then the name | | `checks` | yes, once bound | Test files, reference images or recorded flows that the statements point to | | `binds` | no | Contracts this file touches, with the exact route, type or table | | `face` | no | Reference images and design tokens for the look | | `recipe` | no | Recipes for pictures, texts or data the feature shows | | `rationale` | no | Decisions that explain the rules in this file | | `proof` | yes | Proof level and the edition that reached it: `described`, `bound` or `proven · edition N` | Product files add `features` (the feature files, in reading order), `tokens` (design tokens) and `edition` (the edition currently running). Recipe files add `model`, `refs` and `lineage`; see [recipes](/docs/recipes). ## Rules - Paths are relative to `tell/`, except `checks/`, which points to your test folder. - A reference to part of a file uses `#`: `cart.spec#one-voucher` is the test named `one-voucher`. - `proof` is written by the check run, not by hand. See [proof levels](/docs/proof). # Layers Below the front matter, a file is organised in layers, one section heading each. A small feature may need only Intent and Behaviour; a product file uses most layers. What a new model would otherwise have to guess belongs in one of them. | Layer | Answers | Holds | Example | |---|---|---|---| | **Intent** | What is it for? | Purpose, users, terms, principles, budgets for speed, accessibility and cost | `P1 Prices always show shipping.` | | **Behaviour** | What must happen? | Flows as numbered when-then statements, each with its check | `C1 Orders from €50.00 ship free.` | | **Contracts** | What do others rely on? | Routes, API types, tables, storage keys, events; byte-exact | `POST /api/cart/voucher` | | **Face** | What do people recognise? | Design tokens, components, texts with stable ids, reference images per state | `reference/product.png` | | **Why** | Why is it so? | Decisions with rejected alternatives, lessons from failures, each with a check | `decision/one-voucher` | | **Recipes** | How is content made? | Brief, model, references and parameters for images, texts and data | `recipe/product-photos` | | **Proof** | Does it still hold? | Checks, reference images and recorded flows | `shop.spec#one-voucher` | ## Headings Each layer is a second-level heading. The heading names its [ring](/docs/rings) after a middle dot: ```tell file=tell/features/product-page.tell.md ## Intent Buy without surprises: price, shipping and stock are settled before anyone pays. ## Behaviour · fixed C1 Orders from €50.00 ship free. → shop.spec#free-shipping ## Face · fixed C3 Price and “Add to cart” stay in view without scrolling. → reference/product.png ## Free Layout, speed, stack, internal names. ``` - **Intent** carries no ring; it explains and is never checked directly. - **Build** is an optional layer for stack and architecture, usually `guided`: “The server computes prices. Framework open.” - **Free** lists what the next edition may change without asking. Writing it down is what lets a better model improve it. # Statements Statements are the heart of a Tellscript. Each has an id that never changes, one sentence that a test can prove wrong, and a reference line that names the check. ```tell file=tell/features/cart.tell.md ## Behaviour · fixed C2 When a second voucher arrives, it is declined with a notice. → cart.spec#one-voucher ``` ## Anatomy | Part | Example | Rule | |---|---|---| | Id | `C2` | A letter and a number, unique within the file. `P` for product principles, `C` for feature statements. | | Sentence | When a second voucher arrives, it is declined with a notice. | One rule, in when-then form, with numbers where numbers matter. | | Reference | `→ cart.spec#one-voucher` | The check that fails when the sentence stops being true. | ## Write it so a test can fail | Vague | Checkable | |---|---| | The cart is fast. | `C4` The total updates within 200 ms of a change. | | Vouchers work sensibly. | `C2` When a second voucher arrives, it is declined with a notice. | | It looks like our brand. | `C3` The total stays visible, top right. → `reference/cart.png` | - **One statement, one rule.** If the sentence needs “and”, it probably needs two ids. - **Amounts, times and sizes are exact.** €50.00, not “around fifty”; 200 ms, not “fast”. - **Texts users see are quoted and have ids** in the Face layer, so a rebuild cannot paraphrase them. - **Describe the outcome, not the code.** “Declined with a notice”, not “throws a VoucherError”. ## Ids are forever - Checks point to the id, never to the wording. You can rephrase a statement without touching its test. - A removed statement retires its id. It is never reused for something else, so old test results stay meaningful. - A statement whose reason nobody knows is marked `open`. It stays until someone finds the reason or decides to drop it. ```tell file=tell/features/checkout.tell.md ## Behaviour · fixed C7 Orders to Switzerland show duties before payment. open: reason unknown → checkout.spec#duties ``` # Rings Every section heading names its ring after a middle dot: `## Behaviour · fixed`. The ring tells the next model how much freedom it has. Fixed rules keep your product recognisable; the free ring is where every model generation gets better. | Ring | What it means for the next edition | Typical sections | |---|---|---| | **fixed** | Rebuilt exactly. Changes only through a recorded decision. | Behaviour, Contracts, Face, texts | | **guided** | The model may propose a better way, with a measurable gain. Accepting it becomes a decision. | Build: stack, architecture, libraries | | **free** | Every edition may improve it without asking. Only the checks decide. | Implementation, internal names, algorithms, layout details | ## The same request, three rings A single request meets the three rings differently. Here someone asks for speed and for stacked vouchers. | Ring | The agent's answer | Result | |---|---|---| | free | Speed: prices computed in one pass, photos load lazily. | done | | guided | Build: compute prices at the edge. Faster, but needs a decision. | proposal | | fixed | C2 stays: one voucher per order. Reason: `decision/one-voucher`, stacked discounts were abused. | declined | ## Choosing a ring - **Fix what users and other systems notice**: amounts, flows, texts, URLs, APIs, stored data, the look of key screens. - **Guide what is expensive to change back**: the database, the framework, where code runs. - **Free everything else.** Writing the Free section down is what lets a better model improve it. - **Start with fewer fixed rules.** A fixed rule without a check is only a wish; tighten as your checks grow. # Levels and proof ## Levels Tellscripts are layered like the software itself. The product file holds what is true everywhere; below it sit feature files, contract files and, rarely, file files. | Level | `tell:` prefix | What it holds | Write it | |---|---|---|---| | Product | `product/` | Purpose, users, terms, principles | Always | | Feature | `feature/` | One flow with statements, states and texts | Always | | Contract | `contract/` | What other systems use, byte-exact | Always | | File | `file/` | Interface and rules of one code file | Once the file is proven and others depend on it | ## Proof levels The `proof` key in the front matter says how far a file can be trusted, and which edition got it there. Proof is earned by checks, not declared. | Proof level | Reached when | |---|---| | `described` | Written from the code or by hand. Useful as a map, not yet a source. | | `bound` | Every statement has a check that fails when it no longer holds. | | `proven · edition N` | A model from another lab rebuilt it from the Tellscript alone, in an empty folder, and passed every check, including the hidden ones. | > [!IMPORTANT] > A Tellscript written from existing code is a summary of that code, bugs included, until a rebuild has passed. Treat `described` files as a starting point, and let the [rebuild test](/docs/rebuild-test) move them up. # Checks A statement is only as good as the check that can prove it wrong. The Tellscript says what must hold; the check proves that it does. A test without a statement has no reason, and a statement without a test is a wish. ## One id, in two places ```tell file=tell/features/product-page.tell.md ## Behaviour · fixed C2 A second voucher is declined with a notice. → shop.spec#one-voucher ``` ```ts file=checks/shop.spec.ts test("one-voucher", async ({ cart }) => { // C2 await cart.redeem("SUMMER10"); const second = await cart.redeem("LOYAL5"); expect(second.error).toBe("cart.voucher.used"); await expect(cart.notice) .toHaveText(t("cart.voucher.used")); }); ``` The reference line `→ shop.spec#one-voucher` and the test name `one-voucher` are the binding. The comment `// C2` lets people find their way back. ## Four kinds of check | Statement kind | Checked by | Example | |---|---|---| | Behaviour | Unit, integration or end-to-end tests; the test name carries the id | `shop.spec#one-voucher` | | Contracts | Routes, types and stored data compared byte by byte with the contract file | `contract/http#POST /api/cart/voucher` | | Face | Each screen and state rendered on phone and desktop and compared with its reference image | `reference/cart.png` | | Recipes | Every picture or text keeps a note of the recipe, model and references it came from | `recipes/product-photos` | ## When a check fails An edition that breaks a fixed statement is not accepted. The model may rewrite every line of code, but it cannot quietly change what the product promises. ```text file=tell check edition 6 ✓ C1 free-shipping ✗ C2 one-voucher second voucher accepted ✓ C3 price-in-view ✓ C4 photo-recipe edition 6 not accepted · 1 fixed statement broken ``` - In the free ring, the agent fixes the code and runs the checks again. - It never edits a statement to make a test pass. - A fixed statement changes only together with a [decision](/docs/decisions). ## The hidden test bench A model that sees the tests can learn the tests instead of the product. For a rebuild, keep a second set of checks and screenshots from the running edition that the building model never sees. Only what the Tellscript really carries passes both. Whatever the hidden bench catches was never written down: it becomes a new statement with its own id. # Editions and upgrades An edition is one build of your app from the Tellscript, by one particular model. It is replaceable by design. Edition 5 of a shop may use a different framework than edition 4 and still be the same shop, because the rules that make it that shop are fixed and checked. | In a new edition | What it means | |---|---| | **Replaced** | The code, its structure, internal names, the build setup; the framework, if the guided ring allows it | | **Kept** | Data, migrations, files already shipped to users, URLs and contracts other systems use, check results | | **Carried** | Everything in the Tellscript: statements, rings, decisions, references and recipes | ## The upgrade loop Upgrading is no longer a migration project. It is a rebuild with a review at the end, and it can run overnight. 1. **A new model ships**, or you want a redesign, a new platform, a new framework. 2. **Rebuild in an empty folder.** The model reads only the Tellscript, its references and recipes. 3. **Run every check**: tests, contracts, reference images and the hidden bench. 4. **Review the difference** in a pull request: which statements held, what got fixed, what improved in the free ring, and which guided proposals wait for a decision. ## Three ways to rebuild | Mode | Scope | Use it for | |---|---|---| | Retouch | One file at a time, inside the existing edition | Small upgrades, the first rebuilds of a new Tellscript | | Recompose | One feature, rebuilt next to the old one | New framework or architecture for part of the app | | Full rebuild | The whole app in an empty folder | A new model generation, a platform switch, a redesign | > [!TIP] > Start with retouches. A full rebuild is only as safe as your checks; the [rebuild test](/docs/rebuild-test) tells you when they are ready. # The rebuild test You do not have to wait for a new model to find out whether your Tellscript is complete. Rebuild on purpose, regularly, and write down what goes missing. ## How to run it 1. Create an empty folder or a fresh worktree. 2. Give the agent only `tell/`, the reference images and recipes, and the contract files. No old code. 3. Ask it to build the feature, or the app, from the Tellscript. 4. Run the checks against the result, including the hidden bench. 5. For every failure, add the missing statement or the missing check to the Tellscript. Run again. ```prompt Build this app from tell/ alone, in the empty folder edition-next/. Do not read any existing source code. Follow every fixed statement exactly, propose changes to guided sections, and improve free sections freely. When done, run the checks in checks/ against edition-next/ and list every failing statement id. ``` ## What it tells you - **A failing fixed statement** means the edition is wrong. The agent fixes the code. - **A failing check without a statement** means the Tellscript is incomplete. Write the statement. - **A difference nobody minds** belongs to the free ring. Leave it. - **A difference somebody minds** is a rule nobody wrote down. Write it, with its reason. Teams that do this weekly find that their Tellscript stops growing after a few weeks. From then on it changes when the product changes, not when the code does. # Recipes Wherever AI makes something, the same holds as for code: lose the prompt and you lose the series. A recipe is a Tellscript for generated content. It records the brief, the model, the references and the parameters, and which files came from it. ```tell file=tell/recipes/product-photos.tell.md --- tell: recipe/product-photos model: gpt-image-2.5 · sunburst · 2K refs: [brand/BRAND.md#photography] lineage: every photo from this brief --- # Product photos ## Style · fixed Black-and-white studio photograph, cast concrete on seamless pale grey. Key light upper left, 45 degrees. One colour only: signal green, one detail. ## Why Green means one thing: what stays. ## Subject · free One sentence per piece, e.g. shop-lamp.txt ``` ## Rules for recipes - **The style is fixed, the subject is free.** One brief holds a series together; each picture adds one sentence. - **References are originals.** Real photographs, product shots, logos, screenshots. Never a generated image as the reference for the next one; quality drops with every generation. - **Every output keeps its lineage.** A small sidecar next to each file names the recipe, model, prompt and date, so any file can be traced and made again. - **The same works for documents and design.** Structure, tone, sources and template for a quarterly report; colours, type, spacing and their reasons for a design system. # Decisions Odd rules have reasons. Without the reason, the next agent tidies the rule away and brings back the bug that caused it. A decision keeps the reason next to the rule. ```text file=tell/decisions/one-voucher.md # One voucher per order Decided: 12 March 2026, Cedric May Applies to: feature/cart C2, feature/product-page C2 ## Why Stacked discounts were abused: codes from newsletter, partner and loyalty programmes combined to more than 40 % off. Support spent two days a month on refunds. ## Rejected - A limit per customer: needs accounts; most orders are guests. - A maximum discount: customers found it confusing. ## Check → cart.spec#one-voucher ``` ## When to write one - A fixed statement would look wrong to a newcomer. - You rejected an obvious alternative. - A bug or an incident led to the rule. These are the scars worth keeping; each gets a regression check. - A guided proposal from a model is accepted. The decision records the measured gain. ## Changing a fixed statement Fixed statements change only together with a decision: a new file, or a new dated entry in the existing one, that names the reason and what it replaces. The statement keeps its id if the rule is the same rule, refined; it gets a new id if it is a different rule. # Example: Castwell Castwell is the example used throughout this site: a small shop for cast-concrete homeware. Its Tellscript has four files and a check. [Download all of it as one Markdown file](/downloads/castwell.tell.md). ## Product ```tell file=tell/product.tell.md --- tell: product/shop features: [product-page, cart, checkout] tokens: tokens/brand.json edition: 5 --- # Castwell, cast-concrete homeware ## Intent Find the right piece and buy it in three steps, on a phone as well. ## Principles · fixed P1 Prices always show shipping. → checks/price.spec#shipping P2 No page loads longer than 1 second. → checks/perf.spec#p95 ## Why decision/price-first: shipping questions were the most common support case. ``` ## Product page ```tell file=tell/features/product-page.tell.md --- tell: feature/product-page checks: [checks/shop.spec.ts] face: [reference/product.png, tokens/brand.json] recipe: recipes/product-photos.tell.md rationale: [decision/one-voucher] --- # Product page ## Intent Buy a cast-concrete piece without surprises: price, shipping and look are settled before anyone pays. ## Behaviour · fixed C1 Orders from €50.00 ship free. → shop.spec#free-shipping C2 A second voucher is declined with a notice. → shop.spec#one-voucher ## Face · fixed C3 Price and “Add to cart” stay in view without scrolling. → reference/product.png C4 Every photo follows the recipe. → recipes/product-photos ## Why decision/one-voucher: stacked discounts were abused. ## Free Layout, speed, stack, internal names. ``` ## Cart ```tell file=tell/features/cart.tell.md --- tell: feature/cart binds: [contract/http#POST /api/cart/voucher] checks: [checks/cart.spec.ts] face: [reference/cart.png, tokens/brand.json] rationale: [decision/one-voucher] proof: proven · edition 4 --- # Cart ## Intent Buy without surprises: total and shipping are settled before paying. ## Behaviour · fixed C1 When the goods reach €50.00, shipping is free. → cart.spec#free-shipping C2 When a second voucher arrives, it is declined with a notice. → cart.spec#one-voucher ## Face · fixed C3 The total stays visible, top right. → reference/cart.png · text cart.total ## Build · guided The server computes prices. Framework open. ## Why decision/one-voucher: stacked discounts were abused. Rejected: a limit per customer. ## Free Speed, internal names, accessibility. ``` ## Photo recipe ```tell file=tell/recipes/product-photos.tell.md --- tell: recipe/product-photos model: gpt-image-2.5 · sunburst · 2K refs: [brand/BRAND.md#photography] lineage: every photo from this brief --- # Product photos ## Style · fixed Black-and-white studio photograph, cast concrete on seamless pale grey. Key light upper left, 45 degrees. One colour only: signal green, one detail. ## Why Green means one thing: what stays. ## Subject · free One sentence per piece, e.g. shop-lamp.txt ``` ## Check ```ts file=checks/shop.spec.ts test("one-voucher", async ({ cart }) => { // C2 await cart.redeem("SUMMER10"); const second = await cart.redeem("LOYAL5"); expect(second.error).toBe("cart.voucher.used"); await expect(cart.notice) .toHaveText(t("cart.voucher.used")); }); ``` On the [start page](/#years), the same cart Tellscript is built by five eras, from jQuery in 2008 to a forecast for 2034. The look and the features change completely; the three rules do not. # CLI preview > [!WARNING] > `tell` is in development and not published yet. Everything on this page can already be done by asking your agent; the tool makes it repeatable. The commands and output below show the planned behaviour. ```text file=tell $ tell extract ./shop 14 tells · 212 statements · 38 without a check yet $ tell check ✓ code and Tellscript agree $ tell regen --model latest --out edition-6 $ tell diff edition-5 edition-6 ✓ same 209 · fixed 2 · proposal 1 (guided) $ tell recipe product-photos --again ✓ new photo from recipe/product-photos ``` | Command | What it will do | |---|---| | `tell extract` | Reads code, tests and screenshots of an existing app and writes a Tellscript with its rings, marking what it cannot give a reason for as open | | `tell check` | Checks on every commit whether code and Tellscript still agree: every statement bound, every check passing | | `tell regen` | Rebuilds the app in an isolated folder, with the model and in the language you choose | | `tell diff` | Compares two editions: what stayed, what got fixed, which guided proposals wait for a decision | | `tell recipe` | Makes a picture, text or data set again from its recipe | Planned around it: a hidden test bench for rebuilds, a drift guard for pull requests, a visual compare on phone and desktop, and an upgrade autopilot that rebuilds on every new model and opens a pull request. # Questions ## What is an edition? A code output built from the Tellscript by one particular model. It is replaceable. Data, migrations, shipped files and check results are not part of it; they stay when the next edition arrives. See [editions](/docs/editions). ## Do I have to throw away my code? No. Your code keeps running, and the Tellscript grows next to it. You rebuild when you want: with the next model, for a redesign, when you switch platforms. ## What if the model ignores it? Then the checks fail. Every fixed statement is bound to a test or a reference image. An edition that breaks one is not accepted. See [checks](/docs/checks). ## Are two editions the same? In the fixed ring, yes, and that is checked. In the free ring they may differ. That is exactly where every model generation gets better. ## Who changes the Tellscript? People through a pull request, or the agent with approval. A fixed statement only changes together with a [decision](/docs/decisions) and its reason. ## Which agents does it work with? Any agent that can read files: Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and open models. A Tellscript is readable Markdown in your repository, with no service and no lock-in. See [teach your agent](/docs/agents). ## How long is a Tellscript? About a third as long as the code it describes, split into one file per feature of 30 to 80 lines. Readable for everyone on the team, not only developers. ## How is this different from a spec or a PRD? A PRD says what to build, once, at the start. A Tellscript is checked against every edition, so it cannot go quietly stale, and its rings say how much freedom each part leaves to the model. ## How is it different from AGENTS.md or Cursor rules? Those files tell an agent how to work in your project. A Tellscript tells it what the product must be in the end. They work well together: your AGENTS.md can point the agent to `tell/`. ## Is Tellscript open? Yes. The format is plain Markdown and free to use. The specification and the example files are published openly by Riverlabs. # Glossary | Term | Meaning | |---|---| | **Tellscript** | A folder `tell/` of Markdown files that records what software must do, how it looks and why; the source every edition is built from | | **Statement** | One checkable sentence with a stable id, for example `C2`, and a reference line to its check | | **Id** | The permanent name of a statement; checks point to the id, never to the wording | | **Binding** | The link between a statement and the check that proves it: the arrow line and the test name | | **Check** | A test, contract comparison, reference image or lineage note that fails when a statement stops holding | | **Layer** | A section of a file answering one question: Intent, Behaviour, Contracts, Face, Why, Recipes | | **Ring** | How much a section may change in the next edition: fixed, guided or free | | **Edition** | One build of the app from the Tellscript by one model; replaceable | | **Front matter** | The block at the top of a file that names it and points to its checks, references and decisions | | **Contract** | What other systems rely on, byte-exact: routes, types, tables, events | | **Face** | What people recognise: tokens, components, texts with ids, reference images | | **Reference image** | A screenshot of a screen in one state that the next edition is compared with | | **Decision** | A dated record of why a rule exists and which alternatives were rejected | | **Recipe** | A Tellscript for generated content: brief, model, references, parameters | | **Lineage** | The note next to a generated file that names the recipe and model it came from | | **Open** | A marker for a statement whose reason nobody knows yet | | **Proof level** | How far a file can be trusted: described, bound or proven | | **Hidden bench** | Checks and screenshots the building model never sees during a rebuild | | **Rebuild test** | Rebuilding from the Tellscript alone in an empty folder, to find what was never written down |