From camunda-skills
Creates and edits Camunda Form JSON schemas for user tasks and start events in Camunda 8, including field layouts, validation, and conditional visibility.
How this skill is triggered — by the user, by Claude, or both
Slash command
/camunda-skills:camunda-formsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create Camunda Form JSON schemas for user tasks and start events in Camunda 8.8+.
Create Camunda Form JSON schemas for user tasks and start events in Camunda 8.8+.
<zeebe:formDefinition formId="..."/>Camunda Forms are JSON files with .form extension (not .json). Link to BPMN user tasks via the form's id field, which must match the formId attribute on <zeebe:formDefinition formId="..."/> inside the user task. The user task itself must also include <zeebe:userTask/> (the Camunda user task implementation). Don't link via the older formKey attribute — that's the deprecated job-worker user task, removed in Camunda 8.10. See camunda-bpmn § Form Definition for the BPMN side.
Example — minimal form skeleton:
{
"components": [],
"executionPlatform": "Camunda Cloud",
"executionPlatformVersion": "8.8.0",
"exporter": { "name": "Camunda Modeler", "version": "5.34.0" },
"schemaVersion": 18,
"id": "my-form-id",
"type": "default"
}
All metadata fields are required. Use schemaVersion: 18 and executionPlatformVersion: "8.8.0".
Every component requires type, id, and layout. Input components also need key (maps to process variable name) and label.
{
"type": "textfield",
"id": "Field_Name",
"key": "customerName",
"label": "Customer Name",
"layout": { "row": "row_0", "columns": null }
}
Input components: textfield, textarea, number, checkbox, checklist, radio, select, taglist, datetime
Display components: text (markdown), html, image, separator, button
Layout components: group, spacer
See references/component-reference.md for complete properties of each component type.
Components are arranged in rows. Place components in the same row to display them side-by-side:
{ "type": "textfield", "id": "F1", "key": "firstName", "label": "First Name", "layout": { "row": "row_0", "columns": null } },
{ "type": "textfield", "id": "F2", "key": "lastName", "label": "Last Name", "layout": { "row": "row_0", "columns": null } }
The key property maps a form field to a process variable:
{
"validate": {
"required": true,
"minLength": 2,
"maxLength": 100,
"min": 0,
"max": 10000,
"pattern": "^[A-Z]{2}[0-9]+$",
"validationExpression": "=amount <= budget"
}
}
Custom error messages: requiredErrorMessage, patternErrorMessage.
Hide or show fields based on other field values using FEEL:
{
"conditional": {
"hide": "=approved = false"
}
}
The expression is evaluated against all form field values and process variables.
Static values:
{
"type": "select",
"values": [
{ "label": "Low", "value": "low" },
{ "label": "Medium", "value": "medium" },
{ "label": "High", "value": "high" }
]
}
Dynamic values from process variable:
{
"type": "select",
"valuesExpression": "=departments"
}
The variable should be a list of {label, value} objects.
Display data without allowing edits:
{
"type": "textfield",
"key": "orderId",
"label": "Order ID",
"readonly": true
}
Display static text or instructions using markdown:
{
"type": "text",
"text": "### Review Details\n\nPlease review the information below.",
"id": "Text_Header",
"layout": { "row": "row_0", "columns": null }
}
Organize related fields:
{
"type": "group",
"label": "Contact Information",
"components": [
{ "type": "textfield", "id": "F1", "key": "email", "label": "Email", "layout": { "row": "row_g0", "columns": null } },
{ "type": "textfield", "id": "F2", "key": "phone", "label": "Phone", "layout": { "row": "row_g1", "columns": null } }
],
"id": "Group_Contact",
"layout": { "row": "row_1", "columns": null }
}
Generate complete .form JSON files. Ensure:
id values are unique within the formkey values match expected process variable nameslayout.row values increment sequentially (row_0, row_1, ...)<zeebe:userTask/> and <zeebe:formDefinition formId="..."/> matching the form's id field. The legacy formKey attribute was removed in Camunda 8.10.schemaVersion mismatch error — set schemaVersion: 18 and executionPlatformVersion: "8.8.0"; older values are rejected by 8.8+ clusters.conditional.hide is a FEEL expression that returns true to hide. Forgetting the = prefix turns it into a literal string. See camunda-feel § Common Patterns for the FEEL side.For detailed reference material, read from references/:
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub camunda/skills --plugin camunda-skills