Cratis.Screenplay
1.6.4
Prefix Reserved
dotnet add package Cratis.Screenplay --version 1.6.4
NuGet\Install-Package Cratis.Screenplay -Version 1.6.4
<PackageReference Include="Cratis.Screenplay" Version="1.6.4" />
<PackageVersion Include="Cratis.Screenplay" Version="1.6.4" />
<PackageReference Include="Cratis.Screenplay" />
paket add Cratis.Screenplay --version 1.6.4
#r "nuget: Cratis.Screenplay, 1.6.4"
#:package Cratis.Screenplay@1.6.4
#addin nuget:?package=Cratis.Screenplay&version=1.6.4
#tool nuget:?package=Cratis.Screenplay&version=1.6.4
<div align="center">
π¬ Screenplay
The modeling language for the Cratis platform β one declarative .play file describes a whole system, and the cast performs it live.
</div>
A screenplay is the one document a production works from β it names the cast, sets every scene, and writes
every line, so the director, the actors, and the crew all put on the same show. That's the whole idea. A
Screenplay .play file is the script for an entire system: its concepts, events, commands, queries,
projections, screens, automations, and the rules that govern them β top to bottom, in one place.
Hand that script to Stage and it puts on the performance β a live, running application. Hand it to Studio and it storyboards the same script β visualizing and generating from it. One script; no meaning lost between the model on the whiteboard and the app in production.
π¬ Why "Screenplay"?
Four reasons, and they all line up:
- It's the script for the whole show. A screenplay holds an entire production in one document β cast,
scenes, stage directions, dialogue. A
.playfile holds an entire system the same way: nothing about the behavior hides in another layer or another file. - It's written to be performed, not just read. A screenplay isn't the finished film β it's the thing you perform. Stage reads it and runs the application; Studio reads it and draws it. The script is executable, not merely descriptive.
- The
.playextension wears it on its sleeve. A screenplay is a play; the file is a.play. - The Cratis storytelling family. Cratis names its products after telling a story: Chronicle records what happened, Arc shapes the plot, Narrator, Lens, Studio, Prompter⦠Screenplay is the script the whole cast performs from. It joins the ensemble.
π What a scene looks like
A .play file reads top to bottom like a script β indentation-based, no braces, each construct owning
everything beneath it:
module Invoicing
feature InvoiceManagement
slice StateChange RegisterInvoice
command RegisterInvoice
invoiceId InvoiceId
invoiceNumber InvoiceNumber
dueDate Date
authorize CanManageInvoice
validate
invoiceNumber matches "^INV-[0-9]{6}$" message "Must look like INV-000000"
dueDate > today message "Due date must be in the future"
produces InvoiceRegistered
invoiceId = invoiceId
invoiceNumber = invoiceNumber
dueDate = dueDate
registeredAt = $context.occurred
event InvoiceRegistered
invoiceId InvoiceId
invoiceNumber InvoiceNumber
dueDate Date
registeredAt DateTime
slice StateView InvoiceList
query ListInvoices => InvoiceListReadModel[]
projection InvoiceList => InvoiceListReadModel
from InvoiceRegistered key invoiceId
invoiceNumber = invoiceNumber
status = "draft"
screen InvoiceList
data InvoiceListReadModel[] via query ListInvoices
action RegisterInvoice
One slice, backend to screen: who's allowed in, what has to be true, the fact it records, and the list that shows it β all in a single read. The second slice never touches a database or a controller; it declares how events project into a read model and how that read model appears on screen.
π The whole production in one file
A .play describes an entire system as a set of typed slices, aligned with Event Modeling's vocabulary.
Pick the slice type by what the slice does:
| Slice type | The scene it plays | Constructs |
|---|---|---|
StateChange |
something changes the system | command β event via produces or an imperative handler, with validate, authorize, constraint |
StateView |
something reads the system | query + projection + screen |
Automation |
something reacts to what happened | reactor |
Translate |
something turns outside data into events | capture |
Three ideas keep the script both readable and complete:
- Declarative first, with an escape hatch. Every construct has a clean declarative form β but any of them
can drop into inline C#, TypeScript, React, or HTML (or a
filereference) when a scene needs custom staging. A command, for instance, swaps its declarativeproducesfor an imperativehandler. Common cases stay terse; the hard 10% is never out of reach. - Concepts carry compliance. Value types declare their attributes once β
@pii,@sensitiveβ and every usage inherits them, so GDPR and sensitivity travel with the data instead of being re-litigated per field. - Pluggable sub-languages. Projections are written in the Projection Declaration Language (PDL) and captures in the Change Data Capture Language (CDL) β embedded sub-grammars parsed inside their constructs. They're the reference implementations of a registry you can extend with sub-languages of your own.
The full construct reference and the complete EBNF grammar live in
Documentation/screenplay.
π₯ One script, two performances
The .play file is the single source of truth. The tooling in this repo is the writing room β it makes the
script a joy to author β and downstream, Stage and Studio each read the very same file:
flowchart LR
Author["βοΈ you<br/>write the script"] -->|".play"| Play[["π Screenplay<br/>one whole system"]]
Tools["π§° language service<br/>VS Code Β· editor Β· Monaco"] -.->|"highlight Β· IntelliSense<br/>hover Β· diagnostics"| Play
Play -->|"interpreted by"| Stage["π¬ Stage"]
Play -->|"read by"| Studio["π¨ Studio"]
Stage --> App["βΆοΈ a live application"]
Studio --> Viz["πΌοΈ diagrams + generated code"]
Because the model and the app are the same artifact, there's no drift to reconcile: change the script, and the performance changes with it.
π§° What's in this repo
Screenplay lives here β the language definition, its documentation, and the tools that make writing .play
files pleasant:
| Piece | What it is | Where |
|---|---|---|
| Language & grammar | The language reference for every construct and the full EBNF grammar | Documentation/screenplay |
Cratis.Screenplay |
The .NET compiler β parsing, the shared syntax tree, visitor contracts, diagnostics, and **/*.play file discovery |
Source/DotNET/Screenplay |
Cratis.Screenplay.Tool |
The screenplay CLI (a dotnet tool) β verifies every .play file in a directory tree |
Source/DotNET/Tool |
@cratis/screenplay-language |
Monaco language service β highlighting (incl. embedded C#/TS/React/HTML and PDL/CDL), IntelliSense, hover, diagnostics | Source/Screenplay/Monaco/screenplay-language |
screenplay-editor |
A standalone editor host for writing .play files right in the browser |
Source/Screenplay/Monaco/screenplay-editor |
screenplay (VS Code extension) |
The same language support in VS Code β .play files even get the Cratis icon |
Source/Screenplay/VSCodeExtension |
π οΈ Compile and verify .play files
The compiler ships on NuGet. Install the CLI as a global dotnet tool and run it from the root of any
project β it finds every file matching **/*.play, compiles them, and prints any problems compiler-style
with the offending line and a caret:
dotnet tool install -g Cratis.Screenplay.Tool
screenplay # or: screenplay path/to/screenplays
Embedding the compiler in your own tooling is one package away β see Compiler and CLI:
dotnet add package Cratis.Screenplay
π Quick start
yarn install
yarn build
yarn dev # opens the standalone editor on http://localhost:9200
Prefer to write in your own editor? Press F5 in VS Code β it builds the language service and the extension
and launches an Extension Development Host with full .play support, ready to try on a sample from
screenplay-editor/samples.
πΊοΈ Start here (for contributors)
Documentation/screenplayβ the language overview, design principles, and top-level structure. Start here to learn the language.Documentation/screenplay/slices.mdβ modules, features, and the four slice types.Documentation/screenplay/grammar.mdβ the complete EBNF grammar.Documentation/screenplay/sub-languages.mdβ how PDL, CDL, and your own sub-languages plug in.Source/Screenplay/Monaco/screenplay-language/README.mdβ embedding the language service in a Monaco editor.
β Quality gates
yarn build # every workspace builds clean
yarn lint # zero lint errors
yarn compile # zero TypeScript errors
dotnet build Screenplay.slnx --configuration Release # zero errors, zero warnings
dotnet test Screenplay.slnx # all specs pass
<div align="center">
Part of the Cratis platform Β· Licensed under the MIT license
</div>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.FileSystemGlobbing (>= 10.0.9)
-
net8.0
- Microsoft.Extensions.FileSystemGlobbing (>= 10.0.9)
-
net9.0
- Microsoft.Extensions.FileSystemGlobbing (>= 10.0.9)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Cratis.Screenplay:
| Package | Downloads |
|---|---|
|
Cratis.Stage.Contracts
The Cratis Stage contract β the event model intermediate format, specification run results and their serialization. |
|
|
Cratis.Arc.Screenplay
Generates a Cratis Screenplay .play file from the source of a Cratis Arc application |
|
|
Cratis.Prologue.Screenplay
The Cratis Prologue Screenplay generation β turns an extraction result into a Cratis Screenplay syntax tree and prints it as a .play document. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.6.4 | 689 | 7/29/2026 |
| 1.6.3 | 823 | 7/29/2026 |
| 1.6.2 | 55 | 7/29/2026 |
| 1.6.1 | 64 | 7/29/2026 |
| 1.6.0 | 71 | 7/29/2026 |
| 1.5.3 | 72 | 7/28/2026 |
| 1.5.2 | 3,337 | 7/23/2026 |
| 1.5.1 | 79 | 7/23/2026 |
| 1.5.0 | 93 | 7/23/2026 |
| 1.4.0 | 151 | 7/23/2026 |
| 1.3.0 | 86 | 7/23/2026 |
| 1.2.1 | 823 | 7/20/2026 |
| 1.2.0 | 90 | 7/20/2026 |
| 1.1.0 | 975 | 7/19/2026 |
| 1.0.3 | 284 | 7/19/2026 |
| 1.0.2 | 83 | 7/19/2026 |
| 1.0.1 | 96 | 7/19/2026 |
| 1.0.0 | 352 | 7/19/2026 |