Spring BootSpring Boot CLI
Spring Boot

Spring Boot CLI

Spring Boot CLI is a command-line tool that lets you run Groovy scripts as full Spring Boot applications — no pom.xml, no project structure, no main method required. It's the fastest way to prototype a Spring Boot application, test an idea, or run a quick utility script with the full Spring ecosystem available.

What Is Spring Boot CLI?

Spring Boot CLI (Command Line Interface) is a standalone tool that dramatically reduces the ceremony of running a Spring Boot application. Instead of creating a Maven project, writing a pom.xml, defining a main class, and compiling, you write a single Groovy script and run it directly. Spring Boot CLI automatically: - Detects which Spring libraries you need from the annotations you use - Downloads those dependencies from Maven Central - Adds all necessary imports - Wraps your code in a runnable Spring Boot application - Starts an embedded web server if needed The primary use cases are rapid prototyping, testing API ideas, writing utility scripts that use Spring components, and learning Spring Boot concepts without project overhead.

Installing Spring Boot CLI

Spring Boot CLI can be installed via SDKMAN (recommended on macOS/Linux), Homebrew (macOS), or a manual ZIP download on Windows.
Shell
# Option 1 — SDKMAN (macOS and Linux — recommended):
# Install SDKMAN first if not already installed:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

# Install Spring Boot CLI:
sdk install springboot

# Verify:
spring --version
# Spring CLI v3.2.0

# List available Spring Boot versions:
sdk list springboot

# Switch versions:
sdk use springboot 3.1.5

# Option 2 — Homebrew (macOS):
brew tap spring-io/tap
brew install spring-boot

# Verify:
spring --version

# Option 3 — Manual ZIP (Windows):
# Download from: https://repo.maven.apache.org/maven2/org/springframework/boot/
#                spring-boot-cli/3.2.0/spring-boot-cli-3.2.0-bin.zip
# Extract and add the bin/ directory to your PATH

# Verify on Windows (Command Prompt):
spring --version

Running Your First Groovy Script

A Spring Boot CLI script is a Groovy file with Spring annotations. No imports, no main method, no @SpringBootApplication — the CLI infers everything from what you use.
groovy
// hello.groovy — the simplest possible Spring Boot web application:
@RestController
class HelloController {

    @RequestMapping("/")
    String hello() {
        "Hello from Spring Boot CLI!"
    }

    @RequestMapping("/greet")
    String greet(@RequestParam(defaultValue = "World") String name) {
        "Hello, ${name}!"
    }
}

# Run it — Spring Boot CLI detects @RestController and adds web dependencies:
spring run hello.groovy

# Output:
#   .   ____          _            __ _ _
#  ... Spring Boot banner ...
# Started application in 2.341 seconds
# Tomcat started on port 8080

# Test it:
curl http://localhost:8080/
# Hello from Spring Boot CLI!

curl "http://localhost:8080/greet?name=Alice"
# Hello, Alice!

# Run on a different port:
spring run hello.groovy -- --server.port=9090

# Run with Spring profile active:
spring run hello.groovy -- --spring.profiles.active=dev

# Run multiple scripts together:
spring run *.groovy

What the CLI Infers Automatically

Spring Boot CLI reads the annotations in your Groovy script and automatically resolves the correct Spring Boot starters — no import statements or dependency declarations needed.
groovy
// Annotation used         What CLI adds automatically
// ─────────────────────────────────────────────────────────────────
// @RestController          spring-boot-starter-web
// @Controller              spring-boot-starter-web
// @EnableBatchProcessing   spring-boot-starter-batch
// @EnableRabbit            spring-boot-starter-amqp
// @EnableCaching           spring-boot-starter-cache
// @Test                    spring-boot-starter-test
// @Grab(...)               explicit dependency (see below)

// Example — a script with JPA:
@Grab("com.h2database:h2")   // explicitly grab H2 (not auto-detected)
@RestController
class UserController {

    @Autowired
    UserRepository users

    @GetMapping("/users")
    List findAll() {
        users.findAll()
    }

