3 · The deck format
A deck is a plain-text Markdown file. You can write one in any editor with no tooling, read it back at a glance, and because it’s real Markdown, it renders sensibly anywhere else too: a preview pane, your file host, GitHub.
When you write a deck by hand, initialize it once before it appears in the picker:
alix deck init ~/decks/my-deck.md
The command adds stable deck and card IDs without rewriting the authored
content. A valid id: deck-<token> in the opening frontmatter marks the file as
an initialized deck. The deck- prefix on the value is what carries the
meaning: it is how alix tells its own decks apart, and the same prefixed string
travels everywhere the id appears, in a frontmatter key, a card marker, a
filename, a prerequisite reference, or an error message. Markdown without that
prefixed id is never listed or modified, so ordinary documents with ##
headings can sit in a decks folder untouched. Generated, imported, received, and
tutorial decks are initialized when they are created.
Choosing a card shape
Read the material before choosing its card shape. The shared guide below names the useful choices and distinguishes structural matches from judgement calls. The sections after it show the exact syntax for each shape.
Which card shape suits which material. Read the material first, then pick the shape; do not pick a shape and bend the material into it.
Some rows are structural: the material has a property the shape exploits, and any other shape wastes it. Some are judgement: more than one shape is defensible and the choice is yours. The difference is marked, because a rule that claims uniform authority gets followed badly exactly where thought was needed.
| material | shape | kind | why |
|---|---|---|---|
| Paired items: a word and its meaning, a term and its definition, a symbol and its name. | A card table: a GitHub pipe table, one row per pair, columns front, back, and an optional note. | structural | One row per pair, and each row’s Recognize options come from its own column, so the wrong answers are real siblings and cost no AI call. Prose wastes both. |
| Ordered steps that must be reproduced in order: a recipe, an algorithm, a procedure, a verse. | reveal: line, with one step per answer line. | structural | Order is graded, and the answer uncovers one line at a time so recall is stepwise rather than all-or-nothing. A flip card cannot test order at all. |
| An answer that cannot be typed: a diagram, a circuit, a glyph, notation. | input: draw | structural | The learner sketches and self-grades against the reveal. Typing a diagram is not a check, it is a workaround. |
| A statement turning on one term, where the sentence around it is the cue. | Cloze: wrap the hidden span as \blank{...} in an answer line. | judgement | The context does the cueing, so recall is anchored where it will be used. If nothing in the sentence is a natural target, this is a plain card wearing a disguise. |
| A fact whose common confusions are known and nameable. | Authored multiple choice: a task list with one - [x] and two or more - [ ]. | judgement | The distractors are the teaching. Write them only if you can say what mistaken belief each one represents; if you cannot, the shape is doing nothing. |
| A term that must be recalled from either side: vocabulary, symbols, names. | direction: both | judgement | One authoring act, two cards. Reach for it when both directions are genuinely useful, not by default: it doubles the review load. |
| Anything else: a definition, an explanation, a cause, a comparison. | A plain card: ## front, answer lines below. | judgement | The default, and not a failure. Most material has no structure to exploit, and a plain card drilled well beats a clever shape drilled badly. |
Rules that hold whatever the shape:
- Every card needs at least one answer line.
- Most cards deserve a
>note: an example, a caveat, a mnemonic, or why it matters. Never a restatement of the answer. - One idea per card. Split compound facts rather than nesting them.
- No two cards may test the same fact. Vary what is asked; do not rephrase.
order: and sampling: are not shapes. They modify how an existing
deck is served and are documented with the other directives.
Cards
A card starts with ## at column 0, the front (the question). The lines
beneath it are the answer (the back), written plainly, and may span several
lines:
## What is the capital of France?
Paris.
## Name the three additive primary colors.
Red
Green
Blue
<!-- reveal: line -->
A physical newline inside an ordinary flip answer is a Markdown soft wrap: the
adult and mobile clients display it as a space, so you can wrap long source
lines for editing without creating visual gaps on the card. Add
<!-- reveal: line --> when the lines themselves are the learning sequence;
line reveal and line typing preserve them individually.
Inline formatting
Card fronts, answer lines, and note prose support **bold**, *italic* or
_italic_, and inline `code`. Inline code is verbatim, so
`**literal**` displays the asterisks instead of bold text.
Formatting has two projections: styled display and plain content. Grading uses
the plain content, so type Paris, not **Paris**. To keep emphasis markers
literal, escape them with backslashes such as 2\*3\*4, or wrap the text in
inline code such as `2*3*4`. Run alix doctor <deck> to find card text
that will render as emphasis.
LaTeX math
Use $...$ for a formula inside prose:
## Why does $a^2 + b^2 = c^2$ describe a right triangle?
It is the Pythagorean theorem.
Use $$...$$ for display math. The two delimiters and the formula must occupy
one whole logical line; a multi-line $$ block is not supported:
## What is the Gaussian integral?
$$\int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}$$
An opening dollar must touch the first formula character, and a closing dollar
must touch the last one. A closing inline $ cannot be followed by a digit, so
$5 and $10 stays literal currency. Escape a literal dollar as \$. Unmatched
dollars and $$...$$ surrounded by prose also stay literal. Dollars inside
inline code or fenced code are always verbatim.
Graphical clients render recognized math with the shared RaTeX renderer. If the
delimiters are valid but the LaTeX is malformed, the card still loads and shows
the source with a visible “math could not render” message. alix doctor <deck>
reports the card line, formula snippet, and renderer error.
Grading uses the content between the delimiters, so type x^2, not $x^2$.
Adding or removing math delimiters does not change a card token or stale its
cached augmentations. Generated output that otherwise parses as a deck is
checked before placement; malformed math cannot replace an existing deck.
A ## only starts a card at column 0 and outside a code fence. A ## that is
indented, or sits inside a fenced block, is ordinary answer content, so a Markdown
heading in a sample, a shell comment, or a Dockerfile line needs no escaping:
## What does this script print?
```bash
echo hi
## this line is just part of the answer, inside the fence
```
Multi-line fronts
When the question itself spans more than one line, a --- divider marks where it
ends and the answer begins:
## What does `lo` control in this signature?
def bisect_right(a, x, lo=0, hi=None)
---
The lowest index the search considers; entries below `lo` are ignored.
Here the front is two lines (the prose question plus the code it’s asking about),
and without the --- alix couldn’t tell where the question stops and the answer
starts. (A one-line question needs no divider: the answer just follows on the next
line, as in the cards above.)
Multiple-choice (checkbox) cards
Write the answer as a GitHub task list to supply your own Recognize options:
## Which number is prime?
- [ ] 4
- [x] 5
- [ ] 6
The single [x] item is the correct answer. Alix shows only that answer at
Recall and expects it at Reconstruct; the [ ] items are distractors shown with
it at Recognize. Every option is used, so the card needs no AI choices
augmentation and is skipped by that augment target. The Rust core shuffles the
options: their order stays fixed while one question is on screen, then receives
a fresh seed when the card reappears or a new study session starts. As with any
shuffle, two appearances can still produce the same order by chance.
A checkbox card needs exactly one checked item and at least one unchecked item.
Use -, *, or + bullets, with [x] or [X] for the answer. Put a literal
task list inside a fenced code block to keep it a plain card answer. Task lists
inside notes or a card’s front before the --- divider render as static
checkboxes rather than interactive choices.
Card tables
Flat material at scale (a vocabulary list, countries and capitals, dates) can
be one Markdown pipe table instead of a ## block per fact. Each row is a
card: first column front, second column back, optional third column note. The
header row is shown as the card’s context, never tested:
| word | meaning | note |
|-----------|-----------|----------------------|
| purported | angeblich | often in legal prose |
| feasible | machbar | |
The table must start at column 0 with a header row and a delimiter row
(alignment colons are fine), exactly like GitHub renders it; every line starts
and ends with |. Inside cells, inline formatting and math work as in any
card text. A table inside a fenced code block stays literal text.
Give a table a title by putting a ## heading directly above it, with
nothing between them but blank lines:
## Verbs of arguing
| English | German | usage |
|-----------|-------------|----------------------|
| to refute | widerlegen | eine These widerlegen |
The heading names the group and is shown as the card’s first context line, above the column labels; it is a title only when its body is empty, so a heading with an answer under it is an ordinary card that happens to be followed by a table. Directives written on the title line (including the table’s own ID) belong to the table.
At Recognize, a table card’s wrong options are drawn from its own column: the
other rows’ answers are the distractors, so a table needs no AI choices
augmentation and no authored options (though both take precedence if present).
A row only gets a pick when its column offers at least three other distinct
values; smaller tables stay reviewable at the other depths.
That column sampling is on by default. Turn it off for a table whose rows are
not interchangeable (a mixed list, a table of one-off facts) with
<!-- sampling: off --> among its directive comments, or set sampling: off
in the frontmatter to make that the deck’s default and re-enable single tables
with <!-- sampling: on -->. A table with sampling off and no other option
source is simply not offered at Recognize, and alix doctor reports a
sampling: key that can affect nothing.
Identity works like card IDs, per row. alix deck init (or opening the deck
for review) mints one container ID line after the table, and a short stamp at
the end of each row, after the closing pipe:
| purported | angeblich | often in legal prose | <!-- r:4k2x9w -->
Renderers drop cells beyond the header count, so the stamps stay invisible in a rendered view while keeping the source columns aligned. Both kinds of marker are machine-maintained, never hand-authored, and they travel with their row, so sorting, inserting, and editing rows preserves review history.
Directive comments between the table and its ID line (direction, reveal,
input, sampling) apply to every row. direction: both doubles each row
into a reversed card, which samples its options from the front column.
The format is deliberately narrow: two or three columns only, no cloze
blanks or images inside cells, and nothing but directive comments between a
table and the next card. Anything outside that shape is a parse error rather
than a guess. And a table earns its place at dozens of rows; under roughly
ten cards, plain ## cards read better and can carry everything a card can.
Notes
A line beginning with > is a note: shown after you answer, never part of
what’s tested. Consecutive > lines join into one note:
## Why does TCP open with a three-way handshake?
To agree on initial sequence numbers in both directions.
> SYN, SYN-ACK, ACK: each side learns the other's starting sequence.
Keep the answer to the thing you want to recall, and put the why, the example, or the mnemonic in a note.
Title, and deck-wide settings
A deck’s title is a single-# heading. Deck-wide settings and its
machine-maintained deck ID live in
frontmatter: a ----fenced YAML block at the very top of the file, above the
title.
---
format-version: 1
id: "deck-9w2c7x4k1m8q3z5t0v6b2n4d8f"
authors: [Alex, "Claude (Opus 5)"]
license: CC-BY-4.0
tags: [french, vocabulary]
created-at: 2026-07-31
reveal: line
order: sequential
---
# French vocabulary, chapter 4
format-version is the version of the deck format, not of the deck itself.
alix deck init writes it above id, it stays 1, and alix refuses a deck
declaring any other number rather than guessing at a format it does not know.
It is written first because it says how to read everything below it, but alix
accepts it anywhere in the block.
authors and tags take one value or a list; license and created-at are
single strings, by convention an SPDX identifier and an ISO 8601 date. Put both
people and any AI that helped in authors. These four are yours to fill in and
alix never changes them.
Apart from id and format-version, frontmatter carries only what differs from the defaults,
and a command-line flag always overrides it. Anything else you write before the
first card is just prose (context, a reading order, whatever you like), so a
deck can also read as a normal document. The full set of frontmatter and
per-card keys gets its own Directives reference chapter.
Escaping
Because ##, >, ---, and the fence and cloze markers are structural, an answer
line that must start with one literally is escaped with a leading backslash:
\##, \>, \---. The backslash is consumed; the line displays without it.
## How do you write a second-level heading in Markdown?
\## Section title
Why editing a deck is safe
Every initialized deck and card carries a stable identity. alix deck init
writes the deck ID as id: deck-<token> in frontmatter and each card ID as a
<!-- id: card-<token> --> line. If you later add a card to that initialized deck,
opening review or augmentation assigns the missing card ID. Those tokens, not
the text, are what your review history hangs on. You don’t type or manage them;
alix adds and maintains them after you explicitly initialize the file.
Because identity is the token and not the words, you can edit anything (reword
the question, fix a typo in the answer, rewrite a note, reorder cards) and its
history follows. The only thing that starts a card’s
history over is deliberately replacing it. (alix doctor warns if an id line goes
missing, for instance if an external tool stripped the HTML comments.)
So a deck is safe to refactor freely: your progress rides on the token, not on the words.