You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
What if my application is only going to have a single command? I would love the ability to define a configuration property that says I only have a single command and here is what it is. When I run the program I am dropped into the shell and whatever I type is now the argument to the single default command.
This came up when building a Spring Shell + Spring AI application that interfaces with Open AI's GPT-4. I have included the rep for reference below.
Little clarification when I discussed with Dan. This is about interactive shell and having that one command there without having a need to define that command.
Hi~ What's the progress on this issue? I'm eager to find out how to specify a default command in interactive mode, just like the single-command in non-interactive mode.
@danvega After some exploration, I've found a way to implement a "default command" — by customizing org.springframework.shell.Shell and overriding its evaluate method. The original evaluate method:
So, what we need to do is modify the behavior of evaluate to use a default command for every input (except special commands):
Customize Shell to change the behavior of evaluate:
/** * @see org.springframework.shell.Shell * @see org.springframework.shell.boot.SpringShellAutoConfiguration */@Primary@ComponentpublicclassMyShellextendsShell {
// This is just an example; you may obtain the current system’s command set to replace it.privatestaticfinalSet<String> INTERNAL_COMMANDS = Set.of("help", "exit", "quit");
publicMyShell(ResultHandlerServiceresultHandlerService,
CommandCatalogcommandRegistry,
Terminalterminal,
ShellContextshellContext,
ExitCodeMappingsexitCodeMappings) {
super(resultHandlerService, commandRegistry, terminal, shellContext, exitCodeMappings);
}
@OverrideprotectedObjectevaluate(Inputinput) {
List<String> words = input.words();
if (words.isEmpty() || words.getFirst().isEmpty()) {
returnsuper.evaluate(input);
}
// If the first word is an internal command (like `help`, `exit`), execute the original logic directlyif (INTERNAL_COMMANDS.contains(words.getFirst())) {
returnsuper.evaluate(input);
}
// Use the `chat` command to process the input textStringrawText = input.rawText();
returnsuper.evaluate(() -> "chat " + rawText);
}
}
Running example as shown below. You can see that if the input does not match INTERNAL_COMMANDS, it will default to using the chat command to process the input:
Now there's another issue: because there's no matching command, the "highlighting feature" will treat this as an erroneous input and display it in red, which looks odd. Fortunately, we can also customize the "highlighting feature":
/** * @see org.springframework.shell.boot.LineReaderAutoConfiguration#lineReader() */publicclassMyHighlighterimplementsHighlighter {
// This is just an example; you may obtain the current system’s command set to replace it.privatestaticfinalSet<String> INTERNAL_COMMANDS = Set.of("help", "exit", "quit");
privatefinalCommandCatalogcommandRegistry;
publicMyHighlighter(CommandCatalogcommandRegistry) {
this.commandRegistry = commandRegistry;
}
@OverridepublicAttributedStringhighlight(LineReaderreader, Stringbuffer) {
StringtrimmedBuffer = buffer.trim();
if (trimmedBuffer.isEmpty()) {
returnnewAttributedString(buffer);
}
String[] words = trimmedBuffer.split(" ", 2);
// If the first word of the input is not an internal command (like `help`, `exit`), then it's using the `chat` commandif (!INTERNAL_COMMANDS.contains(words[0])) {
// You can choose a style you like; here I'm using foreground color CYANreturnnewAttributedString(buffer, AttributedStyle.DEFAULT.foreground(AttributedStyle.CYAN));
}
// Copy from org.springframework.shell.boot.LineReaderAutoConfiguration#lineReader()intlen = 0;
Stringbest = null;
// Find the longest matching commandfor (Stringcommand : commandRegistry.getRegistrations().keySet()) {
if (buffer.startsWith(command) && command.length() > len) {
len = command.length();
best = command;
}
}
if (best != null) {
returnnewAttributedStringBuilder(buffer.length())
.append(best, AttributedStyle.BOLD)
.append(buffer.substring(len))
.toAttributedString();
} else {
returnnewAttributedString(buffer, AttributedStyle.DEFAULT.foreground(AttributedStyle.RED));
}
}
}
Customize JLine's LineReader to use MyHighlighter for the "highlighting feature":
Activity
[-]Default Command[/-][+]Single + Default Command[/+]helloshisheng commentedon May 13, 2024
i think u can see this https://docs.spring.io/spring-shell/reference/customization/singlecommand.html
Update docs
jvalkeal commentedon May 23, 2024
Ups, linked and closed wrong issue
jvalkeal commentedon May 24, 2024
Little clarification when I discussed with Dan. This is about interactive shell and having that one command there without having a need to define that command.
zhoumiv commentedon Jul 16, 2025
Hi~ What's the progress on this issue? I'm eager to find out how to specify a default command in interactive mode, just like the single-command in non-interactive mode.
zhoumiv commentedon Feb 11, 2026
@danvega After some exploration, I've found a way to implement a "default command" — by customizing
org.springframework.shell.Shelland overriding itsevaluatemethod. The originalevaluatemethod:So, what we need to do is modify the behavior of
evaluateto use a default command for every input (except special commands):I've defined the default command as
chat:Customize
Shellto change the behavior ofevaluate:Running example as shown below. You can see that if the input does not match INTERNAL_COMMANDS, it will default to using the

chatcommand to process the input:Now there's another issue: because there's no matching command, the "highlighting feature" will treat this as an erroneous input and display it in red, which looks odd. Fortunately, we can also customize the "highlighting feature":
Customize JLine's
LineReaderto useMyHighlighterfor the "highlighting feature":Final result:
My Java version: 25.0.2
My Spring Shell version: 3.4.1