CLAUDE.md Java Project Mastery: Teaching Claude Code Your Codebase

  • Last Updated: May 7, 2026
  • By: javahandson
  • Series
img

CLAUDE.md Java Project Mastery: Teaching Claude Code Your Codebase

A well-written CLAUDE.md Java project file is the single biggest upgrade to your Claude Code workflow. Without it, Claude Code rediscovers your conventions every session. With it, it knows your Spring Boot architecture, Maven commands, testing standards, and what not to do — from the very first interaction. This guide covers every section, advanced techniques, and a ready-to-use template.

Every developer who uses Claude Code has the same early experience: the first few sessions are impressive but imprecise. Claude Code makes suggestions that almost fit the project — but the package names are slightly off, the test framework is not the one the team uses, or the exception handling pattern does not match what already exists in the codebase. You correct it, it adjusts, and the quality improves — but only for that session. The next day, it starts fresh.

The CLAUDE.md file is the solution to this problem. It is a plain Markdown file you place at the root of your project, committed to version control alongside your source code, and filled with the information Claude Code needs to be effective from the very first interaction of every session. Think of it as onboarding documentation written specifically for an AI engineering partner — the equivalent of the README a new team member reads before their first day, but tailored for an agent that will be writing and modifying code.

This article is a thorough guide to CLAUDE.md — what it is, why it matters, what to include for a Java project, how to structure it for different project types, and the advanced techniques that distinguish a basic CLAUDE.md from one that makes Claude Code genuinely excellent. By the end, you will have a clear template to adapt for your own project and the principles to improve it over time as your project evolves.

1. What Is CLAUDE.md and How Does Claude Code Use It?

CLAUDE.md is a Markdown file that Claude Code reads automatically at the start of every session. It is not a configuration file in the sense of setting system variables or enabling features. It is a natural language document in which you describe your project — its purpose, its structure, its conventions, and its constraints — in the same way you would brief an experienced engineer joining the team for the first time.

When you run claude inside a project directory, Claude Code automatically looks for a CLAUDE.md file in the current directory and its parent directories. If it finds one, it reads the content and keeps it in its working context throughout the entire session. Everything written in CLAUDE.md is treated as a persistent, high-priority context that shapes how Claude Code understands and works within the project.

This has a significant practical effect. Without CLAUDE.md, Claude Code must infer your project’s conventions by reading source files on demand. It will often get things mostly right, but it makes assumptions based on what it sees — and what it sees is limited to the files it reads during the session. It may miss team-specific decisions that are reasonable given the context but not obvious from code alone: why a particular pattern was chosen, which areas are under active refactoring, and what third-party libraries the team has decided not to use.

With a well-written CLAUDE.md, Claude Code starts every session already knowing your architectural decisions, naming conventions, build and test commands, coding standards, and important constraints. The quality and consistency of the code it produces improve noticeably because it is working from the full picture rather than a partial one inferred from a subset of source files.

Crucially, CLAUDE.md instructions are also active when Claude Code is running longer autonomous tasks. During a multi-step workflow in which Claude Code executes several build-fix-test cycles without constant prompting from you, the standing instructions in CLAUDE.md provide continuous guidance. They ensure that even during autonomous execution, Claude Code stays within the boundaries and conventions your team has established.

2. Core Section 1 — Project Overview

The project overview is the first thing Claude Code reads, and it sets the frame for everything else. Keep it concise — three to five sentences — but explicitly include the technology stack. Claude Code needs to know the Java version, the build tool, the main framework, and the database to make correct decisions about syntax, annotations, and library choices.

## Project Overview
Customer Management Platform — Spring Boot 3.3 REST API.
Handles customer registration, profile management, and subscription
lifecycle for an e-commerce platform. Consumed by the web frontend
and mobile apps via REST.
 
Java 21 | Maven 3.9 | Spring Boot 3.3 | PostgreSQL 15
Spring Security 6 | JPA/Hibernate | Flyway migrations

The technology versions matter. Claude Code knows that Spring Boot 3.3 uses Jakarta EE 10, so imports should use jakarta.* rather than javax.*. It knows that Java 21 supports records, sealed classes, pattern matching, and virtual threads. Specifying the versions up front means it can make correct syntax choices without inferring them from individual files.

3. Core Section 2 — Build and Test Commands

This section is critical and often the most consequential. Claude Code will use these commands when it compiles your project, runs tests, and verifies changes it makes. If the commands are wrong or incomplete, the build output Claude Code reads will be misleading, and its ability to fix errors will be compromised.

Be precise and complete. If you use Maven profiles for different test types, list them. If integration tests require a running database that must be started separately, note that. If there is a specific order to commands, document it. Do not assume Claude Code will figure out these details — it will, but only if it encounters them during a session, and that delayed discovery is worse than clear upfront documentation.

