The following is a suggestion from my agent as it was profiling my hobby project; it seems to make sense to me?
In particular it would allow me to skip e.g. all of Jackson's engine to be initialized when someone invokes a trivial command such as '--help' :)
Problem
AeshRuntimeRunner.execute() eagerly instantiates every registered command class during AeshCommandRegistryBuilder.create(), before looking at args to determine which command will run. For a CLI app with N commands, every invocation loads all N command classes plus their transitive dependencies.
Profiling a Quarkus CLI app with ~40 command classes on JVM (Java 25, -Xlog:class+init):
- create() triggers 112 class initializations for command + generated metadata classes (~61ms)
- These transitively pull in ~160 more classes (Jackson, TUI framework) referenced by commands that won't run
- Total: ~270 unnecessary class loads on every invocation, regardless of which command runs
In native image this is free (AOT-compiled), but JVM mode — used during development, CI, and on platforms without GraalVM — pays the full class-loading cost every time.
Proposed solution
The annotation processor already generates lightweight *_AeshMetadata classes carrying command names, descriptions, and option definitions as static data. The flow could be:
- Build a metadata-only registry from *_AeshMetadata classes (small, no constructor logic, no transitive deps)
- Parse the command name from args against this metadata
- Only instantiate the matched command class
This is a two-phase approach: route on metadata, then construct on demand.
Impact
Benefits every aesh-based CLI application. Savings scale linearly with the number of registered commands. For the profiled app, it would eliminate ~270 class loads (~61ms) from every JVM-mode invocation.
Environment: Java 25, Quarkus 3.39, aesh 3.17.2, Serial GC.
The following is a suggestion from my agent as it was profiling my hobby project; it seems to make sense to me?
In particular it would allow me to skip e.g. all of Jackson's engine to be initialized when someone invokes a trivial command such as '--help' :)
Problem
AeshRuntimeRunner.execute() eagerly instantiates every registered command class during AeshCommandRegistryBuilder.create(), before looking at args to determine which command will run. For a CLI app with N commands, every invocation loads all N command classes plus their transitive dependencies.
Profiling a Quarkus CLI app with ~40 command classes on JVM (Java 25, -Xlog:class+init):
In native image this is free (AOT-compiled), but JVM mode — used during development, CI, and on platforms without GraalVM — pays the full class-loading cost every time.
Proposed solution
The annotation processor already generates lightweight *_AeshMetadata classes carrying command names, descriptions, and option definitions as static data. The flow could be:
This is a two-phase approach: route on metadata, then construct on demand.
Impact
Benefits every aesh-based CLI application. Savings scale linearly with the number of registered commands. For the profiled app, it would eliminate ~270 class loads (~61ms) from every JVM-mode invocation.
Environment: Java 25, Quarkus 3.39, aesh 3.17.2, Serial GC.