POC of Spring Codebase Migration — with an AI agent that learns from every run.
SpringMind is a shell-based POC that migrates Java 11 / Spring Boot 2.x repositories to Java 25 / Spring Boot 3.5.10. It uses Claude CLI as an embedded AI agent to apply migration rules, auto-fix compiler errors, generate verification tests, and accumulate learned patterns across runs.
claudeCLI installed and authenticatedgitandbashavailable- Target repo uses Maven wrapper (
./mvnw)
./migrate.sh run \
--git-repo <url> \
--git-username <user> \
--git-password <token>./migrate.sh run:apply-rule \
--git-repo <url> \
--git-username <user> \
--git-password <token>Clones the repository and applies pre-defined migration rules learned from past runs, verifies compile (with fix loop). Output: compile SUCCESS + run log recording which rules were attempted and any compile errors.
./migrate.sh run:generate-test --repo-path ./workspace/<repo-name>Reads the latest run log for that repo, generates @SpringBootTest integration tests, runs ./mvnw test, and triages any failures. Migration-caused failures are fixed in source and recorded as new learned rules. Appends test results to the existing run log.
| Flag | Default | Description |
|---|---|---|
--source-branch <branch> |
— | Branch to checkout before creating migration/sb3 |
--max-retries <n> |
3 |
Max compile-fix loop retries before rollback |
--skip-tests |
false | Skip test generation (run only) |
--skip-rules <r1,r2> |
— | Rule IDs to skip (parsed, not yet enforced) |
--git-skip |
false | Skip all git steps. Requires --repo-path. |
--repo-path <path> |
— | Path to an already-cloned repo (required with --git-skip) |
Credentials can also be set via env vars: MIGRATE_GIT_USERNAME, MIGRATE_GIT_PASSWORD.
[1/5] Clone repo → workspace/<repo-name>/
[2/5] Git checkpoint → branch: migration/sb3, tag: migration-checkpoint-pre
[3/5] Apply rules → Claude CLI applies all 20 predefined rules
Compile verify → ./mvnw clean compile
Fix loop → Claude CLI fixes errors, up to --max-retries times
Rollback to checkpoint if exhausted
[4/5] Generate tests → Claude CLI reads test-specs/, writes @SpringBootTest tests
Test triage → Migration-caused failures fixed + recorded as new learned rules
[5/5] Commit + record → git commit on migration/sb3; session log saved to knowledge base
Steps 1–3 and 5 above. No test generation. Run log written with tests_result: NOT_RUN.
[1/2] Read run log → find latest knowledge-base/learned/runs/*_<repo>.yaml
[2/2] Generate + verify → Claude CLI reads test-specs/, generates tests, runs ./mvnw test
Migration gaps → fix source + write new learned pattern YAML
Test/env issues → fix test or @Disabled with comment
Append result → tests_result appended to existing run log
After a successful run, push the migration branch:
git -C ./workspace/<repo-name> push origin migration/sb3migrate.sh # Entry point
lib/
git.sh # Clone, checkpoint, rollback, commit helpers
claude.sh # Claude CLI invocation wrappers
compile.sh # Maven compile / test helpers
report.sh # Session recording and console summary
knowledge-base/
rules/
initial-migration-rules.yaml # 20 predefined migration rules
prompts/
apply-rules.md # Prompt: apply rules phase
fix-errors.md # Prompt: fix-loop phase
generate-tests.md # Prompt: test generation + triage + new rule recording
analyze.md # Prompt: analyze command
test-specs/
migration-test-specs.md # Project-agnostic test specs per rule (read by Claude CLI)
learned/
runs/ # Session logs: rules, compile errors, test results (auto-populated)
patterns/ # Learned fix patterns from fix loop and test triage (auto-populated)
workspace/ # Cloned repos (gitignored)
docs/ # Requirements, spec, and implementation plan
20 predefined rules applied in priority order:
| Priority | ID | Description |
|---|---|---|
| 10 | maven-sb-parent |
Spring Boot parent 2.x → 3.5.10 |
| 20 | maven-java-version |
Java version properties → 25 |
| 30 | maven-dep-versions |
Dependency version updates |
| 40 | maven-compiler-plugin |
Add compiler plugin with annotation processor paths |
| 50 | jakarta-namespace |
javax.* → jakarta.* (EE packages only) |
| 51 | sun-istack-notnull |
com.sun.istack.NotNull → jakarta.annotation.Nonnull |
| 55 | hibernate-type-annotation |
Remove string-based @Type, replace with @Column/@Lob |
| 56 | hibernate-columnresult-types |
@ColumnResult legacy type classes → Java stdlib types |
| 57 | nimbus-json-migration |
Nimbus shaded JSON → net.minidev.json |
| 58 | httpclient-migration |
Apache HttpClient 4 → HttpClient 5 |
| 59 | commons-io-dep |
Add missing commons-io dependency |
| 60 | swagger-migration |
Springfox → SpringDoc OpenAPI 3 annotations |
| 70 | config-properties |
spring.redis.* → spring.data.redis.*, add Hibernate timezone config |
| 80 | maven-wrapper-update |
Maven wrapper → 3.9.6 |
| 90 | couchbase-config |
Couchbase config namespace restructure |
| 100 | couchbase-repository |
Add CrudRepository to CouchbaseRepository interfaces |
| 110 | kafka-error-handler |
setErrorHandler → setCommonErrorHandler |
| 120 | missing-deps |
AI-driven catch-all for missing transitive dependencies |
| 130 | hibernate-embeddedid-mapsid |
Pre-populate nested embeddables for @EmbeddedId/@MapsId |
| 900 | pom-cleanup |
Remove duplicate/redundant POM dependencies |
When the fix loop succeeds, a diff-based learned pattern is saved to knowledge-base/learned/patterns/. These patterns are fed back to Claude CLI in subsequent runs, improving fix accuracy over time.