    @PostMapping("/users")
    User create(@RequestBody User user) {
        users.save(user)
    }
}

@Entity
class User {
    @Id @GeneratedValue
    Long id
    String name
    String email
}

interface UserRepository extends JpaRepository<User, Long> {}

// CLI detects:
// @RestController → adds spring-boot-starter-web
// @Entity + JpaRepository → adds spring-boot-starter-data-jpa
// @Grab("com.h2database:h2") → adds H2 explicitly

# Run:
spring run app.groovy

Using @Grab for Explicit Dependencies

@Grab (from Apache Ivy/Groovy Grape) lets you explicitly declare dependencies in your script when the CLI can't auto-detect them from annotations — database drivers, third-party clients, utility libraries.
groovy
// @Grab pulls dependencies from Maven Central at runtime:

@Grab("org.springframework.boot:spring-boot-starter-data-jpa")
@Grab("com.h2database:h2")
@Grab("org.flywaydb:flyway-core")

// Short form — Spring Boot manages the version automatically:
@Grab("spring-boot-starter-security")

// Full form — specific version:
@Grab(group = "com.auth0", module = "java-jwt", version = "4.4.0")

// Groovy compact form:
@Grab("com.google.guava:guava:32.1.3-jre")

// Exclude a transitive dependency:
@GrabExclude("commons-logging:commons-logging")

// Use a custom Maven repository:
@GrabResolver(name = "central", root = "https://repo.maven.apache.org/maven2/")

// Practical example — script that calls an external REST API:
@Grab("org.springframework.boot:spring-boot-starter-web")

@RestController
class WeatherController {

    @Autowired
    RestTemplate restTemplate

    @GetMapping("/weather/{city}")
    def getWeather(@PathVariable String city) {
        restTemplate.getForObject(
            "https://wttr.in/${city}?format=j1",
            Map
        )
    }
}

@Bean
RestTemplate restTemplate() {
    new RestTemplate()
}

The spring init Command

spring init generates a complete Spring Boot project — the same as using start.spring.io but from the terminal. It's the fastest way to bootstrap a new project without opening a browser.
Shell
# Generate a project with defaults (Maven, Java, latest Spring Boot):
spring init myproject

# Specify dependencies:
spring init --dependencies=web,data-jpa,security,actuator myproject

# Full options:
spring init \
  --build=maven \
  --java-version=21 \
  --boot-version=3.2.0 \
  --group-id=com.example \
  --artifact-id=myapp \
  --name=myapp \
  --description="My Spring Boot App" \
  --package-name=com.example.myapp \
  --packaging=jar \
  --dependencies=web,data-jpa,security,validation,actuator,devtools \
  myapp

# Generate into the current directory (no subdirectory):
spring init --dependencies=web,data-jpa .

# Generate a Gradle project:
spring init --build=gradle --dependencies=web,data-jpa myapp

# Generate a Kotlin project:
spring init --language=kotlin --dependencies=web,data-jpa myapp

# List all available dependencies:
spring init --list

# List available Spring Boot versions:
spring init --list | grep "Available Spring Boot"

# Generate as a ZIP and extract manually:
spring init --dependencies=web,actuator myapp.zip
unzip myapp.zip -d myapp

# Run the generated project immediately:
spring init --dependencies=web myapp && cd myapp && ./mvnw spring-boot:run

Other CLI Commands

Spring Boot CLI provides several commands beyond run and init for testing, packaging, and managing shells.
Shell
# spring run — run a Groovy script:
spring run app.groovy
spring run app.groovy -- --server.port=9090   # pass JVM args after --
spring run *.groovy                            # run multiple scripts
spring run app.groovy --watch                  # restart on file change

# spring test — run Groovy test scripts:
spring test tests.groovy

# spring jar — package a Groovy script as an executable JAR:
spring jar myapp.jar app.groovy
java -jar myapp.jar

# spring war — package as a WAR file:
spring war myapp.war app.groovy

# spring install — install a dependency into the CLI's local repository:
spring install com.example:my-lib:1.0.0

