Home / Docs / CLI / casen generate

casen generate

Generate BPMN files from built-in templates, CompactDiagram JSON, or by patching an existing file — and TypeScript types for job workers from BPMN.

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
TemplatePattern
emptyStart event only — bare skeleton
minimalStart → service task → end
user-taskStart → user task → end
call-activityStart → call activity → end
business-ruleStart → business rule task → end
approvalStart → user task → XOR gateway → approve/reject paths
parallelStart → parallel fork → 2 service tasks → join → end
inclusiveStart → inclusive gateway → 2 conditional tasks → merge → end
timer-startTimer start event → service task → end
message-startMessage start event → service task → end
error-boundaryService task with error boundary → two end events
subprocessStart → embedded sub-process → end
event-subprocessProcess with a non-interrupting error event sub-process

Flags

FlagShortDescriptionDefault
--templateTemplate name (see table above)minimal
--process-id-iProcess element IDprocess
--name-nProcess display name—
--output-oOutput 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 -

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: serviceTask userTask scriptTask businessRuleTask callActivity sendTask receiveTask manualTask task
  • Events: startEvent endEvent intermediateCatchEvent intermediateThrowEvent boundaryEvent
  • Gateways: exclusiveGateway parallelGateway inclusiveGateway eventBasedGateway complexGateway
  • Containers: subProcess adHocSubProcess eventSubProcess transaction

Event types (eventType field on event elements): timer message signal error escalation terminate cancel conditional link compensate

Zeebe extensions:

FieldApplies toEffect
jobTypeserviceTask, sendTaskSets zeebe:taskDefinition.type
taskHeadersserviceTask, sendTaskSets zeebe:taskHeaders key/value pairs
inputsany taskSets zeebe:ioMapping inputs (target → source); connectors read their settings from these
resultVariableserviceTask, businessRuleTaskStores the result: a resultVariable task header for a Camunda connector (io.camunda:…), an output mapping of response for any other job worker
modelerTemplateany element{ "id", "version" } of the applied element template (zeebe:modelerTemplate)
calledProcesscallActivitySets zeebe:calledElement.processId
formIduserTaskSets zeebe:formDefinition.formId
decisionIdbusinessRuleTaskSets 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

FlagDescriptionDefault
--input / -fExisting .bpmn file to load—
--patchJSON patch: {"elements":[...],"flows":[...]}—
--dump-compactPrint CompactDiagram JSON of --input and exit—
--output / -oOutput 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:

ExportWhat it is
processIds / ProcessIdExecutable process ids
jobTypes / JobTypeEvery static job type
<Name>Variables, <Name>Output, <Name>HeadersEach job type’s variables, output and task headers
JobTypesJob type → { variables, output, headers, errors, processIds, elementIds }
Messages, messageNames / MessageNameMessage names, with correlation key expressions
signalNames / SignalNameSignal names thrown or caught
errorCodes / ErrorCodeError codes thrown or caught
escalationCodes / EscalationCodeEscalation 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:

PatternClient
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

FlagDescriptionDefault
--outWrite the generated source to this file (its directory is created)stdout
--checkExit 1 when --out is missing or stale; write nothing—
--check-workersComma-separated globs or directories of worker sources to compare—
--strictWith --check-workers: exit 1 on any mismatch—
--formatjson prints the --check-workers report as JSONtext