Cairn Tutorial
A guided walk through the Examples directory. Each section maps every line of an example to the spec chapter behind it, so the tutorial doubles as an annotated reading list.
This tutorial assumes you have already read Purpose and Scope and Design Principles. If terminology trips you up, the glossary is the fastest jump table.
The reference compiler is not implemented yet. The
cairn compileinvocations are aspirational but match the spec exactly, so reading them is still the right way to build intuition for the CLI surface.
1. A minimum useful build — cottage.crn
Section titled “1. A minimum useful build — cottage.crn”The “Hello, world!” of Cairn: a cottage with a door, a window, and a gable roof.
@cairn 2026.06@requires version>=1.20
theme medieval: slot floor -> @oak_planks slot wall -> @cobblestone slot roof -> @spruce_stairs slot glass -> @glass_pane window[class=small] -> frame=@spruce_wood
struct cottage size=9x7 floor mat_slot=floor walls class=outer mat_slot=wall height=4 door side=front at=center window class=small side=front offset=2 y=2 size=2x2 sym=true mat_slot=glass roof kind=gable mat_slot=roof overhang=1What to notice:
- Headers are optional but cheap.
@cairnrecords the Cairn language version the file was written against;@requiresis a hard capability floor on the Minecraft target. The Minecraft version itself is never written in the source — only in--targetat compile time. (syntax §5.3) themeseparates “what” from “where”. The structure carriesmat_slotinjection points; the theme binds them to canonical block tokens (@oak_planks, etc.). Switching themes never touches the structure. (materials-themes §7.1)- One line, one command, key=value. The leading keyword (
floor,walls,door…) is the only positional token; everything else iskey=value. This is deliberate: it stabilizes LLM generation by giving every parameter an attention anchor. (principles P3, syntax §5.1) - Selectors are semantic, not coordinates.
side=front,offset=2,y=2,at=centerrefer to wall position and offsets along the wall. No absolute coordinates appear in the author surface. (principles P4, syntax §5.4) - Phase order, not source order. The
windowis written after theroofbut is still cut as an opening in the wall — the compiler sorts commands into a fixed phase pipeline before evaluating them. (compilation §4.1, principles P2) - Blockstate is derived by default. No one writes
facing=southfor the door, thenorth=tallfor the wall, or theconnectedstate for the glass pane. The compiler derives them from position and neighbors. (blockstate §6.1)
Compile (aspirational; the reference compiler is still a skeleton):
cairn compile examples/cottage.crn --edition java --target 1.21.4cairn compile examples/cottage.crn --edition bedrock --target 1.21.402. Themes, abstract tokens, override-promotion — themed-tower.crn
Section titled “2. Themes, abstract tokens, override-promotion — themed-tower.crn”A two-floor stone keep introduces three new ideas: abstract material tokens, levels, and override-promotion.
theme keep_dark: slot floor -> @floor.wood.broadleaf # abstract token slot wall -> @wall.stone.cobble slot trim -> @wood.dark slot roof -> @roof.dark_wood
struct keep size=11x9 ... level id=floor2 y=5 walls id=upper class=outer mat_slot=wall height=4 window class=arrow_slit side=front repeat=3 step=2 y=2 size=1x2 shape=slit stair id=eave kind=stairs mat_slot=roof side=front half=top facing=out shape=outer_leftWhat to notice:
- Two tiers of canonical token.
(materials-themes §7.2)
@oak_planksis a canonical block token: a meaning. Silent downgrades are forbidden.@floor.wood.broadleafis an abstract material token: an aesthetic choice that theme policy MAY downgrade (oak ↔ birch) depending on the target.
levelgives you a per-floor localy=0, so the second floor’s window stays aty=2from its own floor rather than from the world floor. (open-issues §15.2 reserves the right to refine this surface, but the present syntax is stable enough to teach.)- Override-promotion. The
stair id=eaveline writeshalf=top facing=out shape=outer_leftexplicitly — those values are now intent, not derived. The blockstate model is “derive by default; any blockstate that can be intent is overridable.” Read blockstate §6.1 for the full list of cases that must remain overridable. shape=slitwindow primitive. Every primitive carriesanchor, declared bbox, and host face in the IR, so an arrow slit with a non-rectangular shape still composes cleanly with the wall blockstate around it. (entities §8.2)
3. Logical redstone — redstone-door.crn
Section titled “3. Logical redstone — redstone-door.crn”The redstone surface is the most spec-leaning part of Cairn: instead of placing dust and repeaters, you declare a signal graph and the compiler synthesizes, places, and routes the circuit.
pressure_plate id=plate at=front.outside offset=0 y=0 -> sig.steppressure_plate id=inner at=inside.front offset=0 y=0 -> sig.exit
logic sig.open = sig.step or sig.exitdoor[id=front] opened_by=sig.open
circuit region=floor void=2
assert truth(sig.step, sig.exit -> sig.open) { 00->0; 01->1; 10->1; 11->1 }assert always(sig.step -> eventually sig.open within 2)What to notice:
- The signal graph is the IR.
sig.*names a dataflow node. Sensors emit signals, actuators consume them, andlogicwrites the dependencies between them. (redstone §14.2–14.3) - No tick arithmetic. The logic expression contains no time. The
within 2in the assertion is the only place a number-as-ticks appears. Delay is determined for the first time in the Placement IR. (redstone §14.4, §14.8) circuit region=…reserves space for place-and-route. If routing congestion exceeds the reserved area, you get anE_ROUTE_CONGESTIONerror with a suggested fix; the compiler will never silently overflow.- Three assertion kinds.
truth(…)for combinational,latency(in → out) <= Nfor bounded delay, andalways(in -> eventually out within N)for bounded temporal. There is no full LTL by design — only what a per-tick simulator can decide cheaply. (redstone §14.7) - Edition difference is in the cell library, not the language. The same logic compiles to a
ComparatorANDcell on Java and aTorchANDcell on Bedrock; QC/BUD-dependent circuits are a compile error rather than a silent footgun. (redstone §14.6)
4. Multi-building — village.crn
Section titled “4. Multi-building — village.crn”Once one cottage works, you reuse it on a site. The site never asks you to compute absolute coordinates.
def cottage class=house size=9x7: ...
site hamlet: place id=home1 use=cottage theme=medieval at=origin place id=home2 use=cottage theme=medieval east_of=home1 gap=4 place id=home3 use=cottage theme=medieval north_of=home1 gap=5
connect home1.entry to home2.entry path=@gravel connect home1.entry to home3.entry path=@gravelWhat to notice:
defis a slot-bearing component. Same mechanism asthemeandsite, so the reference system never fractures across editing, theming, and multi-building. (components-editing-sites §9.1)- Topological placement.
east_of=home1 gap=4is a constraint; absolute coordinates are the compiler’s job. This sidesteps the worst class of LLM arithmetic errors. (principles P4, components-editing-sites §9.3) - Each struct exposes ports.
home1.entryrefers to the door member declared in thedef;connectjoins two ports through a path slot. - The 48³ structure-block limit dissolves. Villages and castles too large for a single
structure block are expressed as the composition of several
defs placed on asite.
Next steps
Section titled “Next steps”- Editing. See components-editing-sites §9.2 for the
patch DSL (
edit window[class=vent] set shape=arch). Edit diffs look only atintent_state, so deriving the resolved state again across an edit is safe. - Targeting. See versioning-editions §10.5 for
cairn info, which reports the registry-compatible range and the semantic-sensitive members for a file. - Import. See ecosystem-interop §12 for the
cairn importworkflow: faithful transliteration first, LLM-driven semantic lift second, voxel-diff to drive the loop. - Evaluation metrics. If you want to push back on the spec, the four metrics in evaluation §13.1 are the language Cairn argues in.