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

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 0fd7d9abf9c2 CAMEL-26428: camel-jbang - The CLI creates only the 
command that the command line runs (#28763)
0fd7d9abf9c2 is described below

commit 0fd7d9abf9c2f500b252fed7f318e1f8e3349aae
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 31 12:12:58 2026 +0100

    CAMEL-26428: camel-jbang - The CLI creates only the command that the 
command line runs (#28763)
    
    Signed-off-by: Claus Ibsen <[email protected]>
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../dsl/jbang/core/commands/CamelJBangMain.java    | 430 ++++++++++++++-------
 .../camel/dsl/jbang/core/common/PluginHelper.java  |  11 +
 .../commands/CamelJBangMainOnlyCommandTest.java    | 105 +++++
 .../core/commands/action/SemanticCommandTest.java  |   7 +-
 .../dsl/jbang/launcher/CamelLauncherMain.java      |   4 +
 5 files changed, 407 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..655ba828fe4e 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 use the other commands of the CLI, besides the ones 
that use the plugins (which may add to any
+    // command, see PluginHelper.isPluginConsumingCommand): the shell and the 
completion script
+    private static final Set<String> FULL_COMMANDS = Set.of("shell", 
"completion");
+
     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,278 @@ 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, a command line that starts with an option (such as {@code 
--version}), or the commands that use the other
+     * commands ({@link #FULL_COMMANDS}) or the plugins ({@link 
PluginHelper#isPluginConsumingCommand(String)}).
+     *
+     * @param  args the command line
+     * @return      the name of the command, or {@code null} 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)
+                || PluginHelper.isPluginConsumingCommand(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             {@code true} 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 {@code null} 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 +448,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/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
index f331f8a39598..cf05692f8090 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginHelper.java
@@ -114,6 +114,17 @@ public final class PluginHelper {
         return !commandLine.getSubcommands().containsKey(target);
     }
 
+    /**
+     * Whether the command of the CLI uses the plugins, so they are loaded 
when it runs (see
+     * {@link #shouldDiscoverPlugins(CommandLine, String...)}).
+     *
+     * @param  command the name of the command
+     * @return         {@code true} for shell, run, export and cmd
+     */
+    public static boolean isPluginConsumingCommand(String command) {
+        return PLUGIN_CONSUMING_BUILTINS.contains(command);
+    }
+
     /**
      * Loads the plugin Json configuration from the user home and goes through 
all configured plugins adding the plugin
      * commands to the current command line. Tries to resolve each plugin from 
the classpath with the factory finder
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