This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-26428-cli-only-command
in repository https://gitbox.apache.org/repos/asf/camel.git

commit c0a1d1c4a669019b715e654cd96412a94cb3f43a
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 31 08:01:15 2026 +0100

    CAMEL-26428: camel-jbang - The CLI creates only the command that the 
command line runs
    
    The CLI created all its commands, and the commands of the plugins embedded
    in the launcher, on every run. It now creates only the command that the
    command line names, and all of them for the help, a command it does not know
    (a plugin, or a typo), and the commands that use the other commands or the
    plugins (shell, completion, run, export, cmd).
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../dsl/jbang/core/commands/CamelJBangMain.java    | 429 ++++++++++++++-------
 .../commands/CamelJBangMainOnlyCommandTest.java    | 105 +++++
 .../core/commands/action/SemanticCommandTest.java  |   7 +-
 .../dsl/jbang/launcher/CamelLauncherMain.java      |   4 +
 4 files changed, 395 insertions(+), 150 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
index cfb612b807ab..2b098e562dab 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
@@ -86,6 +86,10 @@ import picocli.CommandLine.Command;
                  " 70:Internal error: an unexpected exception",
                  "124:Timed out: no reply from the integration in time" })
 public class CamelJBangMain implements Callable<Integer> {
+    // the commands that need all the commands of the CLI: the shell and the 
completion script use the others, and the
+    // plugins, which may add to any command, are loaded for run, export and 
cmd (see PluginHelper.shouldDiscoverPlugins)
+    private static final Set<String> FULL_COMMANDS = Set.of("shell", 
"completion", "run", "export", "cmd");
+
     private static CommandLine commandLine;
 
     private Printer out = new Printer.SystemOutPrinter();
@@ -112,7 +116,14 @@ public class CamelJBangMain implements Callable<Integer> {
             // ignore
         }
 
-        commandLine = createCommandLine();
+        // the CLI creates only the command that the command line names, as 
creating all of them (and loading their
+        // classes) costs more than most commands take to run
+        String only = onlyCommand(args);
+        commandLine = createCommandLine(only);
+        if (only != null && !commandLine.getSubcommands().containsKey(only)) {
+            // not a command of the CLI (such as the command of a plugin, or a 
typo, for which picocli suggests others)
+            commandLine = createCommandLine(null);
+        }
 
         postAddCommands(commandLine, args);
 
@@ -152,155 +163,277 @@ public class CamelJBangMain implements 
Callable<Integer> {
         quit(exitCode);
     }
 
+    /**
+     * The command of the CLI that a command line runs, when the CLI needs to 
create only that command: not for the
+     * help, the version, a command line that starts with an option, or the 
commands that use the other commands or the
+     * plugins (see {@link #FULL_COMMANDS}).
+     *
+     * @param  args the command line
+     * @return      the name of the command, or <tt>null</tt> to create all 
commands
+     */
+    static String onlyCommand(String... args) {
+        if (args == null || args.length == 0) {
+            return null;
+        }
+        String target = args[0];
+        if (target == null || target.isBlank() || target.startsWith("-") || 
FULL_COMMANDS.contains(target)) {
+            return null;
+        }
+        for (String arg : args) {
+            if ("--help".equals(arg) || "-h".equals(arg)) {
+                // the help lists the plugins that are not installed, from all 
commands
+                return null;
+            }
+        }
+        return target;
+    }
+
+    /**
+     * Whether the command line has only the command of the CLI that it runs 
(see {@link #onlyCommand(String...)}), and
+     * not all the commands, so the commands of the plugins are not needed 
either.
+     *
+     * @param  commandLine the command line
+     * @param  args        the arguments it runs
+     * @return             <tt>true</tt> when it has only that command
+     */
+    public static boolean hasOnlyCommand(CommandLine commandLine, String... 
args) {
+        String only = onlyCommand(args);
+        return only != null && commandLine.getSubcommands().size() == 1 && 
commandLine.getSubcommands().containsKey(only);
+    }
+
+    private static boolean shouldCreate(String only, String name) {
+        return only == null || only.equals(name);
+    }
+
     /**
      * The command line with the commands of the CLI.
+     *
+     * @param only the name of the one command to create, or <tt>null</tt> for 
all commands
      */
-    private CommandLine createCommandLine() {
-        CommandLine commandLine = new CommandLine(this)
-                .addSubcommand("bind", new CommandLine(new Bind(this)))
-                .addSubcommand("catalog", new CommandLine(new 
CatalogCommand(this))
-                        .addSubcommand("component", new CommandLine(new 
CatalogComponent(this)))
-                        .addSubcommand("dataformat", new CommandLine(new 
CatalogDataFormat(this)))
-                        .addSubcommand("dev-console", new CommandLine(new 
CatalogDevConsole(this)))
-                        .addSubcommand("kamelet", new CommandLine(new 
CatalogKamelet(this)))
-                        .addSubcommand("transformer", new CommandLine(new 
CatalogTransformer(this)))
-                        .addSubcommand("language", new CommandLine(new 
CatalogLanguage(this)))
-                        .addSubcommand("other", new CommandLine(new 
CatalogOther(this))))
-                .addSubcommand("cmd", new CommandLine(new CamelAction(this))
-                        .addSubcommand("browse", new CommandLine(new 
CamelBrowseAction(this)))
-                        .addSubcommand("disable-processor", new 
CommandLine(new CamelProcessorDisableAction(this)))
-                        .addSubcommand("enable-processor", new CommandLine(new 
CamelProcessorEnableAction(this)))
-                        .addSubcommand("gc", new CommandLine(new 
CamelGCAction(this)))
-                        .addSubcommand("heap-dump", new CommandLine(new 
CamelHeapDump(this)))
-                        .addSubcommand("heap-histogram", new CommandLine(new 
CamelHeapHistogram(this)))
-                        .addSubcommand("memory-leak", new CommandLine(new 
CamelMemoryLeak(this)))
-                        .addSubcommand("load", new CommandLine(new 
CamelLoadAction(this)))
-                        .addSubcommand("logger", new CommandLine(new 
LoggerAction(this)))
-                        .addSubcommand("receive", new CommandLine(new 
CamelReceiveAction(this)))
-                        .addSubcommand("reload", new CommandLine(new 
CamelReloadAction(this)))
-                        .addSubcommand("reset-stats", new CommandLine(new 
CamelResetStatsAction(this)))
-                        .addSubcommand("resume-route", new CommandLine(new 
CamelRouteResumeAction(this)))
-                        .addSubcommand("route-diagram", new CommandLine(new 
CamelRouteDiagramAction(this)))
-                        .addSubcommand("route-dump", new CommandLine(new 
CamelRouteDumpAction(this)))
-                        .addSubcommand("route-structure", new CommandLine(new 
CamelRouteStructureAction(this)))
-                        .addSubcommand("route-topology", new CommandLine(new 
CamelRouteTopologyAction(this)))
-                        .addSubcommand("send", new CommandLine(new 
CamelSendAction(this)))
-                        .addSubcommand("sql", new CommandLine(new 
CamelSqlQueryAction(this)))
-                        .addSubcommand("span", new CommandLine(new 
CamelSpanAction(this)))
-                        .addSubcommand("start-group", new CommandLine(new 
CamelRouteGroupStartAction(this)))
-                        .addSubcommand("start-route", new CommandLine(new 
CamelRouteStartAction(this)))
-                        .addSubcommand("stop-group", new CommandLine(new 
CamelRouteGroupStopAction(this)))
-                        .addSubcommand("stop-route", new CommandLine(new 
CamelRouteStopAction(this)))
-                        .addSubcommand("stub", new CommandLine(new 
CamelStubAction(this)))
-                        .addSubcommand("suspend-route", new CommandLine(new 
CamelRouteSuspendAction(this)))
-                        .addSubcommand("thread-dump", new CommandLine(new 
CamelThreadDump(this))))
-                .addSubcommand("config", new CommandLine(new 
ConfigCommand(this))
-                        .addSubcommand("get", new CommandLine(new 
ConfigGet(this)))
-                        .addSubcommand("list", new CommandLine(new 
ConfigList(this)))
-                        .addSubcommand("set", new CommandLine(new 
ConfigSet(this)))
-                        .addSubcommand("unset", new CommandLine(new 
ConfigUnset(this))))
-                .addSubcommand("completion", new CommandLine(new 
Complete(this)))
-                .addSubcommand("doc", new CommandLine(new CatalogDoc(this)))
-                .addSubcommand("debug", new CommandLine(new Debug(this)))
-                .addSubcommand("dev", new CommandLine(new Dev(this)))
-                .addSubcommand("dependency", new CommandLine(new 
DependencyCommand(this))
-                        .addSubcommand("copy", new CommandLine(new 
DependencyCopy(this)))
-                        .addSubcommand("list", new CommandLine(new 
DependencyList(this)))
-                        .addSubcommand("runtime", new CommandLine(new 
DependencyRuntime(this)))
-                        .addSubcommand("update", new CommandLine(new 
DependencyUpdate(this))))
-                .addSubcommand("dirty", new CommandLine(new Dirty(this)))
-                .addSubcommand("doctor", new CommandLine(new Doctor(this)))
-                .addSubcommand("eval", new CommandLine(new EvalCommand(this))
-                        .addSubcommand("expression", new CommandLine(new 
EvalExpressionCommand(this))))
-                .addSubcommand("export", new CommandLine(new Export(this)))
-                .addSubcommand("explain", new CommandLine(new Explain(this)))
-                .addSubcommand("overview", new CommandLine(new Overview(this)))
-                .addSubcommand("ask", new CommandLine(new Ask(this)))
-                .addSubcommand("harden", new CommandLine(new Harden(this)))
-                .addSubcommand("get", new CommandLine(new CamelStatus(this))
-                        .addSubcommand("activity", new CommandLine(new 
ListActivity(this)))
-                        .addSubcommand("bean", new CommandLine(new 
CamelBeanDump(this)))
-                        .addSubcommand("blocked", new CommandLine(new 
ListBlocked(this)))
-                        .addSubcommand("circuit-breaker", new CommandLine(new 
ListCircuitBreaker(this)))
-                        .addSubcommand("consumer", new CommandLine(new 
ListConsumer(this)))
-                        .addSubcommand("context", new CommandLine(new 
CamelContextStatus(this)))
-                        .addSubcommand("count", new CommandLine(new 
CamelCount(this)))
-                        .addSubcommand("datasource", new CommandLine(new 
ListDataSource(this)))
-                        .addSubcommand("endpoint", new CommandLine(new 
ListEndpoint(this)))
-                        .addSubcommand("error", new CommandLine(new 
ListError(this)))
-                        .addSubcommand("event", new CommandLine(new 
ListEvent(this)))
-                        .addSubcommand("groovy", new CommandLine(new 
ListGroovy(this)))
-                        .addSubcommand("group", new CommandLine(new 
CamelRouteGroupStatus(this)))
-                        .addSubcommand("health", new CommandLine(new 
ListHealth(this)))
-                        .addSubcommand("history", new CommandLine(new 
CamelHistoryAction(this)))
-                        .addSubcommand("inflight", new CommandLine(new 
ListInflight(this)))
-                        .addSubcommand("internal-task", new CommandLine(new 
ListInternalTask(this)))
-                        .addSubcommand("kafka", new CommandLine(new 
ListKafka(this)))
-                        .addSubcommand("metric", new CommandLine(new 
ListMetric(this)))
-                        .addSubcommand("platform-http", new CommandLine(new 
ListPlatformHttp(this)))
-                        .addSubcommand("processor", new CommandLine(new 
CamelProcessorStatus(this)))
-                        .addSubcommand("producer", new CommandLine(new 
ListProducer(this)))
-                        .addSubcommand("properties", new CommandLine(new 
ListProperties(this)))
-                        .addSubcommand("rest", new CommandLine(new 
ListRest(this)))
-                        .addSubcommand("route", new CommandLine(new 
CamelRouteStatus(this)))
-                        .addSubcommand("route-controller", new CommandLine(new 
RouteControllerAction(this)))
-                        .addSubcommand("service", new CommandLine(new 
ListService(this)))
-                        .addSubcommand("source", new CommandLine(new 
CamelSourceAction(this)))
-                        .addSubcommand("sql-trace", new CommandLine(new 
ListSqlTrace(this)))
-                        .addSubcommand("startup-recorder", new CommandLine(new 
CamelStartupRecorderAction(this)))
-                        .addSubcommand("transformer", new CommandLine(new 
ListTransformer(this)))
-                        .addSubcommand("variable", new CommandLine(new 
ListVariable(this)))
-                        .addSubcommand("vault", new CommandLine(new 
ListVault(this))))
-                .addSubcommand("hawtio", new CommandLine(new Hawtio(this)))
-                .addSubcommand("infra", new CommandLine(new InfraCommand(this))
-                        .addSubcommand("get", new CommandLine(new 
InfraGet(this)))
-                        .addSubcommand("list", new CommandLine(new 
InfraList(this)))
-                        .addSubcommand("log", new CommandLine(new 
InfraLog(this)))
-                        .addSubcommand("ps", new CommandLine(new 
InfraPs(this)))
-                        .addSubcommand("restart", new CommandLine(new 
InfraRestart(this)))
-                        .addSubcommand("run", new CommandLine(new 
InfraRun(this)))
-                        .addSubcommand("stop", new CommandLine(new 
InfraStop(this))))
-                .addSubcommand("init", new CommandLine(new Init(this)))
-                .addSubcommand("jolokia", new CommandLine(new Jolokia(this)))
-                .addSubcommand("log", new CommandLine(new 
CamelLogAction(this)))
-                .addSubcommand("nano", new CommandLine(new Nano(this)))
-                .addSubcommand("plugin", new CommandLine(new 
PluginCommand(this))
-                        .addSubcommand("add", new CommandLine(new 
PluginAdd(this)))
-                        .addSubcommand("delete", new CommandLine(new 
PluginDelete(this)))
-                        .addSubcommand("get", new CommandLine(new 
PluginGet(this)))
-                        .addSubcommand("list", new CommandLine(new 
PluginList(this))))
-                .addSubcommand("ps", new CommandLine(new ListProcess(this)))
-                .addSubcommand("restart", new CommandLine(new 
RestartProcess(this)))
-                .addSubcommand("run", new CommandLine(new Run(this)))
-                .addSubcommand("sbom", new CommandLine(new 
SBOMGenerator(this)))
-                .addSubcommand("script", new CommandLine(new Script(this)))
-                .addSubcommand("semantic", new CommandLine(new 
CamelSemantic(this))
-                        .addSubcommand("get", new CommandLine(new 
SemanticGet(this)))
-                        .addSubcommand("eval", new CommandLine(new 
SemanticEvaluate(this)))
-                        .addSubcommand("audit", new CommandLine(new 
SemanticAudit(this)))
-                        .addSubcommand("monitoring", new CommandLine(new 
SemanticMonitoring(this))))
-                .addSubcommand("shell", new CommandLine(new Shell(this)))
-                .addSubcommand("stop", new CommandLine(new StopProcess(this)))
-                .addSubcommand("top", new CommandLine(new CamelTop(this))
-                        .addSubcommand("context", new CommandLine(new 
CamelContextTop(this)))
-                        .addSubcommand("group", new CommandLine(new 
CamelRouteGroupTop(this)))
-                        .addSubcommand("processor", new CommandLine(new 
CamelProcessorTop(this)))
-                        .addSubcommand("route", new CommandLine(new 
CamelRouteTop(this)))
-                        .addSubcommand("source", new CommandLine(new 
CamelSourceTop(this))))
-                .addSubcommand("trace", new CommandLine(new 
CamelTraceAction(this)))
-                .addSubcommand("transform", new CommandLine(new 
TransformCommand(this))
-                        .addSubcommand("dataweave", new CommandLine(new 
TransformDataWeave(this)))
-                        .addSubcommand("message", new CommandLine(new 
TransformMessageAction(this)))
-                        .addSubcommand("route", new CommandLine(new 
TransformRoute(this))))
-                .addSubcommand("update", new CommandLine(new 
UpdateCommand(this))
-                        .addSubcommand("list", new CommandLine(new 
UpdateList(this)))
-                        .addSubcommand("run", new CommandLine(new 
UpdateRun(this))))
-                .addSubcommand("version", new CommandLine(new 
VersionCommand(this))
-                        .addSubcommand("get", new CommandLine(new 
VersionGet(this)))
-                        .addSubcommand("list", new CommandLine(new 
VersionList(this)))
-                        .addSubcommand("set", new CommandLine(new 
VersionSet(this))))
-                .addSubcommand("wrapper", new CommandLine(new 
WrapperCommand(this)))
-                .setParameterExceptionHandler(new 
MissingPluginParameterExceptionHandler(this));
+    private CommandLine createCommandLine(String only) {
+        CommandLine commandLine = new CommandLine(this);
+        if (shouldCreate(only, "bind")) {
+            commandLine.addSubcommand("bind", new CommandLine(new Bind(this)));
+        }
+        if (shouldCreate(only, "catalog")) {
+            commandLine.addSubcommand("catalog", new CommandLine(new 
CatalogCommand(this))
+                    .addSubcommand("component", new CommandLine(new 
CatalogComponent(this)))
+                    .addSubcommand("dataformat", new CommandLine(new 
CatalogDataFormat(this)))
+                    .addSubcommand("dev-console", new CommandLine(new 
CatalogDevConsole(this)))
+                    .addSubcommand("kamelet", new CommandLine(new 
CatalogKamelet(this)))
+                    .addSubcommand("transformer", new CommandLine(new 
CatalogTransformer(this)))
+                    .addSubcommand("language", new CommandLine(new 
CatalogLanguage(this)))
+                    .addSubcommand("other", new CommandLine(new 
CatalogOther(this))));
+        }
+        if (shouldCreate(only, "cmd")) {
+            commandLine.addSubcommand("cmd", new CommandLine(new 
CamelAction(this))
+                    .addSubcommand("browse", new CommandLine(new 
CamelBrowseAction(this)))
+                    .addSubcommand("disable-processor", new CommandLine(new 
CamelProcessorDisableAction(this)))
+                    .addSubcommand("enable-processor", new CommandLine(new 
CamelProcessorEnableAction(this)))
+                    .addSubcommand("gc", new CommandLine(new 
CamelGCAction(this)))
+                    .addSubcommand("heap-dump", new CommandLine(new 
CamelHeapDump(this)))
+                    .addSubcommand("heap-histogram", new CommandLine(new 
CamelHeapHistogram(this)))
+                    .addSubcommand("memory-leak", new CommandLine(new 
CamelMemoryLeak(this)))
+                    .addSubcommand("load", new CommandLine(new 
CamelLoadAction(this)))
+                    .addSubcommand("logger", new CommandLine(new 
LoggerAction(this)))
+                    .addSubcommand("receive", new CommandLine(new 
CamelReceiveAction(this)))
+                    .addSubcommand("reload", new CommandLine(new 
CamelReloadAction(this)))
+                    .addSubcommand("reset-stats", new CommandLine(new 
CamelResetStatsAction(this)))
+                    .addSubcommand("resume-route", new CommandLine(new 
CamelRouteResumeAction(this)))
+                    .addSubcommand("route-diagram", new CommandLine(new 
CamelRouteDiagramAction(this)))
+                    .addSubcommand("route-dump", new CommandLine(new 
CamelRouteDumpAction(this)))
+                    .addSubcommand("route-structure", new CommandLine(new 
CamelRouteStructureAction(this)))
+                    .addSubcommand("route-topology", new CommandLine(new 
CamelRouteTopologyAction(this)))
+                    .addSubcommand("send", new CommandLine(new 
CamelSendAction(this)))
+                    .addSubcommand("sql", new CommandLine(new 
CamelSqlQueryAction(this)))
+                    .addSubcommand("span", new CommandLine(new 
CamelSpanAction(this)))
+                    .addSubcommand("start-group", new CommandLine(new 
CamelRouteGroupStartAction(this)))
+                    .addSubcommand("start-route", new CommandLine(new 
CamelRouteStartAction(this)))
+                    .addSubcommand("stop-group", new CommandLine(new 
CamelRouteGroupStopAction(this)))
+                    .addSubcommand("stop-route", new CommandLine(new 
CamelRouteStopAction(this)))
+                    .addSubcommand("stub", new CommandLine(new 
CamelStubAction(this)))
+                    .addSubcommand("suspend-route", new CommandLine(new 
CamelRouteSuspendAction(this)))
+                    .addSubcommand("thread-dump", new CommandLine(new 
CamelThreadDump(this))));
+        }
+        if (shouldCreate(only, "config")) {
+            commandLine.addSubcommand("config", new CommandLine(new 
ConfigCommand(this))
+                    .addSubcommand("get", new CommandLine(new ConfigGet(this)))
+                    .addSubcommand("list", new CommandLine(new 
ConfigList(this)))
+                    .addSubcommand("set", new CommandLine(new ConfigSet(this)))
+                    .addSubcommand("unset", new CommandLine(new 
ConfigUnset(this))));
+        }
+        if (shouldCreate(only, "completion")) {
+            commandLine.addSubcommand("completion", new CommandLine(new 
Complete(this)));
+        }
+        if (shouldCreate(only, "doc")) {
+            commandLine.addSubcommand("doc", new CommandLine(new 
CatalogDoc(this)));
+        }
+        if (shouldCreate(only, "debug")) {
+            commandLine.addSubcommand("debug", new CommandLine(new 
Debug(this)));
+        }
+        if (shouldCreate(only, "dev")) {
+            commandLine.addSubcommand("dev", new CommandLine(new Dev(this)));
+        }
+        if (shouldCreate(only, "dependency")) {
+            commandLine.addSubcommand("dependency", new CommandLine(new 
DependencyCommand(this))
+                    .addSubcommand("copy", new CommandLine(new 
DependencyCopy(this)))
+                    .addSubcommand("list", new CommandLine(new 
DependencyList(this)))
+                    .addSubcommand("runtime", new CommandLine(new 
DependencyRuntime(this)))
+                    .addSubcommand("update", new CommandLine(new 
DependencyUpdate(this))));
+        }
+        if (shouldCreate(only, "dirty")) {
+            commandLine.addSubcommand("dirty", new CommandLine(new 
Dirty(this)));
+        }
+        if (shouldCreate(only, "doctor")) {
+            commandLine.addSubcommand("doctor", new CommandLine(new 
Doctor(this)));
+        }
+        if (shouldCreate(only, "eval")) {
+            commandLine.addSubcommand("eval", new CommandLine(new 
EvalCommand(this))
+                    .addSubcommand("expression", new CommandLine(new 
EvalExpressionCommand(this))));
+        }
+        if (shouldCreate(only, "export")) {
+            commandLine.addSubcommand("export", new CommandLine(new 
Export(this)));
+        }
+        if (shouldCreate(only, "explain")) {
+            commandLine.addSubcommand("explain", new CommandLine(new 
Explain(this)));
+        }
+        if (shouldCreate(only, "overview")) {
+            commandLine.addSubcommand("overview", new CommandLine(new 
Overview(this)));
+        }
+        if (shouldCreate(only, "ask")) {
+            commandLine.addSubcommand("ask", new CommandLine(new Ask(this)));
+        }
+        if (shouldCreate(only, "harden")) {
+            commandLine.addSubcommand("harden", new CommandLine(new 
Harden(this)));
+        }
+        if (shouldCreate(only, "get")) {
+            commandLine.addSubcommand("get", new CommandLine(new 
CamelStatus(this))
+                    .addSubcommand("activity", new CommandLine(new 
ListActivity(this)))
+                    .addSubcommand("bean", new CommandLine(new 
CamelBeanDump(this)))
+                    .addSubcommand("blocked", new CommandLine(new 
ListBlocked(this)))
+                    .addSubcommand("circuit-breaker", new CommandLine(new 
ListCircuitBreaker(this)))
+                    .addSubcommand("consumer", new CommandLine(new 
ListConsumer(this)))
+                    .addSubcommand("context", new CommandLine(new 
CamelContextStatus(this)))
+                    .addSubcommand("count", new CommandLine(new 
CamelCount(this)))
+                    .addSubcommand("datasource", new CommandLine(new 
ListDataSource(this)))
+                    .addSubcommand("endpoint", new CommandLine(new 
ListEndpoint(this)))
+                    .addSubcommand("error", new CommandLine(new 
ListError(this)))
+                    .addSubcommand("event", new CommandLine(new 
ListEvent(this)))
+                    .addSubcommand("groovy", new CommandLine(new 
ListGroovy(this)))
+                    .addSubcommand("group", new CommandLine(new 
CamelRouteGroupStatus(this)))
+                    .addSubcommand("health", new CommandLine(new 
ListHealth(this)))
+                    .addSubcommand("history", new CommandLine(new 
CamelHistoryAction(this)))
+                    .addSubcommand("inflight", new CommandLine(new 
ListInflight(this)))
+                    .addSubcommand("internal-task", new CommandLine(new 
ListInternalTask(this)))
+                    .addSubcommand("kafka", new CommandLine(new 
ListKafka(this)))
+                    .addSubcommand("metric", new CommandLine(new 
ListMetric(this)))
+                    .addSubcommand("platform-http", new CommandLine(new 
ListPlatformHttp(this)))
+                    .addSubcommand("processor", new CommandLine(new 
CamelProcessorStatus(this)))
+                    .addSubcommand("producer", new CommandLine(new 
ListProducer(this)))
+                    .addSubcommand("properties", new CommandLine(new 
ListProperties(this)))
+                    .addSubcommand("rest", new CommandLine(new ListRest(this)))
+                    .addSubcommand("route", new CommandLine(new 
CamelRouteStatus(this)))
+                    .addSubcommand("route-controller", new CommandLine(new 
RouteControllerAction(this)))
+                    .addSubcommand("service", new CommandLine(new 
ListService(this)))
+                    .addSubcommand("source", new CommandLine(new 
CamelSourceAction(this)))
+                    .addSubcommand("sql-trace", new CommandLine(new 
ListSqlTrace(this)))
+                    .addSubcommand("startup-recorder", new CommandLine(new 
CamelStartupRecorderAction(this)))
+                    .addSubcommand("transformer", new CommandLine(new 
ListTransformer(this)))
+                    .addSubcommand("variable", new CommandLine(new 
ListVariable(this)))
+                    .addSubcommand("vault", new CommandLine(new 
ListVault(this))));
+        }
+        if (shouldCreate(only, "hawtio")) {
+            commandLine.addSubcommand("hawtio", new CommandLine(new 
Hawtio(this)));
+        }
+        if (shouldCreate(only, "infra")) {
+            commandLine.addSubcommand("infra", new CommandLine(new 
InfraCommand(this))
+                    .addSubcommand("get", new CommandLine(new InfraGet(this)))
+                    .addSubcommand("list", new CommandLine(new 
InfraList(this)))
+                    .addSubcommand("log", new CommandLine(new InfraLog(this)))
+                    .addSubcommand("ps", new CommandLine(new InfraPs(this)))
+                    .addSubcommand("restart", new CommandLine(new 
InfraRestart(this)))
+                    .addSubcommand("run", new CommandLine(new InfraRun(this)))
+                    .addSubcommand("stop", new CommandLine(new 
InfraStop(this))));
+        }
+        if (shouldCreate(only, "init")) {
+            commandLine.addSubcommand("init", new CommandLine(new Init(this)));
+        }
+        if (shouldCreate(only, "jolokia")) {
+            commandLine.addSubcommand("jolokia", new CommandLine(new 
Jolokia(this)));
+        }
+        if (shouldCreate(only, "log")) {
+            commandLine.addSubcommand("log", new CommandLine(new 
CamelLogAction(this)));
+        }
+        if (shouldCreate(only, "nano")) {
+            commandLine.addSubcommand("nano", new CommandLine(new Nano(this)));
+        }
+        if (shouldCreate(only, "plugin")) {
+            commandLine.addSubcommand("plugin", new CommandLine(new 
PluginCommand(this))
+                    .addSubcommand("add", new CommandLine(new PluginAdd(this)))
+                    .addSubcommand("delete", new CommandLine(new 
PluginDelete(this)))
+                    .addSubcommand("get", new CommandLine(new PluginGet(this)))
+                    .addSubcommand("list", new CommandLine(new 
PluginList(this))));
+        }
+        if (shouldCreate(only, "ps")) {
+            commandLine.addSubcommand("ps", new CommandLine(new 
ListProcess(this)));
+        }
+        if (shouldCreate(only, "restart")) {
+            commandLine.addSubcommand("restart", new CommandLine(new 
RestartProcess(this)));
+        }
+        if (shouldCreate(only, "run")) {
+            commandLine.addSubcommand("run", new CommandLine(new Run(this)));
+        }
+        if (shouldCreate(only, "sbom")) {
+            commandLine.addSubcommand("sbom", new CommandLine(new 
SBOMGenerator(this)));
+        }
+        if (shouldCreate(only, "script")) {
+            commandLine.addSubcommand("script", new CommandLine(new 
Script(this)));
+        }
+        if (shouldCreate(only, "semantic")) {
+            commandLine.addSubcommand("semantic", new CommandLine(new 
CamelSemantic(this))
+                    .addSubcommand("get", new CommandLine(new 
SemanticGet(this)))
+                    .addSubcommand("eval", new CommandLine(new 
SemanticEvaluate(this)))
+                    .addSubcommand("audit", new CommandLine(new 
SemanticAudit(this)))
+                    .addSubcommand("monitoring", new CommandLine(new 
SemanticMonitoring(this))));
+        }
+        if (shouldCreate(only, "shell")) {
+            commandLine.addSubcommand("shell", new CommandLine(new 
Shell(this)));
+        }
+        if (shouldCreate(only, "stop")) {
+            commandLine.addSubcommand("stop", new CommandLine(new 
StopProcess(this)));
+        }
+        if (shouldCreate(only, "top")) {
+            commandLine.addSubcommand("top", new CommandLine(new 
CamelTop(this))
+                    .addSubcommand("context", new CommandLine(new 
CamelContextTop(this)))
+                    .addSubcommand("group", new CommandLine(new 
CamelRouteGroupTop(this)))
+                    .addSubcommand("processor", new CommandLine(new 
CamelProcessorTop(this)))
+                    .addSubcommand("route", new CommandLine(new 
CamelRouteTop(this)))
+                    .addSubcommand("source", new CommandLine(new 
CamelSourceTop(this))));
+        }
+        if (shouldCreate(only, "trace")) {
+            commandLine.addSubcommand("trace", new CommandLine(new 
CamelTraceAction(this)));
+        }
+        if (shouldCreate(only, "transform")) {
+            commandLine.addSubcommand("transform", new CommandLine(new 
TransformCommand(this))
+                    .addSubcommand("dataweave", new CommandLine(new 
TransformDataWeave(this)))
+                    .addSubcommand("message", new CommandLine(new 
TransformMessageAction(this)))
+                    .addSubcommand("route", new CommandLine(new 
TransformRoute(this))));
+        }
+        if (shouldCreate(only, "update")) {
+            commandLine.addSubcommand("update", new CommandLine(new 
UpdateCommand(this))
+                    .addSubcommand("list", new CommandLine(new 
UpdateList(this)))
+                    .addSubcommand("run", new CommandLine(new 
UpdateRun(this))));
+        }
+        if (shouldCreate(only, "version")) {
+            commandLine.addSubcommand("version", new CommandLine(new 
VersionCommand(this))
+                    .addSubcommand("get", new CommandLine(new 
VersionGet(this)))
+                    .addSubcommand("list", new CommandLine(new 
VersionList(this)))
+                    .addSubcommand("set", new CommandLine(new 
VersionSet(this))));
+        }
+        if (shouldCreate(only, "wrapper")) {
+            commandLine.addSubcommand("wrapper", new CommandLine(new 
WrapperCommand(this)));
+        }
+        commandLine.setParameterExceptionHandler(new 
MissingPluginParameterExceptionHandler(this));
 
         commandLine.getHelpSectionMap().put(
                 CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST,
@@ -314,7 +447,7 @@ public class CamelJBangMain implements Callable<Integer> {
      * {@link CliRunner} runs each command on a new command line.
      */
     public CommandLine newCommandLine() {
-        CommandLine answer = createCommandLine();
+        CommandLine answer = createCommandLine(null);
         postAddCommands(answer, new String[0]);
         for (Plugin plugin : plugins) {
             plugin.customize(answer, this);
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainOnlyCommandTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainOnlyCommandTest.java
new file mode 100644
index 000000000000..39939ab2b169
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMainOnlyCommandTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands;
+
+import java.util.List;
+import java.util.Set;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CamelJBangMainOnlyCommandTest extends CamelCommandBaseTestSupport {
+
+    @BeforeEach
+    public void setup() throws Exception {
+        super.setup();
+
+        useTestHomeDir();
+    }
+
+    @Test
+    public void aCommandOfTheCliCreatesOnlyItself() {
+        CommandLine commandLine = execute("config", "list");
+
+        assertEquals(Set.of("config"), commandLine.getSubcommands().keySet());
+        assertEquals(Set.of("get", "list", "set", "unset"),
+                
commandLine.getSubcommands().get("config").getSubcommands().keySet());
+        assertTrue(CamelJBangMain.hasOnlyCommand(commandLine, "config", 
"list"));
+    }
+
+    @Test
+    public void theHelpCreatesAllCommands() {
+        assertAllCommands(execute("--help"));
+        assertAllCommands(execute());
+        assertAllCommands(execute("config", "--help"));
+    }
+
+    @Test
+    public void aCommandThatIsNotOfTheCliCreatesAllCommands() {
+        // the command of a plugin that is not installed, or a typo, for which 
picocli suggests the commands it knows
+        CommandLine commandLine = execute("confg", "list");
+
+        assertAllCommands(commandLine);
+        assertFalse(CamelJBangMain.hasOnlyCommand(commandLine, "confg", 
"list"));
+    }
+
+    @Test
+    public void 
theCommandsThatUseTheOtherCommandsOrThePluginsCreateAllCommands() {
+        for (String command : List.of("shell", "completion", "run", "export", 
"cmd")) {
+            assertNull(CamelJBangMain.onlyCommand(command, "--foo"), command);
+        }
+        assertNull(CamelJBangMain.onlyCommand("--verbose", "version"));
+        assertEquals("version", CamelJBangMain.onlyCommand("version", "get"));
+    }
+
+    @Test
+    public void aNewCommandLineHasAllCommands() {
+        // camel ask, camel shell and the monitor run any command on a new 
command line
+        CamelJBangMain main = new CamelJBangMain().withPrinter(printer);
+
+        assertAllCommands(main.newCommandLine());
+    }
+
+    private CommandLine execute(String... args) {
+        CommandLine[] executed = new CommandLine[1];
+        CamelJBangMain main = new CamelJBangMain() {
+            @Override
+            public void postExecute(CommandLine commandLine, String[] args, 
int exitCode) {
+                executed[0] = commandLine;
+            }
+
+            @Override
+            public void quit(int exitCode) {
+                // noop
+            }
+        }.withPrinter(printer);
+        main.setDiscoverPlugins(false);
+        main.execute(args);
+        return executed[0];
+    }
+
+    private static void assertAllCommands(CommandLine commandLine) {
+        
assertTrue(commandLine.getSubcommands().keySet().containsAll(List.of("config", 
"get", "run", "shell", "version")),
+                () -> "All commands of the CLI, but was: " + 
commandLine.getSubcommands().keySet());
+    }
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
index 1eb6c98a7310..d5ee5fa1f712 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/action/SemanticCommandTest.java
@@ -488,8 +488,6 @@ class SemanticCommandTest {
                 assertNotNull(semantic.getSubcommands().get("get"));
                 assertNotNull(semantic.getSubcommands().get("eval"));
                 assertNotNull(semantic.getSubcommands().get("audit"));
-                
assertFalse(command.getSubcommands().get("get").getSubcommands().containsKey("semantic"));
-                
assertFalse(command.getSubcommands().get("cmd").getSubcommands().containsKey("semantic-evaluate"));
             }
 
             @Override
@@ -505,6 +503,11 @@ class SemanticCommandTest {
         main.withPrinter(printer);
         main.execute("semantic", "eval", "--bad-option", "--json");
         assertError(2, "Unknown option");
+
+        // the command line of camel semantic has only that command: all of 
them are on a new command line
+        CommandLine all = main.newCommandLine();
+        
assertFalse(all.getSubcommands().get("get").getSubcommands().containsKey("semantic"));
+        
assertFalse(all.getSubcommands().get("cmd").getSubcommands().containsKey("semantic-evaluate"));
     }
 
     @ParameterizedTest
diff --git 
a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
 
b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
index 71f5c17d2ab3..2ab0a379fc67 100644
--- 
a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
+++ 
b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherMain.java
@@ -41,6 +41,10 @@ public class CamelLauncherMain extends CamelJBangMain {
 
     @Override
     public void postAddCommands(CommandLine commandLine, String[] args) {
+        if (hasOnlyCommand(commandLine, args)) {
+            // a command of the CLI, which needs none of the commands of the 
plugins
+            return;
+        }
         // Install embedded plugins. Each plugin must be given the classloader 
that loaded it (this
         // class's classloader, i.e. the fat-jar classloader) so that plugins 
relying on ServiceLoader
         // discovery can see the dependencies bundled in the launcher. The TUI 
plugin installs this

Reply via email to