From camunda-migration
Migrates Camunda 7 Java/Spring codebases to Camunda 8, handling delegates, workers, client code, listeners, and config files. Supports OpenRewrite-assisted or AI-only migration.
How this skill is triggered — by the user, by Claude, or both
Slash command
/camunda-migration:migrate-c7-to-c8-code Optional path to project root (defaults to current directory)Optional path to project root (defaults to current directory)This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a migration expert helping the user migrate a Java codebase from Camunda 7 to Camunda 8.
You are a migration expert helping the user migrate a Java codebase from Camunda 7 to Camunda 8.
Before calling AskUserQuestion, pick a candidate project root (use the provided argument if present, otherwise the current working directory), then detect the build tool by checking that directory for pom.xml (Maven) or build.gradle / build.gradle.kts (Gradle).
Then call AskUserQuestion once with Questions 1-3 below (combine them in a single call — do not ask one at a time):
Question 1 — Code location
"What is the path to the project root?"
/path/to/project — is that correct?").Question 2 — Target Camunda 8 version
Ask which Camunda 8 version the user is migrating to:
The target version changes which patterns apply — record the answer and use it throughout.
Question 3 — Migration approach
Ask the user to choose one of:
// TODO comments, compilation errors, config, and test code. Best for most codebases.Question 4 — Build tool
Ask this only as a follow-up AskUserQuestion call after the user answers Question 3, and only if both conditions are true:
If exactly one build tool was detected, do not ask Question 4; state the detection in the question text of Question 3 instead (for example, "Detected Maven.").
When you do ask Question 4, use explicit question text such as: "Which build tool should I use for the OpenRewrite step: Maven or Gradle?" Do not proceed until you have the answer.
Scan the codebase at the provided path. Identify and classify all Camunda 7 related files:
| File | Type | Complexity | Notes |
|---|---|---|---|
| ... | JavaDelegate / ExternalTaskWorker / Listener / ClientCode / TestCode / Config / JUEL / DMN | Low / Medium / High | Key concerns |
Detection hints:
implements JavaDelegate → JavaDelegate@ExternalTaskSubscription or ExternalTaskHandler → External task workerimplements ExecutionListener or implements TaskListener → Listener (C8: execution listeners 8.6+, user task listeners 8.8+, global user task listeners 8.9+)ProcessEngine, RuntimeService, TaskService autowired → Client codeHistoryService → Client code (maps to Orchestration Cluster search endpoints; historic data needs the History Data Migrator)DecisionService → Client code (maps to newEvaluateDecisionCommand)IdentityService, FormService → Client code, flag for manual design (Identity Data Migrator covers authorizations since 8.9)businessKey usage → flag: maps to Business ID (8.9+) or tags (8.8)...Async methods, ManagementService batches) → Client code (Orchestration Cluster batch operations since 8.8)ZeebeClient / Spring Zeebe SDK (io.camunda.spring:spring-boot-starter-camunda or zeebe-client-java) → legacy C8 client code; migrate to CamundaClient / camunda-spring-boot-starter (ZeebeClient is removed in 8.10)@Test + Camunda 7 test rules → Test codeapplication.properties / application.yaml with camunda.* keys → Config.bpmn files with camunda: namespace attributes → BPMN (flag only — convert using the online tool, see below)ProcessEnginePlugin, BPMN parse listeners → flag: global behavior; user-task cases map to global user task listeners (8.9+), others need manual designSpecial blockers to flag explicitly:
ManagementService#createBatch with custom jobs) — no generic C8 equivalent.After the table, present:
Write the assessment to MIGRATION_REPORT.md in the project root (table, decisions, blockers). Keep this file updated as phases complete — it is the durable record of the migration across sessions.
Use AskUserQuestion to wait for user confirmation before proceeding.
Git checkpoint rule (applies to A and B): before changing anything, verify the working tree is clean (git status). If not, ask the user to commit or stash first. Do not create commits automatically. After OpenRewrite and after each completed phase, ask whether the user wants a commit; only commit if they explicitly approve, using a clear message (e.g. migration: resolve delegate TODOs). This keeps every step reviewable and reversible while preserving user control.
1. Run OpenRewrite
Before adding the plugin, resolve the latest released versions via WebFetch:
rewrite-maven-plugin (OpenRewrite): https://search.maven.org/solrsearch/select?q=g:org.openrewrite.maven+AND+a:rewrite-maven-plugin&rows=1&wt=json → read response.docs[0].latestVersioncamunda-7-to-8-code-conversion-recipes: https://search.maven.org/solrsearch/select?q=g:io.camunda+AND+a:camunda-7-to-8-code-conversion-recipes&rows=1&wt=json → read response.docs[0].latestVersionUse those resolved versions in the snippets below (replacing REWRITE_VERSION and RECIPES_VERSION).
Check if the OpenRewrite plugin is already in the build file. If not, add it:
For Maven — add to pom.xml:
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>REWRITE_VERSION</version>
<configuration>
<activeRecipes>
<recipe>io.camunda.migration.code.recipes.AllClientRecipes</recipe>
<recipe>io.camunda.migration.code.recipes.AllDelegateRecipes</recipe>
<recipe>io.camunda.migration.code.recipes.AllExternalWorkerRecipes</recipe>
</activeRecipes>
<skipMavenParsing>false</skipMavenParsing>
</configuration>
<dependencies>
<dependency>
<groupId>io.camunda</groupId>
<artifactId>camunda-7-to-8-code-conversion-recipes</artifactId>
<version>RECIPES_VERSION</version>
</dependency>
</dependencies>
</plugin>
Before running, check for Spotless + Java version incompatibility and fix proactively:
java -version 2>&1 | head -1grep -r "spotless" pom.xml build.gradle build.gradle.kts 2>/dev/nullMAVEN_OPTS="--add-opens=java.base/java.lang=ALL-UNNAMED \
--add-opens=java.base/java.util=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" \
mvn rewrite:run
mvn rewrite:run -Dspotless.skip=true) or switch to Java 11/17 first?"mvn rewrite:run directly.For Gradle — add to build.gradle:
plugins {
id("org.openrewrite.rewrite") version "REWRITE_VERSION"
}
rewrite {
activeRecipe("io.camunda.migration.code.recipes.AllClientRecipes")
activeRecipe("io.camunda.migration.code.recipes.AllDelegateRecipes")
activeRecipe("io.camunda.migration.code.recipes.AllExternalWorkerRecipes")
}
Run: ./gradlew rewriteRun
Before AI cleanup, ask whether to commit the OpenRewrite result. Commit only if the user explicitly approves.
2. AI cleanup — after OpenRewrite has run
First, fetch the pattern catalog via WebFetch from main — this is your reference for resolving TODOs, config, tests, listeners, and JUEL. Do not rely on training knowledge for API mappings:
https://raw.githubusercontent.com/camunda/camunda-7-to-8-migration-tooling/main/code-conversion/patterns/ALL_IN_ONE.md
If context budget is tight, fetch only the individual pattern files you need from code-conversion/patterns/ (same repo, same raw URL scheme) instead of the full catalog.
Work through each of the following. Confirm each before moving on. Do not auto-commit; ask whether to commit after each item and commit only with explicit user approval.
// TODO comments inserted by OpenRewrite and resolve using the pattern catalogorg.camunda.bpm.* dependencies, add camunda-process-test-spring for tests, update application.properties / application.yaml — replace camunda.* keys with camunda.client.* equivalents (see the properties reference)ExecutionListener / TaskListener implementations — convert per the "Listeners" patterns (execution listener job workers; user task listeners with corrections/deny; global user task listeners for cluster-wide cases on 8.9)HistoryService → search requests; DecisionService → newEvaluateDecisionCommand; batch ...Async methods → batch operation endpoints (8.8+); businessKey → businessId (8.9) or tags (8.8)@Rule Camunda test rules with @CamundaSpringProcessTest, update assertions (e.g. isWaitingAt("id") → hasActiveElements("id")), message correlation, timer handling (processTestContext.increaseTime(...)), user task completion (processTestContext.completeUserTask(...)), worker mocking (processTestContext.mockJobWorker(...)) — OpenRewrite doesn't fully cover tests. For large suites on 8.9+, recommend CPT shared runtime mode to cut execution time.First, fetch the pattern catalog via WebFetch from main — this is your primary reference for all C7→C8 transformations. Do not rely on training knowledge for API mappings:
https://raw.githubusercontent.com/camunda/camunda-7-to-8-migration-tooling/main/code-conversion/patterns/ALL_IN_ONE.md
If context budget is tight, fetch only the individual pattern files you need from code-conversion/patterns/ instead of the full catalog.
Work through each phase sequentially. Confirm completion of each phase before moving to the next. Do not auto-commit; ask whether to commit after each phase and commit only with explicit user approval.
Phase 1: Dependencies and configuration
Before modifying the build file, resolve the latest released Camunda version via WebFetch:
https://search.maven.org/solrsearch/select?q=g:io.camunda+AND+a:camunda-spring-boot-starter&rows=1&wt=json → read response.docs[0].latestVersion as CAMUNDA_VERSIONIf the user's target is 8.8, use the latest 8.8.x patch (8.8.x); if 8.9+, CAMUNDA_VERSION is fine as-is.
Detect the Spring Boot version from the existing pom.xml or build.gradle:
io.camunda:camunda-spring-boot-3-starter (supported for 8.9+; use for 8.8 too)io.camunda:camunda-spring-boot-starterAdd the Camunda public repository if not already present (some Camunda artifacts may not be on Maven Central):
Maven (pom.xml):
camunda-public
Camunda Public Repository
https://artifacts.camunda.com/artifactory/public/
Gradle (build.gradle / build.gradle.kts):
repositories {
maven { url "https://artifacts.camunda.com/artifactory/public/" }
}
Then:
org.camunda.bpm.* dependencies and camunda-bom from pom.xml / build.gradleio.camunda:camunda-process-test-spring at the same version in test scope if tests existspring-boot-starter-parent or the Spring Boot BOM); avoid adding org.springframework.boot:spring-boot-starter solely to “get jakarta.annotation”.@EnableProcessApplication with @Deploymentapplication.properties / application.yaml — replace camunda.* keys with camunda.client.* equivalents (see the properties reference)Phase 2: Client code
ProcessEngine autowiring with CamundaClientbusinessId/tags), correlating messages, broadcasting signals, cancelling instances, user task handling, variable handling, history queries → search requests, DMN evaluation, batch operationsPhase 3: JavaDelegate → Job Worker
implements JavaDelegateexecute(DelegateExecution execution) to @JobWorker-annotated methodexecution.getVariable() → method parameters or @Variable annotationsBpmnError → CamundaError.bpmnError(...)TypedValue API usagePhase 4: External task workers
@ExternalTaskSubscription with @JobWorkerPhase 5: Listeners
ExecutionListener implementations to execution listener job workers (zeebe:executionListener + @JobWorker)TaskListener implementations to user task listener job workers (job result with corrections / deny)Phase 6: Test code
@Rule Camunda test rules with @CamundaSpringProcessTestisWaitingAt("id") → hasActiveElements("id")processTestContext utilities: completeUserTask, completeJob, mockJobWorker, increaseTime)camunda.client.worker.defaults.enabled=false with per-worker overridesPresent the assessment table from Step 2 with additional detail:
Write the full report to MIGRATION_REPORT.md. Then stop — make no code changes.
mvn compile or ./gradlew compileJava — fix all errorsorg.camunda.bpm imports — each is a missed migration// TODO migration comments — each needs manual reviewZeebeClient and zeebe-client-java — deprecated, removed in 8.10; migrate to CamundaClientbusinessKey — map to businessId (8.9+) or tags (8.8), don't silently dropmvn test or ./gradlew test — fix failuresprocessDefinitionKey (the string key like "my-process") becomes C8 bpmnProcessId; C7 processDefinitionId (the UUID) becomes C8 processDefinitionKey — easy to miss, causes silent runtime bugs. Same swap applies to decision definitions.String to Long — check all ID handlingVariableMap usage — variables are now plain JSON, TypedValue API is goneHistoryService references — map to Orchestration Cluster search endpoints (eventually consistent — no read-after-write inside workers); historic data needs the History Data Migrator (8.9, RDBMS)Present a summary:
Validation Summary
------------------
✅ Compilation: OK
⚠️ Remaining org.camunda.bpm imports: 3 → [list files]
⚠️ Remaining TODOs: 5 → [list them]
⚠️ Remaining businessKey usages: 2 → [list them]
✅ Tests: 42 passed, 0 failed
Record the summary in MIGRATION_REPORT.md. For any remaining issues, ask the user: fix now, skip, or flag for manual review.
docs.camunda.io) via WebFetch over training knowledge.MIGRATION_REPORT.md current. Assessment, decisions, phase status, validation results..bpmn files use camunda: attributes, mention them in the assessment summary and recommend the user convert them at https://diagram-converter.camunda.io/ — it handles namespace updates, listener mappings, simple JUEL→FEEL conversions, and (since 8.9) conditional events. Suggest running it after the code migration.AskUserQuestion before applying. When unsure whether a case is unambiguous, ask.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub camunda/camunda-7-to-8-migration-tooling --plugin camunda-migration