## Build and Test Commands
- Build (with tests):    mvn clean install
- Build (skip tests):    mvn clean install -DskipTests
- Unit tests only:       mvn test
- Integration tests:     mvn verify -P integration
  NOTE: Integration tests require a local PostgreSQL instance.
  Start with: docker-compose up -d db
- Code coverage report:  mvn verify jacoco:report
  Report at: target/site/jacoco/index.html
- Checkstyle:            mvn checkstyle:check
- Run locally:           mvn spring-boot:run -Dspring-boot.run.profiles=local

4. Core Section 3 — Project Structure

The package layout section is where you describe how your project is organised. This prevents Claude Code from placing new classes in the wrong packages, which creates noise in code reviews and requires unnecessary correction.

Java projects vary enormously in structure. Some teams organise by technical layer: controller, service, repository, model. Others organise by feature or domain: users, orders, billing, notifications. Some use hexagonal architecture with domain, application, and infrastructure packages. Whatever your structure, describe it explicitly. Do not assume Claude Code will infer the pattern correctly — even a small mismatch in package naming causes real friction.

## Project Structure
src/main/java/com/example/cms/
  api/
    controller/      — REST controllers (@RestController)
    dto/             — Request/Response objects (Java records)
  domain/
    service/         — Business logic (@Service)
    model/           — Domain entities and value objects
    exception/       — Domain-specific exceptions
  infrastructure/
    persistence/     — JPA entities and repositories
    external/        — External API clients
  config/            — Spring configuration classes
  security/          — Spring Security config and JWT handling
 
src/test/java/com/example/cms/
  api/controller/    — MockMvc controller tests (@WebMvcTest)
  domain/service/    — Unit tests for services (Mockito)
  infrastructure/    — JPA integration tests (@DataJpaTest)
 
src/main/resources/
  application.yml          — Base configuration
  application-local.yml    — Local dev overrides
  db/migration/            — Flyway SQL migration scripts (V1__..V2__.. naming)

5. Core Section 4 — Coding Conventions

This is where you encode your team’s engineering standards. The key principle for writing this section effectively is to be specific and actionable. Vague instructions like ‘write clean code’ or ‘follow best practices’ give Claude Code nothing to work with because they do not specify what ‘clean’ or ‘best’ means in the context of your project. Concrete instructions like ‘always use constructor injection, never @Autowired on fields’ are ones Claude Code can follow reliably.

Focus on the conventions that, if violated, would cause a code review rejection. Those are the ones worth documenting. If a pattern is merely a preference that reviewers would accept either way, it is not worth the CLAUDE.md space.

## Coding Conventions
 
### Java Features
- Java 21 features are encouraged throughout: records, sealed classes,
  text blocks, pattern matching in switch, sequenced collections
- Prefer immutable objects. Use records for DTOs and value objects.
- Use Optional<T> for nullable return values in public service methods
- Never return null from a public service or repository method
 
### Dependency Injection
- ALWAYS constructor injection. Never @Autowired on fields.
- All injected dependencies must be final fields.
- Use @RequiredArgsConstructor (Lombok) or write the constructor explicitly.
 
### Naming
- Controllers:    [Domain]Controller       e.g. CustomerController
- Services:       [Domain]Service          e.g. CustomerService
- Repositories:   [Domain]Repository       e.g. CustomerRepository
- Request DTOs:   Create[Domain]Request    e.g. CreateCustomerRequest
- Response DTOs:  [Domain]Response         e.g. CustomerResponse
- Exceptions:     [Description]Exception   e.g. CustomerNotFoundException
 
### Logging
- SLF4J only. Use @Slf4j (Lombok) or private static final Logger.
- Never System.out.println, never e.printStackTrace()
- INFO: business operation entry and success
- DEBUG: internal state, intermediate results
- ERROR: caught exceptions with full stack trace
- Never log passwords, tokens, or full request/response bodies
 
### Exception Handling
- Custom exceptions extend RuntimeException
- @ControllerAdvice GlobalExceptionHandler handles all REST errors
- Return RFC 7807 Problem Details for API error responses
- Never expose stack traces or internal details in API error responses

6. Core Section 5 — Testing Standards

Testing conventions are one of the most impactful things to document because incorrect test structure causes real problems — tests that do not follow your patterns will fail in CI, require rework, and frustrate reviewers. Tell Claude Code exactly how you test, which framework you use, and what a correct test class looks like.

Including an example test structure in CLAUDE.md — even a brief snippet — is more effective than a prose description. Claude Code is very good at pattern matching against examples. An example test that shows the class structure, annotations, method naming, and assertion style gives Claude Code a concrete reference that prose alone cannot fully communicate.

## Testing Standards
 
### Frameworks
- JUnit 5 (Jupiter) for test structure
- Mockito for mocking dependencies
- AssertJ for all assertions — never use JUnit assertions directly
- Testcontainers for integration tests requiring real PostgreSQL
 
### Unit Test Structure
@ExtendWith(MockitoExtension.class)
class CustomerServiceTest {
    @Mock CustomerRepository customerRepository;
    @Mock EmailService emailService;
    @InjectMocks CustomerService customerService;
 
    @Test
    void findById_existingCustomer_returnsCustomerResponse() { ... }
 
    @Test
    void findById_unknownId_throwsCustomerNotFoundException() { ... }
}
 
### Controller Test Structure
@WebMvcTest(CustomerController.class)
class CustomerControllerTest {
    @Autowired MockMvc mockMvc;
    @MockBean CustomerService customerService;
    ...
}
 
### Test Naming Convention
methodName_stateOrCondition_expectedBehaviour
Examples:
  createCustomer_validRequest_returnsCreatedCustomer
  createCustomer_duplicateEmail_throwsConflictException
  findById_nonExistentId_returns404

7. Core Section 6 — Negative Instructions

Negative instructions — things Claude Code should explicitly NOT do — are just as important as positive ones. They prevent Claude Code from introducing patterns, dependencies, or modifications that your team has consciously decided against. Without them, Claude Code may make reasonable-sounding choices that violate constraints it could not have known about.

Write negative instructions specifically. ‘Do not use bad patterns’ is not useful. ‘Do NOT use Lombok @Data on JPA entities because it causes issues with bidirectional relationship hashCode cycles’ is a specific, actionable constraint with a reason attached.

## Do Not
 
- Do NOT use @Data (Lombok) on JPA entities — causes hashCode/equals
  issues with bidirectional relationships and Hibernate proxies
- Do NOT use @Autowired on fields — always constructor injection
- Do NOT use @Transactional on controller methods
- Do NOT add new Maven dependencies to pom.xml without asking first
- Do NOT modify any Flyway migration file that already exists in the repo
  (V1__, V2__, etc.) — create a new migration file instead
- Do NOT use Optional.get() without first checking isPresent()
- Do NOT return JPA entity objects directly from REST controllers
  — always map to a DTO first
- Do NOT use System.out.println or e.printStackTrace() anywhere

8. Advanced Technique 1 — Per-Directory CLAUDE.md Files

You are not limited to a single CLAUDE.md at the project root. Claude Code supports per-directory CLAUDE.md files. When Claude Code is working in a subdirectory, it reads both the root CLAUDE.md and any CLAUDE.md file it finds in the current directory. The subdirectory CLAUDE.md supplements or overrides the root-level context for work happening in that specific part of the project.

This is particularly valuable in multi-module Maven or Gradle projects, microservice monorepos, or large projects with distinct technical areas that have different conventions. Rather than trying to write a single CLAUDE.md that covers every module’s specifics, you write a root CLAUDE.md for project-wide conventions and per-module CLAUDE.md files for module-specific details.

project-root/
  CLAUDE.md                   ← Project-wide: Java version, build commands,
                                 shared conventions, global Do Nots
  services/
    user-service/
      CLAUDE.md               ← User service specific: domain model details,
                                 specific patterns, which external APIs it calls
    order-service/
      CLAUDE.md               ← Order service specific: event patterns,
                                 Kafka topic names, idempotency requirements
    legacy-billing/
      CLAUDE.md               ← Legacy module: Java 8 style (no lambdas),
                                 NO unit tests currently (handle with caution),
                                 full rewrite planned Q3 — do not invest here

9. Advanced Technique 2 — Documenting Known Risks

If there are parts of your codebase that are fragile, in active refactoring, or contain known technical debt that requires special handling, documenting them explicitly in CLAUDE.md prevents Claude Code from inadvertently making things worse. Claude Code will treat these as standing cautions.

## Known Issues and Caution Areas
 
### Legacy Payment Module (src/.../payment/legacy/)
- Written in Java 8 style — no lambdas, streams, or modern patterns
- Zero unit test coverage
- A complete rewrite is planned for Q3 2026
- Do NOT refactor this module. Do NOT add features.
- Any required changes: minimal, isolated, manually tested
 
### CustomerImportService.importBatch()
- Has a known race condition under concurrent load (Ticket #4421)
- Do NOT attempt to fix it — requires architectural redesign
- Ticket is tracked, fix is scoped for next quarter
 
### Database
- 'orders' and 'order_items' tables have 50M+ rows in production
- Any query without indexed WHERE clause will cause full table scan
- Always verify JPA-generated SQL with EXPLAIN before adding queries
- Avoid any query that fetches more than 1000 rows without pagination

10. CLAUDE.md as Human Documentation

One benefit of CLAUDE.md that is often overlooked is its value as documentation for human team members, not just Claude Code. The process of writing a good CLAUDE.md forces you to articulate your team’s conventions explicitly and in one place. Many development teams operate with conventions that exist only as tribal knowledge — every experienced member knows them, but they are never written down. New joiners discover them through painful code-review feedback rather than through upfront documentation.

Writing CLAUDE.md surfaces and centralises this tribal knowledge. The team member who writes the CLAUDE.md sections on coding conventions and testing standards is doing documentation work that benefits the entire team. A new developer joining the project can read CLAUDE.md to get up to speed on the team’s standards, understand the build commands, and learn which areas of the code require special handling — all from a single, well-maintained file at the project root.

This dual-purpose nature of CLAUDE.md — instructing Claude Code and onboarding humans — is worth communicating when you propose adopting Claude Code to your team or organisation. The value is not just ‘AI generates code faster’. It is also ‘we now have living documentation of our engineering standards that updates naturally as part of our workflow’. That is a benefit many engineering managers will immediately appreciate.

To maximise the human readability of CLAUDE.md, use clear headings, keep prose concise, and favour specific examples over abstract descriptions. The same qualities that make CLAUDE.md effective for Claude Code — concrete, unambiguous, specific — also make it readable and useful for humans. The interests of both audiences are aligned.

11. Keeping CLAUDE.md Focused and Current

The most effective CLAUDE.md files are not the longest ones. A focused, well-maintained file of 150 to 250 lines consistently outperforms an exhaustive 1,500-line document that tries to cover every decision ever made on the project. The reason is prioritisation: when Claude Code reads CLAUDE.md, everything in it has equal weight. A file full of marginally relevant details dilutes the impact of the critical conventions.

The right content test is this: would the absence of this information cause Claude Code to produce code that does not fit the project? If yes, include it. If Claude Code would reach the right answer anyway by reading the existing source code, you probably do not need to document it explicitly. Focus on the conventions that are non-obvious, the constraints that exist for non-obvious reasons, the build commands that are not discoverable from the project structure, and the negative instructions that prevent costly mistakes.

Review CLAUDE.md periodically — once per sprint or before each new major development phase — and it works well. Remove outdated content: conventions that have changed, legacy modules that have been cleaned up, and caution notes for issues that have been resolved. Add new content when conventions evolve: a new library the team has adopted, a new testing approach, a new architectural pattern. A CLAUDE.md that is reviewed and updated regularly is a living document that grows in value over time. One that is written once and never touched quickly becomes misleading.

12. Validating and Maintaining Your CLAUDE.md

After writing or significantly updating CLAUDE.md, validate it by testing tasks that should be directly affected by the new instructions. Ask Claude Code to create a new service class and verify it follows the constructor injection convention. Ask it to write a test and check that the structure, framework, and naming match your standards. Treat CLAUDE.md as a specification and test it the same way you test code.

The most common failure mode is Claude Code consistently ignoring instructions. When this happens, the instruction is usually ambiguous, in conflict with something else in CLAUDE.md, or contradicted by the pattern Claude Code observes in your existing source files. If your CLAUDE.md says ‘always use constructor injection’ but most of your existing classes use field injection, Claude Code will be confused by the contradiction. The fix is to either update the instruction to match reality or update the codebase to match the instruction — but not leave the contradiction unresolved.

Keep CLAUDE.md in version control and update it when conventions change. When the team adopts a new testing pattern, update the testing section. When a new library is added to the approved stack, mention it. When a legacy module is finally cleaned up, remove the caution note. A CLAUDE.md that is six months out of date is actively misleading.

Interview Insight: Discussing CLAUDE.md in an interview signals two sophisticated behaviours: first, that you invest in configuring your tools rather than accepting their defaults; second, that you think about negative constraints — what the AI should not do — which demonstrates experience with the failure modes of AI coding tools. Most junior developers who use Claude Code have never written a CLAUDE.md. Describing yours specifically will stand out.

13. Conclusion

CLAUDE.md is the single highest-leverage configuration step you can take to make Claude Code more effective in your Java project. It transforms Claude Code from a capable but generic coding assistant into a project-aware AI partner that understands your conventions, respects your constraints, and produces code that fits seamlessly into your existing codebase from day one.

The six core sections — project overview, build commands, package structure, coding conventions, testing standards, and negative instructions — give Claude Code everything it needs for the vast majority of tasks. The advanced techniques — per-directory files, architecture diagrams, risk documentation, and reference examples — take it further for complex projects. A CLAUDE.md written with care and kept current is a genuine force multiplier for Claude Code’s effectiveness.

Treat CLAUDE.md as living documentation. It should grow and improve as your project evolves, your team’s conventions mature, and you, through experience, discover what Claude Code needs to know to serve your project well. Commit it, review it in PRs like any other file, and keep it focused on what actually affects output quality.

In the next article, we explore custom slash commands — how to define your own /commands that automate the development tasks you perform repeatedly, turning your best prompt engineering work into permanent, reusable tools available in every session.

Leave a Comment