# GitHub Copilot CLI with Spring Boot: a practical guide

URL: https://agentvera.dev/en/blog/copilot-cli-for-spring-boot/ · Published: 2026-11-01

A practical guide to using GitHub Copilot CLI in Spring Boot: instruction files, safe edit loops, JPA pitfalls, Testcontainers, and parallel agents.

**In short:**

- Set a short .github/copilot-instructions.md with Maven/Gradle commands, package conventions, and Spring transaction and injection rules.
- Use a small loop: one task, run the relevant tests, review the diff, then commit before the next prompt.
- Watch JPA lazy loading, transaction self-invocation, and Testcontainers configuration; those are the most common Spring Boot failure points.

GitHub Copilot CLI is the terminal coding agent you start with `copilot` inside a Spring Boot repository; see [GitHub Copilot CLI](/en/agents/copilot-cli/) for setup details. It reads your project instructions, plans edits, runs Maven or Gradle commands, and iterates on failing tests. Use it for controller, service, and Spring Data JPA work, but keep the loop small and verify every change.

## What Copilot CLI brings to Spring Boot development

Spring Boot projects have a predictable shape: controllers, services, repositories, configuration classes, and wrapper scripts. GitHub Copilot CLI fits because it can read the whole module, follow the existing package layout, and run the same `./mvnw test` or `./gradlew test` command you already use. It can parse a stack trace from a failing context load or Testcontainers startup and make a targeted fix instead of guessing. It understands conventions such as `@RestController` and `@Service`, so its edits tend to match the existing codebase instead of introducing a second style. Because it is a terminal agent, it does not need a separate IDE plugin or a special build server; it works from the project root with your current toolchain. Once installed, the workflow in [How to use GitHub Copilot CLI: a step-by-step guide](/en/blog/how-to-use-copilot-cli/) still applies, but Spring Boot work benefits from a tighter instruction file.

## Preparing your Spring Boot repo for the agent

Put a `.github/copilot-instructions.md` at the repo root. AGENTS.md works too, but one file is enough. Keep it short and command-focused. Tell the agent the build wrapper, not `mvn` globally, so it does not pick up the wrong Maven installation. State test commands separately: unit tests run without Docker, full verification runs Testcontainers. Add Spring-specific rules about transaction boundaries and injection style.

Example `.github/copilot-instructions.md`:

```markdown
# Spring Boot project instructions

Build and test:
- Use the Maven wrapper: ./mvnw
- Unit tests: ./mvnw test
- Full verification including Testcontainers: ./mvnw verify
- Formatting and lint: ./mvnw spotless:check

Package layout:
- controller: HTTP and validation only
- service: business logic and transaction boundaries
- repository: Spring Data JPA interfaces

Rules:
- Constructor injection only; no @Autowired on fields.
- Prefer records or immutable DTOs for request/response bodies.
- Use derived query methods first; add @Query only when necessary.
- One transaction per service method; use @Transactional(readOnly = true) for reads.
- Do not commit generated IDE files or local application-local.properties.
- When a test fails, inspect the full Maven output and stack trace before editing.
```

This gives the agent enough context to avoid common Spring Boot mistakes. If you use Gradle, replace the wrapper commands with `./gradlew test` and `./gradlew check`.

## A practical edit loop with example prompts

Use a clean feature branch and let `copilot` take one small slice at a time. Start with a prompt that names the layer, input and output, and the test to add or run. After each turn, run the relevant test command yourself or ask the agent to run it, then review `git diff` before accepting. If a test fails, paste the relevant stack trace back into the same session instead of opening a new prompt.

For larger features, write a short spec first and follow the loop described in [Spec-driven development with AI agents: a practical guide](/en/blog/spec-driven-development-with-ai/).

Example prompts:

- Add a `POST /api/orders` endpoint that accepts a validated `OrderRequest`, calls `OrderService.createOrder`, and returns `201 Created` with an `OrderResponse`; use constructor injection and map validation errors to `ProblemDetail`.
- Implement `OrderService.createOrder` with `@Transactional`. It should check product stock via `ProductRepository`, throw `InsufficientStockException`, and return the persisted order. Add a Mockito unit test for success and failure.
- Create an `OrderRepository` interface extending `JpaRepository<Order, Long>` and add `List<Order> findByCustomerEmailOrderByCreatedAtDesc(String email)`. Add a controller method `GET /api/orders?email=` that uses it.
- The integration test `OrderRepositoryTest` is failing on PostgreSQL startup. Run `./mvnw -Dtest=OrderRepositoryTest test`, capture the full error, and fix only the test configuration or entity mapping that caused it.
- Add a Testcontainers integration test for the service layer using PostgreSQL. Use `@ServiceConnection` and assert that `createOrder` persists and reads back correctly.

Review the diff before staging. If a small prompt changed more than two files, ask `copilot` to explain the scope; around Spring Data, it may unnecessarily touch entities, DTOs, and repositories when a single mapper change would do.

## Common Spring Boot wins and pitfalls with Copilot CLI

The table below shows tasks the agent handles well and the most common failure modes.

