Skip to content
Documentation Generation

Documentation Generation

Aesh can generate documentation files from your command metadata in AsciiDoc, Markdown, or AI Skill format. This produces one page per command/subcommand, suitable for project documentation sites, man page alternatives, API reference, or AI agent skill definitions.

Quick Start

The simplest way to generate documentation is with the built-in --aesh-doc flag:

# Generate AsciiDoc to stdout (default)
$ myapp --aesh-doc

# Generate Markdown
$ myapp --aesh-doc markdown

# Generate AI skill documentation (agentskills.io format)
$ myapp --aesh-doc skill

# Save to a file
$ myapp --aesh-doc asciidoc > docs/myapp.adoc

No code changes needed — this works automatically with the standard AeshRuntimeRunner pattern.

Programmatic API

For build-time generation or more control, use the DocumentationGenerator builder:

import org.aesh.command.DocFormat;
import org.aesh.util.doc.DocumentationGenerator;

// Generate one file per command/subcommand
DocumentationGenerator.builder()
    .commandClass(MyCommand.class)
    .outputDir(new File("docs/pages"))
    .format(DocFormat.ASCIIDOC)
    .generate();

Antora Integration

For Antora documentation sites, set a cross-reference prefix and generate a navigation file:

DocumentationGenerator.builder()
    .commandClass(MyCommand.class)
    .outputDir(new File("docs/modules/cli/pages"))
    .crossRefPrefix("myapp:cli:")
    .navFile(new File("docs/modules/cli/nav.adoc"))
    .format(DocFormat.ASCIIDOC)
    .generate();

This produces:

  • One .adoc file per command/subcommand (e.g., myapp.adoc, myapp-run.adoc)
  • A nav.adoc with Antora-compatible xref: links
  • Cross-reference links between pages using the configured prefix

Single Command Output

Generate documentation for a single command as a string:

String doc = DocumentationGenerator.builder()
    .commandClass(MyCommand.class)
    .format(DocFormat.MARKDOWN)
    .generateSingle();

Generated Sections

Each generated page includes:

SectionContent
NAMECommand name and description
SYNOPSISFormatted usage with short flag clusters, negatable options, exclusive pipes, value placeholders, and [COMMAND] placeholder for groups. Consistent across all formats and --help.
DESCRIPTIONCommand description from the annotation
OPTIONSAll visible options with short/long names, value placeholders, defaults, aliases, and negatable display
ARGUMENTSPositional parameters with labels
COMMANDSSubcommands for group commands, with cross-reference links

HelpSectionProvider Content

If your command uses a HelpSectionProvider, its content is included:

  • Header — inserted between DESCRIPTION and OPTIONS
  • Additional sections — rendered as separate sections (e.g., EXAMPLES)
  • Footer — appended at the end
@CommandDefinition(name = "deploy", description = "Deploy app",
    helpSectionProvider = DeployHelpProvider.class)
public class DeployCommand implements Command<CommandInvocation> { ... }

public class DeployHelpProvider implements HelpSectionProvider {
    @Override
    public String getHeader() {
        return "Deploys the application to the configured environment.";
    }

    @Override
    public Map<String, List<HelpEntry>> getAdditionalSections() {
        return Map.of("Examples", List.of(
            new HelpEntry("deploy --env prod myapp", "Deploy to production"),
            new HelpEntry("deploy --force myapp", "Force redeploy")));
    }

    @Override
    public String getFooter() {
        return "Report bugs to https://github.com/example/deploy/issues";
    }
}

Option Rendering Features

The generator handles all option features:

  • Aliases--ea shown alongside --enableassertions
  • Negatable options — displayed as --[no-]verbose
  • Value placeholders--config=<config>, <key>=<value> for option groups
  • Default values — shown as Default: \dev``
  • Hidden option filteringOptionVisibility.HIDDEN options are excluded
  • Multi-line descriptions — text blocks and \n in descriptions render properly

Output Formats

AsciiDoc

= DEPLOY

== NAME

deploy -- Deploy an application

== SYNOPSIS

[source]
----
deploy [-f] [-e=<environment>] [-D<key>=<value>] <application>
----

