DEV Community

Said Olano
Said Olano

Posted on

Spring Shell: Building Interactive CLI Applications (2026-08-28 02:06)

Spring Shell: Building Interactive CLI Applications

While web applications and REST APIs dominate the Spring ecosystem, command-line tools remain essential for automation, administration, and developer tooling. Spring Shell brings the power and familiarity of the Spring programming model to interactive CLI applications, letting you build robust command-line tools with minimal boilerplate.

In this post, we'll explore how to build a fully functional interactive shell application using Spring Shell.

What Is Spring Shell?

Spring Shell is a framework for building command-line applications on top of Spring Boot. It provides:

  • An interactive shell (REPL) with command history and tab completion
  • Annotation-based command definitions
  • Built-in commands (help, clear, exit, etc.)
  • Input parsing and type conversion
  • Dynamic command availability
  • Customizable prompts and output

It's ideal for building admin tools, DevOps utilities, database clients, or any interactive terminal application.

Getting Started

Add the Spring Shell starter to your pom.xml:

<dependency>
    <groupId>org.springframework.shell</groupId>
    <artifactId>spring-shell-starter</artifactId>
    <version>3.2.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Or with Gradle:

implementation 'org.springframework.shell:spring-shell-starter:3.2.0'
Enter fullscreen mode Exit fullscreen mode

Your main application class is a standard Spring Boot application:

@SpringBootApplication
public class CliApplication {
    public static void main(String[] args) {
        SpringApplication.run(CliApplication.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

When you run this application, Spring Shell automatically launches an interactive shell.

Your First Command

Commands are defined using @ShellComponent and @ShellMethod:

@ShellComponent
public class GreetingCommands {

    @ShellMethod(key = "hello", value = "Print a greeting message")
    public String hello(
            @ShellOption(defaultValue = "World") String name) {
        return "Hello, " + name + "!";
    }
}
Enter fullscreen mode Exit fullscreen mode

Now run the application and try it:

shell:> hello
Hello, World!

shell:> hello --name Alice
Hello, Alice!
Enter fullscreen mode Exit fullscreen mode

The key attribute defines the command name, and value provides the description shown in help output.

Working with Command Options

Spring Shell offers rich support for command arguments through @ShellOption.

Positional and Named Arguments

@ShellComponent
public class MathCommands {

    @ShellMethod(key = "add", value = "Add two numbers")
    public int add(int a, int b) {
        return a + b;
    }

    @ShellMethod(key = "divide", value = "Divide two numbers")
    public double divide(
            @ShellOption(help = "The dividend") double dividend,
            @ShellOption(help = "The divisor") double divisor) {
        if (divisor == 0) {
            throw new IllegalArgumentException("Cannot divide by zero");
        }
        return dividend / divisor;
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

shell:> add 5 3
8

shell:> divide --dividend 10 --divisor 4
2.5
Enter fullscreen mode Exit fullscreen mode

Boolean Flags

Boolean options act as flags — their presence sets them to true:

@ShellMethod(key = "list-files", value = "List files in a directory")
public String listFiles(
        @ShellOption(defaultValue = ".") String path,
        @ShellOption(value = "--verbose") boolean verbose) {
    // ... implementation
    return verbose ? "Detailed listing..." : "Simple listing...";
}
Enter fullscreen mode Exit fullscreen mode
shell:> list-files --verbose
Detailed listing...
Enter fullscreen mode Exit fullscreen mode

Arity for Multiple Values

Use arity to accept multiple values for a single option:

@ShellMethod(key = "sum", value = "Sum multiple numbers")
public int sum(
        @ShellOption(arity = 5, defaultValue = "0") int[] numbers) {
    return Arrays.stream(numbers).sum();
}
Enter fullscreen mode Exit fullscreen mode
shell:> sum --numbers 1 2 3 4 5
15
Enter fullscreen mode Exit fullscreen mode

Dynamic Command Availability

A powerful feature of Spring Shell is the ability to enable or disable commands based on application state. For example, certain commands should only be available after a user logs in.

@ShellComponent
public class SecureCommands {

    private boolean connected = false;

    @ShellMethod(key = "connect", value = "Connect to the server")
    public String connect(String server) {
        this.connected = true;
        return "Connected to " + server;
    }

    @ShellMethod(key = "disconnect", value = "Disconnect from the server")
    public String disconnect() {
        this.connected = false;
        return "Disconnected";
    }

    @ShellMethod(key = "status", value = "Show connection status")
    public String status() {
        return "Fetching status from server...";
    }

    public Availability statusAvailability() {
        return connected
                ? Availability.available()
                : Availability.unavailable("you are not connected");
    }
}
Enter fullscreen mode Exit fullscreen mode

The statusAvailability() method follows a naming convention: <commandMethod>Availability. When status is unavailable, Spring Shell provides a helpful message:

shell:> status
Command 'status' exists but is not currently available because you are not connected
Enter fullscreen mode Exit fullscreen mode

Grouping and Organizing Commands

By default, commands are grouped by their containing class. You can customize groups explicitly:


java
@ShellComponent
@ShellCommandGroup("User Management")
public class UserCommands {

    @ShellMethod(key = "user-create", value = "Create a new user")
    public String createUser(String username) {
        return "Created user: " + username;
    }

    @Shell
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
topstar_ai profile image
Luis Cruz

The dynamic command availability feature you mentioned is a standout aspect of Spring Shell, allowing for a highly interactive user experience. It opens up avenues for more context-aware command execution, which can really enhance usability in complex applications. One improvement idea could be to implement a command that lists available commands based on user permissions or roles, making it even more user-friendly. If you're looking for help in expanding this feature or any other part of your project, I’d be glad to explore a paid collaboration. What other enhancements are you considering for user experience?