Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The cxl CLI Tool

The cxl command-line tool validates, evaluates, and formats CXL source files. It is the standalone companion to the Clinker pipeline engine, useful for testing expressions, validating transforms, and debugging CXL logic.

Commands

cxl check

Parse, resolve, and type-check a .cxl file. Reports errors with source locations and fix suggestions.

$ cxl check transform.cxl
ok: transform.cxl is valid

On errors:

error[parse]: expected expression, found '}' (at transform.cxl:12)
  help: check for missing operand or extra closing brace
error[resolve]: unknown field 'amoutn' (at transform.cxl:5)
  help: did you mean 'amount'?
error[typecheck]: cannot apply '+' to String and Int (at transform.cxl:8)
  help: convert one operand — use .to_int() or .to_string()

cxl eval

Evaluate CXL expressions against provided data and print the result as JSON.

Inline expression:

$ cxl eval -e 'emit result = 1 + 2'
{
  "result": 3
}

From a file with field values:

$ cxl eval transform.cxl \
    --field Price=10.5 \
    --field Qty=3

From a file with JSON input:

$ cxl eval transform.cxl --record '{"price": 10.5, "qty": 3}'

Multiple inline expressions:

$ cxl eval -e 'let tax = 0.21' -e 'emit net = price * (1 - tax)' \
    --field price=100
{
  "net": 79.0
}

cxl fmt

Parse and pretty-print a .cxl file in canonical format with normalized whitespace and consistent styling.

$ cxl fmt transform.cxl

Output is printed to stdout. Redirect to overwrite:

$ cxl fmt transform.cxl > transform.cxl.tmp && mv transform.cxl.tmp transform.cxl

Input data

–field name=value

Provide individual field values as key-value pairs. Values are automatically type-inferred:

InputInferred typeExample
Integer patternInt--field count=42
Decimal patternFloat--field price=10.5
true / falseBool--field active=true
nullNull--field value=null
Anything elseString--field name=Alice
$ cxl eval -e 'emit t = amount.type_of()' --field amount=42
{
  "t": "Int"
}
$ cxl eval -e 'emit t = name.type_of()' --field name=Alice
{
  "t": "String"
}

–record JSON

Provide a full JSON object as input. Mutually exclusive with --field.

$ cxl eval -e 'emit total = price * qty' \
    --record '{"price": 10.5, "qty": 3}'
{
  "total": 31.5
}

JSON types map directly:

JSON typeCXL type
nullNull
true / falseBool
integer numberInt
decimal numberFloat
"string"String
[array]Array

Output format

Output is always JSON. Each emit statement produces a key-value pair:

$ cxl eval -e 'emit a = 1' -e 'emit b = "two"' -e 'emit c = true'
{
  "a": 1,
  "b": "two",
  "c": true
}

Date and DateTime values are serialized as ISO 8601 strings:

$ cxl eval -e 'emit d = #2024-03-15#'
{
  "d": "2024-03-15"
}

Exit codes

CodeMeaning
0Success (or warnings only)
1Parse, resolve, type-check, or evaluation errors
2I/O error (file not found, invalid JSON, etc.)

Pipeline context in eval mode

When running cxl eval, a minimal pipeline context is provided:

VariableValue
$pipeline.name"cxl-eval"
$pipeline.execution_idZeroed UUID
$pipeline.batch_idZeroed UUID
$pipeline.start_timeCurrent wall-clock time
$pipeline.source_fileFilename or "<inline>"
$pipeline.source_row1
nowCurrent wall-clock time (live)

Practical usage

Quick expression testing:

$ cxl eval -e 'emit result = "hello world".upper().split(" ").length()'
{
  "result": 2
}

Validate a transform file:

$ cxl check transforms/enrich_orders.cxl && echo "Valid"

Test conditional logic:

$ cxl eval -e 'emit tier = match {
    amount > 1000 => "high",
    amount > 100 => "med",
    _ => "low"
  }' \
    --field amount=500
{
  "tier": "med"
}

Test date operations:

$ cxl eval -e 'emit year = d.year()' -e 'emit month = d.month()' \
    -e 'emit next_week = d.add_days(7)' \
    --record '{"d": "2024-03-15"}'

Test null handling:

$ cxl eval -e 'emit safe = raw.try_int() ?? 0' --field raw=abc
{
  "safe": 0
}