Syntax and Types
CRADLE scenarios use a block-oriented syntax for declaring scenario components, defining named elements and assigning properties.
This page describes the core syntax of the human-authored CRADLE language.
For a broader introduction to the language, see Language Overview.
Core syntax
A CRADLE file is composed of blocks.
Blocks can declare collections, define named components or assign properties to a scenario section.
The main forms are:
| Element | Form | Purpose |
|---|---|---|
| Simple block | identifier() > ... . | Defines a section without a name. |
| Named block | identifier("name") > ... . | Defines a named component. |
| Property | identifier(value) | Assigns one or more typed values to a block. |
| Reference | identifier() or identifier("name") | Refers to another section or named component. |
| Map | { key = value } | Defines structured named parameters. |
| Separator | , | Separates entries inside a block or map. |
| Terminator | . | Ends a block. |
| Line comment | // comment text | Adds a comment until the end of the line. |
| Block comment | /* comment text */ | Adds a comment that can span multiple lines. |
A typical block looks like:
metadata() >
name("ExampleEnvironment"),
eventType("sequence").
The block begins with:
metadata()
The > operator introduces the contents of the block.
Properties are separated with commas:
,
The final property is followed by a period:
.
Simple blocks
A simple block uses an identifier followed by empty parentheses:
identifier() >
...
For example:
networks() >
network("lan_0").
Here, networks() declares the networks used by the scenario.
Other common simple blocks include:
metadata()
instances()
networks()
events()
preEvent()
mainEvent()
postEvent()
Named blocks
Named blocks identify a specific component using a quoted name.
The general form is:
identifier("name") >
...
For example:
instance("Client") >
os("ubuntu", "20.04").
The name:
Client
identifies this particular instance.
The same pattern is used for other named components, including networks, objects and events.
For example:
network("lan_0") >
endpoint("Client", "DHCP").
object("InitializationScript") >
location("${uriRemote}/scripts/initialize.sh").
event("initialise_client") >
instance("Client").
Properties
Properties appear inside blocks.
The general form is:
property(value)
For example:
name("ExampleEnvironment")
Properties can accept more than one argument:
os("ubuntu", "20.04")
or:
endpoint("Client", "DHCP")
Arguments are comma-separated and enclosed in parentheses.
The properties accepted by a block depend on the type of component being defined.
Multiple properties
A block can contain multiple properties.
Separate them with commas:
instance("Client") >
os("ubuntu", "20.04"),
object("InitializationScript"),
description("Example client system").
Do not place a comma after the final property.
The block ends with a period:
.
Strings
CRADLE string values are written in double quotes.
For example:
name("HelloWorld")
description("Initialize the example client")
instance("Client")
subnet("192.168.10.0/24")
String values can contain spaces.
For example:
description("Initialize the example client")
Escaped characters are also supported by the grammar.
Identifiers
Identifiers are used for block and property names.
An identifier can contain:
- letters
- digits
- underscores
- hyphens
The first character must be:
- an ASCII letter
Examples of identifiers include:
metadata
instance
runObject
pauseBeforeRun
repositoryRemote
lan_0
Named CRADLE elements such as instances and networks are usually referenced through quoted string values rather than used directly as grammar identifiers.
Block terminators
Every CRADLE block ends with a period.
For example:
networks() >
network("lan_0").
The period terminates the entire block.
It does not terminate each individual property.
For example:
instance("Client") >
os("ubuntu", "20.04"),
object("InitializationScript"),
description("Example client system").
There is only one terminating period.
Separators
Entries inside a block are separated by commas.
For example:
instances() >
instance("Client"),
instance("Router").
The comma separates the first entry from the second.
The final entry is followed by the block terminator instead.
Comments
CRADLE supports line comments using:
//
For example:
// Define the systems participating in the scenario
instances() >
instance("Client"),
instance("Router").
A comment continues until the end of the line.
Comments do not form part of the scenario definition.
Declarations and definitions
A common CRADLE pattern is to declare named components first and define them separately.
For example:
instances() >
instance("Client"),
instance("Router").
This declares two instances.
Their definitions then appear in separate blocks:
instance("Client") >
os("ubuntu", "20.04").
instance("Router") >
os("ubuntu", "20.04"),
config("linux-router").
The same pattern applies to networks.
Declare:
networks() >
network("lan_0").
Then define:
network("lan_0") >
subnet("192.168.10.0/24"),
endpoint("Client", "DHCP"),
endpoint("Router", "192.168.10.1").
It also applies to events.
Declare an event within a phase:
mainEvent() >
event("initialize_client").
Then define it:
event("initialize_client") >
instance("Client"),
needRoot(false),
subject("bash", ""),
runObject("InitializationScript", "").
Named references
Names connect declarations and definitions across a CRADLE scenario.
For example:
instances() >
instance("Client").
references:
instance("Client") >
...
Similarly:
network("lan_0") >
endpoint("Client", "DHCP").
references the instance named:
Client
An event can reference both an instance and an object:
event("initialize_client") >
instance("Client"),
runObject("InitializationScript", "").
Those names should resolve to corresponding declarations elsewhere in the scenario.
CRADLE names are cross-references. Use consistent spelling and capitalization whenever an instance, network, object or event is referenced.
Top-level scenario structure
A CRADLE scenario commonly contains these principal sections:
| Section | Purpose |
|---|---|
metadata() | Defines scenario-level information and artifact repositories. |
instances() | Declares systems participating in the scenario. |
networks() | Declares networks used by the scenario. |
events() | Declares the event lifecycle phases. |
object("name") | Defines an external artifact referenced by the scenario. |
For example:
metadata() >
name("ExampleEnvironment"),
eventType("sequence"),
repositoryRemote("https://172.18.178.10:4443"),
object("InitializationScript").
instances() >
instance("Client"),
instance("Router").
networks() >
network("lan_0").
events() >
preEvent(),
mainEvent(),
postEvent().
The named components are then defined elsewhere in the same scenario.
Value conventions
CRADLE values use strings, booleans, integers, durations and structured maps.
The meaning of those strings depends on the property.
Examples include:
| Property | Example value |
|---|---|
| Scenario name | "HelloWorld" |
| Operating system | "ubuntu" |
| Version | "20.04" |
| Boolean value | false |
| Duration | 0 or 5s |
| Address | "DHCP" |
| CIDR range | "192.168.10.0/24" |
| Date-time | "2026-01-15T10:00:00+00:00" |
| Description | "Initialize the example client" |
For example:
event("initialize_client") >
needRoot(false),
pauseBeforeRun(0),
scheduleExecution("2026-01-15T10:00:00+00:00").
The grammar preserves the type represented by each argument.
The compiler determines how a particular property interprets its values.
Boolean values
Boolean properties use the unquoted literals:
true
false
For example:
needRoot(false)
Omit dependsOn() when an event has no explicit dependency.
Numeric values
Integer and duration values are written without quotes.
For example:
pauseBeforeRun(0)
pauseAfterRun(10)
The optional s suffix explicitly denotes seconds.
Date and time values
Scheduled event times use ISO 8601 date-time values.
For example:
scheduleExecution("2026-01-15T10:00:00+00:00")
Use a time-zone designator when specifying scheduled execution times.
Parameter maps
Some properties accept a structured map as an additional argument.
For example:
runObject("InitializationScript", "")
For role variables, use:
role("example.collection", "router", {
lan = "lan_0"
})
Separate multiple parameters with commas. Map values can be strings, booleans, integers or durations.
For example:
runObject("InitializationScript", {
mode = "safe",
retries = 3
})
The interpretation of each parameter depends on the property using the map.
Interpolation
CRADLE values can contain interpolated references.
For example:
object("InitializationScript") >
location("${uriRemote}/scripts/initialize.sh").
Here:
${uriRemote}
references the configured remote repository location.
Interpolation is covered in more detail in Objects and Interpolation.
Property validation
The CRADLE grammar defines the general structure of a valid source file.
This includes:
- blocks
- identifiers
- typed arguments
- separators
- terminators
- comments
The grammar alone does not determine whether every property name or property value is meaningful.
CradleXC performs additional processing when it interprets the source.
For example, the grammar can recognize the general structure:
exampleProperty("value")
without the grammar itself determining whether exampleProperty is valid for the surrounding CRADLE component.
Language, compiler and schema
CRADLE currently has several related sources that describe language behavior:
| Source | Responsibility |
|---|---|
| Grammar | Defines the valid structural form of CRADLE source. |
| CradleXC | Recognizes supported CRADLE properties and processes their values. |
| JSON Schema | Describes the expected structured representation and its properties. |
These sources are related but are not currently identical in every case.
For example, the compiler can recognize properties or defaults that are not represented in the current schema.
The detailed differences are documented separately rather than treated as core syntax rules.
Do not rely on the grammar alone to determine whether a scenario has the intended meaning. Validate the scenario with CradleXC against the CRADLE release you are using.
Validate the syntax
Use:
cxc validate -i <scenario.cradle>
For example:
cxc validate -i scenarios/HelloWorld.cradle
Validation checks the CRADLE source and reports syntax errors that need to be corrected.
For the full validation workflow, see Validate and Compile.
Example
The following example demonstrates several core syntax features:
metadata() >
name("ExampleEnvironment"),
eventType("sequence"),
repositoryRemote("https://172.18.178.10:4443"),
object("InitializationScript").
instances() >
instance("Client"),
instance("Router").
instance("Client") >
os("ubuntu", "20.04"),
object("InitializationScript").
networks() >
network("lan_0").
network("lan_0") >
subnet("192.168.10.0/24"),
endpoint("Client", "DHCP"),
endpoint("Router", "192.168.10.1").
events() >
preEvent(),
mainEvent(),
postEvent().
mainEvent() >
event("initialize_client").
event("initialize_client") >
instance("Client"),
needRoot(false),
subject("bash", ""),
runObject("InitializationScript", ""),
pauseBeforeRun(0),
pauseAfterRun(0),
scheduleExecution("2026-01-15T10:00:00+00:00"),
description("Initialize the example client").
object("InitializationScript") >
location("${uriRemote}/scripts/initialize.sh").
This example contains:
- a simple
metadata()block - an
instances()declaration block - a named
instance("Client")definition - a network declaration and definition
- lifecycle declarations
- a named event definition
- an external object definition
- cross-references between named elements
Related language pages
Continue with the detailed language pages:
- Metadata
- Instances and Roles
- Networks and Routing
- Events and Dependencies
- Objects and Interpolation
- Includes
- Heuristics
- Diagnostics
For a complete working scenario, see First Scenario.