Summary
generateHelp = true on @CommandDefinition only works when the command also declares at least one @Option field. Without any @Option, --help and -h are not recognized by the parser — even though the generated help text lists them as valid options.
Reproducer
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.aesh:aesh:3.16.5
import org.aesh.AeshRuntimeRunner;
import org.aesh.command.Command;
import org.aesh.command.CommandDefinition;
import org.aesh.command.CommandResult;
import org.aesh.command.invocation.CommandInvocation;
import org.aesh.command.option.Argument;
import org.aesh.command.option.Option;
class aeshhelpbug {
// Subcommand WITHOUT any @Option — generateHelp is broken
@CommandDefinition(name = "greet", description = "Greet (no options)", generateHelp = true)
public static class GreetCmd implements Command<CommandInvocation> {
@Argument(description = "Name")
private String name;
public CommandResult execute(CommandInvocation ci) {
ci.println("hello " + name);
return CommandResult.SUCCESS;
}
}
// Subcommand WITH an @Option — generateHelp works
@CommandDefinition(name = "greet2", description = "Greet (has option)", generateHelp = true)
public static class Greet2Cmd implements Command<CommandInvocation> {
@Option(shortName = 'l', name = "loud", hasValue = false, description = "Shout")
boolean loud;
@Argument(description = "Name")
private String name;
public CommandResult execute(CommandInvocation ci) {
var msg = "hello " + name;
ci.println(loud ? msg.toUpperCase() : msg);
return CommandResult.SUCCESS;
}
}
@CommandDefinition(name = "app", description = "Test app", generateHelp = true,
groupCommands = {GreetCmd.class, Greet2Cmd.class})
public static class AppCmd implements Command<CommandInvocation> {
@Option(shortName = 'V', name = "version", hasValue = false, description = "Show version")
boolean version;
public CommandResult execute(CommandInvocation ci) {
if (version) ci.println("1.0");
else ci.println("Usage: app <greet|greet2>");
return CommandResult.SUCCESS;
}
}
public static void main(String[] args) {
AeshRuntimeRunner.builder()
.command(AppCmd.class)
.args(args)
.execute();
}
}
Results
| Command |
Has @Option? |
--help |
-h |
app --help |
✅ yes |
✅ shows help |
✅ shows help |
app greet --help |
❌ no |
❌ "The option --help is unknown." |
❌ silently ignored, command executes |
app greet2 --help |
✅ yes |
✅ shows help |
✅ shows help |
app greet2 -h |
✅ yes |
✅ shows help |
✅ shows help |
Expected
All four commands should show help, since generateHelp = true is set on every @CommandDefinition.
Analysis
The generated help option (-h/--help) is listed in the help text output but is never registered in the parser when the command has no other @Option fields. The parser then treats --help as an unknown option (throwing CommandLineParserException) and -h as an argument value.
Environment
- aesh 3.16.5 (also reproduced on 3.14.3)
- Java 25
- macOS aarch64
Summary
generateHelp = trueon@CommandDefinitiononly works when the command also declares at least one@Optionfield. Without any@Option,--helpand-hare not recognized by the parser — even though the generated help text lists them as valid options.Reproducer
Results
@Option?--help-happ --helpapp greet --helpapp greet2 --helpapp greet2 -hExpected
All four commands should show help, since
generateHelp = trueis set on every@CommandDefinition.Analysis
The generated help option (
-h/--help) is listed in the help text output but is never registered in the parser when the command has no other@Optionfields. The parser then treats--helpas an unknown option (throwingCommandLineParserException) and-has an argument value.Environment