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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Cratis.Screenplay" Version="1.6.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Cratis.Screenplay" Version="1.6.4" />
                    
Directory.Packages.props
<PackageReference Include="Cratis.Screenplay" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Cratis.Screenplay --version 1.6.4
                    
#r "nuget: Cratis.Screenplay, 1.6.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Cratis.Screenplay@1.6.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Cratis.Screenplay&version=1.6.4
                    
Install as a Cake Addin
#tool nuget:?package=Cratis.Screenplay&version=1.6.4
                    
Install as a Cake Tool

<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.

Discord VS Code Marketplace Publish License

</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 .play file 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 .play extension 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 file reference) when a scene needs custom staging. A command, for instance, swaps its declarative produces for an imperative handler. 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)

βœ… 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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