AI IntelliJ IDEA Java JetBrains AI

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 FETCH with 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.

AgentProject-LevelUser-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:

  1. Copy the spring-data-jpa/ directory into {project-root}/.claude/skills/.
  2. Ask Claude Code to implement a paginated REST API endpoint.
  3. 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: With spring-data-jpa skill 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: