From camunda-skills
Authors executable BPMN 2.0 processes for Camunda 8, including Zeebe extensions, diagram coordinates, and XML validation via c8ctl bpmn lint.
How this skill is triggered — by the user, by Claude, or both
Slash command
/camunda-skills:camunda-bpmnThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create and edit executable BPMN 2.0 processes for Camunda 8.8+. Generates valid XML with Zeebe extensions and diagram coordinates.
Create and edit executable BPMN 2.0 processes for Camunda 8.8+. Generates valid XML with Zeebe extensions and diagram coordinates.
c8ctl add profile) — provides c8ctl bpmn lintbpmn format. If the command is unavailable, ask the user to upgrade: npm install -g @camunda8/cli<zeebe:calledDecision decisionId="..." resultVariable="..."/>zeebe:taskDefinition type activatesWhen writing a BPMN file from scratch, follow the canonical bpmn-js style — single-line <bpmn:definitions>, two-space indent, no blank lines between siblings, <el /> self-closing form. Otherwise any round-trip through Camunda Modeler, Web Modeler, or c8ctl element-template apply reformats the file, breaking Edit matches and adding diff noise. Rules and a worked skeleton: references/canonical-style.md.
The zeebe namespace, isExecutable="true", and modeler:executionPlatform="Camunda Cloud" are mandatory — without them, Camunda won't recognize the process correctly.
The <bpmndi:BPMNDiagram> block is also mandatory, not optional polish: c8ctl bpmn lint flags missing DI (no-bpmndi) as an error, and Modeler can't render a process without it. Every <bpmn:process> flow element needs a matching <bpmndi:BPMNShape>, every <bpmn:sequenceFlow> a <bpmndi:BPMNEdge>. Coordinates, sizes, and waypoint conventions: references/layout-rules.md. Note that Zeebe deploys a DI-less BPMN happily — the missing DI surfaces only at lint and in Modeler, so don't rely on a successful deploy as evidence the file is well-formed.
Always encode special characters in XML attribute values:
< → <, > → >, & → &, " → ", ' → 'Start/End Events:
Tasks — one atomic action per task:
<zeebe:userTask /> and link the form via <zeebe:formDefinition formId="X" />. Assign with <zeebe:assignmentDefinition candidateGroups="..." />. Setting formId="X" makes X.form a required deliverable — author it via camunda-forms in the same step, or flag the gap explicitly in your final message. c8ctl bpmn lint checks the attribute is present, not that the file resolves. Do NOT write the deprecated job-worker variant (no <zeebe:userTask />, formKey instead of formId) — see references/zeebe-extensions.md § Form Definition.<zeebe:taskDefinition type="..." retries="3" />. The type must exactly match worker registration (case-sensitive). When backed by an out-of-the-box connector, apply the template via camunda-connectors — don't hand-write the connector input mappings.<zeebe:script expression="=..." resultVariable="..." />.<zeebe:calledDecision decisionId="X" resultVariable="..." />. decisionId="X" makes the corresponding X.dmn a required deliverable — author it via camunda-dmn.Gateways:
default attribute for the fallback flow. Label condition flows.c8ctl bpmn lint — join gateways must match their fork type.Sequence Flows:
= prefix:
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=amount > 1000</bpmn:conditionExpression>
FEEL Expressions in BPMN — all FEEL must be prefixed with =:
=riskLevel = "HIGH"="PT7D" (plain PT7D is rejected)=customer.nameAnything beyond a simple variable reference (function calls, operators, context literals, for / every / some) — validate via camunda-feel before committing.
IDs: Use descriptive PascalCase — ReviewInvoice, AmountExceedsLimit, Flow_ToApproval
Create local variables and control variable propagation:
<zeebe:ioMapping>
<!-- Input: create local variable from parent scope -->
<zeebe:input source="=customer.name" target="customerName" />
<!-- Output: propagate local result to parent scope -->
<zeebe:output source="=result.status" target="paymentStatus" />
</zeebe:ioMapping>
See references/zeebe-extensions.md for detailed variable scoping, propagation rules, and examples.
BPMN files can be large. Follow these rules:
<el /> (single space before />)<bpmn:incoming> and <bpmn:outgoing> flow references on elementsA BPMN edit is not structurally done until c8ctl bpmn lint reports zero errors AND zero warnings. Treat this as the closing structural step of every BPMN task — generation, modification, refactor, or merge.
Run the linter against the file you touched:
c8ctl bpmn lint path/to/process.bpmn
c8ctl bpmn lint auto-detects the Camunda execution platform version from the BPMN file and applies sensible Camunda defaults. If a .bpmnlintrc is present in the project, it is used instead. Stdin also works: cat process.bpmn | c8ctl bpmn lint.
If output is non-empty, fix every reported issue and run the linter again. Common categories:
Loop until the linter is clean. Do not declare the task structurally done while warnings remain — silently-failing BPMN deploys to the cluster and surfaces as runtime incidents.
If a warning is genuinely a false positive, suppress it explicitly in a project-level .bpmnlintrc and flag the suppression in your final message — never silently ignore.
Lint catches structure, not runtime behaviour (FEEL errors, missing workers, unreachable end events). After lint is clean, validate by running the process: prefer camunda-process-test for embedded-engine feedback without a cluster, or fall back to camunda-process-mgmt to deploy and run an instance.
For detailed reference material, read from references/:
npx claudepluginhub camunda/skills --plugin camunda-skillsGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.