== OPTIONS

*-e*, *--environment*=<environment>::
Target environment
+
Default: `dev`

*-f*, *--force*::
Force deployment

Markdown

# DEPLOY

## NAME

deploy -- Deploy an application

## SYNOPSIS

\`\`\`
deploy [-f] [-e=<environment>] [-D<key>=<value>] <application>
\`\`\`

## OPTIONS

### `-e`, `--environment=<environment>`

Target environment

Default: `dev`

### `-f`, `--force`

Force deployment

AI Skill Format

The skill format produces structured Markdown with YAML front matter following the agentskills.io specification, optimized for AI agent consumption:

---
name: deploy
description: >-
  Deploy applications to cloud environments. Use when the user wants
  to ship code to production or staging.
license: Apache-2.0
---

## Usage

deploy [-f] [-e=] [-D =]


## Options

| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| `--environment`, `-e` | String | no | `dev` | Target environment |
| `--force`, `-f` | boolean | no | - | Force deployment |
| `--secret` | boolean | no | - | Internal flag |

## Arguments

| Argument | Type | Required | Description |
|----------|------|----------|-------------|
| `<application>` | String | yes | Application name |

Key differences from the regular Markdown format:

  • YAML front matter with name and description fields per agentskills.io spec
  • Options in a table with Type, Required, Default columns (structured, easy for LLMs to parse)
  • All options included including HIDDEN options (AI agents may need them)
  • Subcommands in a table (not links to separate files)
  • Single document with all subcommand details inline
  • Format-specific content from HelpSectionProvider (see below)

Format-Aware HelpSectionProvider

HelpSectionProvider supports format-specific overloads, allowing commands to provide different content for different output formats. This is especially useful for AI skill documentation where descriptions and examples should be tailored for agent consumption.

public class DeployHelpProvider implements HelpSectionProvider {

    // Default sections (used by --help, asciidoc, markdown)
    @Override
    public Map<String, List<HelpEntry>> getAdditionalSections() {
        return Map.of("Plugins", List.of(
            new HelpEntry("maven", "Maven build integration")));
    }

    // Format-specific sections (used by --aesh-doc skill)
    @Override
    public Map<String, List<HelpEntry>> getAdditionalSections(DocFormat format) {
        if (format == DocFormat.SKILL) {
            return Map.of("Examples", List.of(
                new HelpEntry("deploy --env prod myapp", "Deploy to production"),
                new HelpEntry("deploy --force myapp", "Force redeploy")));
        }
        return getAdditionalSections();
    }

    // Override the annotation description for skill format
    @Override
    public String getDescription(DocFormat format) {
        if (format == DocFormat.SKILL) {
            return "Deploy applications to cloud environments. "
                 + "Use when the user wants to ship code to production or staging.";
        }
        return null; // use @CommandDefinition(description=...) for other formats
    }

    // Additional YAML front matter for skill format
    @Override
    public Map<String, String> getFrontMatter(DocFormat format) {
        if (format == DocFormat.SKILL) {
            return Map.of(
                "license", "Apache-2.0",
                "compatibility", "Requires Java 17+");
        }
        return null;
    }
}

Available Format-Aware Methods

All methods have defaults that delegate to the existing parameterless versions, so existing implementations are fully backward compatible.

MethodPurpose
getAdditionalSections(DocFormat)Format-specific help sections
getHeader(DocFormat)Format-specific header text
getFooter(DocFormat)Format-specific footer text
getDescription(DocFormat)Override the annotation description per format
getFrontMatter(DocFormat)Additional YAML front matter key-value pairs (for SKILL format)

The DocFormat enum values are: ASCIIDOC, MARKDOWN, SKILL.

The runtime --help path does not use DocFormat – it always calls the parameterless methods. Format-aware methods are only used during documentation generation (--aesh-doc or the programmatic API).

Multi-line Descriptions

Descriptions containing newlines are rendered properly in both --help output and generated documentation. This includes text blocks (Java 15+):

@Option(name = "env", description = """
    Target environment.
    Must be one of: dev, staging, prod.
    Defaults to the value of $APP_ENV.""")

Leading indentation from text blocks is automatically stripped.