We’ve all been there: a repository that was once the undisputed star of the organization is now a “look-but-don’t-touch” relic. Of course, it’s running on an end-of-life runtime, uses an ancient version of a framework that most developers have forgotten about for years, and its dependencies have more vulnerabilities than features. When it comes to migrating this sort of technical debt, my usual instincts would have me run away as fast as I can to avoid the weeks of manual “search-and-replace” and dependency hell.
But recently, I decided to see if I could turn this chore into an interesting conversation. Using Gemini CLI and the Conductor extension, I naively took on “Project Sagan” (a legendary but archived Spring Boot reference app) to see if an agentic workflow could handle the heavy lifting for me while I keep in the loop and give high-level strategic guidance.
Obviously modernizing project Sagan is at best a secondary goal of this whole exercise. The main goal was to discover how far Conductor with its spec-driven approach can take us and to distill learnings (mentioned further down below) for applying these tools in a more business-critical environment.
Spoiler alert: I had more fun than I’m willing to admit.
About the Legacy Spring Boot Application – Project Sagan
Project Sagan isn’t a codebase that I was at all familiar with before I asked Gemini something along the lines of “What would be an example of a somewhat popular legacy Spring Boot application that I could use to test some new migration tooling?”. The Sagan project came up as one of the first suggestions, and the rest is history.
In case you are still curious: Sagan acted as the reference application that powered the spring.io website and was designed to serve as a resource for developers to see how the Spring team uses Spring to implement a real-world app. It was officially archived in the Spring of 2023.
Conductor Extension for Gemini CLI
Most AI coding tools fail because they lack context or a clear “definition of done”. Spec-driven development (SDD) changes the game by creating a contract between you and the AI. You approve the plan, then the AI executes the toil.
Conductor is a Gemini CLI extension that uses the native CLI features like context and slash commands to implement SDD and provide you with the tool to specify, plan, and implement sophisticated solutions and, of course, the holy grail: modernize long-forgotten legacy applications.
To get started with Conductor, you can visit the Gemini CLI Extensions Gallery. In addition to extension discovery, the gallery also provides a handy installation shortcut that basically templates the extension installation command for Gemini CLI.

Copy the Gemini CLI to your terminal, hit enter, and let the fun begin:
gemini extensions install \
https://github.com/gemini-cli-extensions/conductor \
--auto-update
Once installed, Conductor consists of three logical workflow steps:
- Setup: Think of this like the employee onboarding period. We’ll create the necessary context for Conductor to fully understand the application, tech stack and give it additional guidance for how to work and what style guides to follow. The creation of these assets is very collaborative and you’ll have the opportunity to review and edit all resources to make sure they match your expectations.
- Track Creation: Work packages are structured as “Tracks” that act as an explicit scope boundary. Usually, you start a track with a high level goal in mind and then collaborate with Conductor to distill that into a tactical specification and execution plan.
- Track implementation: This is where the previously generated plan is executed by Gemini CLI. As a developer, you can still be in the loop, approve tools and give guidance, but the coding agent will try to use all its available resources and information to follow the plan to achieve the specified goals.

Establishing reviewed application context with the Conductor Setup Stage
Let the fun begin! Let’s launch Gemini CLI and start Conductor’s setup and context initialization phase:
/conductor:setup
What follows next are a series of multiple-choice questions like:
Question 1: Who are the primary target users for this reference application?
(Select all that apply)
A) Java developers looking for real-world Spring Boot implementation examples.
B) Spring team members maintaining the spring.io website infrastructure.
C) Technical writers and content creators contributing to Spring guides and blogs.
D) Type your own answer
E) Autogenerate and review product.md
Please respond with A, B, C, D, or E.
These are a simple way to contribute my understanding of the application and give feedback on what the model figured out on its own. As I mentioned before, the Sagan project isn’t a codebase I’m very familiar with, so for most of the questions I’ll be trusting Gemini’s own judgement (aka. Vibe-Yoloing my way through and hoping it will magically work somehow).
The setup stage ends with a very tempting call to action for creating my first Conductor track:
3.2 Propose a Single Initial Track (Automated + Approval)
Since this is an existing project that is currently archived,
I propose a track focused on modernizing and maintaining the
codebase to ensure it remains a high-quality reference
application.
Proposed Track:
- Modernize dependencies and improve observability:
Update core Spring Boot and dependency versions, and
enhance Actuator health indicators for better system
monitoring.
What would you like to do next?
A) Approve: This is a great first step.
B) Suggest a different track: Tell me what you'd like to
work on instead.
Please respond with A or B.
Even though I fear it’s a trap: Let’s go with option A (aka the red pill):

Track 1: Spring Boot Migration
With the first track basically auto-created, we end up with a fully specified track in ./conductor/tracks/modernize_deps_20260119 that contains the following artifacts:
- index.md contains the links to the files below
- metadata.json contains the metadata about the track like its status and timestamps
- spec.md contains the main goal of the track i.e. what should be achieved
- plan.md contains the step by step plan that the implementation should follow and how to validate the outcome.
At this point I would edit the files, add additional goals or tweak the proposed target state. Because I still don’t know much about the Sagan application, I’ll again just go with what was suggested and start the implementation with:
/conductor:implement
What follows is a range of trial and error loops that have the application bump against all sorts of issues like the fact that my Cloud Workstation Image only has Java 17 pre-installed, outdated dependencies, dependency incompatibility etc. Luckily I’ve allowlisted most tools for this experiment such that my involvement in this phase is limited to approving the write operations to a) apply some basic sanity checks and b) hopefully learn a thing or two about Spring Boot migrations.
A few things I realized quite quickly into this first upgrade track:
- Having had the opportunity to review and approve a specification and plan for the implementation phase gives me a lot of confidence in the direction in which the agentic coding is taking me.
- The dependency alignment would have been an absolute nightmare without Gemini CLI’s web search tool that did all the compatibility research on my behalf.
- Comprehensive and fast unit tests as well as good error logging are an absolute must for this level of operation. Without them I’d be pretty much flying blind.
At the end Conductor asks me for a final manual validation before it declares success and marks the first step as completed.
To fully understand what was going on we can use Gemini CLI and ask it to summarize the migration steps using the Git history and the attached Git notes that explain some of the decisions and rationale — a really nice touch in my opinion.
Show me a summary of all commits on this feature branch and also use
the corresponding git notes that are attached to them.
Lastly, we can also use the Genmedia MCP server with Nano Banana Pro to visualize this first update track. Just for fun of course:

Track 2: Migrating to a supported Spring Boot 3.x version.
In our first track half of the fun was spoiled by the Conductor setup stage that automatically suggested a plan for us. That needs to change and it is finally time to experience the full track lifecycle.
How about we create a track that takes Spring Boot and migrates it to the next major version 3.x:
/conductor:newTrack Update my application to Spring Boot 3.x
We’re again walked through a series of questions that help Conductor solidify its track spec.md and plan.md files.
One thing to note is that you can also answer with answers other than the suggested alternatives:
To ensure a smooth upgrade to Spring Boot 3.x, we must address
the Java version requirement. Spring Boot 3 requires Java 17
as a minimum.
How should we handle the Java upgrade? (Select all that apply)
A) Upgrade the project's source compatibility to Java 17.
B) Upgrade the CI/CD pipeline configuration (e.g., Concourse) to use a Java 17 environment.
C) Keep the source compatibility at Java 11 but run on a Java 17 runtime (Not recommended for SB 3).
D) Type your own answer
Please respond with A, B, C, or D.
If I’m unsure about any of the questions I can also ask follow up questions instead of giving an answer:
I'm unsure between A and B. What are the differences and implications?
And Conductor will happily provide the required context and explanations that help me make an informed decision:

After we approve the spec.md and plan.md our second track is ready to be kicked off. My spec.md file still doesn’t clarify the exact minor version and only mentions Spring Boot 3.x but I’m willing to find out if I should have been more specific. Let’s go:
/conductor:implement
It turned out that my hunch about the not fully specified 3.x version was correct. When left to the implementation it decided to go with 3.4 to “go with a more stable version” and dismissed 3.5 as too recent. After I told it to check if 3.4 was already EOL it revised its plan and went with 3.5 instead. Of course, this could have been avoided, if I edited the spec.md before jumping into the implementation.
Once the Java and Spring Boot versions were bumped Gemini CLI takes us on a journey to fix a number of downstream issues including:
- Jakarta EE Migration: Replaced all javax.* imports with jakarta.*
- Gradle 8.12 Upgrade: Updated the build system to support Java 17
- Spring MVC 6 Path Matching: Adjusted to the new default where trailing slashes are no longer automatically matched
At the end Gemini CLI again follows the validation steps in the workflow.md file and runs the test suite to validate everything is running correctly.
And of course, as a bonus, we can create a pretty visualization of what we have achieved:

Lessons Learned
Since it’s unlikely that any of us will use the modernized Sagan application at any point in the future, I wanted to at least extract a few key learnings from this experiment such that the tokens weren’t a total waste:
1. Avoid Ambiguity and provide clear goals
When I asked Conductor to modernize my Spring Boot application to 3.x without a specific minor version it chose 3.4 that it considered the safer bet because it was considered “more stable”. It was only after I prompted it to check the EOL (End of Life) status that it pivoted to version 3.5.x.
Lesson: Read the spec.md carefully and try to remove any ambiguity that you spot before moving on to the implementation phase. This way you save yourself a lot of rework or unnecessary iterations.
2. Useful out-of-the-box, unbeatable with customization
Conductor is already super useful with just the default configuration and by basically telling it “you go figure it out, I trust you”. But there are also opportunities to apply specific learnings for subsequent projects and for example customize your templates and style-guides to match your organization’s needs. This could also help reduce the ambiguity factor as mentioned above.
Lesson: When working in a team or on repeated tasks consider adapting or augmenting the Conductor resources with your own preferences.
3. Giving more Environment Context to the Agent
During the initial migration, I hit a few “trial and error” loops because my Cloud Workstation image didn’t have any Java version older than 17 pre-installed. The Conductor setup stage was great at identifying a lot of information about the Sagan project but it lacked understanding about the developer environment and the target runtime.
Lesson: Always align your agent’s plan with your environment’s reality. Whether it’s pre-installed SDKs, restricted network access, or specific compute limits, make sure to add these constraints to your Conductor context resources during the setup phase.
4. Approval-Loops are a great learning tool
Going full “YOLO” and walking away right when you send your Conductor to implement your plan might sound like a tempting approach to save time and hope for the best. However, the review and approval steps provided me with a surprisingly interesting learning experience, not to mention the few times where I was able to course correct early.
Lesson: Don’t view manual reviews and approvals as a bottleneck. They are a great opportunity to learn the codebase, chat about it, and intervene early if the agent’s logic deviates from your architectural goals.
Summary and Next Steps
We’ve officially “modernized the heck” out of a legacy application that the world had largely moved on from. But the real benefit is far greater than the updated Gradle dependencies on a project that realistically won’t just come back to life because we’ve modernized it.
By using the Gemini CLI and Conductor, we transformed a daunting technical debt project into a structured, manageable, and (I have to admit) enjoyable collaboration. We went from “Vibe-Yoloing” our way through the setup to orchestrating a sophisticated version upgrade with built-in validation.
If you want to get your own hands dirty with a Conductor-guided modernization, grab your own favorite legacy application and start your own adventure.
GitHub – danistrebel/sagan: The spring.io site and reference application [Gemini CLI Conductor Experiment]
If you want to continue the quest that we started, maybe consider cloning the Sagan experiment fork from this post and see if you can create a new track to migrate from Java 17 to Java 21. Just for fun of course!
Just for Fun: Migrating a legacy Spring Boot application with Conductor in Gemini CLI was originally published in Google Cloud – Community on Medium, where people are continuing the conversation by highlighting and responding to this story.
Source Credit: https://medium.com/google-cloud/just-for-fun-migrating-a-legacy-spring-boot-application-with-conductor-in-gemini-cli-ad621d93fdb6?source=rss—-e52cf94d98af—4