| Task | Strong prompt | Watch closely |
| Controller endpoint | Add `GET /api/customers/{id}` returning `CustomerResponse` or `404`. | Agent may add business rules in controller; keep it thin. |
| Spring Data repository | Add `CustomerRepository` with `findByEmailIgnoreCase` and a pageable query. | Derived query names can compile but filter the wrong column; review method names. |
| Service transaction | Add `CustomerService.deactivate` with `@Transactional` and an audit entry. | `@Transactional` must be on a public method of a Spring bean; self-invocation bypasses it. |
| Testcontainers test | Add `@Testcontainers` PostgreSQL test for `CustomerRepository`. | Watch for hard-coded ports and missing `spring.datasource.url` overrides. |
| Configuration properties | Add `@ConfigurationProperties(prefix = "payment")` record and register it. | Ensure the agent does not scatter `@Value` fields instead. |

Beyond the table, watch for these Spring Boot-specific pitfalls. Field injection may appear because it is familiar in generated code, but constructor injection is easier to test and avoids hidden dependencies. Lazy loading outside a transaction causes `LazyInitializationException`; tell the agent to fetch within the transaction or use a projection, not to call repositories from controllers just to populate a response. `@Transactional` on private methods or self-invoked methods silently does nothing, so verify the method is public and called through the Spring proxy. With Testcontainers, have the agent use `@ServiceConnection` or set `spring.datasource.url` and credentials from the container; otherwise tests can pass on one machine and fail on another. Pagination is another area: ensure the agent adds a `Pageable` parameter and returns `Page<...>` instead of materializing all rows with `findAll()` and filtering in memory. If you see `findAll().stream().filter(...)` in a service, reject it and ask for a database query. Entity-to-DTO mapping should happen in a mapper or the service, not in the controller or via lazy-loaded entity serialization. Also, the agent may change `application.properties` instead of adding a profile-specific `application-test.yml`, which can leak test configuration into production.

## How to verify Copilot CLI changes in Spring Boot

Set a rule that no change is complete until the relevant Maven or Gradle command passes. For unit tests, use `./mvnw test`; for full verification including Testcontainers, use `./mvnw verify`. Ask `copilot` to run the command, read the Surefire or Failsafe reports, and quote the actual assertion or log line before editing. Then review `git diff --check` and run formatting with `./mvnw spotless:apply` if you use Spotless. For a service change, ask for both a Mockito unit test and, if persistence is involved, an integration test with Testcontainers. The agent should not mark a task complete until both pass. For HTTP-level checks, you can combine agent-driven browser testing with Spring Boot integration tests; see [AI agent browser testing: let the agent check your app](/en/blog/ai-agent-browser-testing/) for a complementary approach. Always require a passing test for the changed code before merging; if the agent wants to delete a test, treat that as a red flag.

## Parallel agents with AgentVera for Spring Boot

AgentVera runs GitHub Copilot CLI and other agents side by side in real terminal panels. For Spring Boot, the most useful parts are parallel worktrees, so a controller change and a repository change do not overwrite each other; automatic code review after each turn, which catches mismatched method names or transaction boundaries with file:line links; checkpoints that let you undo a bad configuration change; and token budgets that stop runaway test-fix loops while preserving the conversation. This keeps multiple feature branches moving without turning the project into a merge conflict.

## Final notes

GitHub Copilot CLI is most useful in Spring Boot when you give it a small, explicit contract and let it run the build. Keep the instruction file current, review each diff, and make tests part of every prompt. For larger parallel work, running agents in isolated worktrees with budgets and review reduces the risk of conflicting edits. This turns the agent into a reliable pair programmer instead of a code generator you have to clean up.

## Frequently asked questions

**How do I start GitHub Copilot CLI in a Spring Boot project?** Run copilot from the project root after installing the CLI. It will use .github/copilot-instructions.md or AGENTS.md if present, so add Spring Boot build and test commands there first.

**Can GitHub Copilot CLI run Maven or Gradle tests for Spring Boot?** Yes. It can execute ./mvnw test, ./mvnw verify, ./gradlew test, and other wrapper commands. Ask it to run the exact command and read the test report before editing.

**Does GitHub Copilot CLI work with Spring Data JPA and Testcontainers?** It handles repository interfaces, derived queries, entities, and Testcontainers tests well, but you should review transaction boundaries and Docker configuration. Give explicit instructions about package layout and test profiles.

**How do I prevent GitHub Copilot CLI from making bad Spring Boot changes?** Keep tasks small, require tests to pass, review git diff after each turn, and put rules in your instruction file for constructor injection, transactions, and DTO/entity separation.

---

**About AgentVera.** AgentVera is a desktop app for macOS, Windows and Linux, built by Solviera Teknoloji. It runs 18 AI coding agents (Claude Code, Codex, Gemini CLI, Copilot, Cursor, Antigravity, opencode, Hermes, Qwen Code, Kimi Code, Kiro, Amp, Droid, Goose, Vibe, Crush, Aider, Cline) side by side, per project, in real terminals with the user's own CLI installs and logins. The free plan has unlimited agents. Download: https://agentvera.dev/en/download/ · Pricing: https://agentvera.dev/en/pricing/
