From camunda-migration
Use this when migrating or converting a Camunda 7 / camunda-bpm Java/Spring codebase to Camunda 8 — including JavaDelegates, ExternalTaskWorkers, ProcessEngine/RuntimeService client code, and application.properties/application.yaml with camunda.* keys.
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.
Use AskUserQuestion for each question below. Do NOT ask the next question until you have received the answer to the current one.
Question 1 — Code location
Call AskUserQuestion: "What is the path to the project root?"
/path/to/project — is that correct?").Do not proceed to Question 2 until you have the answer.
Question 2 — Migration approach
Call AskUserQuestion asking the user to choose one of:
// TODO comments, compilation errors, config, and test code. Best for most codebases.Do not proceed to Question 3 until you have the answer.
Question 3 — Build tool (only if approach A was chosen)
Before asking, check the project root for pom.xml (Maven) or build.gradle / build.gradle.kts (Gradle).
AskUserQuestion to confirm: e.g. "I detected Maven (pom.xml) — is that correct?"AskUserQuestion: "Are you using 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 / ClientCode / TestCode / Config / JUEL | Low / Medium / High | Key concerns |
Detection hints:
implements JavaDelegate → JavaDelegate@ExternalTaskSubscription or ExternalTaskHandler → External task workerProcessEngine, RuntimeService, TaskService autowired → Client code@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)After the table, present:
Use AskUserQuestion to wait for user confirmation before proceeding.
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
2. AI cleanup — after OpenRewrite has run
First, fetch the pattern catalog via WebFetch — this is your reference for resolving TODOs, config, tests, 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
Work through each of the following. Confirm each before moving on.
// 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@Rule Camunda test rules with @CamundaSpringProcessTest, update assertions (e.g. isWaitingAt("id") → hasActiveElements("id")), message correlation, timer handling — OpenRewrite doesn't fully cover testsFirst, fetch the pattern catalog via WebFetch — 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
Work through each phase sequentially. Confirm completion of each phase before moving to the next.
Phase 1: Dependencies and configuration
org.camunda.bpm.* dependencies from pom.xml / build.gradleio.camunda:camunda-spring-boot-starter and camunda-process-test-spring@EnableProcessApplication with @Deploymentapplication.properties / application.yaml — replace camunda.* keys with camunda.client.* equivalentsPhase 2: Client code
ProcessEngine autowiring with CamundaClientPhase 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: Test code
@Rule Camunda test rules with @CamundaSpringProcessTestisWaitingAt("id") → hasActiveElements("id")Present the assessment table from Step 2 with additional detail:
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 reviewmvn 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 bugsString to Long — check all ID handlingVariableMap usage — variables are now plain JSON, TypedValue API is goneHistoryService references — history API changed significantly in C8Present a summary:
Validation Summary
------------------
✅ Compilation: OK
⚠️ Remaining org.camunda.bpm imports: 3 → [list files]
⚠️ Remaining TODOs: 5 → [list them]
✅ Tests: 42 passed, 0 failed
For any remaining issues, ask the user: fix now, skip, or flag for manual review.
ALL_IN_ONE.md before touching any code. Never guess API mappings..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 and some JUEL→FEEL conversions automatically. 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