Skip to content
Customizing Help Output

Customizing Help Output

Every knob that shapes --help in one place: what renders where, which attribute controls it, and what wins when several apply. (Spacing simplified in the samples below.)

Where everything renders

A fully dressed --help looks like this, top to bottom:

Deploy an application                            <- description
Usage: deploy [OPTIONS] <artifact>               <- synopsis (collapseSynopsis)

Runs the deployment pipeline.                    <- header
Arguments:                                       <- argumentsSection = FIRST (or LAST: after Options:)
  <artifact>         The artifact to deploy
Options:                                         <- default Options section
  -h, --help             Display this help and exit
      --target=<target>  Target environment
Environments:                                    <- helpGroup (@Option)
      --prod             Deploy to production
Examples:                                        <- provider sections
  deploy app.jar       Deploy the jar
Documentation: https://example.com/deploy        <- helpUrl
For support, contact ops@example.com             <- footer

For group commands, a <name> commands: listing (or the named helpGroup sections plus Other:) is inserted after the options and before the footer. A group-level -h behaves like the subcommand’s own: app -h run shows run’s help instead of failing on its required options. The provider’s additional sections merge into that listing: a section whose name matches a helpGroup is appended to the group instead of creating a duplicate heading.

Which knob do I need?

I want to…Use
Collapse a long Usage: line to [OPTIONS]collapseSynopsis = Toggle.ON
Show each option’s default under its descriptionshowDefaultValues = Toggle.ON
Print my own options before named groupsdefaultOptionsFirst = Toggle.ON
Print the header before the Usage: line instead of after it (terminal --help only)headerBeforeSynopsis = Toggle.ON
Reject a repeated single-value optionfailOnDuplicateOptions = Toggle.ON
Give positionals their own Arguments: heading, first or lastargumentsSection = ArgumentsSection.FIRST (or LAST)
Sort options alphabeticallysortOptions = true
Static brand text or examples, top or bottomheader / footer
Dynamic or plugin-provided sectionshelpSectionProvider, or implement HelpSectionProvider on the command itself
One provider serving many commandsA HelpContext overload, keyed by context.fullName()
This command listed under a heading in the parenthelpGroup on the subcommand (it renders in the parent, not here)
Show a positional inside an option grouphelpGroup on @Argument/@Arguments (+ order to position it)
A docs link at the end of helphelpUrl

What wins

Each layer is stated once here; the individual attributes link back to this page.

  • Header/footer/sections: an explicit HelpSectionProvider value beats the annotation header/footer. With no provider set, a command that implements HelpSectionProvider provides for itself.
  • Toggles: an explicit ON/OFF beats the parent group’s resolved value, which beats the fleet default, which beats off. The arguments section works the same way with four states (OFF/FIRST/LAST), defaulting to off instead of a toggle:
AeshCommandRegistryBuilder.<CommandInvocation>builder()
    .helpDefaults(EnumSet.of(HelpFeature.SHOW_DEFAULT_VALUES))
    .argumentsSectionDefault(ArgumentsSection.FIRST)
    .command(MyGroup.class)
    ...

Grouped positionals

A positional with a helpGroup leaves the positional flow and renders inside that option group, sharing the group’s order namespace with its options (lower prints first; ties keep options before positionals, positionals in index order). Ungrouped positionals are unaffected, so a command can mix both.

@Option(description = "Target environment", helpGroup = "Environments", order = 1)
String target;

@Argument(description = "The artifact to deploy", helpGroup = "Environments", order = 2)
String artifact;

Help width

Help wraps to the live terminal width when one answers, so the same --help reflows on narrow and wide terminals. Resolution order: the aesh.help.width system property, then the COLUMNS environment variable, then the terminal width, then 80 columns. Anything below 40 columns clamps up to 40.

One command using several knobs

@CommandDefinition(
    name = "deploy",
    description = "Deploy an application",
    generateHelp = true,
    header = "Runs the deployment pipeline.",
    footer = "For support, contact ops@example.com",
    helpUrl = "https://example.com/deploy",
    argumentsSection = ArgumentsSection.FIRST,
    showDefaultValues = Toggle.ON
)
public class DeployCommand implements Command<CommandInvocation> {

    @Option(description = "Target environment", defaultValue = "staging")
    String target;

    @Option(description = "Deploy to production", helpGroup = "Environments", hasValue = false)
    boolean prod;

    @Argument(description = "The artifact to deploy")
    String artifact;

    @Override
    public CommandResult execute(CommandInvocation invocation) {
        ...
    }
}

Beyond the terminal

The same providers feed the generated docs (AsciiDoc, Markdown, AI skill files), where the HelpContext also carries the output format so content can differ per format. See Documentation Generation.