Skills-Based Development for Java & Spring Boot: A Complete Field Guide
From your first Spring Boot controller to reviewing a staff engineer’s PR — how “skills” change what AI-assisted Java development actually looks like.
Who this is for
This post works at two levels, and I’ve marked them so you can skim to yours:
🟢 Fresher note — if you’re newer to Spring Boot, these boxes explain the “why” in plain terms. 🔵 Architect note — if you’re evaluating this for a team, these boxes go into the governance and tradeoff angle.
Everyone should read the main body — the boxes are additive, not a fork in the road.
1. The problem, stated simply
Ask an AI assistant to build a Spring Boot REST API and you’ll get something that compiles. Whether it compiles into code your team would actually approve is a different question — one that depends on things no prompt fully captures: your logging conventions, your stance on Lombok, how you handle N+1 queries, whether @Transactional is used correctly, what "good" looks like in a code review.
🟢 Fresher note: this is the same gap between “my code runs” and “my code passed review” that you hit as a junior engineer — except now it’s the AI hitting it too, for the same reason: it doesn’t know what your team actually values unless someone tells it, consistently, every time.
🔵 Architect note: the instinct is to write a longer prompt. That doesn’t scale past one session. The structural fix is to encode standards as something the assistant loads and checks itself against, not something a human retypes. That’s what a skills-based development setup does.
I’m using Piotr Minkowski’s Claude Code template for Spring Boot as the concrete reference throughout, because it’s a complete, public example of this pattern applied to a real Java/Spring stack — not a toy demo.
2. The two-layer system: Agents vs. Skills
The repository organizes knowledge into two distinct kinds of files, and conflating them is the most common confusion when people first look at this pattern.
🟢 Fresher note: think of an agent like a colleague with a job title — “the security engineer” — and a skill like a page from the team wiki that colleague consults (“here’s how we configure JWT”). The agent decides what to do; the skill tells it how your team specifically wants it done.
🔵 Architect note: the reason this two-layer split matters is token economy and routing precision. Agents isolate context per role so a security review doesn’t drag the whole codebase into a JPA fix. Skills stay dormant — described only by a short trigger sentence — until a task actually matches, which is what keeps a large skill library from bloating every prompt.
The repository README explains the mechanism plainly: skills are reusable prompts that teach the assistant specific patterns for Java development, and they’re either auto-loaded based on context or invoked directly — for example, saying “commit these changes” loads a git-commit skill, or you can trigger one explicitly with a slash command.
3. The full agent roster
The template ships eight agents, each a specialist role:
The security-engineer agent is a good example of how detailed these get: it's framed as a senior security engineer whose focus spans vulnerability management, compliance automation, incident response, and building security into every phase of the development lifecycle. Its workflow starts by explicitly querying for context — infrastructure topology, compliance requirements, existing controls, vulnerability history — before doing anything, and it reports back in a structured status format with concrete metrics (controls deployed, vulnerabilities fixed, compliance score).
🟢 Fresher note: you don’t need to memorize all eight. In practice you mostly interact with spring-boot-engineer for day-to-day code, and the others get pulled in automatically for specialized asks (security, testing, deployment).
🔵 Architect note: the fact that security-engineer reports a "compliance score" and "incidents prevented" as part of its own definition is worth noting — it's designed to produce an auditable trail, not just a diff. That's the property you want if you're going to defend AI-assisted changes to a security review board.
4. The full skills roster
This is the part most posts skip past in favor of one flashy example. Here’s everything in the template:
🟢 Fresher note: notice that several of these — clean-code, design-patterns — are things you'd otherwise only learn by getting your PRs bounced back a few times. Having them as skills means you get that feedback before you open the PR, which is genuinely one of the best uses of this pattern for someone early in their career.
🔵 Architect note: the split between java-code-review (a skill) and code-reviewer (an agent) is a subtle but useful design choice — it lets a generic review agent invoke a Java-specific checklist without needing a Java-only agent persona. That composability is worth replicating if you extend this to other languages on a polyglot team.
5. Two skills worth looking at closely
5.1 logging-patterns — the one that surprises people
Most teams don’t think about logging as an AI-collaboration concern, but this skill’s premise is sharp: JSON logs are better for AI analysis than text logs — faster parsing, fewer tokens, direct field access. Compare:
# Text format — the AI has to "interpret" the string
2026-01-29 10:15:30 INFO OrderService - Order 12345 created for user-789, total: 99.99
# JSON format — the AI extracts fields directly
{"timestamp":"2026-01-29T10:15:30Z","level":"INFO","orderId":12345,"userId":"user-789","total":99.99}🟢 Fresher note: MDC is what lets you trace a single request across multiple log lines even under concurrent traffic — it attaches a request ID to every log statement in that thread automatically, without you having to manually pass it everywhere.
🔵 Architect note: this is a good example of a skill whose payoff isn’t “cleaner code,” it’s “cheaper and more reliable AI-assisted debugging.” When your logs are structured, an agent troubleshooting a production issue does it in fewer tokens with less risk of misreading a log line — a second-order benefit worth including in your own skill design.
5.2 clean-code — catching over-engineering, not under-engineering
Most linting advice worries about sloppy code. This skill’s stated concern runs the other way — catching unnecessary abstraction. Its own example is blunt:
// ❌ Over-engineered
public interface UserFactory {
User createUser();
}
public class ConcreteUserFactory implements UserFactory {
public User createUser() {
return new User();
}
}A UserFactory interface with exactly one implementation and no polymorphism in sight is complexity with no payoff — just new User() directly.
🟢 Fresher note: this one matters more than it looks. A lot of “clean code” habits picked up from tutorials (interface-everything, factory-everything) actively work against you in a real codebase, because every unnecessary layer is something the next person has to trace through for no reason. This skill exists specifically to push back on that instinct.
Get umesh kushwaha’s stories in your inbox
Join Medium for free to get updates from this writer.
🔵 Architect note: this is the skill that most directly encodes a judgment call — “when is abstraction earning its keep?” — which is exactly the kind of tacit knowledge that’s hardest to onboard new hires with and easiest to lose when a senior engineer leaves. Codifying it as a skill is arguably the single highest-leverage use of this whole pattern.
6. CLAUDE.md: the constitution everything else operates under
Skills describe how to solve a specific problem. CLAUDE.md sits above all of them — the standing rules loaded at the start of every session, regardless of which skill fires. A trimmed version from the template:
## Core Principles
- Simplicity First: make every change as simple as possible; minimal code
- No Laziness: find root causes, no temporary fixes, senior developer standards
## Project General Instructions
- Always use the latest versions of dependencies
- Always write Java code as a Spring Boot application, using Maven
- Always create test cases for generated code — both positive and negative
- Do not use the Lombok library
- Use `pl.piomin.services` as the group ID / base package (adjust to your own)
- Update README.md each time a new version is generatedIt also defines the operating loop the assistant follows for any non-trivial change:
- Plan mode for anything with 3+ steps or an architectural decision
- Self-improvement loop — after any correction, log the pattern to a lessons file so the same mistake isn’t repeated next session
- Verification before done — never mark a task complete without proving it: run tests, check logs, diff behavior
- Demand elegance — for non-trivial changes, pause and ask “is there a more elegant way,” while explicitly skipping this for trivial fixes to avoid overengineering
🟢 Fresher note: point 3 is the one to internalize even outside AI tooling — “prove it works” instead of “it looks right” is the actual habit that separates a junior from a senior reviewer.
🔵 Architect note: point 2 — the self-improvement loop — is the part most teams skip when they first set this up, and it’s the part that compounds. Without it, you correct the same mistake every session forever. With it, corrections become permanent skill/CLAUDE.md updates.
7. Anatomy of a SKILL.md file
Every skill in the repo follows the same shape. Here’s the java-architect skill's frontmatter as a template:
---
name: java-architect
description: Use when building, configuring, or debugging enterprise Java
applications with Spring Boot, microservices, or reactive programming.
Invoke to implement WebFlux endpoints, optimize JPA queries and database
performance, configure Spring Security with OAuth2/JWT, or resolve
authentication issues and async processing challenges in cloud-native
Spring applications.
metadata:
version: "1.0.0"
domain: language
triggers: Spring Boot, Java, microservices, Spring Cloud, JPA, Hibernate,
WebFlux, reactive, Java Enterprise
role: architect
scope: implementation
output-format: code
---
## Core Workflow
1. Architecture analysis — review project structure, dependencies, config
2. Domain design — DDD and Clean Architecture; resolve ambiguous
boundaries before implementation
3. Implementation — build services with Spring Boot best practices
4. Data layer — optimize JPA queries; run `mvn verify -pl <module>` to
confirm correctness; on failure, check Hibernate SQL logs and re-run
5. Security & config — apply Spring Security; run `mvn verify` after
changes to confirm filter chain and JWT wiring
6. Quality assurance — run `mvn verify` / `gradle check`; confirm 85%+
coverage via JaCoCo before closing🟢 Fresher note: the description field is doing the actual work of deciding when this fires. If you ever write your own skill and it never seems to trigger, the description is almost always the reason — it needs to name the exact kind of task, not just the general topic.
🔵 Architect note: notice step 6 hardcodes a coverage threshold (85%) as a gate, not a suggestion. That’s a policy decision embedded directly into the workflow — which is precisely the kind of thing that should go through the same review your CI config does, since it’s functionally equivalent to a quality gate.
8. Worked example: one prompt, traced end to end
Prompt:
“The
OrderService.getOrdersForCustomer()endpoint is slow under load. Investigate and fix."
Here’s what happens when the skill stack is engaged, not just a bare model:
- Routing —
jpa-patternsandjava-architect's JPA-optimization reference match the trigger ("Spring Data JPA," "lazy association," "slow endpoint"). - Reproduce, don’t guess — Hibernate statistics get enabled in the test profile; the existing integration test runs; the query count is reported (say, 1 + 47 for 47 orders — the classic N+1 signature).
- Narrow fix, not a global one — a
JOIN FETCHor@EntityGraphis applied to the specific repository method. The skill explicitly warns against blanket-converting associations toEAGER, since that just relocates the problem. - Verify — the same test re-runs with statistics still on; the query count is now flat regardless of row count.
clean-codesanity pass — before the diff is presented, a check for unnecessary new abstractions introduced by the fix.- Logging check — if the fix touches a code path with existing log statements,
logging-patternsconfirms they stay structured (JSON, not string interpolation). CLAUDE.mdverification-before-done rule — nothing is marked complete without the before/after query counts as evidence.
Compare that to a bare prompt without any of this scaffolding: you’d likely get a fix, with no proof it addressed the root cause, no check for whether it introduced needless complexity, and no guarantee it matches your team’s logging or Lombok conventions.
9. Getting started, practically
🟢 For freshers — the fastest path in:
- Clone the template repo.
- Run
/agentsto see the available specialists and/skillsto see the loaded skills. - Try invoking a skill manually to see what it does before trusting auto-routing — e.g.
/design-patternson an existing class. - Read
CLAUDE.mdtop to bottom once. It's the fastest way to understand why generated code looks the way it does.
🔵 For architects — building your own library:
- Mine real code review comments. The corrections you make repeatedly are your first skill candidates —
clean-codeandlogging-patternsin this template both look like exactly this kind of distilled, repeated feedback. - Write the trigger description first, and test that it actually fires before writing the workflow body.
- Bake in a verification command, not just advice — a skill without a re-runnable check is a paragraph with extra formatting.
- Keep the library small and sharply scoped. Overlapping trigger descriptions cause misrouting; fewer, precise skills beat a large vague library.
- Version skills like code, and route corrections back into them via a lessons-log step, the way
CLAUDE.md's self-improvement loop describes.
10. Skills vs. subagents vs. plain prompting — quick decision table
11. Why this matters more than it looks
The productivity story here — “code gets generated faster” — is the least interesting part. What skills-based development actually gives a team is governability: a place where standards live as reviewable artifacts, get versioned like code, and produce an audit trail (query counts, coverage numbers, compliance scores) instead of a diff you have to just trust.
For a fresher, that means getting the kind of consistent, immediate feedback that used to take several PR review cycles to absorb. For an architect, it means AI-assisted development can be made accountable across a whole team the same way a style guide or an ADR is — not through more careful prompting, but through infrastructure the team owns and keeps improving.
Reference: piomin/claude-ai-spring-boot — the Claude Code template this post is built around, including the full agent and skill set discussed above.








