IntelliJ IDEA
IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin
AI-Assisted Java Application Development with Agent Skills
Agent-assisted development is quickly becoming a common mode of software development. New techniques are emerging to help LLMs generate code that matches your preferences and standards.
One common approach is to create an AGENTS.md, CLAUDE.md, or GEMINI.md file with project details, build instructions, and coding guidelines. The AI agent loads this file into context on every request.
This has two drawbacks:
- It consumes tokens on every request, increasing cost.
- Loading too much context into an LLM degrades its effectiveness.
Agent Skills is a new initiative that solves both problems by managing context progressively and extending AI agent capabilities on demand.
What are Agent Skills?
Agent Skills is an open standard introduced by Anthropic, to extend AI agent capabilities with specialized knowledge and workflows.
Consider a use case where you want an AI to generate presentations using your company’s slide template and design guidelines. You can package those assets (the PPT template, font files, and design rules) into a skill. The agent then uses that skill to generate slides that match your standards automatically.
A skill is a folder containing a SKILL.md file. This file includes metadata (name and description at minimum) and instructions that tell an agent how to perform a specific task. Skills can also bundle scripts, templates, and reference materials.
skill-name/ ├── SKILL.md # Required: instructions + metadata ├── scripts/ # Optional: executable code ├── references/ # Optional: documentation └── assets/ # Optional: templates, resources
The format of a SKILL.md file is:
--- name: name-of-the-skill description: Skill description. license: Apache-2.0 metadata: author: author/org version: "1.0" compatibility: Requires git, docker, jq, and access to the internet --- Skill Content
In a SKILL.md file, name and description are required fields, and you can add optional fields like licence, metadata, compatibility, etc. You can explore more about the Skill Specification here.
How do Agent Skills manage context?
At startup, agents load only the metadata (name and description) of installed skills. When you ask the agent to perform a task, it finds the relevant skill and loads only that SKILL.md into context.
This progressive loading keeps context minimal and pulls in additional information only when needed, unlike a monolithic CLAUDE.md that loads everything upfront.
What can be a skill?
Skills extend AI capabilities across a wide range: from coding guidelines for a specific library, to step-by-step workflows with reference documents and helper scripts.
For example, you can create a skill that:
- Specifies which library APIs to use and which anti-patterns to avoid.
- Bundles reference documentation in a
references/directory. - Includes helper scripts in a
scripts/directory.
Case Study: Implementing Spring Data JPA Pagination
Suppose you ask an AI agent to implement a Spring Boot REST API endpoint that returns a paginated list of Post entities along with their Comment collections.
Without guidance, the agent is likely to produce one of these common mistakes:
- N+1 SELECT problem — lazy-loading comments trigger a separate query per post.
- In-memory pagination — using
JOIN FETCHwith pagination loads all rows into memory, then paginates in the application layer.
You can check out the sample code from the GitHub repository https://github.com/sivaprasadreddy/agent-skills-demo
Let us see how an AI Agent might generate code when asked to implement a REST API endpoint to return paginated posts along with comments.
Without any specific guidelines or skills, the AI Agent generated the following implementation:
@RestController
@RequestMapping("/api/posts")
class PostController {
private final PostService postService;
PostController(PostService postService) {
this.postService = postService;
}
@GetMapping
PagedResult<PostDto> getPosts(
@RequestParam(name = "page", defaultValue = "1") int pageNo,
@RequestParam(name = "size", defaultValue = "10") int pageSize) {
return postService.getPosts(pageNo, pageSize);
}
}
@Service
@Transactional(readOnly = true)
public class PostService {
private final PostRepository postRepository;
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
public PagedResult<PostDto> getPosts(int pageNo, int pageSize) {
Sort sort = Sort.by(Sort.Direction.ASC, "id");
Pageable pageable = PageRequest.of(pageNo <= 0 ? 0 : pageNo - 1, pageSize, sort);
Page<PostDto> postPage = postRepository.findAllWithComments(pageable).map(PostDto::from);
return PagedResult.from(postPage);
}
}
If you run the application and invoke the GET /api/posts endpoint, you will get the results, but in the logs you will find the below WARNING:
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory
This essentially means, Hibernate will load all the entities into memory and then apply pagination. This will result in poor performance and even OutOfMemory exceptions if there are a large number of rows in the posts table.
A Spring Data JPA skill prevents both issues by giving the agent explicit guidelines and a working code example.
Spring Data JPA Agent Skill
Create a spring-data-jpa/SKILL.md file with the following content:
---
name: spring-data-jpa-skill
description: Implement the persistence layer using Spring Data JPA in Spring Boot applications.
---
Follow the below principles when using Spring Data JPA:
1. Disable the Open Session in View (OSIV) filter:
spring.jpa.open-in-view=false
2. Disable in-memory pagination:
spring.jpa.properties.hibernate.query.fail_on_pagination_over_collection_fetch=true
3. Avoid the N+1 SELECT problem: use JOIN FETCH to load associated child collections in a single query.
4. Avoid in-memory pagination: when loading a paginated list of parent entities with child collections:
* First, load only the parent IDs using pagination
* Then, load the full entities with their child collections using JOIN FETCH for those IDs
* Assemble the final Page from the paginated IDs and the loaded entities
## Pagination with child collections example:
PostRepository.java
public interface PostRepository extends JpaRepository<Post, Long> {
@Query("select p.id from Post p order by p.id")
Page<Long> findPostIds(Pageable pageable);
@Query("select distinct p from Post p left join fetch p.comments where p.id in :ids")
List<Post> findAllByIdInWithComments(@Param("ids") Collection<Long> ids);
}
PostService.java
@Service
public class PostService {
private final PostRepository postRepository;
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
@Transactional(readOnly = true)
public Page<Post> findPosts(Pageable pageable) {
Page<Long> idsPage = postRepository.findPostIds(pageable);
if (idsPage.isEmpty()) {
return Page.empty(pageable);
}
List<Post> posts = postRepository.findAllByIdInWithComments(idsPage.getContent());
return new PageImpl<>(posts, pageable, idsPage.getTotalElements());
}
}
How to use Agent Skills?
Agent Skills work with Claude Code, Codex, Gemini CLI, JetBrains Junie, and other agents. Install a skill at the project level or user level depending on your preference.
| Agent | Project-Level | User-Level |
| Junie | .junie/skills/ | ~/.junie/skills/ |
| Claude Code | .claude/skills/ | ~/.claude/skills/ |
| Codex | .agents/skills/ | ~/.agents/skills/ |
| Gemini CLI | .gemini/skills/(or).agents/skills/ | ~/.gemini/skills/(or)~/.agents/skills/ |
To use the Spring Data JPA skill with Claude Code:
- Copy the
spring-data-jpa/directory into{project-root}/.claude/skills/. - Ask Claude Code to implement a paginated REST API endpoint.
- Claude Code discovers the skill automatically and follows the guidelines.
As you can see, Claude Code automatically discovered the Spring Data JPA skill and generated the following implementation following the guidelines given in the skill.
@Service
public class PostService {
private final PostRepository postRepository;
public PostService(PostRepository postRepository) {
this.postRepository = postRepository;
}
@Transactional(readOnly = true)
public Page<Post> findPosts(Pageable pageable) {
Page<Long> idPage = postRepository.findPostIds(pageable);
if (idPage.isEmpty()) {
return Page.empty(pageable);
}
List<Post> posts = postRepository.findAllByIdInWithComments(idPage.getContent());
return new PageImpl<>(posts, pageable, idPage.getTotalElements());
}
}
With this implementation, only the Post IDs of the desired page will be loaded first, and then a list of posts along with their comments will be fetched in a separate query. This will fix the pagination in-memory issue.
Using Agent Skills with Junie
You can use the JetBrains Junie Agent to generate code which automatically loads the necessary skills from .junie/skills and directory.
The Junie agent loaded spring-data-jpa skill based on the given task and applied the guidelines. You can also observe that Junie automatically runs the relevant tests to verify the generated code is working or not and iterate until the tests are passed.
In the sample repository https://github.com/sivaprasadreddy/agent-skills-demo, you can find the following branches to try out the spring-data-jpa Agent Skill:
main: Starting point to try implementing the mentioned usecase without any skills.in-memory-pagination-issue: Usecase implementation generated by AI that results in in-memory pagination issue.skills: Withspring-data-jpaskill to try implementing the mentioned usecase.
Summary
If the AI agent is generating code with any anti-patterns or not following team coding standards and conventions, instead of fixing issues one-by-one with follow-up prompts, consider creating a skill to provide those as guidelines.
To explore more on Agent Skills, please refer to the following resources:
- https://agentskills.io/
- https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview
- https://developers.openai.com/codex/skills/
- https://geminicli.com/docs/cli/skills/
- https://junie.jetbrains.com/docs/agent-skills.html
