casen generate bpmn produces BPMN 2.0 files without the interactive TUI. It has three operating
modes: template, definition (full JSON), and modify-existing (patch). Auto-layout is applied in all modes.
Commands
casen generate (alias: casen gen)
├── bpmn — generate or modify a BPMN file
└── types — generate TypeScript types from BPMN; check workers against it
Template mode
Pick a built-in template by name. Use --process-id and --name to customise the identifiers.
casen generate bpmn --template minimal --process-id order --name "Order Processing"
casen generate bpmn --template approval --process-id leave-request
casen generate bpmn --template parallel --process-id enrichment --name Enrichment
casen generate bpmn --template timer-start --process-id nightly-sync
| Template | Pattern |
|---|---|
empty | Start event only — bare skeleton |
minimal | Start → service task → end |
user-task | Start → user task → end |
call-activity | Start → call activity → end |
business-rule | Start → business rule task → end |
approval | Start → user task → XOR gateway → approve/reject paths |
parallel | Start → parallel fork → 2 service tasks → join → end |
inclusive | Start → inclusive gateway → 2 conditional tasks → merge → end |
timer-start | Timer start event → service task → end |
message-start | Message start event → service task → end |
error-boundary | Service task with error boundary → two end events |
subprocess | Start → embedded sub-process → end |
event-subprocess | Process with a non-interrupting error event sub-process |
Flags
| Flag | Short | Description | Default |
|---|---|---|---|
--template | Template name (see table above) | minimal | |
--process-id | -i | Process element ID | process |
--name | -n | Process display name | — |
--output | -o | Output file path (- for stdout) | <process-id>.bpmn |
Definition mode (AI / scripting path)
Pass a full CompactDiagram JSON object directly. This covers all 23 BPMN element types, all event definition types, boundary events, sub-processes, and Zeebe extensions.
# Inline JSON
casen generate bpmn --definition '{"id":"Definitions_order","processes":[...]}'
# Pipe from a file or AI output
cat definition.json | casen generate bpmn --output order.bpmn
# Write to stdout
echo '{"id":"Defs","processes":[...]}' | casen generate bpmn --output -
Print the JSON schema
Run --help-schema to print the full CompactDiagram reference — element types, event types,
field descriptions, and a worked example — formatted for quick AI consumption:
casen generate bpmn --help-schema
CompactDiagram structure
{
"id": "Definitions_my-process",
"processes": [{
"id": "my-process",
"name": "My Process",
"elements": [
{ "id": "start", "type": "startEvent", "name": "Start" },
{ "id": "task1", "type": "serviceTask", "name": "Do Work", "jobType": "my-worker" },
{ "id": "gw", "type": "exclusiveGateway", "name": "OK?" },
{ "id": "end-ok", "type": "endEvent", "name": "Done" },
{ "id": "end-err","type": "endEvent", "name": "Failed", "eventType": "error" }
],
"flows": [
{ "id": "f1", "from": "start", "to": "task1" },
{ "id": "f2", "from": "task1", "to": "gw" },
{ "id": "f3", "from": "gw", "to": "end-ok", "condition": "= ok", "name": "Yes" },
{ "id": "f4", "from": "gw", "to": "end-err", "condition": "= not ok", "name": "No" }
]
}]
}
Element types — all 23 BPMN types supported:
- Tasks:
serviceTaskuserTaskscriptTaskbusinessRuleTaskcallActivitysendTaskreceiveTaskmanualTasktask - Events:
startEventendEventintermediateCatchEventintermediateThrowEventboundaryEvent - Gateways:
exclusiveGatewayparallelGatewayinclusiveGatewayeventBasedGatewaycomplexGateway - Containers:
subProcessadHocSubProcesseventSubProcesstransaction
Event types (eventType field on event elements):
timer message signal error escalation terminate cancel conditional link compensate
Zeebe extensions:
| Field | Applies to | Effect |
|---|---|---|
jobType | serviceTask, sendTask | Sets zeebe:taskDefinition.type |
taskHeaders | serviceTask, sendTask | Sets zeebe:taskHeaders key/value pairs |
inputs | any task | Sets zeebe:ioMapping inputs (target → source); connectors read their settings from these |
resultVariable | serviceTask, businessRuleTask | Stores the result: a resultVariable task header for a Camunda connector (io.camunda:…), an output mapping of response for any other job worker |
modelerTemplate | any element | { "id", "version" } of the applied element template (zeebe:modelerTemplate) |
calledProcess | callActivity | Sets zeebe:calledElement.processId |
formId | userTask | Sets zeebe:formDefinition.formId |
decisionId | businessRuleTask | Sets zeebe:calledDecision.decisionId |
HTTP connector shorthand:
{
"id": "http1",
"type": "serviceTask",
"name": "Call API",
"jobType": "io.camunda:http-json:1",
"inputs": {
"url": "https://api.example.com/orders",
"method": "POST"
},
"resultVariable": "apiResponse"
}
authentication.type defaults to noAuth. Older answers that put url and method in
taskHeaders still work: they are moved to input mappings, where the connector reads them.
Modify-existing mode (--input)
Load an existing .bpmn file and patch it — add elements and flows, then re-apply auto-layout.
The default output overwrites the input file.
Inspect the current state
Use --dump-compact to print the file’s CompactDiagram JSON. Use this to discover existing
element IDs before writing a patch.
casen generate bpmn --input order.bpmn --dump-compact
Output is a CompactDiagram JSON object — the same format accepted by --definition.
Add elements and flows
# Add a rejection path to an existing gateway with id "gw"
casen generate bpmn --input order.bpmn \
--patch '{"elements":[
{"id":"notify", "type":"serviceTask","name":"Notify Customer","jobType":"notify-worker"},
{"id":"end-reject", "type":"endEvent", "name":"Rejected"}
],"flows":[
{"id":"fn1","from":"gw", "to":"notify", "condition":"= not approved","name":"No"},
{"id":"fn2","from":"notify", "to":"end-reject"}
]}'
Patch mode appends to the first process in the file. Flows in the patch can reference existing element IDs — they are not required to be new.
Pipe a patch from AI output
# AI generates the patch JSON, pipe it in
echo '{"elements":[...],"flows":[...]}' | casen generate bpmn --input order.bpmn
Normalize layout
Run --input without --patch to re-apply auto-layout without changing the process model:
casen generate bpmn --input messy.bpmn --output clean.bpmn
Flags for --input mode
| Flag | Description | Default |
|---|---|---|
--input / -f | Existing .bpmn file to load | — |
--patch | JSON patch: {"elements":[...],"flows":[...]} | — |
--dump-compact | Print CompactDiagram JSON of --input and exit | — |
--output / -o | Output path (- for stdout) | Overwrites --input file |
Typical AI workflow
# 1. Inspect the existing file — AI learns element IDs
casen generate bpmn --input order.bpmn --dump-compact
# 2. Check the schema if needed
casen generate bpmn --help-schema
# 3. AI generates patch JSON and pipes it in
echo '{"elements":[...],"flows":[...]}' | casen generate bpmn --input order.bpmn
# 4. Verify the result
casen view bpmn order.bpmn
Typed code generation (casen generate types)
casen generate types (or casen gen types) reads BPMN files and writes TypeScript types for the
job workers, message publishers and error throwers that run against them. A misspelt job type,
variable or error code then fails at compile time, not at runtime. The command lives under
generate because it produces a file from a model, like generate bpmn does.
# Files, directories (searched for .bpmn) and globs — quote globs to skip shell expansion
casen gen types processes/ --out src/generated/bpmn-types.ts
casen gen types "processes/**/*.bpmn" --out src/generated/bpmn-types.ts
# Print to stdout instead
casen gen types order.bpmn
The output is deterministic: everything is sorted, so the file only changes when the model does.
It starts with // generated by casen gen types — do not edit. It contains:
| Export | What it is |
|---|---|
processIds / ProcessId | Executable process ids |
jobTypes / JobType | Every static job type |
<Name>Variables, <Name>Output, <Name>Headers | Each job type’s variables, output and task headers |
JobTypes | Job type → { variables, output, headers, errors, processIds, elementIds } |
Messages, messageNames / MessageName | Message names, with correlation key expressions |
signalNames / SignalName | Signal names thrown or caught |
errorCodes / ErrorCode | Error codes thrown or caught |
escalationCodes / EscalationCode | Escalation codes thrown or caught |
See the Typed workers guide for the typing rules and for how to use the types with a worker.
Keep the file current in CI
--check compares the generated source with the --out file and exits 1 when the file is missing or
out of date. It writes nothing.
casen gen types processes/ --out src/generated/bpmn-types.ts --check
Check workers against the BPMN
--check-workers <glob> scans TypeScript and JavaScript sources for job worker registrations. It
reports job types that have no worker, and workers whose job type no BPMN element uses. Add
--strict to exit 1 when there is a mismatch.
casen gen types processes/ --check-workers "src/**/*.ts" --strict
casen gen types processes/ --check-workers src,workers --format json
The scan is a heuristic. It finds a job type only when it is a string literal in one of these forms:
| Pattern | Client |
|---|---|
createWorker("type", …) | zeebe-node (legacy) |
taskType: "type" | zeebe-node, @camunda8/sdk |
.createJobWorker({ jobType: "type", … }) (or type:) | @camunda8/orchestration-cluster-api |
registerJobWorker("type", …) | custom registries |
.poll("type") | @bpmnkit/worker-client |
A job type held in a variable or built with ${…} is not found. Job types that start with
io.camunda belong to Camunda connectors. The connector runtime runs them, so they are never
reported as missing a worker.
Flags
| Flag | Description | Default |
|---|---|---|
--out | Write the generated source to this file (its directory is created) | stdout |
--check | Exit 1 when --out is missing or stale; write nothing | — |
--check-workers | Comma-separated globs or directories of worker sources to compare | — |
--strict | With --check-workers: exit 1 on any mismatch | — |
--format | json prints the --check-workers report as JSON | text |