# spring uninstall — remove an installed dependency:
spring uninstall com.example:my-lib:1.0.0

# spring shell — start an interactive Spring Boot shell:
spring shell
# Inside the shell, all commands are available without the 'spring' prefix:
# > run app.groovy
# > init --dependencies=web myproject
# > version
# > help

# spring version — print the CLI version:
spring version
# Spring CLI v3.2.0

# spring help — list all available commands:
spring help

# spring help run — detailed help for a specific command:
spring help run

Practical CLI Scripts

These are real-world patterns for using the CLI — prototyping REST endpoints, testing database connections, and building quick utility scripts.
groovy
// Pattern 1 — Quick REST API prototype:
// api.groovy
@RestController
@RequestMapping("/api")
class ApiController {

    def products = [
        [id: 1, name: "Laptop", price: 999.99],
        [id: 2, name: "Mouse",  price: 29.99],
        [id: 3, name: "Keyboard", price: 79.99]
    ]

    @GetMapping("/products")
    def getAllProducts() { products }

    @GetMapping("/products/{id}")
    def getProduct(@PathVariable int id) {
        products.find { it.id == id } ?: [error: "Not found"]
    }

    @PostMapping("/products")
    def createProduct(@RequestBody Map product) {
        product.id = products.size() + 1
        products << product
        product
    }
}

# Run and test immediately — no project setup:
# spring run api.groovy
# curl http://localhost:8080/api/products
# curl -X POST http://localhost:8080/api/products -H "Content-Type: application/json" -d '{"name":"Monitor","price":299.99}'

// Pattern 2 — Database connection test:
// dbtest.groovy
@Grab("com.mysql:mysql-connector-j")

@Component
class DatabaseTest implements CommandLineRunner {

    @Autowired
    JdbcTemplate jdbc

    void run(String... args) {
        def count = jdbc.queryForObject("SELECT COUNT(*) FROM users", Integer)
        println "Connected! Found ${count} users."

        def users = jdbc.queryForList("SELECT id, name, email FROM users LIMIT 5")
        users.each { println "  User: ${it}" }
    }
}

# spring run dbtest.groovy -- --spring.datasource.url=jdbc:mysql://localhost:3306/mydb --spring.datasource.username=root --spring.datasource.password=secret

// Pattern 3 — Scheduled task script:
// scheduler.groovy
@EnableScheduling
@Component
class DataSyncTask {

    int count = 0

    @Scheduled(fixedDelay = 2000L)
    void sync() {
        count++
        println "[${new Date()}] Sync #${count} completed"
    }
}

# spring run scheduler.groovy

CLI vs Full Project — When to Use Each

Spring Boot CLI and a full Maven/Gradle project serve different purposes. Knowing when to use each saves time.
Java
// USE SPRING BOOT CLI WHEN:
// ─────────────────────────────────────────────────────────────────
// Prototyping a REST endpoint or algorithm quickly
// Testing an API design before building the full service
// Learning Spring Boot concepts without project overhead
// Writing a one-off utility script (DB migration check, data export)
// Demonstrating a Spring concept in a presentation or tutorial
// Verifying a Spring Boot behavior in isolation

// USE A FULL MAVEN/GRADLE PROJECT WHEN:
// ─────────────────────────────────────────────────────────────────
// Building a production application
// Working in a team with version control
// Needing advanced build tooling (CI/CD, Docker, multi-module)
// Requiring IDE support (debugging, refactoring, code completion)
// Using Java (not Groovy) as the primary language
// Writing integration and unit tests in an organized test suite
// Managing multiple environments (dev, staging, prod)

// The typical workflow:
// 1. Use CLI to prototype the API design (20 lines of Groovy)
// 2. Validate the idea works as expected
// 3. Generate the full project: spring init --dependencies=web,data-jpa myapp
// 4. Translate the Groovy prototype to Java in the proper project structure
// 5. Build, test, deploy from the Maven/Gradle project

// CLI scripts are also useful for documentation:
// A working 15-line Groovy script demonstrates a concept far better
// than 200 lines of Java spread across 5 files in a project structure