sprig and prose docs classic docs
Overview

sprig and prose

In ClockworkVillage, a fox can get into the chicken coop — but only after the coop has been damaged, and only before it has been repaired.

That rule is true about the village. It shapes how the whole thing plays. And there is nowhere good to put it. It is not a column in a table or a field on a type. If it is written down at all, it is a condition a few functions deep, beside the code that happens to enforce it.

Every system has a rule like that one. They tend to be the first thing a new person needs and the last thing anyone writes down.

prose is a small language for writing them down. sprig is the toolchain that makes them visible, and then lets real code report back on whether they are still true.

Describe a world

universe ClockworkVillage {
  describe {
    A quiet village where the focus is observation and small moments.
  }

  dimension place    { }
  dimension predator { }

  place ChickenCoop {
    describe {
      Chicken coops are where chickens are kept. Normally they are very
      secure and made of wood.
    }
  }

  predator Fox {
    describe {
      Foxes are small orange predators. They are devious and crafty and
      will find creative ways to get into chicken coops.
    }
  }

  dimension event {
    relationship canOccurWhere and canBeWhere   { }
    relationship canOccurWith  and canBeWith    { }
    relationship canOccurAfter and canOccurBefore { }
  }

  event ChickenCoopDamaged {
    describe {
      A coop can be damaged if it is not properly maintained.
    }

    relationships {
      canOccurWhere { ChickenCoop }
    }
  }

  event ChickenCoopRepaired {
    relationships {
      canOccurAfter { ChickenCoopDamaged }
    }
  }

  event ChickenRaid {
    describe {
      A fox gets into a chicken coop and eats the chickens inside.
    }

    relationships {
      canOccurAfter  { ChickenCoopDamaged }
      canOccurBefore { ChickenCoopRepaired }
      canOccurWhere  { ChickenCoop }
      canOccurWith   { Fox }
    }
  }
}

The raid now reads as a sentence: it happens after damage, before repair, in the coop, with a fox.

Nothing here executes. Nothing is enforced. place, predator, and event are dimensions — kinds — so the village is grouped by what things are rather than by what any program does with them. You can write all of this before you are sure of it, and change it when you learn more.

Make it visible

sprig compile

Compiling writes .sprig/manifest.json: a normalized graph where every concept has a stable identity and every relationship is resolved. It is plain JSON, so other tools can read it.

sprig ui

The field guide is a local reader for that graph. Open ChickenRaid and its four conditions are listed; follow canOccurAfter and you land on ChickenCoopDamaged. Edit a .prose file, save, and the page updates.

The field guide never changes the universe. It only makes it legible.

Try it

npm install -g @sprig-and-prose/sprig
sprig init ClockworkVillage
sprig ui

Two ways on

Everything so far is the same for every universe. What comes next depends on whether yours describes software.

Keep describing. The language, one construct at a time, with the village growing as it goes. ClockworkVillage has no code behind it and never needs any — plenty of universes are like that, and describing one is the thing itself rather than preparation for something else.

Point it at a system. If your universe does describe software, the software can answer. Ordinary comments in source name concepts from the universe, and sprig gathers them into receipts: where each name actually lives, and what it means when one stops matching anything.