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 77f8de5ddff Document camel.jbang options (#18902)
77f8de5ddff is described below

commit 77f8de5ddff3c222027914f24a7181582e0cd646
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Aug 14 11:22:29 2025 +0200

    Document camel.jbang options (#18902)
    
    * CAMEL-22205: camel-jbang: Document all camel.jbang options for tooling
---
 .../jbang/camel-jbang-configuration-metadata.json  |  51 +++++
 .../main/camel-main-configuration-metadata.json    |  16 +-
 .../org/apache/camel/catalog/CamelCatalog.java     |  18 ++
 .../catalog/CamelCatalogJSonSchemaResolver.java    |   6 +
 .../apache/camel/catalog/DefaultCamelCatalog.java  |  21 ++
 .../org/apache/camel/catalog/CamelCatalogTest.java |  23 +++
 .../apache/camel/catalog/JSonSchemaResolver.java   |   7 +
 .../camel/catalog/impl/AbstractCamelCatalog.java   |  10 +
 .../impl/CamelContextJSonSchemaResolver.java       |  24 +++
 .../camel-main-configuration-metadata.json         |  16 +-
 .../camel/yaml/io/ModelJSonSchemaResolver.java     |  11 ++
 .../ROOT/pages/camel-4x-upgrade-guide-4_14.adoc    |   4 +
 .../modules/ROOT/pages/camel-jbang.adoc            | 155 +++++----------
 dsl/camel-jbang/camel-jbang-core/pom.xml           |  44 ++++-
 .../camel-jbang-configuration-metadata.json        |  51 +++++
 .../dsl/jbang/core/commands/DependencyList.java    |  24 +--
 .../camel/dsl/jbang/core/commands/Export.java      |  47 ++---
 .../dsl/jbang/core/commands/ExportBaseCommand.java |  44 +++--
 .../dsl/jbang/core/commands/ExportQuarkus.java     |   3 +-
 .../apache/camel/dsl/jbang/core/commands/Run.java  | 129 ++++++------
 .../dsl/jbang/core/commands/SBOMGenerator.java     |  25 +--
 .../dsl/jbang/core/commands/TransformRoute.java    |   3 +-
 .../dsl/jbang/core/common/CamelJBangConstants.java | 216 +++++++++++++++++++++
 .../camel/dsl/jbang/core/common/RuntimeUtil.java   |   2 +-
 .../camel/dsl/jbang/core/common/VersionHelper.java |   4 +-
 .../org/apache/camel/tooling/model/JBangModel.java |  95 +++++++++
 .../org/apache/camel/tooling/model/JsonMapper.java | 111 ++++++++++-
 ...nDocMojo.java => PrepareCamelJBangDocMojo.java} |  43 ++--
 .../maven/packaging/PrepareCamelJBangMojo.java     | 182 +++++++++++++++++
 .../maven/packaging/PrepareCamelMainDocMojo.java   |   2 +-
 .../camel/maven/packaging/PrepareCatalogMojo.java  |  18 ++
 .../src/main/resources/jbang-options.mvel          |  24 +++
 32 files changed, 1149 insertions(+), 280 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
new file mode 100644
index 00000000000..2a31cc147aa
--- /dev/null
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
@@ -0,0 +1,51 @@
+{
+  "groups": [
+    { "name": "camel.jbang", "description": "Camel JBang configurations" }
+  ],
+  "properties": [
+    { "name": "camel.jbang.buildTool", "description": "Build tool to use 
(Maven or Gradle)", "type": "object", "javaType": "String", "defaultValue": 
"Maven" },
+    { "name": "camel.jbang.camel-version", "description": "The version of 
Apache Camel to use", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.camelSpringBootVersion", "description": "To use a 
custom Camel version when running or export to Spring Boot", "label": 
"spring-boot", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.classpathFiles", "description": "Additional files 
to add to classpath (Use commas to separate multiple files).", "type": 
"object", "javaType": "String" },
+    { "name": "camel.jbang.compileWorkDir", "description": "Work directory for 
compiler. Can be used to write compiled classes or other resources.", "label": 
"advanced", "type": "object", "javaType": "String", "defaultValue": 
".camel-jbang\/compile" },
+    { "name": "camel.jbang.console", "description": "Developer console at 
\/q\/dev on local HTTP server (port 8080 by default)", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.dependencies", "description": "Additional 
dependencies (Use commas to separate multiple dependencies).", "type": 
"object", "javaType": "String" },
+    { "name": "camel.jbang.download", "description": "Whether to allow 
automatic downloading JAR dependencies (over the internet)", "type": "boolean", 
"javaType": "boolean", "defaultValue": true },
+    { "name": "camel.jbang.excludes", "description": "Exclude files by name or 
pattern (Use commas to separate multiple files)", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.exportDir", "description": "Directory where the 
project will be exported", "type": "object", "javaType": "String", 
"defaultValue": "." },
+    { "name": "camel.jbang.gav", "description": "Maven coordinate 
(groupId:artifactId:version)", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.gradleWrapper", "description": "Include Gradle 
Wrapper files in the exported project", "type": "boolean", "javaType": 
"boolean", "defaultValue": true },
+    { "name": "camel.jbang.groovyFiles", "description": "Additional groovy 
source files to export to src\/main\/resources\/camel-groovy directory (Use 
commas to separate multiple files)", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.health", "description": "Health check at 
\/observe\/health on local HTTP server (port 8080 by default)", "type": 
"boolean", "javaType": "boolean", "defaultValue": false, "deprecated": true },
+    { "name": "camel.jbang.ignoreLoadingError", "description": "Whether to 
ignore route loading and compilation errors (use this with care!)", "label": 
"advanced", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.javaVersion", "description": "Java version (17 or 
21)", "type": "object", "javaType": "String", "defaultValue": "21", "enum": [ 
"17", "21" ] },
+    { "name": "camel.jbang.jfr", "description": "Enables Java Flight Recorder 
saving recording to disk on exit", "type": "boolean", "javaType": "boolean", 
"defaultValue": "false" },
+    { "name": "camel.jbang.jfr-profile", "description": "Java Flight Recorder 
profile to use (such as default or profile)", "type": "object", "javaType": 
"String", "defaultValue": "default" },
+    { "name": "camel.jbang.jib-maven-plugin-version", "description": "Version 
to use for jib-maven-plugin if exporting to camel-main and have Kubernetes 
enabled (jkube.xxx options)", "label": "kubernetes", "type": "object", 
"javaType": "String", "defaultValue": "3.4.5" },
+    { "name": "camel.jbang.jkube-maven-plugin-version", "description": 
"Version to use for jkube-maven-plugin if exporting to camel-main and have 
Kubernetes enabled (jkube.xxx options)", "label": "kubernetes", "type": 
"object", "javaType": "String", "defaultValue": "1.18.1" },
+    { "name": "camel.jbang.jkubeFiles", "description": "Resource YAML 
fragments for Kubernetes using Eclipse JKube tool (Use commas to separate 
multiple files).", "label": "kubernetes", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.kameletsVersion", "description": "Apache Camel 
Kamelets version. By default the Kamelets are the same version as Camel.", 
"type": "object", "javaType": "String" },
+    { "name": "camel.jbang.lazyBean", "description": "Whether to use lazy bean 
initialization (can help with complex classloading issues)", "label": 
"advanced", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.localKameletDir", "description": "Local file 
directory for loading custom Kamelets", "type": "object", "javaType": "String" 
},
+    { "name": "camel.jbang.maven-apache-snapshot-enabled", "description": 
"Whether downloading JARs from ASF Maven Snapshot repository is enabled", 
"label": "maven", "type": "boolean", "javaType": "boolean", "defaultValue": 
true },
+    { "name": "camel.jbang.maven-central-enabled", "description": "Whether 
downloading JARs from Maven Central repository is enabled", "label": "maven", 
"type": "boolean", "javaType": "boolean", "defaultValue": true },
+    { "name": "camel.jbang.maven-settings", "description": "Optional location 
of Maven settings.xml file to configure servers, repositories, mirrors, and 
proxies. If set to false, not even the default \/.m2\/settings.xml will be 
used.", "label": "maven", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.maven-settings-security", "description": "Optional 
location of Maven settings-security.xml file to decrypt Maven Settings 
(settings.xml) file", "label": "maven", "type": "object", "javaType": "String" 
},
+    { "name": "camel.jbang.mavenWrapper", "description": "Include Maven 
Wrapper files in the exported project", "type": "boolean", "javaType": 
"boolean", "defaultValue": true },
+    { "name": "camel.jbang.metrics", "description": "Metrics (Micrometer and 
Prometheus) at \/observe\/metrics on local HTTP server (port 8080 by default) 
when running standalone Camel", "type": "boolean", "javaType": "boolean", 
"defaultValue": false, "deprecated": true },
+    { "name": "camel.jbang.openApi", "description": "File name of open-api 
spec file (JSON or YAML) to generate routes from the swagger\/openapi API spec 
file.", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.packageScanJars", "description": "Whether to 
automatic package scan JARs for custom Spring or Quarkus beans making them 
available for Camel JBang", "label": "advanced", "type": "boolean", "javaType": 
"boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.prompt", "description": "Allow user to type in 
required parameters in prompt if not present in application", "label": 
"advanced", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.quarkusArtifactId", "description": "Quarkus 
Platform Maven artifactId", "label": "quarkus", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.quarkusGroupId", "description": "Quarkus Platform 
Maven groupId", "label": "quarkus", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.quarkusVersion", "description": "Quarkus Platform 
version", "label": "quarkus", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.repos", "description": "Additional Maven 
repositories for download on-demand (Use commas to separate multiple 
repositories)", "label": "maven", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.runtime", "description": "Which runtime to use 
(camel-main, spring-boot, quarkus)", "type": "object", "javaType": "String", 
"enum": [ "camel-main", "spring-boot", "quarkus" ] },
+    { "name": "camel.jbang.scriptFiles", "description": "Additional shell 
script files to export to src\/main\/scripts directory", "type": "object", 
"javaType": "String" },
+    { "name": "camel.jbang.sourceDir", "description": "Source directory for 
dynamically loading Camel file(s) to run. When using this, then files cannot be 
specified at the same time.", "label": "advanced", "type": "object", 
"javaType": "String" },
+    { "name": "camel.jbang.springBootVersion", "description": "Spring Boot 
version", "label": "spring-boot", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.stub", "description": "Stubs all the matching 
endpoint with the given component name or pattern. Multiple names can be 
separated by comma. (all = everything).", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.tlsFiles", "description": "Additional SSL\/TLS 
files to export to src\/main\/tls directory", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.verbose", "description": "Verbose output of startup 
activity (dependency resolution and downloading", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" }
+  ]
+}
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
index c829bfc6bf3..6d91d8826a1 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json
@@ -423,13 +423,13 @@
     { "name": "camel.vault.kubernetes.secrets", "description": "Specify the 
secret names (or pattern) to check for updates. Multiple secrets can be 
separated by comma.", "sourceType": 
"org.apache.camel.vault.KubernetesVaultConfiguration", "type": "string", 
"javaType": "java.lang.String" },
     { "name": "camel.vault.kubernetescm.configmaps", "description": "Specify 
the configmap names (or pattern) to check for updates. Multiple configmaps can 
be separated by comma.", "sourceType": 
"org.apache.camel.vault.KubernetesConfigMapVaultConfiguration", "type": 
"string", "javaType": "java.lang.String" },
     { "name": "camel.vault.kubernetescm.refreshEnabled", "description": 
"Whether to automatically reload Camel upon configmaps being updated in 
Kubernetes Cluster.", "sourceType": 
"org.apache.camel.vault.KubernetesConfigMapVaultConfiguration", "type": 
"boolean", "javaType": "boolean", "defaultValue": "false" },
-    { "name": "camel.vault.springConfig.label", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.password", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.profile", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.refreshEnabled", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"boolean", "javaType": "boolean", "defaultValue": "false" },
-    { "name": "camel.vault.springConfig.refreshPeriod", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"integer", "javaType": "long", "defaultValue": 30000 },
-    { "name": "camel.vault.springConfig.token", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.uris", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String", "defaultValue": 
"http:\/\/localhost:8888" },
-    { "name": "camel.vault.springConfig.username", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String", "defaultValue": "user" }
+    { "name": "camel.vault.springConfig.label", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.password", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.profile", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.refreshEnabled", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.vault.springConfig.refreshPeriod", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "integer", 
"javaType": "long", "defaultValue": 30000 },
+    { "name": "camel.vault.springConfig.token", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.uris", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String", "defaultValue": "http:\/\/localhost:8888" },
+    { "name": "camel.vault.springConfig.username", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String", "defaultValue": "user" }
   ]
 }
diff --git 
a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
 
b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
index 0d4d8a87694..6efc1461315 100644
--- 
a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
+++ 
b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalog.java
@@ -29,6 +29,7 @@ import org.apache.camel.tooling.model.ComponentModel;
 import org.apache.camel.tooling.model.DataFormatModel;
 import org.apache.camel.tooling.model.DevConsoleModel;
 import org.apache.camel.tooling.model.EipModel;
+import org.apache.camel.tooling.model.JBangModel;
 import org.apache.camel.tooling.model.Kind;
 import org.apache.camel.tooling.model.LanguageModel;
 import org.apache.camel.tooling.model.MainModel;
@@ -368,6 +369,13 @@ public interface CamelCatalog {
      */
     String mainJsonSchema();
 
+    /**
+     * Returns the camel-jbang json schema
+     *
+     * @return the camel-jbang json schema
+     */
+    String jbangJsonSchema();
+
     /**
      * Parses the endpoint uri and constructs a key/value properties of each 
option
      *
@@ -538,6 +546,11 @@ public interface CamelCatalog {
      */
     String listOthersAsJson();
 
+    /**
+     * Lists all the pojo beans summary details in JSon
+     */
+    String listBeansAsJson();
+
     /**
      * Reports a summary what the catalog contains in JSon
      */
@@ -596,6 +609,11 @@ public interface CamelCatalog {
      */
     MainModel mainModel();
 
+    /**
+     * @return the requested jbang model or {@code null} in case it is not 
available in this {@link CamelCatalog}
+     */
+    JBangModel jbangModel();
+
     /**
      * Lookup the model for the given kind and name
      *
diff --git 
a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java
 
b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java
index fb01ee50468..fce96a27414 100644
--- 
a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java
+++ 
b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/CamelCatalogJSonSchemaResolver.java
@@ -132,6 +132,12 @@ public class CamelCatalogJSonSchemaResolver implements 
JSonSchemaResolver {
         return loadResourceFromVersionManager(file);
     }
 
+    @Override
+    public String getJBangJsonSchema() {
+        final String file = 
"org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json";
+        return loadResourceFromVersionManager(file);
+    }
+
     @Override
     public String getOtherJSonSchema(String name) {
         final String file = 
camelCatalog.getRuntimeProvider().getOtherJSonSchemaDirectory() + "/" + name + 
EXTENSION;
diff --git 
a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
 
b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
index 45f9dd2db0b..d312026b25f 100644
--- 
a/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
+++ 
b/catalog/camel-catalog/src/main/java/org/apache/camel/catalog/DefaultCamelCatalog.java
@@ -40,6 +40,7 @@ import org.apache.camel.tooling.model.ComponentModel;
 import org.apache.camel.tooling.model.DataFormatModel;
 import org.apache.camel.tooling.model.DevConsoleModel;
 import org.apache.camel.tooling.model.EipModel;
+import org.apache.camel.tooling.model.JBangModel;
 import org.apache.camel.tooling.model.JsonMapper;
 import org.apache.camel.tooling.model.LanguageModel;
 import org.apache.camel.tooling.model.MainModel;
@@ -59,6 +60,7 @@ public class DefaultCamelCatalog extends 
AbstractCachingCamelCatalog implements
     private static final String MODELS_CATALOG = 
"org/apache/camel/catalog/models.properties";
     private static final String SCHEMAS_XML = 
"org/apache/camel/catalog/schemas";
     private static final String MAIN_DIR = "org/apache/camel/catalog/main";
+    private static final String JBANG_DIR = "org/apache/camel/catalog/jbang";
     private static final String BASE_RESOURCE_DIR = "org/apache/camel/catalog";
 
     public static final String FIND_COMPONENT_NAMES = "findComponentNames";
@@ -418,6 +420,11 @@ public class DefaultCamelCatalog extends 
AbstractCachingCamelCatalog implements
         return cache("main-model", "main-model", k -> super.mainModel());
     }
 
+    @Override
+    public JBangModel jbangModel() {
+        return cache("jbang-model", "jbang-model", k -> super.jbangModel());
+    }
+
     @Override
     public Set<String> findModelLabels() {
         return cache(FIND_MODEL_LABELS, () -> findLabels(this::findModelNames, 
this::eipModel));
@@ -472,6 +479,11 @@ public class DefaultCamelCatalog extends 
AbstractCachingCamelCatalog implements
         return cache(MAIN_DIR + "/camel-main-configuration-metadata.json", 
this::loadResource);
     }
 
+    @Override
+    public String jbangJsonSchema() {
+        return cache(JBANG_DIR + "/camel-jbang-configuration-metadata.json", 
this::loadResource);
+    }
+
     @Override
     public String listComponentsAsJson() {
         return cache(LIST_COMPONENTS_AS_JSON, () -> 
JsonMapper.serialize(findComponentNames().stream()
@@ -535,6 +547,15 @@ public class DefaultCamelCatalog extends 
AbstractCachingCamelCatalog implements
                 .toList()));
     }
 
+    @Override
+    public String listBeansAsJson() {
+        return cache(LIST_BEANS_AS_JSON, () -> 
JsonMapper.serialize(findBeansNames().stream()
+                .map(this::pojoBeanJSonSchema)
+                .map(JsonMapper::deserialize)
+                .map(o -> o.get("bean"))
+                .toList()));
+    }
+
     @Override
     public String summaryAsJson() {
         return cache(SUMMARY_AS_JSON, () -> {
diff --git 
a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
 
b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
index b77669fb290..e2636a2c1a3 100644
--- 
a/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
+++ 
b/catalog/camel-catalog/src/test/java/org/apache/camel/catalog/CamelCatalogTest.java
@@ -212,6 +212,18 @@ public class CamelCatalogTest {
     public void testMain() {
         String schema = catalog.mainJsonSchema();
         assertNotNull(schema);
+
+        var model = catalog.mainModel();
+        assertNotNull(model);
+    }
+
+    @Test
+    public void testJBang() {
+        String schema = catalog.jbangJsonSchema();
+        assertNotNull(schema);
+
+        var model = catalog.jbangModel();
+        assertNotNull(model);
     }
 
     @Test
@@ -923,6 +935,17 @@ public class CamelCatalogTest {
         assertNotNull(tree);
     }
 
+    @Test
+    public void testListBeansAsJson() throws Exception {
+        String json = catalog.listBeansAsJson();
+        assertNotNull(json);
+
+        // validate we can parse the json
+        ObjectMapper mapper = new ObjectMapper();
+        JsonNode tree = mapper.readTree(json);
+        assertNotNull(tree);
+    }
+
     @Test
     public void testSummaryAsJson() throws Exception {
         String json = catalog.summaryAsJson();
diff --git 
a/core/camel-api/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java 
b/core/camel-api/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
index 0027f93d1df..7b8c99f4c57 100644
--- 
a/core/camel-api/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
+++ 
b/core/camel-api/src/main/java/org/apache/camel/catalog/JSonSchemaResolver.java
@@ -89,6 +89,13 @@ public interface JSonSchemaResolver {
      */
     String getMainJsonSchema();
 
+    /**
+     * Returns the camel-jbang json schema
+     *
+     * @return the camel-jbang json schema
+     */
+    String getJBangJsonSchema();
+
     /**
      * Returns the pojo bean information as JSON format.
      *
diff --git 
a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java
 
b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java
index 238dde62451..a5599694e1b 100644
--- 
a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java
+++ 
b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/AbstractCamelCatalog.java
@@ -52,6 +52,7 @@ import org.apache.camel.tooling.model.ComponentModel;
 import org.apache.camel.tooling.model.DataFormatModel;
 import org.apache.camel.tooling.model.DevConsoleModel;
 import org.apache.camel.tooling.model.EipModel;
+import org.apache.camel.tooling.model.JBangModel;
 import org.apache.camel.tooling.model.JsonMapper;
 import org.apache.camel.tooling.model.LanguageModel;
 import org.apache.camel.tooling.model.MainModel;
@@ -163,6 +164,15 @@ public abstract class AbstractCamelCatalog {
         return json != null ? JsonMapper.generateMainModel(json) : null;
     }
 
+    public String jbangJSonSchema() {
+        return getJSonSchemaResolver().getJBangJsonSchema();
+    }
+
+    public JBangModel jbangModel() {
+        String json = jbangJSonSchema();
+        return json != null ? JsonMapper.generateJBangModel(json) : null;
+    }
+
     public SuggestionStrategy getSuggestionStrategy() {
         return suggestionStrategy;
     }
diff --git 
a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelContextJSonSchemaResolver.java
 
b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelContextJSonSchemaResolver.java
index a737401dd8f..402d22eed0e 100644
--- 
a/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelContextJSonSchemaResolver.java
+++ 
b/core/camel-core-catalog/src/main/java/org/apache/camel/catalog/impl/CamelContextJSonSchemaResolver.java
@@ -140,4 +140,28 @@ public class CamelContextJSonSchemaResolver implements 
JSonSchemaResolver {
         }
         return null;
     }
+
+    @Override
+    public String getJBangJsonSchema() {
+        String path = "META-INF/camel-jbang-configuration-metadata.json";
+        InputStream is = null;
+        if (classLoader != null) {
+            is = classLoader.getResourceAsStream(path);
+        }
+        if (is == null) {
+            ClassResolver resolver = camelContext.getClassResolver();
+            is = resolver.loadResourceAsStream(path);
+        }
+        if (is != null) {
+            try {
+                return IOHelper.loadText(is);
+            } catch (IOException e) {
+                // ignore
+            } finally {
+                IOHelper.close(is);
+            }
+        }
+        return null;
+    }
+
 }
diff --git 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index c829bfc6bf3..6d91d8826a1 100644
--- 
a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ 
b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -423,13 +423,13 @@
     { "name": "camel.vault.kubernetes.secrets", "description": "Specify the 
secret names (or pattern) to check for updates. Multiple secrets can be 
separated by comma.", "sourceType": 
"org.apache.camel.vault.KubernetesVaultConfiguration", "type": "string", 
"javaType": "java.lang.String" },
     { "name": "camel.vault.kubernetescm.configmaps", "description": "Specify 
the configmap names (or pattern) to check for updates. Multiple configmaps can 
be separated by comma.", "sourceType": 
"org.apache.camel.vault.KubernetesConfigMapVaultConfiguration", "type": 
"string", "javaType": "java.lang.String" },
     { "name": "camel.vault.kubernetescm.refreshEnabled", "description": 
"Whether to automatically reload Camel upon configmaps being updated in 
Kubernetes Cluster.", "sourceType": 
"org.apache.camel.vault.KubernetesConfigMapVaultConfiguration", "type": 
"boolean", "javaType": "boolean", "defaultValue": "false" },
-    { "name": "camel.vault.springConfig.label", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.password", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.profile", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.refreshEnabled", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"boolean", "javaType": "boolean", "defaultValue": "false" },
-    { "name": "camel.vault.springConfig.refreshPeriod", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"integer", "javaType": "long", "defaultValue": 30000 },
-    { "name": "camel.vault.springConfig.token", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String" },
-    { "name": "camel.vault.springConfig.uris", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String", "defaultValue": 
"http:\/\/localhost:8888" },
-    { "name": "camel.vault.springConfig.username", "description": null, 
"sourceType": "org.apache.camel.vault.SpringCloudConfigConfiguration", "type": 
"string", "javaType": "java.lang.String", "defaultValue": "user" }
+    { "name": "camel.vault.springConfig.label", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.password", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.profile", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.refreshEnabled", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.vault.springConfig.refreshPeriod", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "integer", 
"javaType": "long", "defaultValue": 30000 },
+    { "name": "camel.vault.springConfig.token", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String" },
+    { "name": "camel.vault.springConfig.uris", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String", "defaultValue": "http:\/\/localhost:8888" },
+    { "name": "camel.vault.springConfig.username", "sourceType": 
"org.apache.camel.vault.SpringCloudConfigConfiguration", "type": "string", 
"javaType": "java.lang.String", "defaultValue": "user" }
   ]
 }
diff --git 
a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/io/ModelJSonSchemaResolver.java
 
b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/io/ModelJSonSchemaResolver.java
index 0f78b2ed679..fbbec6f79b6 100644
--- 
a/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/io/ModelJSonSchemaResolver.java
+++ 
b/core/camel-yaml-io/src/main/java/org/apache/camel/yaml/io/ModelJSonSchemaResolver.java
@@ -152,6 +152,17 @@ class ModelJSonSchemaResolver implements 
JSonSchemaResolver {
         return null;
     }
 
+    @Override
+    public String getJBangJsonSchema() {
+        try {
+            String path = "META-INF/camel-jbang-configuration-metadata.json";
+            return doLoadResource(path);
+        } catch (Exception e) {
+            // ignore
+        }
+        return null;
+    }
+
     private String doLoadResource(String path) throws IOException {
         InputStream is = null;
         if (classLoader != null) {
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
index 6ee8c3bd4d4..2637c44bbd9 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_14.adoc
@@ -64,6 +64,10 @@ this during export.
 
 Notice when exporting to kubernetes then `camel-observabilities-services` is 
always enabled.
 
+When controlling Camel JBang exports with configuration in 
`application.properties` then
+there was a duplicate option (`camel.jbang.repositories` and 
`camel.jbang.repos`) which has been fixed to
+be only `camel.jbang.repos`.
+
 === camel-google
 
 The scopes parameter for camel-google-calendar, camel-google-calendar-streams, 
camel-google-drive, camel-google-mail, camel-google-mail-streams and 
camel-google-sheets-streams has been defined as String instead of 
Collection<String>. For the migration users will need to, eventually, define 
scopes as a comma separated list of scopes instead of a Collection instance. 
For more information the related issue is CAMEL-22247.
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index 3674541605a..04243ab86b0 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -3942,113 +3942,62 @@ TIP: Camel will by default store export logs to `<user 
home>/.camel/camel-export
 The export command will by default load configuration from 
`application.properties`
 which also can be used to specific parameters for export such as selecting the 
runtime and java version.
 
-The follow options related to _exporting_, can be configured in 
`application.properties`:
+The follow options related to _exporting_ or _running_, can be configured in 
`application.properties`:
 
-|===
-|Option | Description
-
-|`camel.jbang.runtime`
-|Runtime (spring-boot, quarkus, or camel-main)
-
-|`camel.jbang.gav`
-|The Maven group:artifact:version
-
-|`camel.jbang.dependencies`
-|Additional dependencies (Use commas to separate multiple dependencies). See 
more details at xref:_adding_custom_jars[].
-
-|`camel.jbang.excludes`
-|Exclude files by name or pattern. Multiple names can be separated by comma.
-
-|`camel.jbang.classpathFiles`
-|Additional files to add to classpath (Use commas to separate multiple files). 
See more details at xref:_adding_custom_jars[].
-
-|`camel.jbang.jkubeFiles`
-|Resource fragments for Kubernetes (Use commas to separate multiple files).
-
-|`camel.jbang.javaVersion`
-|Java version (17 or 21). Java 17 is default.
-
-|`camel.jbang.kameletsVersion`
-|Apache Camel Kamelets version
-
-|`camel.jbang.localKameletDir`
-|Local directory for loading Kamelets
-
-|`camel.jbang.camelSpringBootVersion`
-|Camel version to use with Spring Boot
-
-|`camel.jbang.springBootVersion`
-|Spring Boot version
-
-|`camel.jbang.quarkusGroupId`
-|Quarkus Platform Maven groupId
-
-|`camel.jbang.quarkusArtifactId`
-|Quarkus Platform Maven artifactId
-
-|`camel.jbang.quarkusVersion`
-|Quarkus Platform version
-
-|`camel.jbang.mavenWrapper`
-|Include Maven Wrapper files in the exported project
-
-|`camel.jbang.gradleWrapper`
-|Include Gradle Wrapper files in the exported project
-
-|`camel.jbang.buildTool`
-|Build tool to use (Maven or Gradle)
-
-|`camel.jbang.repos`
-|Additional maven repositories for download on-demand (Use commas to separate 
multiple repositories)
-
-|`camel.jbang.mavenSettings`
-|Optional location of Maven settings.xml file to configure servers, 
repositories, mirrors, and proxies. If set to false, not even the default 
~/.m2/settings.xml will be used.
-
-|`camel.jbang.mavenSettingsSecurity`
-|Optional location of Maven settings-security.xml file to decrypt settings.xml
-
-|`camel.jbang.mavenCentralEnabled`
-|Whether downloading JARs from Maven Central repository is enabled
-
-|`camel.jbang.mavenApacheSnapshotEnabled`
-|Whether downloading JARs from ASF Maven Snapshot repository is enabled
-
-|`camel.jbang.download`
-|Whether to allow automatic downloading JAR dependencies (over the internet)
-
-|`camel.jbang.packageScanJars`
-|Whether to automatic package scan JARs for custom Spring or Quarkus beans 
making them available for Camel JBang
-
-|`camel.jbang.exportDir`
-|Directory where the project will be exported
-
-|`camel.jbang.platform-http.port`
-| HTTP server port to use when running standalone Camel, such as when 
`--console` is enabled (port 8080 by default).
-
-|`camel.jbang.console`
-| Developer console at /q/dev on local HTTP server (port 8080 by default) when 
running standalone Camel
-
-|`camel.jbang.info`
-| Info console at /observe/info on local HTTP server (port 8080 by default) 
when running standalone Camel
-
-|`camel.jbang.health`
-| Health check at /observe/health on local HTTP server (port 8080 by default) 
when running standalone Camel
-
-|`camel.jbang.metrics`
-| Metrics (Micrometer and Prometheus) at /observe/metrics on local HTTP server 
(port 8080 by default) when running standalone Camel
-
-|`camel.jbang.open-api`
-| File name of open-api spec file (JSON or YAML) that are used when using 
`--open-api` to generate routes from the swagger/openapi API spec file.
-
-|`camel.jbang.ignoreLoadingError`
-| Whether to ignore route loading and compilation errors (use this with care!)
-
-|`camel.jbang.jib-maven-plugin-version`
-| Version to use for jib-maven-plugin if exporting to camel-main and have 
Kubernetes enabled (jkube.xxx options).
+// jbang options: START
+=== Camel JBang configurations
+The camel.jbang supports 44 options, which are listed below.
 
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *camel.jbang.buildTool* | Build tool to use (Maven or Gradle) | Maven | 
String
+| *camel.jbang.camel-version* | The version of Apache Camel to use |  | String
+| *camel.jbang.camelSpringBoot{zwsp}Version* | To use a custom Camel version 
when running or export to Spring Boot |  | String
+| *camel.jbang.classpathFiles* | Additional files to add to classpath (Use 
commas to separate multiple files). |  | String
+| *camel.jbang.compileWorkDir* | Work directory for compiler. Can be used to 
write compiled classes or other resources. | .camel-jbang/compile | String
+| *camel.jbang.console* | Developer console at /q/dev on local HTTP server 
(port 8080 by default) | false | boolean
+| *camel.jbang.dependencies* | Additional dependencies (Use commas to separate 
multiple dependencies). |  | String
+| *camel.jbang.download* | Whether to allow automatic downloading JAR 
dependencies (over the internet) | true | boolean
+| *camel.jbang.excludes* | Exclude files by name or pattern (Use commas to 
separate multiple files) |  | String
+| *camel.jbang.exportDir* | Directory where the project will be exported | . | 
String
+| *camel.jbang.gav* | Maven coordinate (groupId:artifactId:version) |  | String
+| *camel.jbang.gradleWrapper* | Include Gradle Wrapper files in the exported 
project | true | boolean
+| *camel.jbang.groovyFiles* | Additional groovy source files to export to 
src/main/resources/camel-groovy directory (Use commas to separate multiple 
files) |  | String
+| *camel.jbang.health* | Health check at /observe/health on local HTTP server 
(port 8080 by default) | false | boolean
+| *camel.jbang.ignoreLoadingError* | Whether to ignore route loading and 
compilation errors (use this with care!) | false | boolean
+| *camel.jbang.javaVersion* | Java version (17 or 21) | 21 | String
+| *camel.jbang.jfr* | Enables Java Flight Recorder saving recording to disk on 
exit | false | boolean
+| *camel.jbang.jfr-profile* | Java Flight Recorder profile to use (such as 
default or profile) | default | String
+| *camel.jbang.jib-maven-plugin-version* | Version to use for jib-maven-plugin 
if exporting to camel-main and have Kubernetes enabled (jkube.xxx options) | 
3.4.5 | String
+| *camel.jbang.jkube-maven-plugin-version* | Version to use for 
jkube-maven-plugin if exporting to camel-main and have Kubernetes enabled 
(jkube.xxx options) | 1.18.1 | String
+| *camel.jbang.jkubeFiles* | Resource YAML fragments for Kubernetes using 
Eclipse JKube tool (Use commas to separate multiple files). |  | String
+| *camel.jbang.kameletsVersion* | Apache Camel Kamelets version. By default 
the Kamelets are the same version as Camel. |  | String
+| *camel.jbang.lazyBean* | Whether to use lazy bean initialization (can help 
with complex classloading issues) | false | boolean
+| *camel.jbang.localKameletDir* | Local file directory for loading custom 
Kamelets |  | String
+| *camel.jbang.maven-apache-snapshot-enabled* | Whether downloading JARs from 
ASF Maven Snapshot repository is enabled | true | boolean
+| *camel.jbang.maven-central-enabled* | Whether downloading JARs from Maven 
Central repository is enabled | true | boolean
+| *camel.jbang.maven-settings* | Optional location of Maven settings.xml file 
to configure servers, repositories, mirrors, and proxies. If set to false, not 
even the default /.m2/settings.xml will be used. |  | String
+| *camel.jbang.maven-settings-security* | Optional location of Maven 
settings-security.xml file to decrypt Maven Settings (settings.xml) file |  | 
String
+| *camel.jbang.mavenWrapper* | Include Maven Wrapper files in the exported 
project | true | boolean
+| *camel.jbang.metrics* | Metrics (Micrometer and Prometheus) at 
/observe/metrics on local HTTP server (port 8080 by default) when running 
standalone Camel | false | boolean
+| *camel.jbang.openApi* | File name of open-api spec file (JSON or YAML) to 
generate routes from the swagger/openapi API spec file. |  | String
+| *camel.jbang.packageScanJars* | Whether to automatic package scan JARs for 
custom Spring or Quarkus beans making them available for Camel JBang | false | 
boolean
+| *camel.jbang.prompt* | Allow user to type in required parameters in prompt 
if not present in application | false | boolean
+| *camel.jbang.quarkusArtifactId* | Quarkus Platform Maven artifactId |  | 
String
+| *camel.jbang.quarkusGroupId* | Quarkus Platform Maven groupId |  | String
+| *camel.jbang.quarkusVersion* | Quarkus Platform version |  | String
+| *camel.jbang.repos* | Additional Maven repositories for download on-demand 
(Use commas to separate multiple repositories) |  | String
+| *camel.jbang.runtime* | Which runtime to use (camel-main, spring-boot, 
quarkus) |  | String
+| *camel.jbang.scriptFiles* | Additional shell script files to export to 
src/main/scripts directory |  | String
+| *camel.jbang.sourceDir* | Source directory for dynamically loading Camel 
file(s) to run. When using this, then files cannot be specified at the same 
time. |  | String
+| *camel.jbang.springBootVersion* | Spring Boot version |  | String
+| *camel.jbang.stub* | Stubs all the matching endpoint with the given 
component name or pattern. Multiple names can be separated by comma. (all = 
everything). |  | String
+| *camel.jbang.tlsFiles* | Additional SSL/TLS files to export to src/main/tls 
directory |  | String
+| *camel.jbang.verbose* | Verbose output of startup activity (dependency 
resolution and downloading | false | boolean
 |===
+// jbang options: END
 
-NOTE: These are options from the export command, so you can see more details 
and default values using `camel export --help`.
 
 == Configuration
 
diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml 
b/dsl/camel-jbang/camel-jbang-core/pom.xml
index 4d0fa06c58f..f1b9286616c 100644
--- a/dsl/camel-jbang/camel-jbang-core/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-core/pom.xml
@@ -17,7 +17,8 @@
     limitations under the License.
 
 -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
 
     <modelVersion>4.0.0</modelVersion>
 
@@ -176,4 +177,45 @@
         </dependency>
     </dependencies>
 
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-package-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>prepare-jbang</goal>
+                            <goal>prepare-jbang-doc</goal>
+                        </goals>
+                        <phase>generate-resources</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <goals>
+                            <goal>add-source</goal>
+                            <goal>add-resource</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>src/generated/java</source>
+                            </sources>
+                            <resources>
+                                <resource>
+                                    
<directory>src/generated/resources</directory>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
 </project>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
new file mode 100644
index 00000000000..2a31cc147aa
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
@@ -0,0 +1,51 @@
+{
+  "groups": [
+    { "name": "camel.jbang", "description": "Camel JBang configurations" }
+  ],
+  "properties": [
+    { "name": "camel.jbang.buildTool", "description": "Build tool to use 
(Maven or Gradle)", "type": "object", "javaType": "String", "defaultValue": 
"Maven" },
+    { "name": "camel.jbang.camel-version", "description": "The version of 
Apache Camel to use", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.camelSpringBootVersion", "description": "To use a 
custom Camel version when running or export to Spring Boot", "label": 
"spring-boot", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.classpathFiles", "description": "Additional files 
to add to classpath (Use commas to separate multiple files).", "type": 
"object", "javaType": "String" },
+    { "name": "camel.jbang.compileWorkDir", "description": "Work directory for 
compiler. Can be used to write compiled classes or other resources.", "label": 
"advanced", "type": "object", "javaType": "String", "defaultValue": 
".camel-jbang\/compile" },
+    { "name": "camel.jbang.console", "description": "Developer console at 
\/q\/dev on local HTTP server (port 8080 by default)", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.dependencies", "description": "Additional 
dependencies (Use commas to separate multiple dependencies).", "type": 
"object", "javaType": "String" },
+    { "name": "camel.jbang.download", "description": "Whether to allow 
automatic downloading JAR dependencies (over the internet)", "type": "boolean", 
"javaType": "boolean", "defaultValue": true },
+    { "name": "camel.jbang.excludes", "description": "Exclude files by name or 
pattern (Use commas to separate multiple files)", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.exportDir", "description": "Directory where the 
project will be exported", "type": "object", "javaType": "String", 
"defaultValue": "." },
+    { "name": "camel.jbang.gav", "description": "Maven coordinate 
(groupId:artifactId:version)", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.gradleWrapper", "description": "Include Gradle 
Wrapper files in the exported project", "type": "boolean", "javaType": 
"boolean", "defaultValue": true },
+    { "name": "camel.jbang.groovyFiles", "description": "Additional groovy 
source files to export to src\/main\/resources\/camel-groovy directory (Use 
commas to separate multiple files)", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.health", "description": "Health check at 
\/observe\/health on local HTTP server (port 8080 by default)", "type": 
"boolean", "javaType": "boolean", "defaultValue": false, "deprecated": true },
+    { "name": "camel.jbang.ignoreLoadingError", "description": "Whether to 
ignore route loading and compilation errors (use this with care!)", "label": 
"advanced", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.javaVersion", "description": "Java version (17 or 
21)", "type": "object", "javaType": "String", "defaultValue": "21", "enum": [ 
"17", "21" ] },
+    { "name": "camel.jbang.jfr", "description": "Enables Java Flight Recorder 
saving recording to disk on exit", "type": "boolean", "javaType": "boolean", 
"defaultValue": "false" },
+    { "name": "camel.jbang.jfr-profile", "description": "Java Flight Recorder 
profile to use (such as default or profile)", "type": "object", "javaType": 
"String", "defaultValue": "default" },
+    { "name": "camel.jbang.jib-maven-plugin-version", "description": "Version 
to use for jib-maven-plugin if exporting to camel-main and have Kubernetes 
enabled (jkube.xxx options)", "label": "kubernetes", "type": "object", 
"javaType": "String", "defaultValue": "3.4.5" },
+    { "name": "camel.jbang.jkube-maven-plugin-version", "description": 
"Version to use for jkube-maven-plugin if exporting to camel-main and have 
Kubernetes enabled (jkube.xxx options)", "label": "kubernetes", "type": 
"object", "javaType": "String", "defaultValue": "1.18.1" },
+    { "name": "camel.jbang.jkubeFiles", "description": "Resource YAML 
fragments for Kubernetes using Eclipse JKube tool (Use commas to separate 
multiple files).", "label": "kubernetes", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.kameletsVersion", "description": "Apache Camel 
Kamelets version. By default the Kamelets are the same version as Camel.", 
"type": "object", "javaType": "String" },
+    { "name": "camel.jbang.lazyBean", "description": "Whether to use lazy bean 
initialization (can help with complex classloading issues)", "label": 
"advanced", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.localKameletDir", "description": "Local file 
directory for loading custom Kamelets", "type": "object", "javaType": "String" 
},
+    { "name": "camel.jbang.maven-apache-snapshot-enabled", "description": 
"Whether downloading JARs from ASF Maven Snapshot repository is enabled", 
"label": "maven", "type": "boolean", "javaType": "boolean", "defaultValue": 
true },
+    { "name": "camel.jbang.maven-central-enabled", "description": "Whether 
downloading JARs from Maven Central repository is enabled", "label": "maven", 
"type": "boolean", "javaType": "boolean", "defaultValue": true },
+    { "name": "camel.jbang.maven-settings", "description": "Optional location 
of Maven settings.xml file to configure servers, repositories, mirrors, and 
proxies. If set to false, not even the default \/.m2\/settings.xml will be 
used.", "label": "maven", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.maven-settings-security", "description": "Optional 
location of Maven settings-security.xml file to decrypt Maven Settings 
(settings.xml) file", "label": "maven", "type": "object", "javaType": "String" 
},
+    { "name": "camel.jbang.mavenWrapper", "description": "Include Maven 
Wrapper files in the exported project", "type": "boolean", "javaType": 
"boolean", "defaultValue": true },
+    { "name": "camel.jbang.metrics", "description": "Metrics (Micrometer and 
Prometheus) at \/observe\/metrics on local HTTP server (port 8080 by default) 
when running standalone Camel", "type": "boolean", "javaType": "boolean", 
"defaultValue": false, "deprecated": true },
+    { "name": "camel.jbang.openApi", "description": "File name of open-api 
spec file (JSON or YAML) to generate routes from the swagger\/openapi API spec 
file.", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.packageScanJars", "description": "Whether to 
automatic package scan JARs for custom Spring or Quarkus beans making them 
available for Camel JBang", "label": "advanced", "type": "boolean", "javaType": 
"boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.prompt", "description": "Allow user to type in 
required parameters in prompt if not present in application", "label": 
"advanced", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
+    { "name": "camel.jbang.quarkusArtifactId", "description": "Quarkus 
Platform Maven artifactId", "label": "quarkus", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.quarkusGroupId", "description": "Quarkus Platform 
Maven groupId", "label": "quarkus", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.quarkusVersion", "description": "Quarkus Platform 
version", "label": "quarkus", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.repos", "description": "Additional Maven 
repositories for download on-demand (Use commas to separate multiple 
repositories)", "label": "maven", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.runtime", "description": "Which runtime to use 
(camel-main, spring-boot, quarkus)", "type": "object", "javaType": "String", 
"enum": [ "camel-main", "spring-boot", "quarkus" ] },
+    { "name": "camel.jbang.scriptFiles", "description": "Additional shell 
script files to export to src\/main\/scripts directory", "type": "object", 
"javaType": "String" },
+    { "name": "camel.jbang.sourceDir", "description": "Source directory for 
dynamically loading Camel file(s) to run. When using this, then files cannot be 
specified at the same time.", "label": "advanced", "type": "object", 
"javaType": "String" },
+    { "name": "camel.jbang.springBootVersion", "description": "Spring Boot 
version", "label": "spring-boot", "type": "object", "javaType": "String" },
+    { "name": "camel.jbang.stub", "description": "Stubs all the matching 
endpoint with the given component name or pattern. Multiple names can be 
separated by comma. (all = everything).", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.tlsFiles", "description": "Additional SSL\/TLS 
files to export to src\/main\/tls directory", "type": "object", "javaType": 
"String" },
+    { "name": "camel.jbang.verbose", "description": "Verbose output of startup 
activity (dependency resolution and downloading", "type": "boolean", 
"javaType": "boolean", "defaultValue": "false" }
+  ]
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
index 8890851e6ae..f7091d787df 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/DependencyList.java
@@ -40,6 +40,8 @@ import org.apache.camel.util.CamelCaseOrderedProperties;
 import org.apache.camel.util.FileUtil;
 import picocli.CommandLine;
 
+import static org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.*;
+
 @CommandLine.Command(name = "list",
                      description = "Displays all Camel dependencies required 
to run", sortOptions = false,
                      showDefaultValues = true)
@@ -230,21 +232,21 @@ public class DependencyList extends Export {
             } catch (IOException e) {
                 // ignore
             }
-            if (this.runtime == null && 
prop.containsKey("camel.jbang.runtime")) {
-                this.runtime = 
RuntimeType.fromValue(prop.getProperty("camel.jbang.runtime"));
+            if (this.runtime == null && prop.containsKey(RUNTIME)) {
+                this.runtime = 
RuntimeType.fromValue(prop.getProperty(RUNTIME));
             }
             if (this.gav == null) {
-                this.gav = prop.getProperty("camel.jbang.gav");
+                this.gav = prop.getProperty(GAV);
             }
             // allow configuring versions from profile
-            this.javaVersion = prop.getProperty("camel.jbang.javaVersion", 
this.javaVersion);
-            this.camelVersion = prop.getProperty("camel.jbang.camelVersion", 
this.camelVersion);
-            this.kameletsVersion = 
prop.getProperty("camel.jbang.kameletsVersion", this.kameletsVersion);
-            this.localKameletDir = 
prop.getProperty("camel.jbang.localKameletDir", this.localKameletDir);
-            this.quarkusGroupId = 
prop.getProperty("camel.jbang.quarkusGroupId", this.quarkusGroupId);
-            this.quarkusArtifactId = 
prop.getProperty("camel.jbang.quarkusArtifactId", this.quarkusArtifactId);
-            this.quarkusVersion = 
prop.getProperty("camel.jbang.quarkusVersion", this.quarkusVersion);
-            this.springBootVersion = 
prop.getProperty("camel.jbang.springBootVersion", this.springBootVersion);
+            this.javaVersion = prop.getProperty(JAVA_VERSION, 
this.javaVersion);
+            this.camelVersion = prop.getProperty(CAMEL_VERSION, 
this.camelVersion);
+            this.kameletsVersion = prop.getProperty(KAMELETS_VERSION, 
this.kameletsVersion);
+            this.localKameletDir = prop.getProperty(LOCAL_KAMELET_DIR, 
this.localKameletDir);
+            this.quarkusGroupId = prop.getProperty(QUARKUS_GROUP_ID, 
this.quarkusGroupId);
+            this.quarkusArtifactId = prop.getProperty(QUARKUS_ARTIFACT_ID, 
this.quarkusArtifactId);
+            this.quarkusVersion = prop.getProperty(QUARKUS_VERSION, 
this.quarkusVersion);
+            this.springBootVersion = prop.getProperty(SPRING_BOOT_VERSION, 
this.springBootVersion);
         }
 
         // use temporary export dir
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
index 7ce7e16bf99..a60ebeb99c2 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
@@ -26,6 +26,7 @@ import java.util.Comparator;
 import java.util.Date;
 import java.util.Properties;
 
+import org.apache.camel.dsl.jbang.core.common.CamelJBangConstants;
 import org.apache.camel.dsl.jbang.core.common.RuntimeType;
 import org.apache.camel.dsl.jbang.core.common.RuntimeUtil;
 import org.apache.camel.dsl.jbang.core.common.SourceScheme;
@@ -36,6 +37,8 @@ import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.IOHelper;
 import picocli.CommandLine.Command;
 
+import static org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.*;
+
 @Command(name = "export",
          description = "Export to other runtimes (Camel Main, Spring Boot, or 
Quarkus)", sortOptions = false,
          showDefaultValues = true)
@@ -141,37 +144,37 @@ public class Export extends ExportBaseCommand {
             Properties props = new CamelCaseOrderedProperties();
             RuntimeUtil.loadProperties(props, path);
             // read runtime and gav from profile if not configured
-            String rt = props.getProperty("camel.jbang.runtime");
+            String rt = props.getProperty(CamelJBangConstants.RUNTIME);
             if (rt != null) {
                 this.runtime = RuntimeType.fromValue(rt);
             }
-            this.gav = props.getProperty("camel.jbang.gav", this.gav);
+            this.gav = props.getProperty(GAV, this.gav);
             // allow configuring versions from profile
-            this.javaVersion = props.getProperty("camel.jbang.javaVersion", 
this.javaVersion);
-            this.camelVersion = props.getProperty("camel.jbang.camelVersion", 
this.camelVersion);
-            this.kameletsVersion = 
props.getProperty("camel.jbang.kameletsVersion", this.kameletsVersion);
-            this.localKameletDir = 
props.getProperty("camel.jbang.localKameletDir", this.localKameletDir);
-            this.quarkusGroupId = 
props.getProperty("camel.jbang.quarkusGroupId", this.quarkusGroupId);
-            this.quarkusArtifactId = 
props.getProperty("camel.jbang.quarkusArtifactId", this.quarkusArtifactId);
-            this.quarkusVersion = 
props.getProperty("camel.jbang.quarkusVersion", this.quarkusVersion);
+            this.javaVersion = props.getProperty(JAVA_VERSION, 
this.javaVersion);
+            this.camelVersion = props.getProperty(CAMEL_VERSION, 
this.camelVersion);
+            this.kameletsVersion = props.getProperty(KAMELETS_VERSION, 
this.kameletsVersion);
+            this.localKameletDir = props.getProperty(LOCAL_KAMELET_DIR, 
this.localKameletDir);
+            this.quarkusGroupId = props.getProperty(QUARKUS_GROUP_ID, 
this.quarkusGroupId);
+            this.quarkusArtifactId = props.getProperty(QUARKUS_ARTIFACT_ID, 
this.quarkusArtifactId);
+            this.quarkusVersion = props.getProperty(QUARKUS_VERSION, 
this.quarkusVersion);
             this.camelSpringBootVersion = VersionHelper.getSpringBootVersion(
-                    () -> 
props.getProperty("camel.jbang.camelSpringBootVersion", 
this.camelSpringBootVersion));
-            this.springBootVersion = 
props.getProperty("camel.jbang.springBootVersion", this.springBootVersion);
+                    () -> props.getProperty(CAMEL_SPRING_BOOT_VERSION, 
this.camelSpringBootVersion));
+            this.springBootVersion = props.getProperty(SPRING_BOOT_VERSION, 
this.springBootVersion);
             this.mavenWrapper
-                    = 
"true".equals(props.getProperty("camel.jbang.mavenWrapper", this.mavenWrapper ? 
"true" : "false"));
+                    = "true".equals(props.getProperty(MAVEN_WRAPPER, 
this.mavenWrapper ? "true" : "false"));
             this.gradleWrapper
-                    = 
"true".equals(props.getProperty("camel.jbang.gradleWrapper", this.gradleWrapper 
? "true" : "false"));
-            this.exportDir = props.getProperty("camel.jbang.exportDir", 
this.exportDir);
-            this.buildTool = props.getProperty("camel.jbang.buildTool", 
this.buildTool);
-            this.openapi = props.getProperty("camel.jbang.openApi", 
this.openapi);
-            this.repositories = props.getProperty("camel.jbang.repos", 
this.repositories);
-            this.mavenSettings = 
props.getProperty("camel.jbang.maven-settings", this.mavenSettings);
-            this.mavenSettingsSecurity = 
props.getProperty("camel.jbang.maven-settings-security", 
this.mavenSettingsSecurity);
+                    = "true".equals(props.getProperty(GRADLE_WRAPPER, 
this.gradleWrapper ? "true" : "false"));
+            this.exportDir = props.getProperty(EXPORT_DIR, this.exportDir);
+            this.buildTool = props.getProperty(BUILD_TOOL, this.buildTool);
+            this.openapi = props.getProperty(OPEN_API, this.openapi);
+            this.repositories = props.getProperty(REPOS, this.repositories);
+            this.mavenSettings = props.getProperty(MAVEN_SETTINGS, 
this.mavenSettings);
+            this.mavenSettingsSecurity = 
props.getProperty(MAVEN_SETTINGS_SECURITY, this.mavenSettingsSecurity);
             this.mavenCentralEnabled = "true"
-                    
.equals(props.getProperty("camel.jbang.maven-central-enabled", 
mavenCentralEnabled ? "true" : "false"));
-            this.mavenApacheSnapshotEnabled = 
"true".equals(props.getProperty("camel.jbang.maven-apache-snapshot-enabled",
+                    .equals(props.getProperty(MAVEN_CENTRAL_ENABLED, 
mavenCentralEnabled ? "true" : "false"));
+            this.mavenApacheSnapshotEnabled = 
"true".equals(props.getProperty(MAVEN_APACHE_SNAPSHOTS,
                     mavenApacheSnapshotEnabled ? "true" : "false"));
-            this.excludes = RuntimeUtil.getCommaSeparatedPropertyAsList(props, 
"camel.jbang.excludes", this.excludes);
+            this.excludes = RuntimeUtil.getCommaSeparatedPropertyAsList(props, 
EXCLUDES, this.excludes);
         }
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index f8afb46c95b..3429a14c0c6 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -69,6 +69,8 @@ import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.StringHelper;
 import picocli.CommandLine;
 
+import static org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.*;
+
 public abstract class ExportBaseCommand extends CamelCommand {
 
     protected static final String BUILD_DIR = 
CommandLineHelper.CAMEL_JBANG_WORK_DIR + "/work";
@@ -77,12 +79,12 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
             "camel.main.routesIncludePattern",
             "camel.component.properties.location",
             "camel.component.kamelet.location",
-            "camel.jbang.classpathFiles",
-            "camel.jbang.localKameletDir",
-            "camel.jbang.groovyFiles",
-            "camel.jbang.scriptFiles",
-            "camel.jbang.tlsFiles",
-            "camel.jbang.jkubeFiles",
+            CLASSPATH_FILES,
+            LOCAL_KAMELET_DIR,
+            GROOVY_FILES,
+            SCRIPT_FILES,
+            TLS_FILES,
+            JKUBE_FILES,
             "kamelet"
     };
 
@@ -485,8 +487,8 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
                         }
                     }
                 }
-            } else if (line.startsWith("camel.jbang.dependencies=")) {
-                String deps = StringHelper.after(line, 
"camel.jbang.dependencies=");
+            } else if (line.startsWith(DEPENDENCIES + "=")) {
+                String deps = StringHelper.after(line, DEPENDENCIES + "=");
                 if (!deps.isEmpty()) {
                     for (String d : deps.split(",")) {
                         answer.add(d.trim());
@@ -503,8 +505,8 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
                         }
                     }
                 }
-            } else if (line.startsWith("camel.jbang.classpathFiles")) {
-                String deps = StringHelper.after(line, 
"camel.jbang.classpathFiles=");
+            } else if (line.startsWith(CLASSPATH_FILES + "=")) {
+                String deps = StringHelper.after(line, CLASSPATH_FILES + "=");
                 if (!deps.isEmpty()) {
                     for (String d : deps.split(",")) {
                         // special to include local JARs in export lib folder
@@ -621,7 +623,7 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
         Properties prop = new CamelCaseOrderedProperties();
         RuntimeUtil.loadProperties(prop, settings);
 
-        String localKameletDir = 
prop.getProperty("camel.jbang.localKameletDir");
+        String localKameletDir = prop.getProperty(LOCAL_KAMELET_DIR);
         if (localKameletDir != null) {
             String scheme = getScheme(localKameletDir);
             if (scheme != null) {
@@ -659,12 +661,12 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
                     }
                     boolean java = "java".equals(ext);
                     boolean kamelet = "kamelet".equals(k) || 
"camel.component.kamelet.location".equals(k)
-                            || "camel.jbang.localKameletDir".equals(k) || 
"kamelet.yaml".equalsIgnoreCase(ext2);
+                            || LOCAL_KAMELET_DIR.equals(k) || 
"kamelet.yaml".equalsIgnoreCase(ext2);
                     boolean camel = !kamelet && 
"camel.main.routesIncludePattern".equals(k);
-                    boolean jkube = "camel.jbang.jkubeFiles".equals(k);
-                    boolean script = "camel.jbang.scriptFiles".equals(k);
-                    boolean groovy = "camel.jbang.groovyFiles".equals(k);
-                    boolean tls = "camel.jbang.tlsFiles".equals(k);
+                    boolean jkube = JKUBE_FILES.equals(k);
+                    boolean script = SCRIPT_FILES.equals(k);
+                    boolean groovy = GROOVY_FILES.equals(k);
+                    boolean tls = TLS_FILES.equals(k);
                     boolean web = ext != null && List.of("css", "html", "ico", 
"jpeg", "jpg", "js", "png").contains(ext);
                     Path targetDir;
                     if (java) {
@@ -957,7 +959,7 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
     protected String getMavenRepositories(Path settings, Properties prop, 
String camelVersion) throws Exception {
         Set<String> answer = new LinkedHashSet<>();
 
-        String propRepositories = prop.getProperty("camel.jbang.repositories");
+        String propRepositories = prop.getProperty(CLASSPATH_FILES);
         if (propRepositories != null) {
             answer.add(propRepositories);
         }
@@ -1025,12 +1027,12 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
     protected static String jibMavenPluginVersion(Path settings, Properties 
prop) {
         String answer = null;
         if (prop != null) {
-            answer = prop.getProperty("camel.jbang.jib-maven-plugin-version");
+            answer = prop.getProperty(JIB_MAVEN_PLUGIN_VERSION);
         }
         if (answer == null) {
             try {
                 List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
-                answer = lines.stream().filter(l -> 
l.startsWith("camel.jbang.jib-maven-plugin-version="))
+                answer = lines.stream().filter(l -> 
l.startsWith(JIB_MAVEN_PLUGIN_VERSION + "="))
                         .map(s -> StringHelper.after(s, 
"=")).findFirst().orElse(null);
             } catch (Exception e) {
                 // ignore
@@ -1042,13 +1044,13 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
     protected static String jkubeMavenPluginVersion(Path settings, Properties 
props) {
         String answer = null;
         if (props != null) {
-            answer = 
props.getProperty("camel.jbang.jkube-maven-plugin-version");
+            answer = props.getProperty(JKUBE_MAVEN_PLUGIN_VERSION);
         }
         if (answer == null) {
             try {
                 List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
                 answer = lines.stream()
-                        .filter(l -> 
l.startsWith("camel.jbang.jkube-maven-plugin-version=") || 
l.startsWith("jkube.version="))
+                        .filter(l -> l.startsWith(JKUBE_MAVEN_PLUGIN_VERSION + 
"=") || l.startsWith("jkube.version="))
                         .map(s -> StringHelper.after(s, 
"=")).findFirst().orElse(null);
             } catch (Exception e) {
                 // ignore
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
index b96dd2b260a..28574e60132 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
@@ -44,6 +44,7 @@ import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.StringHelper;
 
 import static 
org.apache.camel.dsl.jbang.core.commands.ExportHelper.exportPackageName;
+import static org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.*;
 
 class ExportQuarkus extends Export {
 
@@ -186,7 +187,7 @@ class ExportQuarkus extends Export {
                 sj.add(v);
             }
             // extra classpath files
-            if ("camel.jbang.classpathFiles".equals(k)) {
+            if (CLASSPATH_FILES.equals(k)) {
                 v = Arrays.stream(v.split(","))
                         .filter(d -> !d.endsWith(".jar")) // skip local lib 
JARs
                         .map(ExportQuarkus::stripPath) // remove scheme
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index fa3a84dd8bc..5d25b720d69 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -75,6 +75,7 @@ import picocli.CommandLine.Parameters;
 
 import static 
org.apache.camel.dsl.jbang.core.common.CamelCommandHelper.CAMEL_INSTANCE_TYPE;
 import static 
org.apache.camel.dsl.jbang.core.common.CamelCommandHelper.extractState;
+import static org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.*;
 import static 
org.apache.camel.dsl.jbang.core.common.GistHelper.asGistSingleUrl;
 import static org.apache.camel.dsl.jbang.core.common.GistHelper.fetchGistUrls;
 import static 
org.apache.camel.dsl.jbang.core.common.GitHubHelper.asGithubSingleUrl;
@@ -331,7 +332,7 @@ public class Run extends CamelCommand {
     protected boolean ignoreLoadingError;
 
     @Option(names = { "--lazy-bean" }, defaultValue = "false",
-            description = "Whether to use lazy bean initialization (can help 
with complex classloading issues")
+            description = "Whether to use lazy bean initialization (can help 
with complex classloading issues)")
     protected boolean lazyBean;
 
     @Option(names = { "--prompt" }, defaultValue = "false",
@@ -600,7 +601,7 @@ public class Run extends CamelCommand {
                 sj.add(n);
             }
             stub = sj.toString();
-            writeSetting(main, profileProperties, "camel.jbang.stub", stub);
+            writeSetting(main, profileProperties, STUB, stub);
             main.setStubPattern(stub);
         }
 
@@ -610,7 +611,7 @@ public class Run extends CamelCommand {
             writeSetting(main, profileProperties, 
"camel.main.shutdownTimeout", "5");
         }
         if (sourceDir != null) {
-            writeSetting(main, profileProperties, "camel.jbang.sourceDir", 
sourceDir);
+            writeSetting(main, profileProperties, SOURCE_DIR, sourceDir);
         }
         if (trace) {
             writeSetting(main, profileProperties, "camel.main.tracing", 
"true");
@@ -621,37 +622,37 @@ public class Run extends CamelCommand {
             main.configure().withModeline(true);
         }
         if (ignoreLoadingError) {
-            writeSetting(main, profileProperties, 
"camel.jbang.ignoreLoadingError", "true");
+            writeSetting(main, profileProperties, IGNORE_LOADING_ERROR, 
"true");
         }
         if (lazyBean) {
-            writeSetting(main, profileProperties, "camel.jbang.lazyBean", 
"true");
+            writeSetting(main, profileProperties, LAZY_BEAN, "true");
         }
         if (prompt) {
-            writeSetting(main, profileProperties, "camel.jbang.prompt", 
"true");
+            writeSetting(main, profileProperties, PROMPT, "true");
         }
-        writeSetting(main, profileProperties, "camel.jbang.compileWorkDir",
+        writeSetting(main, profileProperties, COMPILE_WORK_DIR,
                 Paths.get(CommandLineHelper.CAMEL_JBANG_WORK_DIR, 
"compile").toString());
 
         if (gav != null) {
-            writeSetting(main, profileProperties, "camel.jbang.gav", gav);
+            writeSetting(main, profileProperties, GAV, gav);
         }
-        writeSetting(main, profileProperties, "camel.jbang.open-api", openapi);
+        writeSetting(main, profileProperties, OPEN_API, openapi);
         if (repositories != null) {
-            writeSetting(main, profileProperties, "camel.jbang.repos", 
repositories);
+            writeSetting(main, profileProperties, REPOS, repositories);
         }
-        writeSetting(main, profileProperties, "camel.jbang.health", health ? 
"true" : "false");
-        writeSetting(main, profileProperties, "camel.jbang.metrics", metrics ? 
"true" : "false");
-        writeSetting(main, profileProperties, "camel.jbang.console", console ? 
"true" : "false");
-        writeSetting(main, profileProperties, "camel.jbang.verbose", verbose ? 
"true" : "false");
+        writeSetting(main, profileProperties, HEALTH, health ? "true" : 
"false");
+        writeSetting(main, profileProperties, METRICS, metrics ? "true" : 
"false");
+        writeSetting(main, profileProperties, CONSOLE, console ? "true" : 
"false");
+        writeSetting(main, profileProperties, VERBOSE, verbose ? "true" : 
"false");
         // the runtime version of Camel is what is loaded via the catalog
-        writeSetting(main, profileProperties, "camel.jbang.camel-version", new 
DefaultCamelCatalog().getCatalogVersion());
-        writeSetting(main, profileProperties, "camel.jbang.springBootVersion", 
springBootVersion);
-        writeSetting(main, profileProperties, "camel.jbang.quarkusVersion", 
quarkusVersion);
-        writeSetting(main, profileProperties, "camel.jbang.quarkusGroupId", 
quarkusGroupId);
-        writeSetting(main, profileProperties, "camel.jbang.quarkusArtifactId", 
quarkusArtifactId);
+        writeSetting(main, profileProperties, CAMEL_VERSION, new 
DefaultCamelCatalog().getCatalogVersion());
+        writeSetting(main, profileProperties, SPRING_BOOT_VERSION, 
springBootVersion);
+        writeSetting(main, profileProperties, QUARKUS_VERSION, quarkusVersion);
+        writeSetting(main, profileProperties, QUARKUS_GROUP_ID, 
quarkusGroupId);
+        writeSetting(main, profileProperties, QUARKUS_ARTIFACT_ID, 
quarkusArtifactId);
 
         if (observe) {
-            main.addInitialProperty("camel.jbang.dependencies", 
"camel:observability-services");
+            main.addInitialProperty(DEPENDENCIES, 
"camel:observability-services");
         }
 
         // command line arguments
@@ -670,14 +671,14 @@ public class Run extends CamelCommand {
             if (!verbose) {
                 main.setSilent(true);
             }
-            main.addInitialProperty("camel.jbang.export", "true");
+            main.addInitialProperty(EXPORT, "true");
             // enable stub in silent mode so we do not use real components
             main.setStubPattern("*");
             // do not run for very long in silent run
             main.addInitialProperty("camel.main.autoStartup", "false");
             main.addInitialProperty("camel.main.durationMaxSeconds", "-1");
         } else if (debugRun) {
-            main.addInitialProperty("camel.jbang.debug", "true");
+            main.addInitialProperty(DEBUG, "true");
         } else if (transformRun) {
             main.setSilent(true);
             // enable stub in silent mode so we do not use real components
@@ -706,10 +707,10 @@ public class Run extends CamelCommand {
         if (managementPort != -1) {
             writeSetting(main, profileProperties, "camel.management.port", () 
-> String.valueOf(managementPort));
         }
-        writeSetting(main, profileProperties, "camel.jbang.jfr", jfr || 
jfrProfile != null ? "jfr" : null);
-        writeSetting(main, profileProperties, "camel.jbang.jfr-profile", 
jfrProfile != null ? jfrProfile : null);
+        writeSetting(main, profileProperties, JFR, jfr || jfrProfile != null ? 
"jfr" : null);
+        writeSetting(main, profileProperties, JFR_PROFILE, jfrProfile != null 
? jfrProfile : null);
 
-        writeSetting(main, profileProperties, "camel.jbang.kameletsVersion", 
kameletsVersion);
+        writeSetting(main, profileProperties, KAMELETS_VERSION, 
kameletsVersion);
 
         StringJoiner js = new StringJoiner(",");
         StringJoiner sjReload = new StringJoiner(",");
@@ -867,34 +868,34 @@ public class Run extends CamelCommand {
             writeSetting(main, profileProperties, 
"camel.main.routesIncludePattern", () -> null);
         }
         if (sjClasspathFiles.length() > 0) {
-            main.addInitialProperty("camel.jbang.classpathFiles", 
sjClasspathFiles.toString());
-            writeSettings("camel.jbang.classpathFiles", 
sjClasspathFiles.toString());
+            main.addInitialProperty(CLASSPATH_FILES, 
sjClasspathFiles.toString());
+            writeSettings(CLASSPATH_FILES, sjClasspathFiles.toString());
         } else {
-            writeSetting(main, profileProperties, 
"camel.jbang.classpathFiles", () -> null);
+            writeSetting(main, profileProperties, CLASSPATH_FILES, () -> null);
         }
         if (sjScriptFiles.length() > 0) {
-            main.addInitialProperty("camel.jbang.scriptFiles", 
sjScriptFiles.toString());
-            writeSettings("camel.jbang.scriptFiles", sjScriptFiles.toString());
+            main.addInitialProperty(SCRIPT_FILES, sjScriptFiles.toString());
+            writeSettings(SCRIPT_FILES, sjScriptFiles.toString());
         } else {
-            writeSetting(main, profileProperties, "camel.jbang.scriptFiles", 
() -> null);
+            writeSetting(main, profileProperties, SCRIPT_FILES, () -> null);
         }
         if (sjGroovyFiles.length() > 0) {
-            main.addInitialProperty("camel.jbang.groovyFiles", 
sjGroovyFiles.toString());
-            writeSettings("camel.jbang.groovyFiles", sjGroovyFiles.toString());
+            main.addInitialProperty(GROOVY_FILES, sjGroovyFiles.toString());
+            writeSettings(GROOVY_FILES, sjGroovyFiles.toString());
         } else {
-            writeSetting(main, profileProperties, "camel.jbang.groovyFiles", 
() -> null);
+            writeSetting(main, profileProperties, GROOVY_FILES, () -> null);
         }
         if (sjTlsFiles.length() > 0) {
-            main.addInitialProperty("camel.jbang.tlsFiles", 
sjTlsFiles.toString());
-            writeSettings("camel.jbang.tlsFiles", sjTlsFiles.toString());
+            main.addInitialProperty(TLS_FILES, sjTlsFiles.toString());
+            writeSettings(TLS_FILES, sjTlsFiles.toString());
         } else {
-            writeSetting(main, profileProperties, "camel.jbang.tlsFiles", () 
-> null);
+            writeSetting(main, profileProperties, TLS_FILES, () -> null);
         }
         if (sjJKubeFiles.length() > 0) {
-            main.addInitialProperty("camel.jbang.jkubeFiles", 
sjJKubeFiles.toString());
-            writeSettings("camel.jbang.jkubeFiles", sjJKubeFiles.toString());
+            main.addInitialProperty(JKUBE_FILES, sjJKubeFiles.toString());
+            writeSettings(JKUBE_FILES, sjJKubeFiles.toString());
         } else {
-            writeSetting(main, profileProperties, "camel.jbang.jkubeFiles", () 
-> null);
+            writeSetting(main, profileProperties, JKUBE_FILES, () -> null);
         }
 
         if (sjKamelets.length() > 0) {
@@ -955,8 +956,8 @@ public class Run extends CamelCommand {
         addDependencies(RuntimeUtil.getDependenciesAsArray(profileProperties));
         if (!dependencies.isEmpty()) {
             var joined = String.join(",", dependencies);
-            main.addInitialProperty("camel.jbang.dependencies", joined);
-            writeSettings("camel.jbang.dependencies", joined);
+            main.addInitialProperty(DEPENDENCIES, joined);
+            writeSettings(DEPENDENCIES, joined);
         }
 
         // if we have a specific camel version then make sure we really need 
to switch
@@ -1257,7 +1258,7 @@ public class Run extends CamelCommand {
         if (dev && (sourceDir != null || sjReload.length() > 0)) {
             main.addInitialProperty("camel.main.routesReloadEnabled", "true");
             if (sourceDir != null) {
-                main.addInitialProperty("camel.jbang.sourceDir", sourceDir);
+                main.addInitialProperty(SOURCE_DIR, sourceDir);
                 main.addInitialProperty("camel.main.routesReloadDirectory", 
sourceDir);
                 main.addInitialProperty("camel.main.routesReloadPattern", "*");
                 
main.addInitialProperty("camel.main.routesReloadDirectoryRecursive", "true");
@@ -1333,29 +1334,29 @@ public class Run extends CamelCommand {
                     = "true".equals(answer.getProperty("loggingColor", 
loggingColor ? "true" : "false"));
             loggingJson
                     = "true".equals(answer.getProperty("loggingJson", 
loggingJson ? "true" : "false"));
-            repositories = answer.getProperty("camel.jbang.repos", 
repositories);
-            mavenSettings = answer.getProperty("camel.jbang.maven-settings", 
mavenSettings);
-            mavenSettingsSecurity = 
answer.getProperty("camel.jbang.maven-settings-security", 
mavenSettingsSecurity);
+            repositories = answer.getProperty(REPOS, repositories);
+            mavenSettings = answer.getProperty(MAVEN_SETTINGS, mavenSettings);
+            mavenSettingsSecurity = 
answer.getProperty(MAVEN_SETTINGS_SECURITY, mavenSettingsSecurity);
             mavenCentralEnabled = "true"
-                    
.equals(answer.getProperty("camel.jbang.maven-central-enabled", 
mavenCentralEnabled ? "true" : "false"));
-            mavenApacheSnapshotEnabled = 
"true".equals(answer.getProperty("camel.jbang.maven-apache-snapshot-enabled",
+                    .equals(answer.getProperty(MAVEN_CENTRAL_ENABLED, 
mavenCentralEnabled ? "true" : "false"));
+            mavenApacheSnapshotEnabled = 
"true".equals(answer.getProperty(MAVEN_APACHE_SNAPSHOTS,
                     mavenApacheSnapshotEnabled ? "true" : "false"));
-            openapi = answer.getProperty("camel.jbang.open-api", openapi);
-            download = 
"true".equals(answer.getProperty("camel.jbang.download", download ? "true" : 
"false"));
+            openapi = answer.getProperty(OPEN_API, openapi);
+            download = "true".equals(answer.getProperty(DOWNLOAD, download ? 
"true" : "false"));
             packageScanJars
-                    = 
"true".equals(answer.getProperty("camel.jbang.packageScanJars", packageScanJars 
? "true" : "false"));
-            background = 
"true".equals(answer.getProperty("camel.jbang.background", background ? "true" 
: "false"));
-            backgroundWait = 
"true".equals(answer.getProperty("camel.jbang.backgroundWait", backgroundWait ? 
"true" : "false"));
-            jvmDebugPort = 
parseJvmDebugPort(answer.getProperty("camel.jbang.jvmDebug", 
Integer.toString(jvmDebugPort)));
-            camelVersion = answer.getProperty("camel.jbang.camel-version", 
camelVersion);
-            kameletsVersion = 
answer.getProperty("camel.jbang.kameletsVersion", kameletsVersion);
-            springBootVersion = 
answer.getProperty("camel.jbang.springBootVersion", springBootVersion);
-            quarkusGroupId = answer.getProperty("camel.jbang.quarkusGroupId", 
quarkusGroupId);
-            quarkusArtifactId = 
answer.getProperty("camel.jbang.quarkusArtifactId", quarkusArtifactId);
-            quarkusVersion = answer.getProperty("camel.jbang.quarkusVersion", 
quarkusVersion);
-            gav = answer.getProperty("camel.jbang.gav", gav);
-            stub = answer.getProperty("camel.jbang.stub", stub);
-            excludes = RuntimeUtil.getCommaSeparatedPropertyAsList(answer, 
"camel.jbang.excludes", excludes);
+                    = "true".equals(answer.getProperty(PACKAGE_SCAN_JARS, 
packageScanJars ? "true" : "false"));
+            background = "true".equals(answer.getProperty(BACKGROUND, 
background ? "true" : "false"));
+            backgroundWait = "true".equals(answer.getProperty(BACKGROUND_WAIT, 
backgroundWait ? "true" : "false"));
+            jvmDebugPort = parseJvmDebugPort(answer.getProperty(JVM_DEBUG, 
Integer.toString(jvmDebugPort)));
+            camelVersion = answer.getProperty(CAMEL_VERSION, camelVersion);
+            kameletsVersion = answer.getProperty(KAMELETS_VERSION, 
kameletsVersion);
+            springBootVersion = answer.getProperty(SPRING_BOOT_VERSION, 
springBootVersion);
+            quarkusGroupId = answer.getProperty(QUARKUS_GROUP_ID, 
quarkusGroupId);
+            quarkusArtifactId = answer.getProperty(QUARKUS_ARTIFACT_ID, 
quarkusArtifactId);
+            quarkusVersion = answer.getProperty(QUARKUS_VERSION, 
quarkusVersion);
+            gav = answer.getProperty(GAV, gav);
+            stub = answer.getProperty(STUB, stub);
+            excludes = RuntimeUtil.getCommaSeparatedPropertyAsList(answer, 
EXCLUDES, excludes);
         }
 
         return answer;
@@ -1768,7 +1769,7 @@ public class Run extends CamelCommand {
                 sj.add(part);
             }
             main = new KameletMain(CAMEL_INSTANCE_TYPE, sj.toString());
-            writeSettings("camel.jbang.localKameletDir", sj.toString());
+            writeSettings(LOCAL_KAMELET_DIR, sj.toString());
         }
         return main;
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
index 7087333b9ec..826e9bad392 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/SBOMGenerator.java
@@ -22,6 +22,7 @@ import java.nio.file.Paths;
 import java.util.Properties;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.camel.dsl.jbang.core.common.CamelJBangConstants;
 import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
 import org.apache.camel.dsl.jbang.core.common.RuntimeType;
 import org.apache.camel.dsl.jbang.core.common.RuntimeUtil;
@@ -29,6 +30,8 @@ import org.apache.camel.util.CamelCaseOrderedProperties;
 import org.apache.camel.util.FileUtil;
 import picocli.CommandLine;
 
+import static org.apache.camel.dsl.jbang.core.common.CamelJBangConstants.*;
+
 @CommandLine.Command(name = "sbom",
                      description = "Generate a CycloneDX or SPDX SBOM for a 
specific project", sortOptions = false,
                      showDefaultValues = true)
@@ -165,21 +168,21 @@ public class SBOMGenerator extends Export {
         if (Files.exists(profile)) {
             Properties prop = new CamelCaseOrderedProperties();
             RuntimeUtil.loadProperties(prop, profile);
-            if (this.runtime == null && 
prop.containsKey("camel.jbang.runtime")) {
-                this.runtime = 
RuntimeType.fromValue(prop.getProperty("camel.jbang.runtime"));
+            if (this.runtime == null && 
prop.containsKey(CamelJBangConstants.RUNTIME)) {
+                this.runtime = 
RuntimeType.fromValue(prop.getProperty(CamelJBangConstants.RUNTIME));
             }
             if (this.gav == null) {
-                this.gav = prop.getProperty("camel.jbang.gav");
+                this.gav = prop.getProperty(GAV);
             }
             // allow configuring versions from profile
-            this.javaVersion = prop.getProperty("camel.jbang.javaVersion", 
this.javaVersion);
-            this.camelVersion = prop.getProperty("camel.jbang.camelVersion", 
this.camelVersion);
-            this.kameletsVersion = 
prop.getProperty("camel.jbang.kameletsVersion", this.kameletsVersion);
-            this.localKameletDir = 
prop.getProperty("camel.jbang.localKameletDir", this.localKameletDir);
-            this.quarkusGroupId = 
prop.getProperty("camel.jbang.quarkusGroupId", this.quarkusGroupId);
-            this.quarkusArtifactId = 
prop.getProperty("camel.jbang.quarkusArtifactId", this.quarkusArtifactId);
-            this.quarkusVersion = 
prop.getProperty("camel.jbang.quarkusVersion", this.quarkusVersion);
-            this.springBootVersion = 
prop.getProperty("camel.jbang.springBootVersion", this.springBootVersion);
+            this.javaVersion = prop.getProperty(JAVA_VERSION, 
this.javaVersion);
+            this.camelVersion = prop.getProperty(CAMEL_VERSION, 
this.camelVersion);
+            this.kameletsVersion = prop.getProperty(KAMELETS_VERSION, 
this.kameletsVersion);
+            this.localKameletDir = prop.getProperty(LOCAL_KAMELET_DIR, 
this.localKameletDir);
+            this.quarkusGroupId = prop.getProperty(QUARKUS_GROUP_ID, 
this.quarkusGroupId);
+            this.quarkusArtifactId = prop.getProperty(QUARKUS_ARTIFACT_ID, 
this.quarkusArtifactId);
+            this.quarkusVersion = prop.getProperty(QUARKUS_VERSION, 
this.quarkusVersion);
+            this.springBootVersion = prop.getProperty(SPRING_BOOT_VERSION, 
this.springBootVersion);
         }
 
         // use temporary export dir
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
index 2076b260bde..4ae62e8d283 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/TransformRoute.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Stack;
 
+import org.apache.camel.dsl.jbang.core.common.CamelJBangConstants;
 import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
 import org.apache.camel.main.KameletMain;
 import org.apache.camel.util.IOHelper;
@@ -92,7 +93,7 @@ public class TransformRoute extends CamelCommand {
                 
main.addInitialProperty("camel.main.dumpRoutesResolvePlaceholders", 
Boolean.toString(resolvePlaceholders));
                 
main.addInitialProperty("camel.main.dumpRoutesUriAsParameters", 
Boolean.toString(uriAsParameters));
                 main.addInitialProperty("camel.main.dumpRoutesOutput", target);
-                main.addInitialProperty("camel.jbang.transform", "true");
+                main.addInitialProperty(CamelJBangConstants.TRANSFORM, "true");
                 
main.addInitialProperty("camel.component.properties.ignoreMissingProperty", 
"true");
                 if (ignoreLoadingError) {
                     // turn off bean method validator if ignore loading error
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
new file mode 100644
index 00000000000..a17fcff8707
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
@@ -0,0 +1,216 @@
+/*
+ * 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.common;
+
+import org.apache.camel.spi.Metadata;
+
+/**
+ * Common set of camel.jbang.xxx configuration options that can be defined in 
application.properties to control running
+ * and exporting commands.
+ */
+public final class CamelJBangConstants {
+
+    // internal options which is not intended for Camel users
+    public static final String BACKGROUND = "camel.jbang.background";
+    public static final String BACKGROUND_WAIT = "camel.jbang.backgroundWait";
+    public static final String JVM_DEBUG = "camel.jbang.jvmDebug";
+    public static final String TRANSFORM = "camel.jbang.transform";
+    public static final String EXPORT = "camel.jbang.export";
+    public static final String DEBUG = "camel.jbang.debug";
+
+    @Metadata(description = "Additional files to add to classpath (Use commas 
to separate multiple files).",
+              javaType = "String")
+    public static final String CLASSPATH_FILES = "camel.jbang.classpathFiles";
+
+    @Metadata(description = "Local file directory for loading custom Kamelets",
+              javaType = "String")
+    public static final String LOCAL_KAMELET_DIR = 
"camel.jbang.localKameletDir";
+
+    @Metadata(description = "Additional groovy source files to export to 
src/main/resources/camel-groovy directory (Use commas to separate multiple 
files)",
+              javaType = "String")
+    public static final String GROOVY_FILES = "camel.jbang.groovyFiles";
+
+    @Metadata(description = "Additional shell script files to export to 
src/main/scripts directory",
+              javaType = "String")
+    public static final String SCRIPT_FILES = "camel.jbang.scriptFiles";
+
+    @Metadata(description = "Additional SSL/TLS files to export to 
src/main/tls directory",
+              javaType = "String")
+    public static final String TLS_FILES = "camel.jbang.tlsFiles";
+
+    @Metadata(description = "Resource YAML fragments for Kubernetes using 
Eclipse JKube tool (Use commas to separate multiple files).",
+              javaType = "String", label = "kubernetes")
+    public static final String JKUBE_FILES = "camel.jbang.jkubeFiles";
+
+    @Metadata(description = "Which runtime to use (camel-main, spring-boot, 
quarkus)",
+              javaType = "String", enums = "camel-main,spring-boot,quarkus")
+    public static final String RUNTIME = "camel.jbang.runtime";
+
+    @Metadata(description = "Maven coordinate (groupId:artifactId:version)",
+              javaType = "String")
+    public static final String GAV = "camel.jbang.gav";
+
+    @Metadata(description = "Java version (17 or 21)",
+              javaType = "String", enums = "17,21", defaultValue = "21")
+    public static final String JAVA_VERSION = "camel.jbang.javaVersion";
+
+    @Metadata(description = "Apache Camel Kamelets version. By default the 
Kamelets are the same version as Camel.",
+              javaType = "String")
+    public static final String KAMELETS_VERSION = 
"camel.jbang.kameletsVersion";
+
+    @Metadata(description = "Quarkus Platform Maven groupId",
+              javaType = "String", label = "quarkus")
+    public static final String QUARKUS_GROUP_ID = "camel.jbang.quarkusGroupId";
+
+    @Metadata(description = "Quarkus Platform Maven artifactId",
+              javaType = "String", label = "quarkus")
+    public static final String QUARKUS_ARTIFACT_ID = 
"camel.jbang.quarkusArtifactId";
+
+    @Metadata(description = "Quarkus Platform version",
+              javaType = "String", label = "quarkus")
+    public static final String QUARKUS_VERSION = "camel.jbang.quarkusVersion";
+
+    @Metadata(description = "Spring Boot version",
+              javaType = "String", label = "spring-boot")
+    public static final String SPRING_BOOT_VERSION = 
"camel.jbang.springBootVersion";
+
+    @Metadata(description = "Include Maven Wrapper files in the exported 
project",
+              javaType = "boolean", defaultValue = "true")
+    public static final String MAVEN_WRAPPER = "camel.jbang.mavenWrapper";
+
+    @Metadata(description = "Include Gradle Wrapper files in the exported 
project",
+              javaType = "boolean", defaultValue = "true")
+    public static final String GRADLE_WRAPPER = "camel.jbang.gradleWrapper";
+
+    @Metadata(description = "Build tool to use (Maven or Gradle)",
+              javaType = "String", defaultValue = "Maven")
+    public static final String BUILD_TOOL = "camel.jbang.buildTool";
+
+    @Metadata(description = "Directory where the project will be exported",
+              javaType = "String", defaultValue = ".")
+    public static final String EXPORT_DIR = "camel.jbang.exportDir";
+
+    @Metadata(description = "File name of open-api spec file (JSON or YAML) to 
generate routes from the swagger/openapi API spec file.",
+              javaType = "String")
+    public static final String OPEN_API = "camel.jbang.openApi";
+
+    @Metadata(description = "Additional Maven repositories for download 
on-demand (Use commas to separate multiple repositories)",
+              javaType = "String", label = "maven")
+    public static final String REPOS = "camel.jbang.repos";
+
+    @Metadata(description = "Optional location of Maven settings.xml file to 
configure servers, repositories, mirrors, and proxies. If set to false, not 
even the default ~/.m2/settings.xml will be used.",
+              javaType = "String", label = "maven")
+    public static final String MAVEN_SETTINGS = "camel.jbang.maven-settings";
+
+    @Metadata(description = "Optional location of Maven settings-security.xml 
file to decrypt Maven Settings (settings.xml) file",
+              javaType = "String", label = "maven")
+    public static final String MAVEN_SETTINGS_SECURITY = 
"camel.jbang.maven-settings-security";
+
+    @Metadata(description = "Whether downloading JARs from Maven Central 
repository is enabled",
+              javaType = "boolean", defaultValue = "true", label = "maven")
+    public static final String MAVEN_CENTRAL_ENABLED = 
"camel.jbang.maven-central-enabled";
+
+    @Metadata(description = "Whether downloading JARs from ASF Maven Snapshot 
repository is enabled",
+              javaType = "boolean", defaultValue = "true", label = "maven")
+    public static final String MAVEN_APACHE_SNAPSHOTS = 
"camel.jbang.maven-apache-snapshot-enabled";
+
+    @Metadata(description = "Exclude files by name or pattern (Use commas to 
separate multiple files)",
+              javaType = "String")
+    public static final String EXCLUDES = "camel.jbang.excludes";
+
+    @Metadata(description = "Additional dependencies (Use commas to separate 
multiple dependencies).",
+              javaType = "String")
+    public static final String DEPENDENCIES = "camel.jbang.dependencies";
+
+    @Metadata(description = "Version to use for jib-maven-plugin if exporting 
to camel-main and have Kubernetes enabled (jkube.xxx options)",
+              javaType = "String", defaultValue = "3.4.5", label = 
"kubernetes")
+    public static final String JIB_MAVEN_PLUGIN_VERSION = 
"camel.jbang.jib-maven-plugin-version";
+
+    @Metadata(description = "Version to use for jkube-maven-plugin if 
exporting to camel-main and have Kubernetes enabled (jkube.xxx options)",
+              javaType = "String", defaultValue = "1.18.1", label = 
"kubernetes")
+    public static final String JKUBE_MAVEN_PLUGIN_VERSION = 
"camel.jbang.jkube-maven-plugin-version";
+
+    @Metadata(description = "Stubs all the matching endpoint with the given 
component name or pattern. Multiple names can be separated by comma. (all = 
everything).",
+              javaType = "String")
+    public static final String STUB = "camel.jbang.stub";
+
+    @Metadata(description = "Source directory for dynamically loading Camel 
file(s) to run. When using this, then files cannot be specified at the same 
time.",
+              javaType = "String", label = "advanced")
+    public static final String SOURCE_DIR = "camel.jbang.sourceDir";
+
+    @Metadata(description = "Whether to ignore route loading and compilation 
errors (use this with care!)",
+              javaType = "boolean", label = "advanced")
+    public static final String IGNORE_LOADING_ERROR = 
"camel.jbang.ignoreLoadingError";
+
+    @Metadata(description = "Whether to use lazy bean initialization (can help 
with complex classloading issues)",
+              javaType = "boolean", label = "advanced")
+    public static final String LAZY_BEAN = "camel.jbang.lazyBean";
+
+    @Metadata(description = "Allow user to type in required parameters in 
prompt if not present in application",
+              javaType = "boolean", label = "advanced")
+    public static final String PROMPT = "camel.jbang.prompt";
+
+    @Metadata(description = "Work directory for compiler. Can be used to write 
compiled classes or other resources.",
+              javaType = "String", defaultValue = ".camel-jbang/compile", 
label = "advanced")
+    public static final String COMPILE_WORK_DIR = "camel.jbang.compileWorkDir";
+
+    @Deprecated
+    @Metadata(description = "Health check at /observe/health on local HTTP 
server (port 8080 by default)",
+              javaType = "boolean", defaultValue = ".camel-jbang/compile", 
deprecationNote = "Deprecated: use observe instead")
+    public static final String HEALTH = "camel.jbang.health";
+
+    @Deprecated
+    @Metadata(description = "Metrics (Micrometer and Prometheus) at 
/observe/metrics on local HTTP server (port 8080 by default) when running 
standalone Camel",
+              javaType = "boolean", defaultValue = ".camel-jbang/compile", 
deprecationNote = "Deprecated: use observe instead")
+    public static final String METRICS = "camel.jbang.metrics";
+
+    @Metadata(description = "Developer console at /q/dev on local HTTP server 
(port 8080 by default)",
+              javaType = "boolean")
+    public static final String CONSOLE = "camel.jbang.console";
+
+    @Metadata(description = "Verbose output of startup activity (dependency 
resolution and downloading",
+              javaType = "boolean")
+    public static final String VERBOSE = "camel.jbang.verbose";
+
+    @Metadata(description = "The version of Apache Camel to use",
+              javaType = "String")
+    public static final String CAMEL_VERSION = "camel.jbang.camel-version";
+
+    @Metadata(description = "Enables Java Flight Recorder saving recording to 
disk on exit",
+              javaType = "boolean")
+    public static final String JFR = "camel.jbang.jfr";
+
+    @Metadata(description = "Java Flight Recorder profile to use (such as 
default or profile)",
+              javaType = "String", defaultValue = "default")
+    public static final String JFR_PROFILE = "camel.jbang.jfr-profile";
+
+    @Metadata(description = "Whether to allow automatic downloading JAR 
dependencies (over the internet)",
+              javaType = "boolean", defaultValue = "true")
+    public static final String DOWNLOAD = "camel.jbang.download";
+
+    @Metadata(description = "Whether to automatic package scan JARs for custom 
Spring or Quarkus beans making them available for Camel JBang",
+              javaType = "boolean", label = "advanced")
+    public static final String PACKAGE_SCAN_JARS = 
"camel.jbang.packageScanJars";
+
+    @Metadata(description = "To use a custom Camel version when running or 
export to Spring Boot",
+              javaType = "String", label = "spring-boot")
+    public static final String CAMEL_SPRING_BOOT_VERSION = 
"camel.jbang.camelSpringBootVersion";
+
+    private CamelJBangConstants() {
+    }
+
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
index 0d641e07970..864a1d9547f 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/RuntimeUtil.java
@@ -187,7 +187,7 @@ public final class RuntimeUtil {
     }
 
     public static String getDependencies(Properties properties) {
-        String deps = properties != null ? 
properties.getProperty("camel.jbang.dependencies") : null;
+        String deps = properties != null ? 
properties.getProperty(CamelJBangConstants.DEPENDENCIES) : null;
         if (deps != null) {
             deps = deps.trim();
             if (!deps.isEmpty() && deps.charAt(0) == ',') {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/VersionHelper.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/VersionHelper.java
index c5377952f86..cb8c6c78bf7 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/VersionHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/VersionHelper.java
@@ -46,8 +46,8 @@ public final class VersionHelper {
      * @return          the Spring Boot version string, or null if no version 
can be determined
      */
     public static String getSpringBootVersion(Supplier<String> supplier) {
-        if (System.getProperty("camel.jbang.camelSpringBootVersion") != null) {
-            return System.getProperty("camel.jbang.camelSpringBootVersion");
+        if (System.getProperty(CamelJBangConstants.CAMEL_SPRING_BOOT_VERSION) 
!= null) {
+            return 
System.getProperty(CamelJBangConstants.CAMEL_SPRING_BOOT_VERSION);
         } else if (supplier != null) {
             return supplier.get();
         }
diff --git 
a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JBangModel.java
 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JBangModel.java
new file mode 100644
index 00000000000..a48a99d825e
--- /dev/null
+++ 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JBangModel.java
@@ -0,0 +1,95 @@
+/*
+ * 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.tooling.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JBangModel {
+
+    protected final List<JBangGroupModel> groups = new ArrayList<>();
+    protected final List<JBangOptionModel> options = new ArrayList<>();
+
+    public List<JBangGroupModel> getGroups() {
+        return groups;
+    }
+
+    public void addGroup(JBangGroupModel group) {
+        groups.add(group);
+    }
+
+    public List<JBangOptionModel> getOptions() {
+        return options;
+    }
+
+    public void addOption(JBangOptionModel option) {
+        options.add(option);
+    }
+
+    public static class JBangGroupModel {
+
+        private String name;
+        private String description;
+        private String sourceType;
+
+        public JBangGroupModel() {
+        }
+
+        public JBangGroupModel(String name, String description, String 
sourceType) {
+            this.name = name;
+            this.description = description;
+            this.sourceType = sourceType;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getDescription() {
+            return description;
+        }
+
+        public void setDescription(String description) {
+            this.description = description;
+        }
+
+        public String getSourceType() {
+            return sourceType;
+        }
+
+        public void setSourceType(String sourceType) {
+            this.sourceType = sourceType;
+        }
+    }
+
+    public static class JBangOptionModel extends BaseOptionModel {
+
+        private String sourceType;
+
+        public String getSourceType() {
+            return sourceType;
+        }
+
+        public void setSourceType(String sourceType) {
+            this.sourceType = sourceType;
+        }
+    }
+}
diff --git 
a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
index 26dc20cb597..302afa0cc72 100644
--- 
a/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
+++ 
b/tooling/camel-tooling-model/src/main/java/org/apache/camel/tooling/model/JsonMapper.java
@@ -30,6 +30,8 @@ import 
org.apache.camel.tooling.model.ComponentModel.EndpointHeaderModel;
 import org.apache.camel.tooling.model.ComponentModel.EndpointOptionModel;
 import org.apache.camel.tooling.model.DataFormatModel.DataFormatOptionModel;
 import org.apache.camel.tooling.model.EipModel.EipOptionModel;
+import org.apache.camel.tooling.model.JBangModel.JBangGroupModel;
+import org.apache.camel.tooling.model.JBangModel.JBangOptionModel;
 import org.apache.camel.tooling.model.LanguageModel.LanguageOptionModel;
 import org.apache.camel.tooling.model.MainModel.MainGroupModel;
 import org.apache.camel.tooling.model.MainModel.MainOptionModel;
@@ -604,6 +606,12 @@ public final class JsonMapper {
         option.setSourceType(mp.getString("sourceType"));
     }
 
+    private static void parseGroup(JsonObject mp, JBangGroupModel option) {
+        option.setName(mp.getString("name"));
+        option.setDescription(mp.getString("description"));
+        option.setSourceType(mp.getString("sourceType"));
+    }
+
     private static void parseFunction(JsonObject mp, 
LanguageModel.LanguageFunctionModel func, String name) {
         func.setName(name);
         func.setConstantName(name);
@@ -768,14 +776,43 @@ public final class JsonMapper {
         return model;
     }
 
+    public static JBangModel generateJBangModel(String json) {
+        JsonObject obj = deserialize(json);
+        return generateJBangModel(obj);
+    }
+
+    public static JBangModel generateJBangModel(JsonObject obj) {
+        JBangModel model = new JBangModel();
+        JsonArray mgrp = (JsonArray) obj.get("groups");
+        for (Object entry : mgrp) {
+            JsonObject mg = (JsonObject) entry;
+            JBangGroupModel group = new JBangGroupModel();
+            parseGroup(mg, group);
+            model.addGroup(group);
+        }
+        JsonArray mprp = (JsonArray) obj.get("properties");
+        for (Object entry : mprp) {
+            JsonObject mp = (JsonObject) entry;
+            JBangOptionModel option = new JBangOptionModel();
+            parseOption(mp, option, mp.getString("name"));
+            option.setSourceType(mp.getString("sourceType"));
+            model.addOption(option);
+        }
+        return model;
+    }
+
     public static JsonObject asJsonObject(MainModel model) {
         JsonObject json = new JsonObject();
         JsonArray groups = new JsonArray();
         for (MainGroupModel group : model.getGroups()) {
             JsonObject j = new JsonObject();
             j.put("name", group.getName());
-            j.put("description", group.getDescription());
-            j.put("sourceType", group.getSourceType());
+            if (group.getDescription() != null) {
+                j.put("description", group.getDescription());
+            }
+            if (group.getSourceType() != null) {
+                j.put("sourceType", group.getSourceType());
+            }
             groups.add(j);
         }
         json.put("groups", groups);
@@ -783,8 +820,69 @@ public final class JsonMapper {
         for (MainOptionModel prop : model.getOptions()) {
             JsonObject j = new JsonObject();
             j.put("name", prop.getName());
-            j.put("description", prop.getDescription());
-            j.put("sourceType", prop.getSourceType());
+            if (prop.getDescription() != null) {
+                j.put("description", prop.getDescription());
+            }
+            if (prop.getGroup() != null) {
+                j.put("group", prop.getGroup());
+            }
+            if (prop.getLabel() != null) {
+                j.put("label", prop.getLabel());
+            }
+            if (prop.getSourceType() != null) {
+                j.put("sourceType", prop.getSourceType());
+            }
+            j.put("type", prop.getType());
+            j.put("javaType", prop.getJavaType());
+            if (prop.getDefaultValue() != null) {
+                j.put("defaultValue", prop.getDefaultValue());
+            }
+            if (prop.getEnums() != null) {
+                j.put("enum", prop.getEnums());
+            }
+            if (prop.isDeprecated()) {
+                j.put("deprecated", prop.isDeprecated());
+            }
+            if (prop.isAutowired()) {
+                j.put("autowired", prop.isAutowired());
+            }
+            props.add(j);
+        }
+        json.put("properties", props);
+        return json;
+    }
+
+    public static JsonObject asJsonObject(JBangModel model) {
+        JsonObject json = new JsonObject();
+        JsonArray groups = new JsonArray();
+        for (JBangGroupModel group : model.getGroups()) {
+            JsonObject j = new JsonObject();
+            j.put("name", group.getName());
+            if (group.getDescription() != null) {
+                j.put("description", group.getDescription());
+            }
+            if (group.getSourceType() != null) {
+                j.put("sourceType", group.getSourceType());
+            }
+            groups.add(j);
+        }
+        json.put("groups", groups);
+        JsonArray props = new JsonArray();
+        for (JBangOptionModel prop : model.getOptions()) {
+            JsonObject j = new JsonObject();
+            j.put("name", prop.getName());
+            if (prop.getDescription() != null) {
+                j.put("description", prop.getDescription());
+            }
+            if (prop.getGroup() != null) {
+                j.put("group", prop.getGroup());
+            }
+            if (prop.getLabel() != null) {
+                j.put("label", prop.getLabel());
+            }
+            if (prop.getSourceType() != null) {
+                j.put("sourceType", prop.getSourceType());
+            }
             j.put("type", prop.getType());
             j.put("javaType", prop.getJavaType());
             if (prop.getDefaultValue() != null) {
@@ -836,6 +934,11 @@ public final class JsonMapper {
         return serialize(wrapper);
     }
 
+    public static String createJsonSchema(JBangModel model) {
+        JsonObject wrapper = asJsonObject(model);
+        return serialize(wrapper);
+    }
+
     public static JsonObject deserialize(String json) {
         try {
             return (JsonObject) Jsoner.deserialize(json);
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainDocMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelJBangDocMojo.java
similarity index 79%
copy from 
tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainDocMojo.java
copy to 
tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelJBangDocMojo.java
index e0557270bc8..8f19da01cbd 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainDocMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelJBangDocMojo.java
@@ -25,8 +25,8 @@ import java.util.Map;
 
 import javax.inject.Inject;
 
+import org.apache.camel.tooling.model.JBangModel;
 import org.apache.camel.tooling.model.JsonMapper;
-import org.apache.camel.tooling.model.MainModel;
 import org.apache.camel.tooling.util.PackageHelper;
 import org.apache.camel.tooling.util.Strings;
 import org.apache.maven.plugin.MojoExecutionException;
@@ -41,55 +41,56 @@ import org.codehaus.plexus.build.BuildContext;
 import org.mvel2.templates.TemplateRuntime;
 
 /**
- * Prepares camel-main by updating the main documentation.
+ * Prepares camel-jbang by updating the jbang documentation.
  */
-@Mojo(name = "prepare-main", defaultPhase = LifecyclePhase.PROCESS_CLASSES, 
threadSafe = true,
+@Mojo(name = "prepare-jbang-doc", defaultPhase = 
LifecyclePhase.PROCESS_CLASSES, threadSafe = true,
       requiresDependencyResolution = ResolutionScope.COMPILE)
-public class PrepareCamelMainDocMojo extends AbstractGeneratorMojo {
+public class PrepareCamelJBangDocMojo extends AbstractGeneratorMojo {
 
     /**
      * The documentation directory
      */
-    @Parameter(defaultValue = "${project.basedir}/src/main/docs")
+    @Parameter(defaultValue = 
"${project.basedir}/../../../docs/user-manual/modules/ROOT/pages")
     protected File docDocDir;
 
     /**
-     * The documentation directory
+     * The metadata file
      */
-    @Parameter(defaultValue = 
"${project.basedir}/src/generated/resources/META-INF/camel-main-configuration-metadata.json")
-    protected File mainJsonFile;
+    @Parameter(defaultValue = 
"${project.basedir}/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json")
+    protected File jbangJsonFile;
 
     @Inject
-    public PrepareCamelMainDocMojo(MavenProjectHelper projectHelper, 
BuildContext buildContext) {
+    public PrepareCamelJBangDocMojo(MavenProjectHelper projectHelper, 
BuildContext buildContext) {
         super(projectHelper, buildContext);
     }
 
     @Override
     public void execute(MavenProject project)
             throws MojoFailureException, MojoExecutionException {
-        docDocDir = new File(project.getBasedir(), "src/main/docs");
-        mainJsonFile
+        docDocDir = new File(
+                
project.getBasedir().getParentFile().getParentFile().getParent(), 
"docs/user-manual/modules/ROOT/pages");
+        jbangJsonFile
                 = new File(project.getBasedir(), 
"src/generated/resources/META-INF/camel-main-configuration-metadata.json");
         super.execute(project);
     }
 
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
-        if (!mainJsonFile.exists()) {
+        if (!jbangJsonFile.exists()) {
             // it's not this module so skip
             return;
         }
 
-        File file = new File(docDocDir, "main.adoc");
+        File file = new File(docDocDir, "camel-jbang.adoc");
         boolean exists = file.exists();
         boolean updated;
         try {
-            String json = PackageHelper.loadText(mainJsonFile);
-            MainModel model = JsonMapper.generateMainModel(json);
-            String options = evaluateTemplate("main-options.mvel", model);
-            updated = updateOptionsIn(file, "main", options);
+            String json = PackageHelper.loadText(jbangJsonFile);
+            JBangModel model = JsonMapper.generateJBangModel(json);
+            String options = evaluateTemplate("jbang-options.mvel", model);
+            updated = updateOptionsIn(file, "jbang", options);
         } catch (IOException e) {
-            throw new MojoExecutionException("Error preparing main docs", e);
+            throw new MojoExecutionException("Error preparing jbang docs", e);
         }
 
         if (updated) {
@@ -99,17 +100,17 @@ public class PrepareCamelMainDocMojo extends 
AbstractGeneratorMojo {
                 getLog().debug("No changes to doc file: " + file);
             }
         } else {
-            getLog().warn("No main doc file: " + file);
+            getLog().warn("No jbang doc file: " + file);
         }
     }
 
-    private static String evaluateTemplate(final String templateName, final 
MainModel model) throws MojoExecutionException {
+    private static String evaluateTemplate(final String templateName, final 
JBangModel model) throws MojoExecutionException {
         StringBuilder sb = new StringBuilder(256);
 
         try (InputStream templateStream = 
UpdateReadmeMojo.class.getClassLoader().getResourceAsStream(templateName)) {
             String template = PackageHelper.loadText(templateStream);
             // loop each group and eval
-            for (MainModel.MainGroupModel group : model.getGroups()) {
+            for (JBangModel.JBangGroupModel group : model.getGroups()) {
                 Map<String, Object> root = new HashMap<>();
                 root.put("group", group);
                 root.put("options", model.getOptions().stream()
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelJBangMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelJBangMojo.java
new file mode 100644
index 00000000000..91dde407a9d
--- /dev/null
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelJBangMojo.java
@@ -0,0 +1,182 @@
+/*
+ * 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.maven.packaging;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.tooling.model.JBangModel;
+import org.apache.camel.tooling.model.JsonMapper;
+import org.apache.camel.tooling.util.JavadocHelper;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.annotations.ResolutionScope;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectHelper;
+import org.codehaus.plexus.build.BuildContext;
+import org.jboss.forge.roaster.Roaster;
+import org.jboss.forge.roaster.model.StaticCapable;
+import org.jboss.forge.roaster.model.source.AnnotationSource;
+import org.jboss.forge.roaster.model.source.FieldSource;
+import org.jboss.forge.roaster.model.source.JavaClassSource;
+
+/**
+ * Prepares camel-jbang by generating Camel JBang configuration metadata for 
tooling support.
+ */
+@Mojo(name = "prepare-jbang", defaultPhase = LifecyclePhase.PROCESS_CLASSES, 
threadSafe = true,
+      requiresDependencyResolution = ResolutionScope.COMPILE)
+public class PrepareCamelJBangMojo extends AbstractGeneratorMojo {
+
+    @Parameter(defaultValue = "${project.basedir}/src/generated/resources")
+    protected File outFolder;
+
+    @Inject
+    public PrepareCamelJBangMojo(MavenProjectHelper projectHelper, 
BuildContext buildContext) {
+        super(projectHelper, buildContext);
+    }
+
+    /**
+     * Parses the Camel JBang configuration java source file.
+     */
+    public static List<JBangModel.JBangOptionModel> 
parseConfigurationSource(String fileName) throws IOException {
+        return parseConfigurationSource(new File(fileName));
+    }
+
+    /**
+     * Parses the Camel JBang configuration java source file.
+     */
+    public static List<JBangModel.JBangOptionModel> 
parseConfigurationSource(File file) throws IOException {
+        final List<JBangModel.JBangOptionModel> answer = new ArrayList<>();
+
+        JavaClassSource clazz = (JavaClassSource) Roaster.parse(file);
+        List<FieldSource<JavaClassSource>> fields = clazz.getFields();
+        fields = fields.stream().filter(StaticCapable::isStatic).toList();
+        fields.forEach(f -> {
+            AnnotationSource<?> as = f.getAnnotation(Metadata.class);
+            if (as != null) {
+                String name = f.getStringInitializer();
+                String javaType = as.getStringValue("javaType");
+                String defaultValue = as.getStringValue("defaultValue");
+                String desc = as.getStringValue("description");
+                String label = as.getStringValue("label");
+                boolean deprecated = clazz.getAnnotation(Deprecated.class) != 
null || f.getAnnotation(Deprecated.class) != null;
+                String type = fromMainToType(javaType);
+                JBangModel.JBangOptionModel model = new 
JBangModel.JBangOptionModel();
+                model.setName(name);
+                model.setType(type);
+                model.setJavaType(javaType);
+                model.setDescription(JavadocHelper.sanitizeDescription(desc, 
false));
+                model.setLabel(label);
+                model.setSourceType(null);
+                model.setDefaultValue(asDefaultValue(type, defaultValue));
+                model.setDeprecated(deprecated);
+                List<String> enums = null;
+                String text = as.getStringValue("enums");
+                if (text != null) {
+                    enums = Arrays.asList(text.split(","));
+                }
+                model.setEnums(enums);
+                answer.add(model);
+            }
+        });
+
+        return answer;
+    }
+
+    private static String fromMainToType(String type) {
+        if ("boolean".equals(type) || "java.lang.Boolean".equals(type)) {
+            return "boolean";
+        } else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
+            return "integer";
+        } else if ("long".equals(type) || "java.lang.Long".equals(type)) {
+            return "integer";
+        } else if ("float".equals(type) || "java.lang.Float".equals(type)) {
+            return "number";
+        } else if ("double".equals(type) || "java.lang.Double".equals(type)) {
+            return "number";
+        } else if ("string".equals(type) || "java.lang.String".equals(type)) {
+            return "string";
+        } else {
+            return "object";
+        }
+    }
+
+    private static Object asDefaultValue(String type, String defaultValue) {
+        if (defaultValue != null) {
+            if ("boolean".equals(type)) {
+                return Boolean.parseBoolean(defaultValue);
+            } else if ("integer".equals(type)) {
+                return Integer.parseInt(defaultValue);
+            }
+        }
+        if (defaultValue == null && "boolean".equals(type)) {
+            return "false";
+        }
+        return defaultValue;
+    }
+
+    @Override
+    public void execute(MavenProject project) throws MojoFailureException, 
MojoExecutionException {
+        outFolder = new File(project.getBasedir(), "src/generated/resources");
+        super.execute(project);
+    }
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        // scan for configuration files
+        File[] files = new File(project.getBasedir(), 
"src/main/java/org/apache/camel/dsl/jbang/core/common")
+                .listFiles(f -> f.isFile() && 
f.getName().endsWith("Constants.java"));
+        if (files == null || files.length == 0) {
+            return;
+        }
+
+        final List<JBangModel.JBangOptionModel> data = new ArrayList<>();
+
+        for (File file : files) {
+            getLog().info("Parsing Camel JBang configuration file: " + file);
+            try {
+                List<JBangModel.JBangOptionModel> model = 
parseConfigurationSource(file);
+                data.addAll(model);
+            } catch (Exception e) {
+                throw new MojoFailureException("Error parsing file " + file + 
" due " + e.getMessage(), e);
+            }
+        }
+
+        // lets sort so they are always ordered
+        data.sort((o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()));
+
+        if (!data.isEmpty()) {
+            JBangModel model = new JBangModel();
+            model.getOptions().addAll(data);
+            model.getGroups().add(new JBangModel.JBangGroupModel(
+                    "camel.jbang", "Camel JBang configurations", null));
+            String json = JsonMapper.createJsonSchema(model);
+
+            updateResource(outFolder.toPath(), 
"META-INF/camel-jbang-configuration-metadata.json", json);
+        }
+    }
+
+}
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainDocMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainDocMojo.java
index e0557270bc8..15f5740b43b 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainDocMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCamelMainDocMojo.java
@@ -54,7 +54,7 @@ public class PrepareCamelMainDocMojo extends 
AbstractGeneratorMojo {
     protected File docDocDir;
 
     /**
-     * The documentation directory
+     * The metadata file
      */
     @Parameter(defaultValue = 
"${project.basedir}/src/generated/resources/META-INF/camel-main-configuration-metadata.json")
     protected File mainJsonFile;
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
index fcba61832e1..eb0908b6551 100644
--- 
a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareCatalogMojo.java
@@ -162,6 +162,12 @@ public class PrepareCatalogMojo extends AbstractMojo {
     @Parameter(defaultValue = 
"${project.basedir}/src/generated/resources/org/apache/camel/catalog/main")
     protected File mainOutDir;
 
+    /**
+     * The output directory for generated jbang
+     */
+    @Parameter(defaultValue = 
"${project.basedir}/src/generated/resources/org/apache/camel/catalog/jbang")
+    protected File jbangOutDir;
+
     /**
      * The components directory where all the Apache Camel components are
      */
@@ -216,6 +222,12 @@ public class PrepareCatalogMojo extends AbstractMojo {
     @Parameter(defaultValue = 
"${project.basedir}/../../core/camel-main/target/classes/META-INF")
     protected File mainDir;
 
+    /**
+     * The directory where the camel-jbang metadata are
+     */
+    @Parameter(defaultValue = 
"${project.basedir}/../../dsl/camel-jbang/camel-jbang-core/target/classes/META-INF")
+    protected File jbangDir;
+
     /**
      * Skip the execution of this mojo
      */
@@ -397,6 +409,7 @@ public class PrepareCatalogMojo extends AbstractMojo {
             executeDocuments(components, dataformats, languages, others);
             executeXmlSchemas();
             executeMain();
+            executeJBang();
         } catch (Exception e) {
             throw new MojoFailureException("Error preparing catalog", e);
         }
@@ -997,6 +1010,11 @@ public class PrepareCatalogMojo extends AbstractMojo {
         
copyFile(mainDir.toPath().resolve("camel-main-configuration-metadata.json"), 
mainOutDir.toPath());
     }
 
+    protected void executeJBang() throws Exception {
+        getLog().info("Copying camel-jbang metadata");
+        
copyFile(jbangDir.toPath().resolve("camel-jbang-configuration-metadata.json"), 
jbangOutDir.toPath());
+    }
+
     protected void executeDocuments(
             Set<String> components, Set<String> dataformats, Set<String> 
languages, Set<String> others) {
         // lets use sorted set/maps
diff --git 
a/tooling/maven/camel-package-maven-plugin/src/main/resources/jbang-options.mvel
 
b/tooling/maven/camel-package-maven-plugin/src/main/resources/jbang-options.mvel
new file mode 100644
index 00000000000..c7491e55c48
--- /dev/null
+++ 
b/tooling/maven/camel-package-maven-plugin/src/main/resources/jbang-options.mvel
@@ -0,0 +1,24 @@
+@comment{
+  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.
+}
+=== @{group.description}
+The @{group.name} supports @{options.size()} options, which are listed below.
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===@comment{ Render table cells. If description contains newline, prefix cell 
with `a`, so the content is rendered with formatting. }
+| Name | Description | Default | Type
+@foreach{row : options}| *@{row.getShortName(30)}* 
@{row.description.?contains("\n") ? "a" : ""}| @{util.escape(row.description)} 
| @{row.getShortDefaultValue(20)} | @{row.getShortJavaType()}
+@end{}|===


Reply via email to