This file provides stable reference documentation for Claude Code when working with the riddl-models repository.
Important: Read ../CLAUDE.md for general protocols and instructions on working on Ossum Inc. project which are described in that file; this is one of them.
riddl-models is the canonical repository for example RIDDL models and reusable patterns. It serves as a library for AI-assisted RIDDL development, providing:
- Reusable Patterns - DDD/Reactive patterns (event-sourced entity, saga, projector, etc.)
- Domain Examples - Industry-specific RIDDL models organized by sector
- Best Practices - Idioms, conventions, and anti-patterns documentation
- Metadata - Structured metadata for model discovery and categorization
riddl-models/
├── patterns/ # Reusable DDD/Reactive Patterns
│ ├── entity/ # Aggregate patterns
│ ├── saga/ # Distributed transaction patterns
│ ├── projection/ # CQRS read models
│ ├── gateway/ # API and integration patterns
│ └── workflow/ # Process orchestration patterns
│
├── technology/ # Technology & SaaS
├── investment/ # Investment & Venture Capital
├── finance/ # Financial Services
├── insurance/ # Insurance
├── commerce/ # Retail & Commerce
├── hospitality/ # Accommodation & Food Service
├── entertainment/ # Arts, Entertainment & Media
├── marketing/ # Marketing & Advertising
├── healthcare/ # Healthcare & Life Sciences
├── manufacturing/ # Manufacturing & Production
├── construction/ # Construction & Real Estate
├── engineering/ # Engineering Services
├── transportation/ # Transportation (all modes)
├── logistics/ # Supply Chain & Warehousing
├── natural-resources/ # Natural Resources & Mining
├── utilities/ # Utilities & Energy
├── telecommunications/ # Telecommunications
├── government/ # Government & Public Sector
├── education/ # Education & Training
├── professional-services/ # Professional Services
│
├── schemas/ # JSON Schemas for validation
│ └── model-metadata.schema.json
│
├── CLAUDE.md # This file
├── NOTEBOOK.md # Development journal
└── README.md # Project documentation
The repository organizes models into 18 top-level sectors covering enterprise, SMB, and startup needs. Each sector has 2-5 subsectors, with individual models at level 3.
| Sector | Description | Key Subsectors |
|---|---|---|
technology |
Technology & SaaS | saas, devops, platform |
investment |
Investment & Venture Capital | venture-capital, private-equity, asset-management |
finance |
Financial Services | banking, payments, trading |
insurance |
Insurance | property-casualty, life-annuity, reinsurance |
commerce |
Retail & Commerce | e-commerce, retail, marketplace, wholesale |
hospitality |
Accommodation & Food Service | lodging, food-service, travel, events |
entertainment |
Arts, Entertainment & Media | media, gaming, live-events, sports |
marketing |
Marketing & Advertising | campaigns, advertising, analytics |
healthcare |
Healthcare & Life Sciences | hospitals, clinical, pharmacy, payer, life-sciences |
manufacturing |
Manufacturing & Production | discrete, process, machining, textiles, maintenance |
construction |
Construction & Real Estate | project-management, field-operations, real-estate |
engineering |
Engineering Services | project-engineering, product-development, consulting |
transportation |
Transportation (all modes) | freight, passenger, fleet, maritime |
logistics |
Supply Chain & Warehousing | warehousing, fulfillment, supply-chain |
natural-resources |
Natural Resources & Mining | mining, oil-gas, forestry, agriculture |
utilities |
Utilities & Energy | electric, gas, water, metering |
telecommunications |
Telecommunications | network, billing, customer |
government |
Government & Public Sector | citizen-services, regulatory, public-safety |
education |
Education & Training | academic, corporate-training, certification |
professional-services |
Professional Services | legal, accounting, hr-services |
Each model directory contains:
commerce/e-commerce/shopping-cart/
├── shopping-cart.conf # riddlc configuration
├── shopping-cart.riddl # The RIDDL model (domain entry point)
├── shopping-cart.bast # Binary AST (generated by sbt bastify)
├── types.riddl # Shared types
├── Cart.riddl # Entity definitions
├── CartContext.riddl # Main bounded context
├── external-contexts.riddl # External systems
├── shopping-cart.metadata.json # Model metadata (optional)
└── README.md # Human-readable explanation
Every model README includes a ## NAICS Code section near the top
with the closest NAICS industry classification code. The repository
uses BLS sector/subsector decomposition which doesn't map perfectly
to NAICS, so codes are approximate best-fit matches.
Model metadata files follow this structure:
{
"name": "Shopping Cart",
"description": "E-commerce shopping cart with add/remove/checkout",
"author": "Ossum Inc.",
"version": "1.0.0",
"tags": ["e-commerce", "cart", "checkout", "beginner"],
"difficulty": "beginner",
"riddl_version": "1.0.0",
"simulation_ready": true,
"related_patterns": ["entity/event-sourced", "saga/checkout"],
"complexity": "standard"
}Models can include a complexity field to indicate suitability:
| Tier | Description |
|---|---|
starter |
Simplified version for SMB (fewer entities, basic workflows) |
standard |
Full-featured for mid-market |
enterprise |
Advanced features, integrations, compliance |
The patterns/ directory contains reusable RIDDL pattern templates:
| Pattern | Directory | Description |
|---|---|---|
| Event-Sourced Entity | entity/event-sourced/ |
Entity persisting changes as events |
| Aggregate Root | entity/aggregate-root/ |
Entity managing child entities |
| Saga | saga/distributed-transaction/ |
Multi-step process with compensation |
| Repository | entity/repository/ |
Persistence and query capabilities |
| Projector | projection/read-model/ |
CQRS read-optimized views |
| Process Manager | workflow/process-manager/ |
Event-driven workflow coordination |
Each pattern includes:
template.riddl- Parameterized RIDDL template with{Placeholders}README.md- When to use, how to customizeexample.riddl- Concrete example instantiation
- RIDDL files:
kebab-case.riddl(e.g.,shopping-cart.riddl) - Metadata files: Match RIDDL filename with
.metadata.jsonsuffix - README files: Always
README.md(uppercase)
Follow these idioms when writing RIDDL (canonical form as of riddlc 1.23.0 prettify):
- Use
iskeyword for readability:entity Order is { } - Use
???for placeholders - empty bodies not allowed - Commands use imperative -
CreateOrder,ShipProduct - Events use past tense -
OrderCreated,ProductShipped - Always add
brieflydescriptions - Use explicit states - avoid flag-based state machines
- Type IDs as
{Name}Id-type OrderId is Id(Order) - Colon field syntax -
fieldName: Type(notfieldName is Type) - Postfix optional -
Type?(notoptional Type) - Markdown descriptions -
described as { |text }(notdescribed by "text") - No commas between aggregate fields
Description Syntax — canonical form uses described as with
markdown pipe syntax:
described as {
|Markdown text here.
|Second line of description.
}
CRITICAL: The | character consumes everything to end of
line including any } on the same line. The } must be on its
own line.
Naming Collision Avoidance:
- Enum values and state names in the same scope cannot match
- Use suffixes like
StateorStatusto disambiguate - Example: enum
DeliveryFailedvs stateDeliveryFailedState
Field Overloading (riddlc 1.8.0+):
- The same field name cannot appear with different types across a
context scope (including
Typevsoptional Type,many Typevsmany optional Type) - Fix by renaming with semantic prefixes:
status→orderStatus,paymentStatus, etc.amount→paymentAmount,refundAmount, etc.reason→cancellationReason,holdReason, etc.- Query filter fields →
filterStatus,filterEndDate, etc. - Optional variants in state →
updatedCompletedAt,currentBooking,assignedDriver, etc.
Repository Handlers:
- Repositories handle commands, not events
- Use
on command Entity.CreateEntity, NOTon event - Event-to-command name mapping:
EntityCreated→CreateEntity,EntityUpdated→UpdateEntity, etc.
"to" Adaptor Handlers:
- Must reference the target context's command types
- Use
on command TargetContext.CommandName, NOT source events
Projector Handlers:
- Projectors handle events to build read models
- Do NOT use
on commandoron queryin projector handlers
External Contexts:
- Mark external bounded contexts with
option is externalin thewithblock - NOT inside the context body
context PaymentGateway is {
// events and types only, no handlers
} with {
option is external
briefly "External payment processing system"
}
Messaging:
- Use
tell event X to entity Yfor entity-to-entity messaging - Use
tell command X to entity Yfor command dispatch send to outletis only for streamlet flows
State Transitions:
- Use
morph entity X to state Y with command Zfor state changes - The
with commandprovides the data source for the new state
- Sectors:
kebab-case(e.g.,natural-resources) - Subsectors:
kebab-case(e.g.,oil-gas) - Models:
kebab-case(e.g.,well-management)
Validation is run explicitly via sbt riddlcValidate (alias
sbt v). The sbt-riddl plugin downloads riddlc on first use.
Validate-on-compile is disabled in build.sbt to keep sbt compile
fast; run validation as a separate step. The MCP server can still
be used for querying grammar, idioms, and patterns.
The build uses the sbt-riddl plugin (com.ossuminc:sbt-riddl)
which provides all riddlc integration. Configuration in build.sbt:
riddlcSourceDir— Set tobaseDirectory.value(repo root) so the plugin scans all sector directories for.conffilesriddlcConfExclusions— Excludespatterns/from scanningriddlc(..., validateOnCompile = false)— validation is not wired intosbt compile; invokeriddlcValidateexplicitly
sbt riddlcValidate # Validate all models
sbt v # Short alias
sbt riddlcBastify # Generate .bast for all models
sbt b # Short alias
sbt riddlcPrettify # Reformat all models with prettify
sbt r # Short alias
sbt riddlcParse # Parse-only (no validation)
sbt riddlcInfo # Show riddlc build infoThe riddlc binary is cached in ~/.cache/riddlc/ (shared across
projects). To update riddlc, change the sbt-riddl plugin version
in project/plugins.sbt and re-run — the new version downloads
automatically.
Each model has a .bast (Binary AST) file alongside its .riddl
source. These are generated by sbt bastify and committed to the
repository. BAST files enable fast loading without re-parsing and
are used by tools like riddl-mcp-server and synapify.
To regenerate all .bast files after model changes:
sbt bastify # Regenerates all 187 .bast files (~4s)Round-trip verified: All 187 models pass full round-trip verification with riddlc 1.10.2 (unbastify, binary comparison, and prettify+flatten source diff).
A reusable script verifies .bast round-trip fidelity. Run after any riddlc upgrade or .bast format change:
./scripts/verify-bast-roundtrip.sh # all 187 models
./scripts/verify-bast-roundtrip.sh 10 # first 10 (spot check)Three checks per model:
- Unbastify — .bast → .riddl (catches deserialization bugs)
- Binary round-trip — prettify+flatten original to single file, bastify that and the unbastified .riddl from the same path, compare .bast byte-for-byte
- Source round-trip — prettify+flatten both original and unbastified .riddl, diff text AND compare bastified output (catches semantic loss)
Each model directory has a .conf file:
validate {
input-file = "model-name.riddl"
}# From the model directory
riddlc from model-name.conf validateriddlc is available via:
- sbt (automatic):
~/.cache/riddlc/{version}/bin/riddlc(downloaded by sbt-riddl plugin) - Homebrew:
brew install ossuminc/tap/riddlc - Staged build:
../riddl/riddlc/jvm/target/universal/stage/bin/riddlc
Current version: 1.23.0 (set via sbt-riddl plugin version
in project/plugins.sbt).
Break models into separate files using include:
model-directory/
├── model-name.conf # riddlc configuration
├── model-name.riddl # Domain entry point with includes
├── types.riddl # Shared types
├── Entity1.riddl # Entity definitions
├── Entity2.riddl
├── Context.riddl # Main bounded context
├── external-contexts.riddl # External systems (option is external)
└── README.md
The main .riddl file uses include "filename.riddl" to compose
the model.
- Choose the appropriate sector and subsector
- Create a directory:
sector/subsector/model-name/ - Create the configuration file:
model-name.conf - Add the main RIDDL file:
model-name.riddl - Break into separate files using
includefor types, entities, contexts - Add README.md explaining the model's purpose
- Validate with
riddlc from model-name.conf validate - Optionally add metadata:
model-name.metadata.json
- Has
model-name.conffor riddlc validation - All definitions have
brieflydescriptions - All definitions have
described byfor longer descriptions - Commands use imperative naming
- Events use past tense naming
- States are explicit (not flag-based)
- No naming collisions between enum values and state names
- Handlers have implementation or
??? - Types are domain-specific (not generic
String) - Sagas have compensation logic
- Validates with
riddlc(0 errors)
Models in this repository are designed to work with the riddl-mcp-server tools:
validate-text/validate-url- Validate model syntax and semanticsvalidate-partial- Validate incomplete models during developmentcheck-completeness- Find missing elementscheck-simulability- Verify model can run in riddlsimexpand-pattern- Generate code from patterns in this repo
- riddl - RIDDL language compiler and tooling
- riddl-mcp-server - MCP server using these models as resources
- riddlsim - Simulation engine for RIDDL models
- synapify - Visual editor for RIDDL
| Component | Version | Notes |
|---|---|---|
| riddlc | 1.23.0 | Driven by sbt-riddl plugin version |
| sbt-riddl | 1.23.0 | Plugin in project/plugins.sbt |
| sbt-ossuminc | 1.4.0 | Build plugin |
Models are validated against the RIDDL grammar using riddlc via
sbt riddlcValidate (alias sbt v).