About this talk
In this talk, Thomas Schilling introduces Cloud Code for Spring developers, sharing his experiences and best practices built over four months of using the tool. He demonstrates how Cloud Code acts as a sophisticated code companion, utilizing natural language prompts to automate programming tasks and enhance development workflows within Spring Boot applications. By analyzing code, creating features, and generating tests, Cloud Code significantly improves commit velocity and productivity. Schilling emphasizes the importance of establishing project context through structured rules, skills, and hooks to guide the AI agent effectively. Through practical examples, he illustrates how to leverage Cloud Code's capabilities for tasks ranging from simple fixes to complex architectural decisions, highlighting the necessity of discipline and ownership in software engineering.
Full transcript
[music] >> So, welcome everyone. I'm Thomas Schilling and this is Cloud Code for Spring developers. I've been building with Cloud Code in Spring for the last 4 months. Today, I will share the patterns, the tools, and the workflows I use every day. I'm based in Stuttgart. I'm the founder of Futterquest, a wedding photo game platform built with Spring Boot, Kotlin, and HTMX. Everything I will show you
today comes from building that product with Cloud Code. I've been speaking at conferences and Java user groups all across Europe. And I'm open to new opportunities. So, if you want to level up your team on cutting edge ones or need an engineer shipping at a genetic velocity, add me on LinkedIn. This is my GitHub contribution graph since 2022. That little spike on the right is Cloud Code,
mid-December to mid-March, about 3 In this time, I shipped 3,700 commits across 1,700 sessions. I sent over 11,000 prompts to Cloud and my commit velocity went up five times. Let me show you what makes Cloud Code amazing. Quick show of hands, who has tried Cloud? For those who have, I want to show why Spring is the best bet for a genetic development. For those who haven't, I
will cover the basics. Before we dive in, let me show you the project we will use for all demos today. Futterquest is a wedding photo game platform. It's built with Spring Boot, Kotlin, juke, and HTMX. This is the ranking game feature I always wanted to build but never got to. Guests can react to photos on a beamer with a limited emoji budget. At the end, the top
images for each category are revealed. I built this feature multiple times with Claude, improving my setup each iteration. So, what is Claude Code? >> [snorts] >> Claude Code is a CLI tool that runs in your terminal. You type a prompt, the agent reads your code, and makes a plan. Then it edits files, runs commands, and checks the result. And it keeps going. You describe what you want,
and Claude figures out how, across the whole code base. The loop stops in three ways. Claude decides the task is done. Sometimes that's true, sometimes it's not. You press escape to interrupt, or Claude hits a permission prompt and waits for your okay. Every run is non-deterministic, so the same prompt can produce different results each time. That's normal, and you will learn to work with it. I gave
Claude a simple task: add timer validation to the create session method. First, Claude searched for the file, read the code, and looked at the existing exception to follow the project pattern. Claude then creates a new exception class, German for the user-facing message, English for the system error code. Claude picked this up from the existing exceptions without being told. In the second edit, it adds the validation check
at the top of the Then it runs the compiler to verify. Read, plan, act, observe. That's the loop, and Claude keeps going until it thinks the task is done. And you can invoke this loop from a lot of places. The primary interface is the CLI in your terminal. That's where I spend most of my time. But you can also run it inside VS Code or IntelliJ. You
can use Claude Code with the desktop app in your browser, or in your browser. For coding on the go, you use the smartphone app. You can also remote control it there, your local session. I mostly use the terminal because I want full control and the newest features, but you can also interact via Slack or GitHub actions. So, what can you actually do with it? Think of Cloud
Code as a co-worker that's really fast. You can design the architecture together. Claude will challenge your assumption and ask clarifying questions. You can create a plan and let the agent implement it. Claude builds features, designs UIs, and writes tests. And the agent reads the documentation for you. If you If you have a question about your co-worker, just ask them. Use Cloud Code Guide and the agent fetches
the last latest Cloud Code docs, so you don't have to click through the website. The difference to pair programming, your pair partner writes code really fast while you focus on the decisions. So, why does this work so well for Spring? The conventions in Spring are strong and opinionated, so Claude already knows the patterns. Controllers, services, repositories. The agent has seen millions of Spring projects. You get compile-time
verification. Claude runs the build, sees errors, and fixes them in the same turn. Testability is built in with Spring Boot Test, Mock MVC, and Test Containers. The agent can verify its own work. The structure is predictable, which means Claude can navigate your code base without you explaining where things live. The stack you already use is the best foundation for genetic development. So, your co-worker knows the stack.
How smart do you need them to be? Sonnet is best for fast iteration, simple fixes, and cheap sub agents. Opus is perfect for complex architecture, multi-file refactorings, planning, and debugging, the hard stuff. I mostly run Opus and I run out of tokens often, but the quality difference is worth it for complex tasks. With the effort command, you control how deep Claude thinks. Low for quick lookups, medium
for straightforward tasks, high for planning, and max for hard debugging. My default is Opus with high effort. I use Sonnet for sub-agents or when I have a straightforward task. But, what happens when the agent goes in the wrong direction? Claude tracks every file change as a checkpoint, so nothing is lost. If Claude goes in the wrong direction, {slash} rewind takes you back. You save your context window,
refine your prompt, and try again. With {slash} branch, you can fork a session to try a different approach without losing the context you've already built up. Experimentation is free. You're never stuck. Just rewind and try a different path. Let me show you what that looks like. I asked Claude to refactor the game state to use a sealed interface. Claude started editing, four updates to ranking game servers,
changing return times, refactoring methods. But, when I thought about it again, the tradeoffs, I wanted to stay with enums. I interrupted the agent with escape. You then invoke rewind with the {slash} rewind command or press escape twice. Claude shows me exactly what it changed. It added 37 lines and removed 23, all in one file. I press enter and all changes are reverted. My context window is preserved.
Rewind saves your context after Claude went the wrong path. Sub-agents protected by keeping heavy research out of your main thread. Heavy research burns through your context window. Once it's full, Claude's Claude starts forgetting the early parts of your conversation. Sub-agents solve this. A sub-agent runs in its own context window. Only the summary comes back to you. You invoke one just by asking research whatever with a sub-agent,
and Claude spins one up. Let me show you what that I asked Claude to use a sub-agent to analyze the server send event system of Photo Quest. The sub-agent spun up its own context window. It did 49 tool calls, read 84,000 tokens of code, and it took 90 seconds. And this is what came back, a complete architecture summary with for both SSE subsystem and an architecture diagram.
My main context window still clean, only the summary landed here, not the 84,000 tokens of research. And research is just one use. Launch multiple sub-agents in parallel, keep working in your main session. The heavy work happens on the side. But you can also run Claude without any UI at all. With Claude -p, you can launch the agent in headless mode. You give it a prompt and get
a result back. You can also tag Claude in PR comments. The Claude GitHub app then triggers an actions workflow. You can use it for code reviews, fixes, or documentation. Let me show you headless mode with a fast model. Notice the flag, --model haiku. This runs on the fastest, cheapest model. For quick look up like this, you don't need Opus. Haiku reads the migration files, finds the free
ranking name tables, lists all columns and constraints, and it takes only couple seconds. Pipe the result into other commands, use it in CI scripts, whatever you need. First, I tried Claude with zero config and vibe coded the photo reaction feature in a single shot. Three things came out of that session. Not one test was written. There were eight fundamental bugs that I had to find with manual
testing. And the one that actually hurt, Claude built three of the four game states and silently skipped the entire review review phase. The prompt mentioned it, but without a spec, the requirement drifted out of the Claude wrote over 2,000 lines just from one prompt, but I spent most of the session just debugging. The join endpoint returned raw JSON instead of HTML. Claude didn't know the convention for
rendering a fragment. All the photos showed up on the beamer at once, stacked on top of each other, and the game didn't even auto start for guests. At the end, the result page said "No votes." The query was broken. The core feature didn't work. And I find found five more bugs like these. I wasn't designing a feature, I was firefighting. Code alone isn't enough. Claude needs knowledge,
skills, and a plan. Think about it this way. Every new session is like a new developer joining your team. A new dev can read code, but you don't just send them the repo and say, "Good luck." You give them documentation, walk them through the architecture, explain the domain, and show them your workflow. Claude is the same, except every single session is day one. Claude doesn't remember the
last session. By giving great context from the start, you set up Claude for success. But first, let me show you what can happen when you skip that step. Photo Quest prints personalized game cards for winning guests. One card per A6 page. After adding a digital-only plan, I forgot that customers need to actually download the cards at some point. So, I sent the prompt from my phone through
Telegram bot connected to Claude code. No plan, no context. Claude researched, proposed 12 steps and started building. But, it's hard coded as six cards per A4 page layout. The cards print on one per A6 page. Claude had no way to know the fact that lived in my head. I never added it to the documentation. The agent only knows what's in the context you give it. You can't
blame the for missing whatever you never told it. So, how do you give Claude the right context? It starts with a file called Claude MD. Let me show you how to build one. Claude MD is the first thing the agent reads when it starts a session. Your rules live here. But, don't write a giant file on day one. Start with five lines. Your build command, your test
command, done. Then, use Claude code and observe what goes wrong. Wrong assumption, add a rule. Wrong import, add a rule. Every rule needs to earn its place through a real failure. Let me show you three critical rules from my Claude MD after months of the cycle. Each rule rule plays a different role. Compile after Kotlin changes. Run Gradle compile Kotlin, compile test Kotlin. This fast feedback loop
enables Claude to self-correct errors. Verify before done. Never mark a task complete without proving it works. Run tests, demonstrate correctness. Claude might think the task is done, but doesn't prove it. The vibe coding round in the last section showed exactly this. Last, multi-instance safe. No in-memory state for D dub or guards. Use database checks. Use advisory lock for distributed consensus. This is an architecture rule Claude can't
really deduct from the code. The rule doesn't explain advisory logs. It points to advisory log.kt, the file that contains the patterns. Claude reads the file on demand. That keeps the Claude MD short and the knowledge accurate. Every rule was earned through real friction. Session 100 benefits from every rule added in session 1 through 99. My full Claude MD has more than those three rules. It has an
architecture overview, tech stack, and onboarding contacts. It's below the official 200-line recommendation. Detail goes in .claude/rules. Separate files, one per topic. I have Kotlin, Spring Boot component, Tailwind, testing, and payment, just to name a few. Each file has a path field and a front matter. It only loads when Claude touches matching paths. Package by feature maps perfectly to Off conventions load for the off package, payment for
payment, and testing for tests. Claude only sees what's relevant to the code being changed. The last layer is auto memory. Claude takes automatically notes across sessions. It's stored in your user folder, not in Git. I actually disabled it because I have prefer everything trackable in Git. Here's the full hierarchy. Claude MD for the most important information. .claude/rules for path-specific conventions, and auto memory for personal local notes.
Your context window has a limit. /context shows you where you're spending it. You can see how many tokens the system prompt, tools, memory, files, skills, and messages use. It's useful for debugging your own setup if your Claude MD is too big, for example. Opus 4.6 gives you 1 million tokens by default. That sounds like a lot, but the problem is the more you fill it, the more
Claude attention drifts. You can trigger manual compression with {slash} compact when you need space, but I prefer fresh sessions. I don't use {slash} compact. I even turned off auto compact. Even with a million tokens, performance degrades when crossing a certain amount of tokens. Fresh sessions are cheaper than long ones. The prompt cache expires after 5 minutes. Resume a large session and every token gets reread uncashed. On
resume, resume can cost more than a whole session before it. So, have a resumable artifact when you take a break. Track the state in a markdown file. What's done, what's next, key decisions. When a session gets long, wrap it up manually. Tell Claude to summarize the progress and what and write a continuation prompt. In the next session, you can start with the continuation prompt or pull the
markdown file straight back into the Fresh session, fresh attention. Claude reads the artifact and picks up where you left off. We covered Claude MD and rules. That's project level context. But, Claude still doesn't know how your team works. Every team has a senior dev who knows, we always do test-driven development like this. Commits follow this format. Plan before you code. That knowledge lives in people's head, passed
through code reviews, and pairing Working with an agent forces you to write it down because the agent can't learn from watching, only from files in the file system. And here's the thing, once you write it down, new human developers benefit, too. These bundle of knowledges are called skills. Let me show you how they compare to Cloud MD. Cloud MD loads once when the session starts. It's always
in the context, but as the conversation grows, the agent's attention drifts away from it. Skills work differently. Only the name and a one-line description are loaded at startup. The full content loads fresh when the skill is invoked. Think of Cloud MD as your always-do X rules, build commands, conventions, project structure. Skills are for detailed workflow, like TDD steps or commit conventions. The key insight is skills inject
fresh context at the moment of action. So, keep your Cloud MD lean. Move detailed knowledge into skills. Let me show you which skills I use every These four skills are the ones I use on nearly every feature. Interview, TDD task, test, and commit. All of these things I used to do manually, except I wasn't disciplined about them. I used to skip tests when I was in a
rush. I wrote lazy commit messages when I just wanted to move on. Who wrote a lazy commit message before? You know. The agent doesn't get in a rush. Same discipline every time. That frees me up to focus what actually matters, verifying the tests, designing the features, or thinking about the architecture. And the discipline compounds. After 1,700 sessions, my Git history is clean, test coverage is high, and
every feature starts with a spec. So, what does a skill actually look like? Let me show you my simple one. Commit. A skill is just a markdown file in .cloud/skill. Each skill starts with front matter. The name field is what you invoke as a slash command. The description loads at session start. That's how the agent knows when to invoke the skill on its own. The body is
your instructions, steps, constraints, pattern. This commit skill is just four lines. Now, every change set gets grouped by logical feature with a proper commit message. And commit messages matter more now because the agent reads Git history, too. Cloud can quickly find out how features evolve and when bugs were introduced. Think of this like package by feature, but for your workflow. Each skill encapsulates one concern. But, the
biggest leverage isn't in commits. Let me show you where the real work happens before any code. If an AI generates code from a spec, the spec is now the highest leverage artifact for catching errors. This is from the future of software development event hosted by Martin Fowler. Think about your last big feature. 80% of the work happened before any code. Talking to stakeholders, making design decisions, shaping
what to build. If the agent generates code from your spec, then the spec is where errors get caught or where they sneak in. My interview skill makes my specs rock solid. It changed my workflow more than anything else. Let me show you what it Remember the demo project prompt from earlier? I handed it to interview. The explore sub agent read the code base to understand the architecture.
Then, it started the interview like a product manager doing discovery. First question, where does the manager find the ranking game? This multiple choice UI is the built-in ask user question tool. The interview skill tells the agent when to use it. Every option is grounded in what the explore found. This question actually exposed a gap in my Cloud MD. The docs mix the rating manager, the person running
the event, with the system admin. I went back and defined three roles: guest, manager, admin. I gave a custom answer. Create a doc link in the quest component because I knew exactly where my customer would expect the game. A few rounds later, the interview asked about security. Should we prevent react manipula- reaction manipula- manipulation? I gave a custom answer again, client-side with a cookie. Quick answer, didn't
think hard about it. And they actually put pushed back in the next round. You want reactions stored in the database, but the budget tracked client-side via cookie? That question made me think again. I gave a custom answer, database enforcement. Each reaction is tied to the event guest row. I wouldn't have caught this if I just started coding. But that's not all the interview does. I asked how
reaction buttons should appear on the guest's phone. The agent didn't ask you wireframe mock-up right in the terminal. Either show an overlay on the thumbnail or tap to enlarge. And the mock-up updates to show the detailed view. We're making UX decisions with visual wireframes before writing any code in the terminal. What the heck? I did eight rounds of questions like this. About 20 architecture and UX decisions
made explicit. The output, 170 lines back. But the interview is just the first half. You still need to review the spec. I review the spec in IntelliJ and add inline comments marked with a percentage sign. The agent reads the file, researches the code base, and updates the spec in place, or asks me clarifying question. It then suggested 10 changes. So I asked asked, "Explain why each is
necessary." Turns out eight were hallucinated urgency, edge cases that didn't matter. You are still the engineer. You need to understand each decision. Ask, what's the simplest approach? Reason together and chat about the trade-offs. What you saw on the terminal on the previous slide was iteration four of the demo. The entry point question, the state transition follow-ups, those come came from painful failures. Let me show you how
I got there, starting with iteration two, the first time I used interview on this feature. In iteration two, the agent completed seven phases and 17 tests were green. there was no navigation link, no button, no entry point. The manager couldn't reach the feature. The spec described what the feature does, not what the user does. And the plan was sliced by technical layers. That was a gap in
the skill itself. The interview didn't ask about entry points, so I improved the skill. The skill improved across each iteration. Iteration two was entry points, so I added mandatory topics and user stories. Iteration three had dead end screens, so I added state transitions and terminal states. In iteration four, 26 user stories, zero missing entry point. That's the version you just saw running. It's the same friction loop
as CloudMD. Observe failure, improve the skill, repeat. Let me show you what that looks like in the SkillMD. In iteration two, the skill was about eight lines. Interview me used the ask user question tool, explore the code base, write the spec to a file. That's For iteration four, I added mandatory topics, the specific gaps I hit in earlier iterations, codified as required Entry points, that's why the
demo asked, where does the manager find the game? State transition and terminal states. No more dead end screens. Every spec ends with a user story section. The screw skill grew specific because I hit specific failures. Same friction loop as Cloud MD. But where do you find expert offered skill that fit into your stack? General skill directories exist, but they're not focused on the JVM. The most popular
Spring Boot skill has 10,000 installs and it says use construction injection transactional. Things every LLM already knows. At jvmskills.com every skill teaches the agent a pattern or practice it wouldn't know on its own. Every skill is either expert offered or reviewed by an expert. No prompt injections. We started with Spring Boot best practices, testing conventions and workflows that improve the quality of your code base instead of
reducing it. If you're an expert on a topic, let's work on a skill together. Your knowledge benefits everyone and we have to catch up to the JavaScript ecosystem. Cloud code is non-deterministic. Skills under Cloud MD can be skipped. Hooks can't. They're wired into the life cycle. Every tool call from the agent invokes a hook. That's how you turn optional conventions into guaranteed behavior. Cloud code exposes dozens
of life cycle events. These are the three I use every Pre-tool use fires before every tool call and can block it. Post-tool use fires after the tool call and feeds the results back. Session end fires when the CLI session closes. Most hooks are shell scripts, but you can also post to an HTTP endpoint, run a single turn LLM evaluation, or spawn a sub agent with tool access.
practice. I have four hooks across three life cycle events. Pre-tool use has two. Git guardrail blocks dangerous Git commands. Pre-commit gate blocks the commit if lint or compile fails. Post-tool use feeds lint violations back after every file edit, scope to edit and write, not read. Session end warns on uncommitted work when the CLI closes. Let's start by walking through the Git guardrails hook. The Git guardrails hook
The Git guardrails script blocks dangerous Git commands. Pre-tool use fires before any tool call. Exit two means hard block. Claude literally cannot run the command. Claude sees blocked with a clear reason and adapts. Claude now can't mess up your Git history. It's not just about safety. Hooks can also enforce works workflow conventions. I don't want Claude to run Gradle test directly as it pollutes the context I
created a test skill that passes failures and reports only what matters. When Claude tried to run Gradle directly, the hook said, "No." And told Claude to use the test skill instead. In iteration two of the demo, Claude wanted to serialize the ranking participants to JSON and imported Jackson to object mapper. But, in Spring Boot 4, Jackson 2 doesn't exist anymore. The app failed to start. Claude then
serialized the JSON with string concatenation. Not exactly what we want. Detekt is the Kotlin equivalent of Checkstyle, static analysis that catches bad pattern before they ship. I added a forbidden import rule that blocks the import and tells Claude what to use instead. In this case, Jackson mapper from Jackson 3. Post tool use fires after every edit. The tech catches it immediately. Claude fixes it in the same
turn. No humans needed. That mistake can never happen again. The constraint is automated, not a suggestion. Remember, constraints compound from earlier? Claude MD compound across sessions, but they can be ignored. Hooks compound and they're enforced every time. Anything you put in a hook, you should put in a hook. Skills drift out of context, the Claude MD gets buried. Hooks fire every time at the moment of Hooks
handle what Claude does inside the code base, but Claude also needs to reach things outside the code base. Not every tool has a CLI available. Instead, we use the model context protocol. MCP is the open standard for connecting any application with AI. Without MCP, Claude is limited to shell commands and files on disk. With MCP, Claude talks to your issue tracker, your error monitoring, your IDE at
runtime. Let me show you which ones I actually IntelliJ gives Claude IDE actions like reformat file, rename symbols, or executing run configurations. With Linear, Claude can read issues, update their status, and pick up the next task. It organized my whole workspace in a few prompts. With the Sentry MCP, the agent can investigate production errors directly. No more copying stack traces. Javadoc Central gives Claude up-to-date documentation for
the libraries you use. Need something custom? Spring AI has an MCP service starter. IntelliJ is the one I use most. Let me show you why. The same tools you use every day are now available to the agent. Claude reaches for SED to format. It rewrites imports by hand and starts the app through Gradle. The agent is actively fighting the tool chain. With MCP, Claude calls reformat file,
does auto import optimization, and re-executes run configurations. The agent uses the IDE the way you do. The ID IE becomes an API for the agent. That's agent developer experience. The MCP Seurat project takes this a step further and gives agents access to the full IntelliJ API. Debugger, refactorings, inspections, even screenshots. The thesis is bold. The agent is the user, not the developer. Design tools for agents first.
The long-term vision is a headless IntelliJ runtime with no UI at all. Because the tools below the IDE matter more than the UI. But you need to tell Claude to use these tools. Claude discovers MCP tools automatically, but the model is trained on built-in tools, bash, and SED. Those are what Claude reaches for first. That's why I added a Claude MD rule that tells Claude use reformat
file instead. One line, now Claude picks the IntelliJ MCP every time. You should wrap more complex skills more complex workflows in a skill. My restart skill stops the running application, starts via MCP, waits for readiness, and then checks the logs. Four steps every time. We've covered the building blocks, context, skills, hooks, and MCP. The task decides which ones you reach for. A bug fix doesn't need a
nine-phase plan. A complex feature doesn't survive by coding. Match the approach to the problem. I will show you five levels from basic human-in-the-loop all the way to autonomous agents. Human-in-the-loop is where everyone starts and where you should start. Describe, watch, redirect. It's the most interactive mode. You stay in control. You need to space to build intuition for how the agent thinks. If you jump straight to autonomous
agents, you won't understand the It works great for bug fixes, small features, anything you can verify visually or with a quick test. I run up to like five terminals at a time, so it really is also fast. But, when the scope grows, exploring while implementing gets expensive. You want structure before code. That's what plan mode does. Claude thinks about structure before touching a file. Claude often invokes
plan mode on its own. You can also trigger it manually with shift tab. Claude explores the code base, proposes an approach. You review before any code gets written. No spec, no interview. You're exploring and prototyping, iterating fast. In level two, you react to Claude's proposals. But, when Claude keeps making wrong assumptions, the require- -ments only exist in your head. Level three, you drive the design. You need
to get them out into your specification. That's exactly what Simon uh told us yesterday. You become a product The spec externalizes what's in your head: requirements, edge cases, business rules. Pair on the spec, not the code. A 20-minute interview can replace hours of meetings. You already saw the interview skill section four. This is where it lives in the workflow. When do you need this? When the what
isn't obvious. When the feature needs decisions, not just code to write. Remember iteration one from the beginning? The same prompt, the same code code base, but now with context, And we had 37 tests at the end. 20 design decisions surfaced before a single line of code. We added eight rules to the Claude MD during the session. The iterate by friction loop running in real time. That's what
the first three levels give you. But, can we push further? In iteration four, the rankings game, I created a very detailed plan from the interview spec. Every phase should use the front-end design skill for the UI, verify with browser screenshot with the agent browser, and refactor with the simplify skill. Claude followed the plan at first. But, front-end design was only used once in phase one, then gone.
Browser verification, phases one through three, then was dropped. Simplify was never used at all. Even though it was in every phase of the Cross-cutting concerns drift out of the context window as the session grows. The agent isn't a deterministic machine, so let's introduce one. This is our deterministic machine. His name is Ralph. He doesn't stop. He does the same thing over and over again until you tell
him to stop. And that's exactly what we want. Claude gets lazy, skips skills, cuts corners, drops steps from the plan. Ralph, he doesn't. One phase executes, next phase, no drift. We start with interview and a spec first, like in level three. Then we start Ralph. Ralph executes each phase of the plan on its own and each phase gets a fresh In the simplest version, Ralph is just
a bash loop. A while loop that calls Claude-P with the plan file. That's it. Fresh context means the skill checklist isn't buried under thousands of lines of messages. The plan is the entire prompt. No drift. Let Ralph run while you do other work, reviewing code or designing the next Matt Pocock coined it, the day shift is thinking, the night shift is Claude implementing. That is our goal.
But the first version of Ralph I tried still had gaps. Iteration five used a flat markdown checklist. Claude ticks boxes in the markdown, no enforcement, 39 tests, but bunched at the end of phase instead of test first. In iteration seven, I changed the mechanism. Same plan structure, different contract. Not a markdown checklist, the built-in to-do right When the agent drifts, the to-do list injects a system reminder
with the open task. Markdown drifts out of the 60 tests, test first every phase. The instructions become the track state. But 60 tests only check what you thought to check. So, how do we find what we missed? I brought in second reviewer. Codex is OpenAI's command line agentic coding tool, their equivalent of Claude code. Same branch, same prompt. Let's look what each one caught. Claude went deep
on concurrency and state. The timer that hangs at the beamer tab closes. The guest zone that never gets redirected when the game finishes. A race condition in the budget check. Claude X went deep on authorization. The controller never checks its manager, so any guest can hit set up or reveal. A script injection in the live guest One overlap, the budget race condition. Everything else was different, and
they found a lot more than just these five. Claude found correctness bugs. Claude X found security bugs. Different models, different blind spots. I still review every line myself. I want to understand what my code is doing. Those are the workflow levels. Now, here's what makes them stick day to day. Now, I'll show you the tools and the tips I actually use every day. My first tip is
the sandbox, which is the single biggest reason I let Claude run long autonomous loops without watching every command. File system rights are locked to your project directory, and the network is locked to approved approved domains. In my config, only Maven Central, Gradle, and GitHub are allowed. Docker sandboxes go even further, strictly isolation. Each agent runs in a dedicated micro VM. You can delete and respawn in seconds.
I actually talk to the agent every day, and I think you should, too. I use handy.computer. It's open source, runs completely local, and has no usage limits. Voice is faster than typing, especially for planning, reviews, and brainstorming. Claude is actually very good at processing rambling speech, and it extracts the the intent behind your spoken words. When I type, I'm lazy. When I speak, I think out loud,
go back, reconsider. Claude sees my reasoning chain, not the polished prompt. Voice handles how you talk to one agent. What about multiple in parallel? When you want to run multiple agents in parallel, each one needs its own environment. That's what work trunk Three core commands make Git work trees as easy as branches, plus hooks to automate the setup. With my setup, the agent gets access to a
full isolated development environment, a dedicated Postgres instance, a dedicated local stack for S3 and email with deterministic port hashing. IntelliJ opens automatically via post start hook. So, you can run three agents on three features, and they never touch each other. When you're done, one command squashes, rebases, and tears everything down. When you're coding human in the loop, especially with multiple terminals, and across multiple sessions, you end
up with a lot of commit noise. The rebase commit skill rebases all unpushed commits into clean, logical feature Each commit contains a feature and its test. So, reviewers see features and not debugging and fixing noise. We've covered all the building blocks for working with cloud code on a Spring project. Now, I want to step back and ask, what does this actually mean for us engineers? Let's start
with where the discipline goes. With coding agents, you can produce mountains of code in a day, but without discipline, AI amplifies the mess. Engineering quality doesn't disappear. It moves to specs, test constraints, and risk management. And that changes what your job actually looks like. Your role expands because implementation is now cheap. The bottleneck moves to judgment. You decide what to build. You verify it's right, and you
own the outcome. You can't blame the AI. Your customer judges what you ship. And here's the uncomfortable truth. Building bad software has never been easier. That's why ownership matters more than ever, not less. Which brings us to the red line of this whole talk. The speed is free, but the discipline is yours. Remember iteration one? Claude generated code, tests failed, no hooks caught the errors, no skills
guided the structure. The speed was already there in iteration one. Claude was even faster than with the other setups. What changed was everything around Claude, the Claude MD, the skills, the hooks, and the specs. But none of this matters if you do until you start. Open your spring project, type Claude, pick a task from your backlog. Then observe what goes wrong. Add a rule, add a skill,
add a hook, and then you repeat. That loop is the whole method. There is no shortcut. And here's the thing that actually makes it worth it. Your setup compounds. Every rule, every skill, every session, Claude gets better at your project. The agent learns how your team works. You get faster every day, not because the AI gets smarter, but because your setup knows more about your project. Thank
you. I hope you learned something new today. Everything from today is available here on jvmskills.com. The slides, the skills I showed, links to every blog post and repository I mentioned. This whole talk was about engineers who care about quality and own the outcome. If your team values that kind of engineer, find me after or ping me on >> [applause]
More from this event
See all 38 talks →
Spring I/O 2026 Keynote
1:08:44
The Spring AI Ecosystem in 2026: From Foundations to Agents @ Spring I/O 2026
43:39
Breaching LLM-Powered Applications: Overcoming Security and Privacy Challenges by Brian Vermeer
48:40
New in Spring Security 7: MFA, OAuth2 and more by Daniel Garnier @ Spring I/O 2026
46:43